openapi: 3.0.3 info: title: spark-mcp-go Admin API version: 0.0.0 description: | Admin API for cluster and audit log configuration. All endpoints require `Authorization: Bearer ` (matches any token in the comma-separated ADMIN_TOKENS env var). servers: - url: http://localhost:8080 description: Default local dev components: securitySchemes: bearerAuth: type: http scheme: bearer schemas: Cluster: type: object required: [id, name, rm_url, shs_url, spark_submit_execute_bin] properties: id: { type: string, example: prod } name: { type: string, example: Production } rm_url: { type: string, format: uri, example: http://rm:8088 } shs_url: { type: string, format: uri, example: http://shs:18080 } spark_submit_execute_bin: type: string example: /opt/spark/bin/spark-submit description: Absolute path to spark-submit binary is_active: { type: boolean, default: true } auth_type: type: string enum: [none, simple, basic] default: none auth_username: { type: string, description: 'simple: user.name, basic: username' } ssl_verify: { type: boolean, default: true } ssl_ca_bundle: { type: string } url_allowlist: type: array items: { type: string } description: Additional host patterns (besides RM/SHS) permitted for fetch_url default_submit_args: type: array items: { type: string } description: Prepended to every spark_submit args rate_limit_per_min: type: integer default: 10 minimum: 0 created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } AuditEntry: type: object properties: id: { type: integer } timestamp: { type: string, format: date-time } actor: { type: string, example: 'admin:secret-a' } action: { type: string, enum: [cluster.create, cluster.update, cluster.delete] } cluster_id: { type: string, nullable: true } details: { type: string, description: 'JSON-encoded before/after diff' } Error: type: object properties: error: { type: string } security: - bearerAuth: [] paths: /admin/clusters: get: summary: List all clusters responses: '200': description: Array of clusters (always [] even if empty) content: application/json: schema: type: array items: { $ref: '#/components/schemas/Cluster' } post: summary: Create a cluster requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/Cluster' } responses: '201': { description: Created, content: { application/json: { schema: { $ref: '#/components/schemas/Cluster' } } } } '400': { description: Validation error, content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } } /admin/clusters/{id}: parameters: - name: id in: path required: true schema: { type: string } get: summary: Get a single cluster responses: '200': { description: OK, content: { application/json: { schema: { $ref: '#/components/schemas/Cluster' } } } } '404': { description: Not found } put: summary: Update a cluster (password in body is ignored; set via dedicated endpoint) requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/Cluster' } responses: '200': { description: OK } '404': { description: Not found } delete: summary: Delete a cluster responses: '204': { description: Deleted } '404': { description: Not found } /admin/audit: get: summary: Query audit log (most recent first) parameters: - name: limit in: query schema: { type: integer, default: 100, minimum: 1, maximum: 1000 } responses: '200': description: Array of audit entries content: application/json: schema: type: array items: { $ref: '#/components/schemas/AuditEntry' }