Skip to content

Commit 7c71ea6

Browse files
hotlongclaude
andcommitted
fix(rest): withdraw the single-kernel boot refusal (B′)
Decision 1 narrows to A alone, per the maintainer ruling of 2026-09-04 recorded on the card; the measurement B′ was asking for moves to #15163. `RestApiPlugin` no longer refuses to start when a wall-enforcing tenancy posture is configured on a deployment with no `kernel-manager` service. `packages/rest/src/rest-api-plugin.ts` is now byte-identical to `main`. Why the refusal goes, from the CI triage on this branch: the only registrar of a `kernel-manager` service in this repository was B′'s own narrowness control test, so the refusal fired on every real walled composition the open core can build — the `os serve` process under an `isolated` posture, the ADR-0105 `bootStack multiTenant` harness, and seven dogfood suites — for `group` as well as `isolated`. Its premise was also false wherever it fired: a wall-enforcing effective posture requires `org-scoping`, which is exactly what keeps the platform's `organization_id` row policies standing (ADR-0105 D3), so the Layer 0 row wall the message claimed was unenforced was in fact standing in every case the refusal could reach. Decision 1 A (a registered-but-failed `tenancy` service answers 503 in `computeExecCtx`) and decision 2 B (an active ADR-0069 auth gate whose session re-read fails answers 503) are untouched — both stand exactly as ruled on 2026-09-02. - delete the boot-refusal block and its two now-unused imports (`effectiveTenancyPosture`, `postureEnforcesWall`); `isServiceNotRegisteredError` stays, used by the pre-existing objectql provider one layer down - delete `rest-api-plugin-tenancy-posture-boot-refusal.test.ts` — every one of its 2 refusal tests and 4 narrowness controls measures a behaviour that no longer exists - re-aim the phase-1 pin file's header: the ruling it records is now A alone, the dangling pointer to the deleted file is replaced by the withdrawal note, and §3's "the provider wiring still measures 200" reading is restated as CORRECT and PINNED — it is #15163's subject, not a regression introduced here - drop the B′ paragraphs from the changeset; the 503 rows stay ⛔ Not done, deliberately: B′ is not replaced by a warning, a softer refusal, an env escape hatch, or a narrowed condition. The ruling moved the question to a measurement card; the code now says nothing about single-kernel posture at boot. Part of #13906 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 9de1b0e commit 7c71ea6

4 files changed

Lines changed: 32 additions & 407 deletions

File tree

.changeset/execctx-authz-input-seams-fail-closed.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
'@objectstack/rest': minor
33
---
44

5-
REST no longer reads a FAILED authorization-input lookup as "this check does not apply" — the tenancy-posture and ADR-0069 auth-gate seams in `computeExecCtx` fail closed, and a wall-enforcing posture is refused at boot on wiring that cannot enforce it
5+
REST no longer reads a FAILED authorization-input lookup as "this check does not apply" — the tenancy-posture and ADR-0069 auth-gate seams in `computeExecCtx` fail closed
66

77
Two seams inside `RestServer.computeExecCtx` absorbed a FAILURE into the same `undefined` an
88
ABSENT wiring produces, and both feed authorization inputs. Unlike the sibling repairs in this
@@ -29,18 +29,12 @@ removed:
2929
outage instead of serving the request. The classification is the registry's, never message text.
3030
The WIRING fact is taken from the kernel's presence and never inferred from what the read
3131
returned.
32-
- **Single-kernel wiring.** On deployments with no `kernel-manager` service, `computeExecCtx`
33-
never reads a tenancy posture at all — measured with a recording factory, invocation count 0 —
34-
so a healthy, correctly-configured, wall-enforcing tenancy service enforced nothing there, with
35-
no failure required. The REST plugin now **refuses to start** in exactly that composition, naming
36-
the configured posture and how to fix it, rather than serving requests that silently skip the
37-
Layer 0 organization wall. Deployments with no tenancy service, with a `single` posture, or with a
38-
kernel-manager are untouched.
3932
- **ADR-0069 auth gate.** Fails closed in one precisely measured window only: `isAuthGateActive()`
4033
answered `true` **and** the gate's session re-read then failed. A gate the deployment declared
4134
active no longer vanishes silently. The common inactive path, a probe that throws, and a
4235
successful re-read carrying no gate all keep their existing behaviour.
4336

