# Docs Endpoints Implementation Plan ## Endpoints | Endpoint | Method | Path | Status | Response | |---|---|---|---|---| | IndexDoc | POST | `/v1/search/{instanceId}/docs` | 201 | `DocumentIndexResponse` | | SearchDocs | GET | `/v1/search/{instanceId}/docs` | 200 | `[]Document` | | DeleteDoc | DELETE | `/v1/search/{instanceId}/docs/{docId}` | 204 | — | ## Shared Helpers (add to `server.go`) ### `defaultIndex(idx *string) string` Returns `"default"` if `idx` is nil/empty, otherwise the dereferenced value. ### `readESBody(resp *esapi.Response) ([]byte, error)` Reads and closes the ES response body, returns bytes. Prevents body leaks. ### `validateInstanceOwner(ctx context.Context, instanceId string, username string) error` Fetches the ES cluster from K8s, checks: - Instance exists → 404 if not - `paas-instance-owner` label matches `username` → 404 if not (consistent with existing pattern) Returns error with appropriate message; callers map to HTTP status. ## Endpoint Implementations ### IndexDoc 1. Parse body → `DocumentCreateRequest` (via `reqBody[T]`) 2. `validateInstanceOwner` → 404 if not owner/missing 3. `getESClient` → 500 if fails (instance not ready) 4. Resolve index via `defaultIndex(req.Index)` 5. Build JSON body: `{"text": req.Text}` 6. Call `esClient.Index(index, body, nil, ptr("wait_for"))` — auto-generate doc ID, `refresh=wait_for` for immediate searchability 7. Parse ES response JSON → extract `_id` and `_index` 8. Return `201` + `DocumentIndexResponse{DocumentId, Index}` ### SearchDocs 1. `validateInstanceOwner` → 404 2. `getESClient` → 500 3. Resolve index via `defaultIndex(params.Index)` 4. Build ES query: `{"query": {"match": {"text": params.Q}}}` 5. Call `esClient.Search(index, body)` 6. Parse hits → `[]api.Document`: - `_id` → `DocumentId` - `_source.text` → `Text` - `_index` → `Index` - `_score` → `Score` (pointer, omit if zero) 7. Return `200` + document array ### DeleteDoc 1. `validateInstanceOwner` → 404 2. `getESClient` → 500 3. Call `esClient.Delete(params.Index, docId)` 4. Check ES response status: if 404 → return `404` "document not found" 5. Return `204` No Content ## Design Decisions | Decision | Choice | Rationale | |---|---|---| | Index default | `"default"` | Matches OpenAPI spec default | | Index mapping | ES dynamic mapping | Simplest — ES auto-creates index and maps `text` field | | IndexDoc refresh | `wait_for` | Document immediately searchable after indexing | | SearchDocs query | `match` on `text` field | Simple full-text search, sufficient for MVP | | Ownership check | `paas-instance-owner` label | Returns 404 for both not-found and not-owned (consistent with existing pattern) | | Auth requirement | Owner-only | User must own the ES instance to operate on its docs |