diff --git a/.changeset/20595-core-provenance-anchors.md b/.changeset/20595-core-provenance-anchors.md new file mode 100644 index 00000000000..47fa503319e --- /dev/null +++ b/.changeset/20595-core-provenance-anchors.md @@ -0,0 +1,20 @@ +--- +'@objectstack/core': patch +--- + +Provenance comments in `@objectstack/core` cite the commits that decided them, not tracker numbers that no longer resolve + +Clause-②: no + +Docblocks and comments across the package cited issue-tracker numbers that now answer 404 on GitHub. +Each now cites the commit in this repository's history that made the decision it describes, except +three source comments: one in `resolve-authz-context.ts` that quotes a maintainer ruling now cites +ADR-0131's 2026-09-17 amendment, which records that ruling verbatim, and two on the unpack-time +integrity re-verification leg, which pointed at a tracker for work that was never built, now say in +words that the leg is unbuilt. One test comment named a maintainer-ruling comment that also answers +404; it now cites ADR-0025 §3.7, which records that ruling's effect. Some of these docblocks sit on +exported members, so the reworded text appears in the published declaration files (`index.d.ts` / +`index.d.cts`), and the comments esbuild keeps appear in the JavaScript output (`index.js` / +`index.cjs`). + +Comment only: no export, type, error code, status, message text or runtime behaviour changes. diff --git a/packages/core/src/artifact-packages.ts b/packages/core/src/artifact-packages.ts index aeebb900c8f..918b3814dcc 100644 --- a/packages/core/src/artifact-packages.ts +++ b/packages/core/src/artifact-packages.ts @@ -89,7 +89,7 @@ * not disagree. * * ⛔ The other half of that reason — "and Zod strips undeclared keys" — is GONE, - * not merely reworded. `ManifestSchema` is `strictObject` since #14192 and + * not merely reworded. `ManifestSchema` is `strictObject` since commit 4d0d9445a and * `AssembledPackageBodySchema` inherits the closed posture through `.extend()`, * so an undeclared key on an entry is REFUSED by this very parse, by name, and * never reaches a clone to be dropped from. Defaults are what still move bytes; diff --git a/packages/core/src/hot-reload.test.ts b/packages/core/src/hot-reload.test.ts index 85062be9fb2..19d19b60611 100644 --- a/packages/core/src/hot-reload.test.ts +++ b/packages/core/src/hot-reload.test.ts @@ -260,7 +260,7 @@ describe('[#12340] stateStrategy refusal', () => { expect(m).toContain('were removed'); expect(m).toContain("Use 'memory'"); expect(m).toContain('p'); // locates the offending plugin - // The negative twin (#13179's strip): the prescription anchors on the + // The negative twin (commit fd289be45's strip): the prescription anchors on the // ADR and the version — never on a tracker id the refused author // cannot resolve. Mirrors the spec-side door's own pin. expect(m).not.toMatch(/(? { expect(m).toContain('never watched'); expect(m).toContain('scheduleReload'); expect(m).toContain('p'); // locates the offending plugin - // The negative twin (#13179's strip, extended to this door's sibling id): + // The negative twin (commit fd289be45's strip, extended to this door's sibling id): // anchored on the ADR and the migration call, never on a tracker id. expect(m).not.toMatch(/(? { /** - * Before #16721 every refusal above had an accepting twin on this kernel: + * Before commit 51ae73123 every refusal above had an accepting twin on this kernel: * `LiteKernel.use()` wrote the object straight into its registry, so the * object group A refuses mounted routes here. `AGENTS.md` names this * kernel for tests, so "green in vitest, refused at boot" was the shape @@ -469,7 +469,7 @@ describe('G — the SAME contract on LiteKernel.use() (#16721)', () => { ['staticPath', { name: '@os-fixture/lite-ui-no-static-path', type: 'ui', slug: 'lite-ui-no-static-path' }], ['slug', { name: '@os-fixture/lite-ui-no-slug', type: 'ui', staticPath: UI_STATIC_PATH }], ] as const)('refuses a `ui` plugin with no `%s`, naming the key and the spec code (#16334 reaches this kernel now)', (key, overrides) => { - // The two inputs #16721 was filed on: refused by `ObjectKernel` (group F), + // The two inputs behind commit 51ae73123: refused by `ObjectKernel` (group F), // and until now stored verbatim here — the hono auto-discovery pin's // group F carried the accepting readings and was rewritten with this. const kernel = makeLiteKernel(); @@ -542,7 +542,7 @@ describe('G — the SAME contract on LiteKernel.use() (#16721)', () => { // was excluded from the schema check it was the ONE declared key this // kernel did not judge at all: `version: 'v1.0.0'` registered here and // was refused by `ObjectKernel` at boot — precisely the green-in-vitest, - // refused-in-production split #16721 converged the other eight keys to + // refused-in-production split commit 51ae73123 converged the other eight keys to // close. It now travels the ordinary envelope. const kernel = makeLiteKernel(); const bad = fixture({ name: 'com.example.lite-bad-version', version: 'v1.0.0' }); @@ -567,7 +567,7 @@ describe('G — the SAME contract on LiteKernel.use() (#16721)', () => { // "An author gets ONE refusal, with the same code and message shape, // from either kernel." `ObjectKernel.use()` re-wraps a failed load as // `Failed to load plugin: - ` for EVERY load failure — - // its existing wrapper, untouched by #16721 — so the parity to pin is + // its existing wrapper, untouched by commit 51ae73123 — so the parity to pin is // that the LiteKernel message is exactly what follows that prefix. const make = () => fixture({ name: '@os-fixture/parity', type: 'ui', staticPath: UI_STATIC_PATH, slug: 'Not A Slug' }); @@ -596,7 +596,7 @@ describe('G — the SAME contract on LiteKernel.use() (#16721)', () => { }); it('ORDER — state is checked before the contract: after bootstrap the refusal is the idle one', async () => { - // `validateIdle()` first, then the contract — the wiring #16721 step 1 + // `validateIdle()` first, then the contract — the wiring step 1 (before commit 51ae73123) // measured with. A kernel that can no longer register plugins says so, // and does not run the schema over an object it would not store anyway. const kernel = makeLiteKernel(); diff --git a/packages/core/src/plugin-contract.ts b/packages/core/src/plugin-contract.ts index c3843ed85e5..362e8a56a1b 100644 --- a/packages/core/src/plugin-contract.ts +++ b/packages/core/src/plugin-contract.ts @@ -7,7 +7,7 @@ import type { Plugin } from './types.js'; * The DECLARED plugin contract, enforced at `use()` on BOTH kernels — one * statement, shared by `LiteKernel.use()` and by * `PluginLoader.validatePluginContract` on the `ObjectKernel.use()` path - * (#16721, maintainer ruling 2026-09-08, option A). + * (maintainer ruling 2026-09-08, option A, landed as commit 51ae73123). * * ## Why it is written down here rather than in each kernel * @@ -113,7 +113,7 @@ import type { Plugin } from './types.js'; * line, and the first violated key is the one to fix. * * The code is spelled the ADR-0112 way and is REGISTERED in - * `ERROR_CODE_LEDGER` under `@objectstack/core` (#16649, under the #16404 + * `ERROR_CODE_LEDGER` under `@objectstack/core` (commit 613bfbd3d, under the #16404 * door-or-no-door rule), exactly like `SERVICE_NOT_REGISTERED_CODE` one module * over. `door: 'none'` on this tree — it is raised while the kernel is still * assembling itself, before any HTTP boundary exists. If a transport ever @@ -152,7 +152,7 @@ import type { Plugin } from './types.js'; * version` message, not `PLUGIN_CONTRACT_VIOLATION`; that ordering is * unchanged and is pinned. `LiteKernel` has never run `validatePluginStructure` * and still does not — so on that kernel a malformed `version` is refused for - * the first time here, by the schema, which is exactly the convergence #16721 + * the first time here, by the schema, which is exactly the convergence landed in commit 51ae73123 as * ruled for the other eight keys. */ const PLUGIN_CONTRACT_VIOLATION_CODE = 'PLUGIN_CONTRACT_VIOLATION'; diff --git a/packages/core/src/plugin-loader.retired-fields.pin.test.ts b/packages/core/src/plugin-loader.retired-fields.pin.test.ts index 8199a058f30..8babc87d3a5 100644 --- a/packages/core/src/plugin-loader.retired-fields.pin.test.ts +++ b/packages/core/src/plugin-loader.retired-fields.pin.test.ts @@ -17,7 +17,7 @@ // `@objectstack/core` "has no `typecheck` script (type-check DEBT ledger // entry)", making a `@ts-expect-error` here a phantom pin // `check:type-check-coverage` refuses. False on this tree in BOTH halves: -// #14613 split a `tsconfig.test.json` out of the build config, +// Commit 81208086a split a `tsconfig.test.json` out of the build config, // `package.json`'s `typecheck` NAMES it (via `check:test-typecheck // --project`), and this package holds no DEBT entry. A directive here WOULD be // evaluated — against `./plugin-loader.ts`, this package's own SOURCE, which diff --git a/packages/core/src/plugin-loader.ts b/packages/core/src/plugin-loader.ts index e3a36c6753a..1a2b065ccde 100644 --- a/packages/core/src/plugin-loader.ts +++ b/packages/core/src/plugin-loader.ts @@ -418,7 +418,7 @@ export class PluginLoader { * * The check itself — `PluginSchema.safeParse` for validation only, the * nine keys it reaches and the `PLUGIN_CONTRACT_VIOLATION` envelope — - * lives in `plugin-contract.ts`, because since #16721 it is ONE statement + * lives in `plugin-contract.ts`, because since commit 51ae73123 it is ONE statement * run by BOTH kernels: * `LiteKernel.use()` calls it directly, and `ObjectKernel.use()` reaches * it here, through `loadPlugin`. That module's comment is the authority on diff --git a/packages/core/src/plugin-type-closed-set.test.ts b/packages/core/src/plugin-type-closed-set.test.ts index 787a2f13650..36eeb386e6f 100644 --- a/packages/core/src/plugin-type-closed-set.test.ts +++ b/packages/core/src/plugin-type-closed-set.test.ts @@ -22,7 +22,7 @@ // ⚠️ This used to read as though the split were forced — that // `@objectstack/core` "has no `typecheck` script (type-check DEBT ledger // entry)", making a `@ts-expect-error` here a phantom pin -// `check:type-check-coverage` refuses. False on this tree: #14613 split a +// `check:type-check-coverage` refuses. False on this tree: commit 81208086a split a // `tsconfig.test.json` out of the build config, `package.json`'s `typecheck` // NAMES it (via `check:test-typecheck --project`), and this package holds no // DEBT entry. A directive here WOULD be evaluated — against `./types.ts`, diff --git a/packages/core/src/security/admin-standing-surface.test.ts b/packages/core/src/security/admin-standing-surface.test.ts index 5b398a33064..2bfdd40bfb4 100644 --- a/packages/core/src/security/admin-standing-surface.test.ts +++ b/packages/core/src/security/admin-standing-surface.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#8734] The FIRST of the two links that bind `plugin-auth`'s break-glass + * [commit f8eb73601] The FIRST of the two links that bind `plugin-auth`'s break-glass * standing-key lists to what this resolver actually reads. * * This half answers one question mechanically: **which columns does @@ -97,7 +97,7 @@ function makeRecordingQl(tables: Record>>, return raw(row, key) === cond; }), ); - // [#10978] Enforce the caller's bound — presence, not truthiness, so + // [commit 4c9780c7a] Enforce the caller's bound — presence, not truthiness, so // `limit: 0` returns nothing rather than everything. Bounding BEFORE the // Proxy wrap keeps the column-observation ledger honest: a row the real // read would never have returned must not record column reads either. diff --git a/packages/core/src/security/admin-standing-surface.ts b/packages/core/src/security/admin-standing-surface.ts index 295ae697189..e1adba746d3 100644 --- a/packages/core/src/security/admin-standing-surface.ts +++ b/packages/core/src/security/admin-standing-surface.ts @@ -4,7 +4,7 @@ * ADMIN_STANDING_SURFACE — what `resolveAuthzContext` READS when it decides * who is an administrator, declared beside the resolver that reads it. * - * ## Why this file exists (#8734) + * ## Why this file exists (commit f8eb73601) * * `plugin-auth`'s break-glass guard (`last-admin-guard.ts`, ADR-0135 D5.2) * decides whether a pending write can empty the administrator population by diff --git a/packages/core/src/security/api-key.test.ts b/packages/core/src/security/api-key.test.ts index 8ccfa0b4897..5ebcb905080 100644 --- a/packages/core/src/security/api-key.test.ts +++ b/packages/core/src/security/api-key.test.ts @@ -16,7 +16,7 @@ import { /** * In-memory sys_api_key store exposing the `find` shape the verifier uses. * - * [#10978] `limit` is ENFORCED — presence, not truthiness, so `limit: 0` returns + * [commit 4c9780c7a] `limit` is ENFORCED — presence, not truthiness, so `limit: 0` returns * nothing rather than everything. A double that drops the bound makes any limit * change on this read green by construction; the verifier reads with `limit: 1`. */ diff --git a/packages/core/src/security/assemble-execution-context.test.ts b/packages/core/src/security/assemble-execution-context.test.ts index 93c58a85ecb..b4da636e83f 100644 --- a/packages/core/src/security/assemble-execution-context.test.ts +++ b/packages/core/src/security/assemble-execution-context.test.ts @@ -1,13 +1,13 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. // -// #6216 — the ExecutionContext assembly converges onto ONE module, and the +// Commit f586f1a89 — the ExecutionContext assembly converges onto ONE module, and the // maintainer ruling of 2026-08-08 (Option A) is explicit that **neither surface // changes runtime behaviour**: what changes is that the anonymous divergence // becomes named API instead of drift. // // A green suite proves nothing about that on its own — the suite was green // before the change too. So the load-bearing test here is a PARITY PIN: the -// pre-#6216 assembly of each face is transcribed VERBATIM below, frozen, and +// assembly of each face before commit f586f1a89 is transcribed VERBATIM below, frozen, and // every shape either face can serve is assembled both ways and compared. // // ⚠ The two `legacy*` functions are FROZEN TRANSCRIPTIONS of code that no @@ -30,9 +30,9 @@ import { } from './assemble-execution-context.js'; import type { ResolvedAuthzContext } from './resolve-authz-context.js'; -// ───────────────────────── frozen pre-#6216 transcriptions ───────────────────────── +// ───────────────────────── frozen transcriptions from before commit f586f1a89 ───────────────────────── -/** Runtime / MCP dispatcher assembly, verbatim, pre-#6216. FROZEN — see header. */ +/** Runtime / MCP dispatcher assembly, verbatim, before commit f586f1a89. FROZEN — see header. */ function legacyDispatcherAssembly( authz: ResolvedAuthzContext, oauthPrincipal: OAuthTokenProvenance | undefined, @@ -49,7 +49,7 @@ function legacyDispatcherAssembly( if (oauthPrincipal?.clientId) { ctx.principalKind = 'agent'; ctx.onBehalfOf = { userId: authz.userId, principalKind: 'human' }; - // Pre-#6216 these two read `scopesToAgentPermissionSets(oauthPrincipal.scopes)` + // Before commit f586f1a89 these two read `scopesToAgentPermissionSets(oauthPrincipal.scopes)` // and `oauthPrincipal.scopes?.includes(MCP_OAUTH_SCOPE_ACTIONS)` inline. // Both are now interpreted at the `/mcp` door and arrive pre-derived; the // scope→ceiling mapping itself is pinned end-to-end through the real @@ -88,7 +88,7 @@ function legacyDispatcherAssembly( } /** - * REST `computeExecCtx` assembly, verbatim, pre-#6216. FROZEN — see header. + * REST `computeExecCtx` assembly, verbatim, before commit f586f1a89. FROZEN — see header. * `authGate` / `__kernel` are outside: at the time this was frozen neither was * an `ExecutionContext` field, and the REST face added both after assembly. * @@ -280,7 +280,7 @@ describe('#6216 — REST face: byte-for-byte parity with the pre-#6216 assembly' localization, requestLocale, // The named per-face divergence: REST has never carried the - // session bearer, and #6216 preserves that. + // session bearer, and commit f586f1a89 preserves that. accessToken: undefined, authGate: undefined, }); @@ -494,7 +494,7 @@ describe('#6216 — the field set is CLOSED', () => { }); describe('#6216 — the measured residual: keys that were present-with-undefined', () => { - // Reported rather than hidden. The pre-#6216 dispatcher assigned + // Reported rather than hidden. The dispatcher before commit f586f1a89 assigned // `ctx.timezone` / `ctx.locale` unconditionally inside its authenticated // branch, and the REST literal always spelled `tenantId` / `email` — so both // faces could emit a key whose value was `undefined`. The shared assembler diff --git a/packages/core/src/security/assemble-execution-context.ts b/packages/core/src/security/assemble-execution-context.ts index 5dac8581f1b..c779a5a9f8e 100644 --- a/packages/core/src/security/assemble-execution-context.ts +++ b/packages/core/src/security/assemble-execution-context.ts @@ -14,7 +14,7 @@ * enforcement judgment reading it (explain's guest⇒EXTERNAL floor, the * security plugin's agent baseline, the perf-disclosure gate) was silently * never-true on that face. - * - **#6206 / #6551 — dropped fields.** The share-link copies omitted + * - **commit 8e13ca876 / #6551 — dropped fields.** The share-link copies omitted * `accessible_org_ids`, and the `group` posture's Layer 0 wall reads it * directly: real 403s for callers who should have been let through. Both * surfaces were since converted to pass the WHOLE envelope through. @@ -27,9 +27,9 @@ * fails to compile until it is either assembled or listed as * non-entry-resolved. * - * ## Two named entries — the anonymous face is genuinely divergent (#6216) + * ## Two named entries — the anonymous face is genuinely divergent (commit f586f1a89) * - * The maintainer ruling of 2026-08-08 on #6216 (Option A) settled the one + * The maintainer ruling of 2026-08-08 (Option A, landed as commit f586f1a89) settled the one * question that blocked convergence: what an anonymous request yields. * * - {@link assembleExecutionContext} — the DEFAULT, fail-closed entry. No @@ -230,7 +230,7 @@ export interface ExecutionContextAssemblyInput { * `session.accessToken` (`objectql/engine.ts` `buildSession`, * `spec/data/hook.zod.ts`). * - * A NAMED per-face divergence, preserved deliberately (#6216): the runtime / + * A NAMED per-face divergence, preserved deliberately (commit f586f1a89): the runtime / * MCP dispatcher passes `authz.accessToken`; the REST face has never carried * it and passes `undefined`, because widening a published hook surface to * expose the session token on a second transport is a product decision, not a @@ -353,7 +353,7 @@ function entryFields( /** Fellow-org user IDs for RLS scoping of identity tables. */ org_user_ids: authz.org_user_ids, // [ADR-0105 D2] The caller's org access set — the `group` posture's Layer 0 - // wall reads it directly, so every transport must carry it (#6206). + // wall reads it directly, so every transport must carry it (commit 8e13ca876). accessible_org_ids: authz.accessible_org_ids, // OAuth provenance: surface the token's granted scopes so the MCP // dispatcher can narrow the exposed tool families (undefined for every @@ -370,7 +370,7 @@ function entryFields( } /** - * The DEFAULT, fail-closed entry (#6216 Option A). An unauthenticated request + * The DEFAULT, fail-closed entry (commit f586f1a89, the ruled Option A). An unauthenticated request * yields NO context — the surface answers 401. Every surface uses this one * unless serving anonymous principals is part of its product semantics. */ @@ -382,7 +382,7 @@ export function assembleExecutionContext( } /** - * The EXPLICIT guest entry (#6216 Option A). An unauthenticated request becomes + * The EXPLICIT guest entry (commit f586f1a89, the ruled Option A). An unauthenticated request becomes * a first-class guest principal — `principalKind: 'guest'`, `positions: * ['guest']` — which enforcement consumers read today * (`plugin-security/explain-engine.ts`: guest ⇒ `EXTERNAL` posture). diff --git a/packages/core/src/security/auth-gate.ts b/packages/core/src/security/auth-gate.ts index 5c52f8a7257..058cf61b899 100644 --- a/packages/core/src/security/auth-gate.ts +++ b/packages/core/src/security/auth-gate.ts @@ -25,7 +25,7 @@ import type { ExecutionContext } from '@objectstack/spec/kernel'; * * It was a hand-written interface while the envelope field was undeclared, so * the two could have drifted with nothing to catch it — the exact class of - * defect the closed entry field set (#6216) exists to make unrepresentable. + * defect the closed entry field set (commit f586f1a89) exists to make unrepresentable. * One declaration, one type. */ export type AuthGate = NonNullable; diff --git a/packages/core/src/security/authz-store-unavailable.test.ts b/packages/core/src/security/authz-store-unavailable.test.ts index 5025f267b71..a6ffd344625 100644 --- a/packages/core/src/security/authz-store-unavailable.test.ts +++ b/packages/core/src/security/authz-store-unavailable.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#13279] A permission-store OUTAGE must not be answerable as a capability + * [commit 6a180e42d] A permission-store OUTAGE must not be answerable as a capability * denial — at the resolver, and at every transport that authorizes through it. * * Maintainer ruling, 2026-08-30, verbatim 「第一批其余同意」: @@ -337,7 +337,7 @@ describe('[#13279] every transport that authorizes through resolveAuthzContext', // whose `sys_*` tables were never created (measured: it turned four CI // suites red — client CRUD, runtime notifications, and two integration // noise guards). -// - only the QUIET direction ⇒ satisfied by the pre-#13279 `return []`, +// - only the QUIET direction ⇒ satisfied by the `return []` before commit 6a180e42d, // i.e. the defect itself: an outage answered as a capability denial. // // ⚠️ The accepted risk lives in the first direction. A false POSITIVE from diff --git a/packages/core/src/security/authz-store-unavailable.ts b/packages/core/src/security/authz-store-unavailable.ts index 89638bbf302..dfd7962124a 100644 --- a/packages/core/src/security/authz-store-unavailable.ts +++ b/packages/core/src/security/authz-store-unavailable.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#13279] The LOUD failure an unreachable permission store raises. + * [commit 6a180e42d] The LOUD failure an unreachable permission store raises. * * ## The defect this exists to end * diff --git a/packages/core/src/security/granted-permissions-not-enforced.pin.test.ts b/packages/core/src/security/granted-permissions-not-enforced.pin.test.ts index 9ac9330e79a..f2e7b8935f8 100644 --- a/packages/core/src/security/granted-permissions-not-enforced.pin.test.ts +++ b/packages/core/src/security/granted-permissions-not-enforced.pin.test.ts @@ -1,17 +1,17 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * ── [#17147] The granted permission set is REGISTERED and refuses nothing ── + * ── [commit aaacf1d5c] The granted permission set is REGISTERED and refuses nothing ── * * #13457 / PR #17137 gave `PluginPermissionEnforcer.registerGrantedPermissions` * its first production caller: `AppPlugin.init()` binds an artifact's * install-time `grantedPermissions` to the packages that artifact carries. What - * it did NOT do — deliberately, and fenced by maintainer ruling `5486840233`, + * it did NOT do — deliberately, and fenced by the maintainer ruling ADR-0025 §3.7 records, * which assigns the per-plugin context to the ADR-0025 install-flow design * effort — is make anything QUERY that registry. * * Maintainer ruling 2026-09-12, option B (the same option ruled for the sibling - * half of this very sentence in #11330): **say it truthfully now.** Enforcing is + * half of this very sentence, executed by commit a9ee98992): **say it truthfully now.** Enforcing is * a later, separately designed direction. This file is the mechanical half of * that ruling — without it, "registered, not enforced" is prose that rots the * moment someone edits around it, which is exactly how the retracted sentence @@ -175,7 +175,7 @@ describe('[#17147] the install-time granted permission set is registered, not en expect(text).toMatch(/ZERO production construction\s+\*?\s*sites/); // The negative pin. Without it a future edit could re-add the retracted // sentence beside the truthful one and every positive assertion above - // would stay green — the same failure mode #11330 closed on the tier half. + // would stay green — the same failure mode commit a9ee98992 closed on the tier half. expect( text, 'the retracted sentence must not come back beside the truthful one', @@ -183,7 +183,7 @@ describe('[#17147] the install-time granted permission set is registered, not en }); it('the retracted phrasing is absent from the WHOLE repo, not just its own file', () => { - // [#17147 follow-up] The single-file version above missed one: the runtime's + // [commit 65481183b, the follow-up] The single-file version above missed one: the runtime's // own seam test carried `a CONSENTED entry enforces exactly the consented // surface` as a CASE TITLE. Nothing in it asserted a refusal — it reads a // permission bag and checks what the bag answers — but a case title is read diff --git a/packages/core/src/security/index.ts b/packages/core/src/security/index.ts index b1238235b97..5cf405b01f2 100644 --- a/packages/core/src/security/index.ts +++ b/packages/core/src/security/index.ts @@ -38,7 +38,7 @@ export { // portable like the signature contract above; consumed by the // `os plugin publish` preflight. Unpack-time re-verification is owned by // the future runtime loader (ADR-0025 §3.5 steps 4–7), not by the cloud -// control plane (#11331). +// control plane (that leg is unbuilt). export { verifyIntegrity, formatIntegrityViolation, @@ -82,7 +82,7 @@ export { type ResourceUsage, } from './sandbox-runtime.js'; -// `./security-scanner.js` was RETIRED in #14919 (ADR-0049 enforce-or-remove). +// `./security-scanner.js` was RETIRED in commit cc00df2f7 (ADR-0049 enforce-or-remove). // `PluginSecurityScanner` and its two companion types (`ScanTarget`, // `SecurityIssue`) shipped on this barrel and on `@objectstack/core`'s root // barrel with zero constructors anywhere in this repo, in objectui at the @@ -124,7 +124,7 @@ export { type TenancyServiceResolver, } from './admission-tenancy-posture.js'; -// [#13279] The LOUD failure an unreachable permission store raises, and the +// [commit 6a180e42d] The LOUD failure an unreachable permission store raises, and the // brand predicate a fail-closed `catch` uses to re-raise it instead of // degrading an outage into a capability denial. Ruled 2026-08-30. export { @@ -168,7 +168,7 @@ export { type ApiExposureSchemaLike, } from './effective-object-permissions.js'; -// #6216 (maintainer ruling 2026-08-08, Option A) — the SINGLE ExecutionContext +// Commit f586f1a89 (maintainer ruling 2026-08-08, Option A) — the SINGLE ExecutionContext // assembly shared by every transport entry point, with the anonymous face as // two NAMED entries (fail-closed default / explicit guest) instead of drift. export { @@ -219,7 +219,7 @@ export { isGrantActive, isGrantExpired, type GrantValidityWindow } from './grant // enforces it and the break-glass guard that simulates a write to it. export { isRowActive, type ActivatableRow } from './row-active.js'; -// [#8734] The measured read surface of the administrator derivation — the +// [commit f8eb73601] The measured read surface of the administrator derivation — the // single source `plugin-auth`'s break-glass standing-key lists correspond to. export { ADMIN_STANDING_SURFACE, diff --git a/packages/core/src/security/operation-private-keys.ts b/packages/core/src/security/operation-private-keys.ts index 82cce21c75b..61d1abc1ab5 100644 --- a/packages/core/src/security/operation-private-keys.ts +++ b/packages/core/src/security/operation-private-keys.ts @@ -5,7 +5,7 @@ * CONSUMER side. * * `assemble-execution-context.ts` next door is the single place an - * `ExecutionContext` is BUILT at a transport entry point (#6216). This file is + * `ExecutionContext` is BUILT at a transport entry point (commit f586f1a89). This file is * its counterpart at the other end: the single place one is stripped back down * before being forwarded to a question it was not resolved for. * @@ -24,7 +24,7 @@ * `__expandRead` marks a read as a lookup EXPANSION sub-read (it no longer * relaxes any gate — #7626 removed that waiver — but it still travels with * one operation and must not be inherited by another), `__referentialFieldClear` - * authorizes the referential-clear write. [#13644] The latter also has a + * authorizes the referential-clear write. [commit 34ce8e7db] The latter also has a * DECLARED, read-only projection — `HookContext.referentialFieldClear` * (`@objectstack/spec/data`), populated by objectql's `update()` assembly * and carried across the sandbox boundary by contract — which is what an diff --git a/packages/core/src/security/plugin-artifact-integrity.ts b/packages/core/src/security/plugin-artifact-integrity.ts index a3989a40136..4dba5eb6eb8 100644 --- a/packages/core/src/security/plugin-artifact-integrity.ts +++ b/packages/core/src/security/plugin-artifact-integrity.ts @@ -9,8 +9,8 @@ * `plugin-artifact-signature.ts`, this module is pure and dependency-free * (node:crypto only) so it stays byte-for-byte portable to whatever runs * the unpack-time re-verification leg — the future runtime loader - * (ADR-0025 §3.5 steps 4–7), not the cloud control plane (tracked on - * #11331, NOT discharged by this module). The framework caller is the + * (ADR-0025 §3.5 steps 4–7), not the cloud control plane (that leg is + * unbuilt, and NOT discharged by this module). The framework caller is the * `os plugin publish` preflight: the publisher self-checks its own * artifact before upload. * diff --git a/packages/core/src/security/plugin-permission-enforcer.ts b/packages/core/src/security/plugin-permission-enforcer.ts index 5b2af87de29..0f12c5285f3 100644 --- a/packages/core/src/security/plugin-permission-enforcer.ts +++ b/packages/core/src/security/plugin-permission-enforcer.ts @@ -116,7 +116,7 @@ export class PluginPermissionEnforcer { * fails on the claim AND on the measurement, so it goes red the day the * seam lands and tells that author the sentence is theirs to rewrite. * Building the per-plugin context is the ADR-0025 materialize seam - * (#17147, Phase 1b of #11333). + * (measured and recorded in commit aaacf1d5c; the phase after commit ea4d16420). * * Prefer this over {@link registerPluginPermissions} for distributed * plugins: it registers what was granted, not what was declared. diff --git a/packages/core/src/security/resolve-authz-context.test.ts b/packages/core/src/security/resolve-authz-context.test.ts index ce19eb45311..cdc349efcda 100644 --- a/packages/core/src/security/resolve-authz-context.test.ts +++ b/packages/core/src/security/resolve-authz-context.test.ts @@ -31,7 +31,7 @@ const apiKeyRefusalReasons = (spy: ReturnType) => // Minimal in-memory ObjectQL: find(object, { where, limit }) with `===` + `$in` // match, and the caller's `limit` ENFORCED. // -// [#10978] The bound is not decoration. A double that matches `where` and hands +// [commit 4c9780c7a] The bound is not decoration. A double that matches `where` and hands // back every row it matched cannot tell a read bounded at 200 from the same read // bounded at 1000, or from one carrying no bound at all — so raising a limit, // lowering it, or folding two reads that carry different ones is green BY @@ -1538,7 +1538,7 @@ describe('[#8613] the `active` flag on the grant catalogues (ADR-0049)', () => { }); /** - * [#10978] The instrument's own contract. + * [commit 4c9780c7a] The instrument's own contract. * * Every assertion in this file stands on `makeQl`, and a double that drops * `opts.limit` cannot fail a limit regression: raising a bound, lowering it, or diff --git a/packages/core/src/security/resolve-authz-context.ts b/packages/core/src/security/resolve-authz-context.ts index cc4b63ba7b1..30f90006020 100644 --- a/packages/core/src/security/resolve-authz-context.ts +++ b/packages/core/src/security/resolve-authz-context.ts @@ -24,7 +24,7 @@ * `ql` yields a partial context (even `{ positions: [], permissions: [] }`) and * enforcement stays the SecurityPlugin's job, never this resolver's. * - * ⚠️ [#13279] A FAILED read is not a missing service, and since the 2026-08-30 + * ⚠️ [commit 6a180e42d] A FAILED read is not a missing service, and since the 2026-08-30 * ruling the two no longer share an answer. When a permission-store read is * issued and THROWS, this resolver raises {@link AuthzStoreUnavailableError} * instead of reporting an empty grant set: an outage must not be answerable as @@ -39,7 +39,7 @@ */ import { AuthzStoreUnavailableError } from './authz-store-unavailable.js'; -// [#13279, ruled 2026-08-30] `isMissingTableError` is the one "was this READ +// [commit 6a180e42d, ruled 2026-08-30] `isMissingTableError` is the one "was this READ // failure just an unprovisioned table?" predicate. It was `@objectstack/metadata`'s // until this resolver needed it; metadata depends on core, so the ruling relocated // it to `@objectstack/types` — which core already depends on — rather than let a @@ -269,7 +269,7 @@ async function tryFind( if (rows && (rows as any).value) rows = (rows as any).value; return Array.isArray(rows) ? rows : []; } catch (err) { - // [#13279] THE loud failure. This `catch` used to `return []`, which made a + // [commit 6a180e42d] THE loud failure. This `catch` used to `return []`, which made a // FAILED read and an EMPTY one the same answer — so an outage of the // permission store resolved as an authenticated principal holding zero // capabilities, and the door answered a `403` byte-identical to a genuine @@ -326,7 +326,7 @@ async function tryFind( // Both directions are pinned by name in `authz-store-unavailable.test.ts` // ('THE OUTAGE DIRECTION' / 'THE UNPROVISIONED DIRECTION'); keep them. // - // `object` is passed as `readObject` so the #13324 narrowing applies: a + // `object` is passed as `readObject` so commit 4cda78c9b's narrowing applies: a // phrase that names some OTHER relation is not evidence about the table // this read asked for, and stays loud. if (isMissingTableError(err, object)) return []; @@ -338,7 +338,7 @@ async function tryFind( * Resolve the authorization context for an inbound request. Anonymous requests * yield `{ positions: [], permissions: [], ... }`. * - * ⚠️ [#13279] This function used to document itself as "Always resolves — never + * ⚠️ [commit 6a180e42d] This function used to document itself as "Always resolves — never * throws", and that total guarantee WAS the defect: the only way to always * resolve across a permission-store outage is to report a capability set the * resolver never actually read. It now throws exactly one error — @@ -711,7 +711,7 @@ function grantAppliesInTenant(organizationId: unknown, tenantId: string | undefi * Fail-closed like its parent: a missing engine yields an empty-but-valid * envelope. * - * ⚠️ [#13279] "and it never throws" was removed from this sentence deliberately. + * ⚠️ [commit 6a180e42d] "and it never throws" was removed from this sentence deliberately. * A permission-store read that is issued and FAILS now raises * {@link AuthzStoreUnavailableError} rather than contributing an empty grant * set, so a `runAs:'user'` automation cannot silently run with the authority of @@ -922,7 +922,7 @@ export async function resolveUserAuthzGrants( // the flag exists rather than a plain deletion. Under `single` — the DEFAULT, what // a deployment that configured no tenancy at all resolves to — `bootstrapPlatformAdmin` // MINTS this very row for the first human user, and that promotion is ruled correct - // and unchanged (Choice 4A, #11974; maintainer 2026-09-08 on #16682, verbatim: "The + // and unchanged (Choice 4A, #11974; maintainer 2026-09-08, recorded in ADR-0131's 2026-09-17 amendment, verbatim: "The // rest of Choice 4A (#11974, 2026-08-25) stands: retiring the walled write must not // retire the `single` one"). A development environment started for a moment cannot be // asked to declare an administrator first, so deleting the row route for every posture diff --git a/packages/core/src/security/resolve-localization-cache.test.ts b/packages/core/src/security/resolve-localization-cache.test.ts index 6549c8629ae..d6c29e3f29b 100644 --- a/packages/core/src/security/resolve-localization-cache.test.ts +++ b/packages/core/src/security/resolve-localization-cache.test.ts @@ -58,7 +58,7 @@ function makeQl(rows: Array>, opts: { epoch?: boolean } return r[k] === v; }), ); - // [#10978] Hold the caller's bound, AFTER the filter and by PRESENCE — a + // [commit 4c9780c7a] Hold the caller's bound, AFTER the filter and by PRESENCE — a // double that hands back everything it matched cannot tell this read's // `limit: 10` from no bound at all, so folding or dropping that bound // would stay green here by construction. diff --git a/packages/core/src/security/security-scanner-retirement.pin.test.ts b/packages/core/src/security/security-scanner-retirement.pin.test.ts index 2e2192dc6fb..c46733ec8ff 100644 --- a/packages/core/src/security/security-scanner-retirement.pin.test.ts +++ b/packages/core/src/security/security-scanner-retirement.pin.test.ts @@ -5,7 +5,7 @@ import { describe, it, expect } from 'vitest'; import * as coreBarrel from '../index.js'; import * as securityBarrel from './index.js'; -// ─── [#14919] `PluginSecurityScanner` is RETIRED ──────────────────────────── +// ─── [commit cc00df2f7] `PluginSecurityScanner` is RETIRED ──────────────────────────── // // ADR-0049 enforce-or-remove; maintainer ruling 2026-09-05 (director summon // #14, decision batch #42). The class, its two companion types (`ScanTarget`, diff --git a/packages/core/src/service-not-registered.ts b/packages/core/src/service-not-registered.ts index 88c7a24c6ea..d36529c990a 100644 --- a/packages/core/src/service-not-registered.ts +++ b/packages/core/src/service-not-registered.ts @@ -75,7 +75,7 @@ * The code carried by the "never registered" rejection. * * Spelled the ADR-0112 way and REGISTERED in `ERROR_CODE_LEDGER` under - * `@objectstack/core` (#16649, under the #16404 door-or-no-door rule: every + * `@objectstack/core` (commit 613bfbd3d, under the #16404 door-or-no-door rule: every * `code` that ships in `dist` carries a ledger row, whether or not a door * answers with it). `door: 'none'` on this tree — this value is read * in-process by the seam that catches the rejection and is never serialized diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 93f2b4fdffd..1b2b25c5fe8 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -138,7 +138,7 @@ export type PluginType = 'standard' | (typeof CORE_PLUGIN_TYPES)[number]; * onto the object. A value outside the set no longer type-checks, and since * #16049 `kernel.use()` REFUSES it at boot — `assertPluginContract` * (`plugin-contract.ts`, run by BOTH `ObjectKernel.use()` and `LiteKernel.use()` - * since #16721) runs `PluginSchema` over every plugin object and raises + * since commit 51ae73123) runs `PluginSchema` over every plugin object and raises * `PLUGIN_CONTRACT_VIOLATION` naming the plugin and the first violated key. * `type: 'ui'` additionally owes `staticPath` and `slug` (#16334, * `PLUGIN_UI_REQUIRED_KEY_MISSING`), refused on the same path. diff --git a/packages/core/src/utils/analytics-date-range-conformance.ts b/packages/core/src/utils/analytics-date-range-conformance.ts index e13dcecc45a..eb946692078 100644 --- a/packages/core/src/utils/analytics-date-range-conformance.ts +++ b/packages/core/src/utils/analytics-date-range-conformance.ts @@ -121,7 +121,7 @@ export const ANALYTICS_DATE_RANGE_EXPLICIT_WINDOW: readonly [string, string] = [ * The kit's only array case used to be the two-element window above, so the * arity itself was governed NOWHERE and every face was free to invent a * reading for the rest. Four faces in one package had invented three — - * MEASURED on `abc4b83ce` (#17124), one authored document over the same rows: + * MEASURED on `abc4b83ce` (the defect commit 86c505286 fixed), one authored document over the same rows: * `['2026-01-01']` was a point window, an upper bound left unwritten, and a * window dropped to ALL OF HISTORY, depending on which backend answered. A * fifth face — `driver-memory`'s cube face — dropped it too (#17596, measured diff --git a/packages/core/src/utils/json-membership-sql.test.ts b/packages/core/src/utils/json-membership-sql.test.ts index f69a03a35aa..28d37e9107f 100644 --- a/packages/core/src/utils/json-membership-sql.test.ts +++ b/packages/core/src/utils/json-membership-sql.test.ts @@ -3,7 +3,7 @@ /** * [#20987] `jsonMembershipCandidates` and `jsonMembershipPredicate` — the one * `$contains` membership construct `driver-sql` and the analytics read scope - * and `where` ask, moved here from `driver-sql` (#17590). + * and `where` ask, moved here from `driver-sql`, where commit e04a0aff2 wrote it. * * What each face does with the SQL is pinned in its own package (the driver's * move proof `sql-driver-20987-json-membership-move.test.ts`, its executed diff --git a/packages/core/tsconfig.examples.json b/packages/core/tsconfig.examples.json index 16cda9cbaf9..610e7b9abde 100644 --- a/packages/core/tsconfig.examples.json +++ b/packages/core/tsconfig.examples.json @@ -1,5 +1,5 @@ -// The EXAMPLES-layer type-check program (#14613), the sibling-config pattern -// `packages/plugins/plugin-auth/tsconfig.examples.json` (#10869 / #14386) and +// The EXAMPLES-layer type-check program (commit 81208086a), the sibling-config pattern +// `packages/plugins/plugin-auth/tsconfig.examples.json` (#10869 / commit 7cbe705b0) and // `packages/spec/tsconfig.scripts.json` (#5475) already run. // // WHY IT ARRIVED WITH THE `typecheck` SCRIPT AND NOT BEFORE. Until that script @@ -19,7 +19,7 @@ // self-referencing by a name it declares in no dependency block. An unresolved // import makes every symbol it names `any`, which is where 3 of the 12 TS7006 // came from; the pile was one third module resolution and two thirds its -// cascade. That is the same shape #14386 found in plugin-auth's example (a +// cascade. That is the same shape commit c49007a7c found in plugin-auth's example (a // published example that could not resolve, compile or run for anyone who // copied it) and the reason the repo's answer to an examples directory is a // sibling program rather than a debt row — there is no ledger here, on purpose. diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 621320a9cc0..3418323fe79 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -27,7 +27,7 @@ } }, "include": ["src/**/*"], - // [#14613] The TEST layer moved to the `tsconfig.test.json` sibling, which + // [commit 81208086a] The TEST layer moved to the `tsconfig.test.json` sibling, which // `package.json`'s `typecheck` NAMES via `check:test-typecheck --project`. // This stays the BUILD config. Splitting the two is what let a `typecheck` // script exist here at all: this package carried a `check:type-check-coverage` diff --git a/packages/core/tsconfig.test.json b/packages/core/tsconfig.test.json index 6c827ec86b7..d51f5f214b0 100644 --- a/packages/core/tsconfig.test.json +++ b/packages/core/tsconfig.test.json @@ -1,4 +1,4 @@ -// The TEST-layer type-check program (#14613), adopting the mechanism #5286 set +// The TEST-layer type-check program (commit 81208086a), adopting the mechanism #5286 set // for `packages/spec`, #5449 generalised, and `packages/rest` / `packages/objectql` // already run. `tsconfig.json` beside it stays the BUILD config; this sibling // puts the layer that config excludes back in front of tsc, and `package.json`'s diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index e36432a98e5..2237eebf38d 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -18,7 +18,7 @@ import { // repo. `extends: true` keeps the root options (aliases included) on both. const REPO_TESTS: string[] = JSON.parse(readFileSync(path.join(__dirname, 'vitest.repo-tests.json'), 'utf8')); -// #17853 / #17978 — say so when a path named on the command line will run no +// Commit 08f5f0e5a / #17978 — say so when a path named on the command line will run no // tests. Invoked HERE, at config load, and ⛔ deliberately NOT as a // `test.reporters` entry: naming that option replaces vitest's own reporter // defaulting instead of extending it, which measurably changes a healthy run's