44-
Operators running a wall-enforcing tenancy posture on a single-kernel REST deployment must mount a
45-
kernel-manager service or set the posture to `single`; that composition was never enforcing the
46-
wall it declared, and now says so at boot instead of at audit time.
37+
Boot behaviour is unchanged: no composition that starts today stops starting. Single-kernel REST
38+
deployments — the wiring with no `kernel-manager` service — keep their current behaviour exactly,
39+
including the fact that `computeExecCtx` reads no tenancy posture there. What that wiring actually
40+
skips is being measured separately and is not changed here.

packages/rest/src/execctx-authz-input-seam-reachability.test.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
* **Maintainer ruling, 2026-09-02** (director seat, summon #8; verbatim
1717
* 「14324 等我发版,其他同意」 adopting the recommendation as presented):
1818
*
19-
* - **Decision 1 — tenancy posture: A + B′.** A: absorb ONLY the branded
19+
* - **Decision 1 — tenancy posture: A.** Absorb ONLY the branded
2020
* not-registered rejection (`isServiceNotRegisteredError`, the
2121
* discriminator the shipped `objectQLProvider` already uses one layer
2222
* down); every unbranded failure fails closed instead of collapsing into
23-
* the absent-posture path. B′: on the single-kernel provider wiring a
24-
* configured wall-enforcing posture is refused LOUDLY AT BOOT — that
25-
* wiring cannot enforce it, so it must not pretend to. ⛔ Option B (wiring
26-
* a tenancy provider into the single-kernel path) was NOT taken.
23+
* the absent-posture path. ⛔ Option B (wiring a tenancy provider into the
24+
* single-kernel path) was NOT taken. ⭐ The 2026-09-02 ruling also carried
25+
* a B′ half — a BOOT refusal of a wall-enforcing posture on the
26+
* single-kernel wiring — and the **2026-09-04 ruling WITHDREW it**; see
27+
* the note below.
2728
* - **Decision 2 — ADR-0069 auth gate: B.** Fail closed in the measured
2829
* window ONLY: `isAuthGateActive()` answered `true` AND the gate re-read
2930
* then failed. ⛔ The common inactive path, and a probe that throws, are
@@ -34,11 +35,26 @@
3435
* not widen either repair on the strength of this file — the narrowness
3536
* controls below exist precisely to make widening fail.
3637
*
37-
* B′'s own half is driven in `rest-api-plugin-tenancy-posture-boot-refusal
38-
* .test.ts`, because it is a BOOT refusal in the plugin rather than a
39-
* request-time seam. ⚠️ Consequently §3 below still measures 200 on the
40-
* provider wiring and that is CORRECT: B′ refuses the composition at boot, it
41-
* does not change `computeExecCtx`, which still never reads a posture there.
38+
* **Maintainer ruling, 2026-09-04** (live chat, verbatim
39+
* 「按照你的建议,你帮我跟进处理15020」, recorded on the card):
40+
* decision 1 narrows to **A alone**; **B′ is WITHDRAWN** and its plugin block
41+
* and dedicated test file are removed. It supersedes only the B′ half of the
42+
* 2026-09-02 ruling — A and decision 2 stand exactly as ruled there.
43+
*
44+
* Why: the only registrar of a `kernel-manager` service in this repository was
45+
* B′'s own narrowness control, so the refusal fired on every real walled
46+
* composition the open core can build (`os serve` under `isolated`, the
47+
* ADR-0105 harness, seven dogfood suites), and its premise was false where it
48+
* fired — a wall-enforcing effective posture REQUIRES `org-scoping`, which is
49+
* exactly what keeps the platform's `organization_id` row policies standing
50+
* (ADR-0105 D3). B′'s underlying question — what the single-kernel provider
51+
* wiring actually skips — survives as its own measurement card, #15163.
52+
*
53+
* ⚠️ §3 below therefore measures 200 on the provider wiring, and that stays
54+
* CORRECT and stays PINNED: withdrawing B′ returns that wiring to `main`'s
55+
* behaviour, and neither ruling changed `computeExecCtx`, which still never
56+
* reads a posture there. ⛔ That 200 is the subject of #15163, not a
57+
* regression introduced here.
4258
*
4359
* ## Why this card is not its siblings, and why the direction matters
4460
*

packages/rest/src/rest-api-plugin-tenancy-posture-boot-refusal.test.ts

Lines changed: 0 additions & 300 deletions
This file was deleted.

0 commit comments

Comments
 (0)