# 8.8 — `X-Service: memory` adapter, core resources (GREEN) Phase: 8 — ServiceAdapter CRD rollout Stage: RED Depends on: 8.1, 8.2, 8.3 Design contract: [API_ROUTING_HYBRID_DESIGN.md](../API_ROUTING_HYBRID_DESIGN.md) §6. Covers only the poimen-memory endpoints confirmed **already built and tested** (`~/workplace/Poimen/memory/DESIGN.md`'s M3.5 phase): `GET /memory/query`, `GET /memory/projects`, `GET /memory/projects/{id}/status`, `GET /memory/skills`, `GET /memory/skills/{name}`, `POST /memory/ingest`. `/memory/context`, `/memory/projects/{id}/notes` and the git-aware `/memory/nodes/*` endpoints are **not** in scope here — see [8.9](8.9-memory-adapter-extended.md). **Hard prerequisite, not optional — do in this order:** 1. `NetworkPolicy` in namespace `poimen` restricting ingress on `poimen-memory` to the `api` namespace's gateway pod only. Must land before step 2. 2. Remove the `apikey:` middleware from `poimen-memory` itself — separate change in the `~/workplace/Poimen/memory` repo, out of scope for this repo but a hard prerequisite for this adapter being safe to expose. Do not apply the CR below before this lands. 3. Provision `memory:read`/`memory:write` as real Authentik scopes (via 8.7's `iam` adapter or `core mwinit`-issued tokens). - [ ] `k8s/serviceadapter-memory.yaml` CR per §6's example, `auth.capability: memory:read` default, `ingest` method overrides to `memory:write` - [ ] `responseSchema` on `query` uses 8.3's array-of-object extension: `type: array, items: { fields: { level: string, sha256: string, text: string, score: number } }` - [ ] `responseSchema` on `projects` uses the array-of-scalar extension: `type: array, items: string` - [ ] `responseSchema` on `skills`/`skills/{name}` marks `generated_from` as `{type: string, nullable: true}` — the real upstream response sends `null` for un-derived skills, confirmed in `DESIGN.md`'s example - [ ] `requestSchema` on `ingest`: `required: ["project", "source", "records"]`, `ingest_id` optional (`strict: false` — server may compute it if absent) - [ ] A `memory:read`-scoped token can `GET` `query`/`skill`/`project` and gets 403 on `ingest`; a `memory:write`-scoped token can `POST ingest` ## Verify ```bash curl -s -H 'Authorization: Bearer ' \ https://api.riotpiao.com/ -H 'X-Service: memory' -H 'X-Resource: query' \ -G --data-urlencode 'query=why did requests over 10KB fail' \ --data-urlencode 'project=poimen' --data-urlencode 'level=L1,L2' # expected: 200, JSON array of {level,sha256,text,score,parents} curl -s -H 'Authorization: Bearer ' \ https://api.riotpiao.com/ -H 'X-Service: memory' -H 'X-Resource: project' # expected: 200, ["poimen", ...] curl -s -o /dev/null -w '%{http_code}\n' -X POST \ -H 'Authorization: Bearer ' \ https://api.riotpiao.com/ -H 'X-Service: memory' -H 'X-Resource: ingest' -d '{}' # expected: 403 — memory:read token, ingest needs memory:write curl -s -X POST -H 'Authorization: Bearer ' \ https://api.riotpiao.com/ -H 'X-Service: memory' -H 'X-Resource: ingest' \ -d '{"project":"poimen","source":"agent:uuid","records":[]}' # expected: 202, {"job_id":"ingest-...","status_url":"..."} kubectl -n poimen get networkpolicy -o yaml | grep -A5 poimen-memory # expected: ingress restricted to the api namespace's gateway pod selector only ```