Repository navigation
Commit 2bddb19
Fixes #21061
Clause-②: no (narrowing)
This PR carries direction 1 of the emergency triage grade on the card,
the door half. Direction 2, the security layer treating "no permission
set resolved" as no grant, was split by triage to its own
`domain:services` card and is not part of this change.
## What changed
`handleAnalyticsRequest` (`packages/runtime/src/domains/analytics.ts`)
now opens with the shared anonymous-deny decision, `shouldDenyAnonymous`
from `@objectstack/core` (ADR-0056 D2). The call is the handler's first
statement. It runs before the analytics service is looked up and before
the request body is validated, in the hoisted form `domains/security.ts`
and `domains/ai.ts` use.
Every analytics dispatcher face (cube read, SQL echo, meta) now answers
a caller without a session `401 UNAUTHENTICATED` in the
dispatcher-wrapper envelope. A signed-in caller, an API-key caller and
an internal system context are unchanged.
- ⛔ No second gate at the dispatcher mount: `dispatcher-plugin.ts` is
untouched.
- ⛔ No zero-set admission rule copied into `service-analytics`: that
package is untouched.
## Readings (class level: doors, caller classes, codes and statuses)
Stock showcase boot (`pnpm dev -- --fresh`), measured privately on the
merge base before the fix and on the branch after it. The signed-in
caller is a plain member created on the same boot.
| face | caller | before | after |
|---|---|---|---|
| cube read | unauthenticated | 200 | **401 UNAUTHENTICATED** |
| cube read | signed-in member | 200 | 200 |
| SQL echo | unauthenticated | 200 | **401 UNAUTHENTICATED** |
| SQL echo | signed-in member | 200 | 200 |
| meta | unauthenticated | 200 | **401 UNAUTHENTICATED** |
| meta | signed-in member | 200 | 200 |
| cube read, malformed body | unauthenticated | 400 VALIDATION_FAILED |
**401 UNAUTHENTICATED** |
| cube read, malformed body | signed-in member | 400 VALIDATION_FAILED |
400 VALIDATION_FAILED |
| SQL echo, malformed body | unauthenticated | 400 VALIDATION_FAILED |
**401 UNAUTHENTICATED** |
| SQL echo, malformed body | signed-in member | 400 VALIDATION_FAILED |
400 VALIDATION_FAILED |
| control: record door | unauthenticated / member | 401 / 200 | 401 /
200 |
## Pins
- **Runtime unit pin, per face:**
`packages/runtime/src/domains/analytics-anonymous-deny.test.ts`.
- Anonymous callers get 401: both shapes the dispatcher produces, an
unresolved context and the guest envelope.
- The service is never consulted: neither the slot lookup nor any
service method runs.
- A malformed body still gets 401, and an empty slot still gets 401.
- Signed-in control: the member is served 200 with their own execution
context; a system context passes; an empty slot still answers a member
the 404; a malformed member body still reaches the validator's 400.
- **Dogfood:** `showcase-anonymous-deny-surfaces.dogfood.test.ts` gains
the analytics family in the dispatcher-wrapper family.
- Each face is driven anonymously, with a well-formed body and with a
malformed one.
- A signed-in member is the 200 control, and the member's malformed body
is still a 400.
- Each anonymous body is classified into exactly one envelope family.
The file claims the new matrix row.
- No pin title states a request: titles and seam labels name the face.
- **Conformance matrix:** a new `enforced` row,
`anonymous-deny-analytics`.
- It covers a GATE_PIN key on the domain's `shouldDenyAnonymous` call,
`analytics:domains/analytics.ts:anonymous-gate`, and the
dispatcher-domain key `dispatcher-domain:route-ledger.ts:/analytics`.
- That key leaves the shrink-only `authz-ledger-population.baseline.ts`:
MAX goes from 33 to 32, with a dated note.
- The header figures the row moves are updated: probes 18 to 19, named
files 13 to 14, rows 51 to 52, rows with `covers` 7 to 8, covers keys 15
to 17, gate pins 5 to 6, ledger keys 39 with 7 classified and 32
baselined.
- **Checklist:** `access-security.anonymous-deny-surfaces` goes to
revision 2 with a history entry. It gains the analytics variant, a step
that names the three faces and points at the `/analytics` rows of
`route-ledger.ts` for the routes, and an acceptance clause for the
ordering and the member control. `docs/qa/platform-checklist/README.md`
"Change" rule followed: fields edited, `revision` bumped, `history`
appended.
## Ablation (reverse verification, from the committed fix)
The mutation replaced the gate's condition with a never-true comparison
against a planted literal (`ablation-replace.mjs`, anchor hit x1, blob
changed). The restore leg was proven on disk: blob equals HEAD and `git
diff HEAD` is empty.
- **Source-resolved legs (no build):**
- The runtime unit pin went **18 failed / 11 passed**. Every anonymous
case was red; every signed-in control stayed green.
- `authz-conformance.test.ts` went **6 failed / 49 passed**, naming
`STALE covers: analytics:domains/analytics.ts:anonymous-gate` and `DEAD
PROBE: packages/runtime/src/domains/analytics.ts`.
- **dist-resolved leg (dogfood):**
- `ablation-dist-preflight` found the marker present in 2 built files
after the rebuild.
- `showcase-anonymous-deny-surfaces` went **9 failed / 46 passed**: the
5 anonymous analytics cases, the 3 envelope classifications and the
shared code-and-message case. All 5 analytics member controls stayed
green.
- On the restore leg, after a rebuild, the marker was absent from all 6
built files and the tree was clean.
- **Direction:** red as predicted, in every leg.
## Verification (HEAD `8364f40c4a`)
- **Runtime:**
- Full suite: 301 files, 5029 passed, 5 skipped, run at `3905d4f385`.
The commits after it change no file under `packages/runtime`.
- Typecheck: `tsc --noEmit` plus `check:test-typecheck` over the test
layer, exit 0.
- **Dogfood:** `showcase-anonymous-deny-surfaces`,
`showcase-anonymous-deny` and `authz-conformance` gave 3 files and 114
passed; typecheck exit 0.
- **Gates:** `dispatch-gates --commands` derived 93 families at
`8364f40c4a`. All 93 were re-run there after the last commit, with each
exit code written to disk before reading: 92 exit 0 and 1 exit 1.
`--ran` reconciles 93 of 93.
- Two were red on an earlier pass and are fixed in `8364f40c4a`:
`check-system-context-census`, from the new elevation read site, and
`check:doc-authoring`, from a tracker id in the new row's summary
string.
- The one red predates this branch: `check:platform-checklist`, an
absent-symbol anchor in `areas/identity-auth.json`. Control: the same
command on `origin/main` `b3d7a70864` exits 1 with the identical single
problem. This branch does not touch that file or the file it anchors.
- **Lint, a proven narrowing rather than `pnpm lint`:**
- Population read from eslint's own config: all 24 changed paths were
passed explicitly. eslint ignored the 3 non-TS paths by configuration
and linted 21.
- Count read from the `--format json` output: 21 linted files, 0 errors,
0 warnings, at `8364f40c4a`.
- Invariance: `eslint.config.mjs` enables no type-aware linting (no
`parserOptions.project`, no typed rules), and this diff touches no lint
config or rule input. So it cannot move the verdict on any untouched
file.
- **Scope note:** `turbo ls --affected` was not used for any narrowing
claim here.
## File surface beyond the claim, declared
- `packages/qa/dogfood/test/authz-conformance.test.ts`: one GATE_PIN
probe and one line in the exact-equality list of classified ledger keys.
The ruled "enforced row carrying a gate pin" can only be minted there,
and that list must equal the population once the key leaves the
baseline.
- `content/docs/permissions/system-context.mdx`: one anchor on row 51
(the anonymous-deny seams), plus the declared counts regenerated by
`check-system-context-census --fix` (108 to 109). The floor reads
`ExecutionContext.isSystem`, and that gate is red without the anchor.
- Fifteen existing runtime suites drove the analytics route with no
identity, as the smallest context that compiled. They now carry a
signed-in caller: an `auth` slot answering a session, or the
dispatcher's resolution seam stubbed the way the `/packages` fixtures
already do. Only identity is stubbed; every expectation is unchanged.
- One merge of `origin/main` into the branch, so the gate derivation
reads a current tree.
## Acceptance notes
Noted only, not filed:
- The `anonymous-deny.ts` docblock in `@objectstack/core` names "the
five runtime domains" (ai, meta, security, actions, automation).
`/packages` and now `/analytics` also hold the floor. The table header
in `packages/runtime/src/endpoint-policy.ts` is in the same state. Both
are documentation drift; carrier: none.
- The `/analytics` rows of `packages/runtime/src/route-ledger.ts` carry
no `authz:` declaration. The field is optional and phased, and the
classified `/actions` and `/packages` rows carry none either. Carrier:
none.
- `check:platform-checklist` is red on `main` because of the
`identity-auth.json` anchor above. That gate runs on a manual cadence,
not per PR. Carrier: none.
- The changeset is `minor` with the BREAKING banner, the launch-window
convention for a door narrowing. ADR-0087 disposition: `not-required
(no-migration-prescription)`.
## Update: head `fa039bb8c5` (the census fix)
- **What the head commit fixes:** `Dogfood Regression Gate (3/3)` was
red on `8364f40c4a`. The new `GATE_PIN` probe grew the conformance
`PROBES` table, which `authz-probe-blind-spot` pins (PR note
`5926114686`).
- **Two more files beyond the claim's surface:**
`packages/qa/dogfood/test/authz-probe-blind-spot.census.ts` and
`packages/qa/dogfood/test/authz-probe-blind-spot.test.ts`.
- They take the table shape 18 / 13 / 15 → 19 / 14 / 17, the header
claim 18 → 19, and a `PROBE_FILE_CENSUS` row for the analytics domain
file (gate pin, blind spot 0) with its controls.
- No assertion is weakened. They are declared on the card in claim
amendment 2 (`5926289415`).
- **Verification at `fa039bb8c5`:**
- the four `authz` and anonymous-deny dogfood files pass, 149 tests;
- the dogfood typecheck exits 0;
- CI on this head: 33 success, 2 skipped, 0 red.
The "Verification" section above was measured at `8364f40c4a`; the
runtime sources are unchanged since.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent d98bf24 commit 2bddb19
26 files changed
Lines changed: 657 additions & 92 deletions
File tree
- .changeset
- content/docs/permissions
- docs/qa/platform-checklist/areas
- packages
- qa/dogfood/test
- runtime/src
- domains
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
141 | | - | |
| 141 | + | |
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
| |||
172 | 172 | | |
173 | 173 | | |
174 | 174 | | |
175 | | - | |
| 175 | + | |
176 | 176 | | |
177 | 177 | | |
178 | 178 | | |
| |||
281 | 281 | | |
282 | 282 | | |
283 | 283 | | |
284 | | - | |
| 284 | + | |
285 | 285 | | |
286 | 286 | | |
287 | 287 | | |
| |||
355 | 355 | | |
356 | 356 | | |
357 | 357 | | |
358 | | - | |
| 358 | + | |
359 | 359 | | |
360 | 360 | | |
361 | 361 | | |
362 | | - | |
363 | | - | |
| 362 | + | |
| 363 | + | |
364 | 364 | | |
365 | 365 | | |
366 | | - | |
367 | | - | |
| 366 | + | |
| 367 | + | |
368 | 368 | | |
369 | 369 | | |
370 | 370 | | |
| |||
428 | 428 | | |
429 | 429 | | |
430 | 430 | | |
431 | | - | |
| 431 | + | |
432 | 432 | | |
433 | 433 | | |
434 | 434 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
838 | 838 | | |
839 | 839 | | |
840 | 840 | | |
841 | | - | |
| 841 | + | |
842 | 842 | | |
843 | 843 | | |
844 | 844 | | |
| |||
854 | 854 | | |
855 | 855 | | |
856 | 856 | | |
| 857 | + | |
857 | 858 | | |
858 | 859 | | |
859 | 860 | | |
| |||
875 | 876 | | |
876 | 877 | | |
877 | 878 | | |
878 | | - | |
| 879 | + | |
879 | 880 | | |
880 | 881 | | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
881 | 888 | | |
882 | 889 | | |
883 | 890 | | |
| |||
906 | 913 | | |
907 | 914 | | |
908 | 915 | | |
909 | | - | |
| 916 | + | |
| 917 | + | |
910 | 918 | | |
911 | 919 | | |
912 | 920 | | |
| |||
921 | 929 | | |
922 | 930 | | |
923 | 931 | | |
924 | | - | |
| 932 | + | |
| 933 | + | |
925 | 934 | | |
926 | 935 | | |
927 | 936 | | |
928 | 937 | | |
929 | 938 | | |
930 | 939 | | |
931 | 940 | | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
932 | 947 | | |
933 | 948 | | |
934 | 949 | | |
| |||
0 commit comments