Repository navigation
Description
Slice 2 of #514 (modular monolith). Enforcement only — no production code. Needs slice 1.
Declare the two surfaces MCP and OAuth are about to add, before they exist, so the ledger is not
wrong the day they land. Track A of the
2026-09-14 re-plan.
Why this wants to precede #806 and #795
MCP tool classes inject repositories by design.
docs/plans/770-mcp-server/01-design.md:112 sanctions
WaterTools(McpCallContext call, IWaterUsageRepository water). #514's §8 rule 4 says an adapter "may
call a module contract or approved workflow, not handlers/repositories/context". Both cannot hold.
If #806–#809 merge first, #514's later adapter guard is red on merged code the day it is written, and
the cheap fix is to weaken the guard — the "a wrong guard reads as safety" failure #407 spent five
review rounds on. #514 resolves it on its own side, with a named and dated tier rather than a
watered-down rule.
OpenIddict adds four unowned tables. Today's 38 mapped tables map onto §3.3's owner list with
no gap (verified against docs/schema/). #795 makes it 42. With the ledger already committed,
assigning them is four lines inside #795's own PR, written by the author who knows why they carry no
AccountId — rather than reconstructed later by someone else.
Both are requests, not blocks. #514 is priority:tier4 and will not hold a tier3 slice. Notes
are on #806, #807 and #795.
Scope
- An
AdapterTierconcept in the ledger: a named set of namespaces carrying a privilege a module may
not have, each with a reason and a review issue, so the exemption has an end date. - Row one —
Mcp/→DirectRepository, reason citing770-mcp-server/01-design.md:112. - The four OpenIddict tables → Access owner, reason citing
788-mcp-oauth/04-verified-findings.md(noAccountId, structurally skipped by the tenancy walks,
boot unaffected).
The one mechanic that matters
Key the Mcp/ tier on EndpointDataSource, not on the folder. src/Cluckwork.Api/Mcp/ does not
exist yet. A guard that fails closed on an absent folder is red from the moment it lands until #806
merges, which trains everyone to ignore it. Assert the tier only once /mcp is actually mapped.
Done when
| Mutation | Expected |
|---|---|
add a tool-shaped class injecting a repository, outside the declared Mcp/ namespaces |
red — undeclared adapter privilege |
delete the Mcp tier row while a mapped /mcp surface exists |
red |
| add a mapped table with no owner row | red |
remove the ReviewBy issue from a tier row |
red — an exemption with no end date |
Green on a clean tree today, with /mcp absent and OpenIddict absent. That is the point: it must
be committable before either epic lands.
Explicitly not in this slice
Changes no MCP or OAuth code. Does not ask #807–#809 to call contracts instead of repositories —
that is a Track C question, and #514 absorbs the crossing on its side for now. Table-owner
completeness across all 38 tables is Track B; this slice only adds the four that #795 introduces.
Activity
[-]#514 slice 2: adapter-tier rows for the MCP and OpenIddict surfaces[/-][+][A] #514 slice 2: adapter-tier rows for the MCP and OpenIddict surfaces[/+]mforce commentedon Sep 15, 2026
Status: the adapter-tier mechanism and the dormant
Cluckwork.Api.Mcprow ship in the PR linked above. The second scope bullet (owner rows for the four OpenIddict tables) is met by #877's table-owner guard onmain: it fails #795's PR the moment a mapped table has no owner row, so those rows are written in #795 by its author. The "add a mapped table with no owner row → red" criterion is therefore already enforced; the other four criteria are the PR's mutation table.test(arch): adapterTiers ledger section and syntax scanner (#843)
test(arch): union adapter tiers into the reach ratchet's roots (#843)
docs(decisions): adapter-tiers decision record and AGENTS.md rule (#843)
test(arch): fold tier namespaces into the ledger's adapter and persis…
fix(arch): validate adapterTiers surface against the scanner's own cl…
fix(arch): resolve using aliases before matching the tool attribute (#…
fix(arch): fail the walk when a project defines an undeclared preproc…
test(arch): drop narration comments from the alias and define-constan…
fix(arch): over-approximate MSBuild define-constants instead of resol…
fix(arch): resolve alias chains to a fixed point before matching a to…
fix(arch): tie a tier row's privilege to its surface's mapped value (#…
test(arch): drop round-2 narration comments (#843)
docs: correct the #843 dormant-tier claim, which said red was stale