Skip to content

The subject namespace is the platform's, and it says so - #131

Merged
czpython merged 1 commit into
mainfrom
commonzenpython/eng-779-platform-owns-the-subject-namespace
Jul 27, 2026
Merged

The subject namespace is the platform's, and it says so#131
czpython merged 1 commit into
mainfrom
commonzenpython/eng-779-platform-owns-the-subject-namespace

Conversation

@czpython

Copy link
Copy Markdown
Owner

Declaring a subject mounts a read surface the extension writes none of, and review's trigger sat next to it looking like the same noun spelled twice:

POST /api/review/pull-requests      the author's router
GET  /api/review/pull_request       the platform's board

They were never the same noun. GET /api/review/pull_request is not a list of pull requests — it is the board of open review runs, keyed by subject. What the POST creates is a review, so that is what it is called now:

router = APIRouter(prefix="/reviews")

Nothing changes about authoring. An extension declares routers in routes.py and they mount under its namespace, exactly as before — there is no way to attach an action to the platform's subject path, and there should not be: the operation is the author's own resource and belongs on its own path. ship has proved that since the subject read-side landed, serving /api/ship/work_item beside /api/ship/work-items with nothing to reconcile.

Two spellings run through druks and never mean the same thing: snake_case is identity — a subject type, a run's kind, an event's attributes — and kebab-case is a URL segment. Under that rule pull_request and pull-requests were never in conflict. It is how the repo already behaved and it had never been written down.

What did need enforcing is the one case where the two surfaces genuinely collide. Declared routers mount ahead of the platform's, so a router reaching into the subject's own segment takes the board or a detail read with it — and nothing collides at import, so the loss surfaces much later as a 404 from a route nobody deleted. That fails at load now, naming the segment and what owns it. The rule is exact: the subject's segment, whatever the method, and no resemblance check — /widgets is an author's own resource and says nothing about /widget.

The order the guard protects is pinned by a test rather than left to a list literal.

An extension's routers are also tagged with its name at mount, where the platform already applies the prefix and the identity gate. tags= had drifted to mean two things across four routers — the extension in two, the resource in the others — and a router now declares only what its own resource is called.

@czpython
czpython merged commit 8040a4f into main Jul 27, 2026
1 check passed
@czpython
czpython deleted the commonzenpython/eng-779-platform-owns-the-subject-namespace branch July 27, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant