openapi: 3.0.3 info: title: pageDB description: | Backend facade for provisioning Elasticsearch deployments via the Elasticsearch Operator on Kubernetes, plus document indexing and search operations. version: 1.0.0 contact: name: Marry Poppins servers: - url: https://pagedb.stackit.gg description: Production - url: http://localhost:8080 description: Local development tags: - name: Auth description: User authentication and registration - name: Infrastructure description: Provision and manage Elasticsearch instances in Kubernetes - name: Search description: Index, retrieve, delete, and search documents paths: # ─────────────────────────────────────────────────────────────────────────── # Auth API # ─────────────────────────────────────────────────────────────────────────── /v1/auth/register: post: tags: [Auth] summary: Register a new user description: Creates a new user account. Returns a JWT token and the assigned role. operationId: registerUser security: [] # Public endpoint requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AuthRequest' responses: '201': description: User registered successfully content: application/json: schema: $ref: '#/components/schemas/AuthResponse' '400': $ref: '#/components/responses/BadRequest' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' '500': $ref: '#/components/responses/InternalError' /v1/auth/login: post: tags: [Auth] summary: Authenticate user and return token description: Validates credentials and returns a JWT token and the user's role. operationId: loginUser security: [] # Public endpoint requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AuthRequest' responses: '200': description: Login successful content: application/json: schema: $ref: '#/components/schemas/AuthResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' # ─────────────────────────────────────────────────────────────────────────── # Infrastructure API # ─────────────────────────────────────────────────────────────────────────── /v1/elasticsearch/instances: get: tags: [Infrastructure] summary: List all Elasticsearch instances operationId: listInstances responses: '200': description: A list of instances content: application/json: schema: type: array items: $ref: '#/components/schemas/Instance' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' post: tags: [Infrastructure] summary: Create a new Elasticsearch instance operationId: createInstance requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/InstanceCreateRequest' responses: '201': description: Instance created successfully content: application/json: schema: $ref: '#/components/schemas/Instance' '400': $ref: '#/components/responses/BadRequest' '409': $ref: '#/components/responses/Conflict' '500': $ref: '#/components/responses/InternalError' /v1/elasticsearch/instances/{instanceId}: parameters: - name: instanceId in: path required: true schema: type: string pattern: '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$' description: Unique identifier / Kubernetes name of the Elasticsearch cluster get: tags: [Infrastructure] summary: Get details of a specific instance operationId: getInstance responses: '200': description: Instance details content: application/json: schema: $ref: '#/components/schemas/Instance' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' delete: tags: [Infrastructure] summary: Delete an Elasticsearch instance operationId: deleteInstance responses: '204': description: Instance deleted successfully '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /v1/elasticsearch/instances/{instanceId}/logs: parameters: - name: instanceId in: path required: true schema: type: string pattern: '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$' description: Unique identifier / Kubernetes name of the Elasticsearch cluster get: tags: [Infrastructure] summary: Get operation logs for a specific instance operationId: getInstanceLogs responses: '200': description: List of log entries content: application/json: schema: type: array items: $ref: '#/components/schemas/LogEntry' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' # ─────────────────────────────────────────────────────────────────────────── # Search API # ─────────────────────────────────────────────────────────────────────────── /v1/search/{instanceId}/docs: parameters: - name: instanceId in: path required: true schema: type: string description: Elasticsearch instance identifier get: tags: [Search] summary: Search documents in an index operationId: searchDocs parameters: - name: q in: query required: true description: Search query string schema: type: string - name: index in: query required: false description: Index to search in (defaults to 'default') schema: type: string default: default responses: '200': description: Search results content: application/json: schema: type: array items: $ref: '#/components/schemas/Document' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' post: tags: [Search] summary: Index a text document operationId: indexDoc requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DocumentCreateRequest' responses: '201': description: Document indexed content: application/json: schema: $ref: '#/components/schemas/DocumentIndexResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /v1/search/{instanceId}/indices: parameters: - name: instanceId in: path required: true schema: type: string description: Elasticsearch instance identifier get: tags: [Search] summary: List indices in an Elasticsearch instance operationId: listIndices responses: '200': description: List of index names content: application/json: schema: $ref: '#/components/schemas/IndexList' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /v1/search/{instanceId}/docs/{docId}: parameters: - name: instanceId in: path required: true schema: type: string description: DB instance identifier - name: docId in: path required: true schema: type: string description: Document identifier delete: tags: [Search] summary: Delete a document operationId: deleteDoc parameters: - name: index in: query required: true description: Index the document belongs to (defaults to 'default') schema: type: string default: default responses: '204': description: Document deleted successfully '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT apiKey: type: apiKey in: header name: X-API-KEY schemas: # Added from Auth file AuthRequest: type: object required: [username, password] properties: username: type: string example: "johndoe" password: type: string format: password example: "s3cureP@ssw0rd" inviteCode: type: string description: Invite code required when invite-only mode is enabled example: "sunset-rocket-42" AuthResponse: type: object required: [token, role] properties: token: type: string description: JWT access token role: type: string enum: [default, admin] example: "default" # Kept from Original file InstanceCreateRequest: type: object required: [instanceId] properties: instanceId: type: string pattern: '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$' description: | Kubernetes-compatible name for the Elasticsearch cluster. All other configuration (version, node count, storage, etc.) is managed by the server. Instance: type: object required: [id, name, status, createdAt, updatedAt] properties: id: type: string description: Unique identifier of the instance name: type: string description: Kubernetes-compatible name of the Elasticsearch cluster version: type: string example: "8.11.0" description: Elasticsearch version deployed by the server nodeCount: type: integer description: Number of Elasticsearch nodes deployed by the server storageSize: type: string example: "10Gi" description: Persistent volume claim size per node, managed by the server endpoint: type: string format: uri description: Internal cluster endpoint for the Elasticsearch cluster status: type: string enum: [pending, creating, ready, degraded, failed, deleting] health: type: string enum: [green, yellow, red, unknown] createdAt: type: string format: date-time updatedAt: type: string format: date-time InstanceList: type: object required: [items] properties: items: type: array items: $ref: '#/components/schemas/Instance' DocumentCreateRequest: type: object required: [text] properties: text: type: string description: Text content to index example: "The quick brown fox jumps over the lazy dog" index: type: string default: default description: Target Elasticsearch index (defaults to 'default') example: "articles" DocumentIndexResponse: type: object required: [documentId, index] properties: documentId: type: string description: Auto-generated document ID assigned by Elasticsearch index: type: string description: The index the document was stored in Document: type: object required: [documentId, text, index] properties: documentId: type: string description: Document identifier text: type: string description: Document text content index: type: string description: Index the document belongs to score: type: number format: double description: Relevance score from search LogEntry: type: object required: [id, instanceId, operation, status, message, timestamp, username] properties: id: type: string description: Unique identifier of the log entry instanceId: type: string description: Instance this log entry belongs to operation: type: string enum: [create_instance, get_instance, list_instances, delete_instance, index_doc, search_docs, delete_doc, list_indices] description: The operation that was performed status: type: string enum: [success, failure] description: Whether the operation succeeded or failed message: type: string description: Human-readable summary of the operation timestamp: type: string format: date-time description: When the operation occurred username: type: string description: User who performed the operation IndexList: type: object required: [indices] properties: indices: type: array items: type: string description: List of index names in the Elasticsearch instance responses: BadRequest: description: The request was invalid or cannot be served Unauthorized: description: Authentication failed or user lacks permissions Forbidden: description: The request is forbidden (e.g. invalid invite code) NotFound: description: The requested resource was not found Conflict: description: The request could not be completed due to a conflict with the current state of the resource InternalError: description: An unexpected error occurred on the server