feat(gateway,admin-ui): corpus create/delete admin CRUD (Step 3.10)#189
Merged
Merged
Conversation
Corpus management in the admin console was local-only: the "New corpus"
button mutated React state and never called the gateway, and the gateway
had no write route (POST /v1/corpora returned 405). This wires it end to end.
- CorpusStore SPI: add tenant-scoped create / delete (NoopCorpusStore +
PgCorpusStore), with the same cross-tenant invisibility rule as get.
- Gateway: POST /v1/corpora (201, server-minted id, tenant from ctx) and
DELETE /v1/corpora/{id} (204/404). New CreateCorpusRequest wire type.
- Admin UI: createCorpus / deleteCorpus client + Corpora page calls them
when live, keeps local behaviour in demo mode (mirrors the Webhooks page).
- Tests: gateway routes (test_corpora.py), SPI conformance, Pg integration.
- Docs + regenerated dist/openapi.{json,yaml}.
Verified locally (CI billing-blocked): full create -> list -> delete -> 404
lifecycle + tenant isolation + CORS preflight/POST from :3100; ruff,
mypy --strict, pytest, admin-ui tsc + vitest all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
officialCodeWork
pushed a commit
that referenced
this pull request
Jun 11, 2026
Recently-shipped bullet + PR & Branch History row + Status note for the first post-GA V1.1 feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
officialCodeWork
added a commit
that referenced
this pull request
Jun 12, 2026
…-corpus-admin-crud docs(tracker): record Step 3.10 corpus admin CRUD (#189)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Creating a corpus from the admin console triggered no API call — the New corpus button only mutated React state, and the gateway had no write route at all (
POST /v1/corpora→ 405). So corpora "created" in the UI never persisted and vanished on refresh. Same for delete (local filter) and edit (no-op).This is the Step 3.10 admin write surface the
CorpusStoreSPI + corpus router docstrings always anticipated ("Create / delete are operator actions tied to the admin surface, Step 3.10").Change (vertical slice)
CorpusStoregains tenant-scopedcreate/delete— same cross-tenant invisibility rule asget(tenant A can neither see nor delete tenant B's corpus). Implemented inNoopCorpusStore+PgCorpusStore(newDELETE … RETURNING;createreuses the tested upsert path).CreateCorpusRequest— body carries only display/embedding fields;idis server-minted (corpus_…) andtenant_idcomes from the authenticated request, so a caller can't choose an id or write into another tenant.POST /v1/corpora(201) +DELETE /v1/corpora/{id}(204 / 404). Mirrors the webhook write surface; emitscorpus.created/corpus.deleted.createCorpus/deleteCorpusclient; the Corpora page calls them when live and keeps local behaviour in demo mode (sameGATEWAY_URL && source === "live"gate as the Webhooks page).Corpus update (
PATCH) stays deferred — the console edits no corpus fields yet; the Edit row action remains a placeholder.Verification (CI is billing-blocked → verified locally)
POST→201(server-minted id,tenant_idfrom auth) →GETlists it →DELETE→204→ secondDELETE→404 corpus_not_found→ list back to0.globexcan neitherGETnorDELETEacme's corpus (404).http://localhost:3100→200(allows POST/DELETE + the UI's headers); real cross-originPOST→201.pytest(gateway incl. newtest_corpora.py, contract incl. policy-coverage + SPI-signature linters, logs/event-registry, retrieval, backends, ragctl),ruff,mypy --strict(163 files), admin-uitsc, admin-uivitest, OpenAPI + schema drift — all green.Documentation
docs/reference/gateway.md— newPOST /v1/corpora+DELETE /v1/corpora/{id}sections (request table, curl, status codes) + routes table.docs/architecture/gateway.md— corpus CRUD note updated (read shipped v0; create/delete in 3.10; update still deferred).docs/reference/admin-ui.md— Corpora row now reflects live create/delete.dist/openapi.{json,yaml}regenerated (45 paths;create_corpus/delete_corpusoperations).🤖 Generated with Claude Code