The subprocessor seam proves its LOGIC and not the live AGREEMENT — nothing compares the published page against the manifest motir-core is actually serving
Opened by Zhu Yue ·
Found by motir run MOTIR-3909 while building MOTIR-4011 (2026-09-02). It holds nothing up and is filed forward.
⚠️ AMENDED ON THE RECORD 2026-09-02 by
motir run MOTIR-4139(guard #4). Two things this card asserted were false when it was sealed, and both are corrected below rather than silently re-scoped: the "Noblocked_byis owed" disposition (it was owed — see Advisory dispositions), and the single-repository pin (criterion 1 can only be discharged inmotir-core— see Repository split). The card is Blocked on MOTIR-3909 untilmotir-corePR #2513 merges and the manifest is actually served.
The gap, stated precisely
docs/decisions/public-surface-hosts.md AMENDMENT 2 §E requires one property of the split subprocessor guard: the seam FAILS when the two sides diverge. Two halves now exist and neither closes it:
| half | asserts | shipped |
|---|---|---|
motir-core tests/legal/egress-manifest-guard.test.ts | lib/legal/egress-manifest.json matches that tree's signatures, both directions | MOTIR-4008 |
motir-marketing tests/legal/subprocessorSeam.test.ts | the parse against the real pages, and the comparison both directions from FIXTURES | MOTIR-4011 |
Neither compares the real page against the real manifest. The second half proves that compareSeam would report a divergence if it were given one — not that there is none. A vendor could be added to motir-core's tree, land in its manifest, turn that repository's guard green, and never appear on the published page, with both suites green the whole time.
Why MOTIR-4011 did not close it, and why that was right
That card's lane is Vitest/jsdom with no network, and the manifest is a served artifact by decision (§E chose the transport MOTIR-4046 shipped for the OpenAPI document — a published artifact the consumer fetches, never a committed copy that rots).
A test that fetched app.motir.co from CI would close the gap and couple this repository's CI to that deployment's uptime — which is the coupling §E's own cost note says the split exists to avoid: "Neither repository blocks on the other's CI." So the honest options are a build-time consumption or an out-of-band check, and both are more than a test card should invent on its own.
What this card should decide, then do
Decide the mechanism first and record it, because the choice has consequences the ADR already reasons about:
| option | what it buys | what it costs |
|---|---|---|
Fetch at BUILD time — the /legal/subprocessors render (or a build step) pulls the manifest and fails the build on divergence | a real seam failure, no test network, and the site cannot deploy while it is lying | a build that depends on app.motir.co being up; needs a decided answer for what happens when the fetch fails |
| A scheduled out-of-band check — a workflow that fetches both sides and opens an issue / goes red | zero coupling to either build | it reports AFTER the divergence has shipped, which for a legal document is the window that matters |
| Publish the manifest as an installed artifact | CI has it with no network, and §8's "a published artifact the consumer INSTALLS does not rot" applies literally | a package publish for one JSON file, and a version to keep current |
Then build it, and make the failure demonstrated rather than asserted: the PR shows the seam going red with a real divergence between the two sides, not a fixture.
Boundary
- It does not re-do MOTIR-4011. The parse, the comparison, the transfer-basis guard and the reachability guard are shipped and stay; this adds the one assertion they deliberately do not make.
- It does not change
motir-core's half. That guard is correct and complete about its own side. Amending the ADR is not changing the guard — see Repository split. - It does not weaken §E's transport. A committed copy of the manifest is explicitly rejected there; if the chosen mechanism involves one, it needs a drift check and the ADR needs amending to say so.
Acceptance criteria
- (
motir-core) The chosen mechanism is recorded — indocs/decisions/public-surface-hosts.mdAMENDMENT 2 §E or a new amendment — with the rejected alternatives and the reason, in that record's table style. - (
motir-marketing) The seam is shown RED against a REAL divergence between the published page and the manifestmotir-coreactually serves, in the PR body. A fixture does not discharge this criterion; that is what it exists to distinguish. - (
motir-marketing) The failure mode when the manifest is UNREACHABLE is decided and stated — a red check, a skipped check, or a build failure — and it is not silence. - (
motir-marketing)motir-marketing's existing suite still passes with no network, so the offline lane keeps working. - (
motir-marketing) The comment intests/legal/subprocessorSeam.test.tsthat says this is not covered is updated to point at what now covers it.
Repository split (ADDED 2026-09-02, on the record)
The card was pinned motir-marketing alone and criterion 1 cannot be discharged there. Measured on the merged trunks of both sides:
motir-marketingorigin/mainhas nodocs/decisions/directory at all —git ls-tree -r origin/main --name-only docs/decisions | wc -l→0.docs/decisions/public-surface-hosts.mdlives inmotir-core, and so does the AMENDMENT 2 §E the criterion names.
A bug carries a repository SET (only kind: subtask is bound by ONE REPO = ONE PR), so this is one card with targetRepos: ['motir-marketing', 'motir-core'] and two pull requests — not a split into siblings. The set is now ['motir-marketing', 'motir-core']; the card does not complete until both have merged.
Context refs
motir-marketing/lib/legal/subprocessorSeam.ts·tests/legal/subprocessorSeam.test.ts— the logic half, and the comment recording this gap (both onorigin/mainsince PR #27 merged 2026-09-02T14:20:27Z)motir-core/lib/legal/egress-manifest.json·app/api/legal/egress-manifest/route.ts— the artifact and where it is served. NOT onmotir-coreorigin/main; they live only onparent/MOTIR-3909-legal-manifest(PR #2513, OPEN)motir-core/tests/legal/egress-manifest-guard.test.ts— the evidence halfmotir-core/docs/decisions/public-surface-hosts.mdAMENDMENT 2 §E — the property, the transport, and the two-failure window it already writes down as a cost. AMENDMENT 2 is NOT onmotir-coreorigin/maineither — same open PRmotir-marketing/lib/docs.ts·tests/docs/docs.test.ts— MOTIR-4046's precedent for the same transport, and the structural check it settles for- MOTIR-4011 — the card that found it;
relates_to - MOTIR-4008 — the evidence half
Advisory dispositions
⚠️ CORRECTED 2026-09-02 — the struck disposition below was FALSE, and it is kept rather than deleted because a disposition that reasons an edge away leaves no error message behind.
No blocked_by is owed. Both halves it composes are shipped: motir-core's manifest and route are committed on parent/MOTIR-3909-legal-manifest, and motir-marketing's comparison is on that repository's parent branch. This card needs them to EXIST, which they do; it does not consume anything either is still producing.
A blocked_by WAS owed, and it is now wired to MOTIR-3909 — the sibling container under epic MOTIR-3875 that owns motir-core's half. Committed on a branch is not shipped, and criterion 2 does not merely need the manifest to exist: §E's chosen transport is a served artifact, so the criterion reads on a deployment.
Rung-2 evidence, re-measured 2026-09-02 immediately before the halt:
| claim | command | result |
|---|---|---|
| the manifest is served | curl -s -o /dev/null -w '%{http_code}' https://app.motir.co/api/legal/egress-manifest | 404 |
the manifest is on motir-core main | git ls-tree origin/main lib/legal/egress-manifest.json app/api/legal/egress-manifest/route.ts | wc -l | 0 |
AMENDMENT 2 §E is on motir-core main | git show origin/main:docs/decisions/public-surface-hosts.md | grep -c 'AMENDMENT 2' | 0 |
| the producing PR has merged | gh pr view 2513 --json state,mergedAt | OPEN, mergedAt: null |
motir-marketing's half has merged | gh pr list --head parent/MOTIR-3909-legal-manifest --repo moooon-B-V/motir-marketing | #27 MERGED 2026-09-02T14:20:27Z ✅ |
So the motir-marketing half is genuinely shipped and owes nothing; the motir-core half is not, and every criterion that reads on it is unbuildable until PR #2513 merges and the route is deployed. The artifact-obtainable check applies in the consuming direction: a done/implemented card is not a promise that anything was published.
validate_work_itemalso returnsshape/likely-ordering-violationon criterion 2 (phrase "the published"). It is not a criterion to cut: it is the card's whole point, and it is correctly diagnosed as reading on post-merge state. It is discharged by theblocked_byabove, not by an edit.subsumption/likely-already-shippedontests/legal/subprocessorSeam.test.ts(PR #27, merged) — read and expected: that is MOTIR-4011's half, which this card edits by design (criterion 5).- The
referenceadvisories on MOTIR-4008 / MOTIR-4011 remainrelates_to: the container edge to MOTIR-3909 is what gates readiness, and gate 7 forbids a cross-parent leaf edge.
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.