From a9a4ea47894201111dcc7621760a8cb9f8b64cab Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 23:24:52 +0000 Subject: [PATCH 1/2] docs(plugin-audit): re-anchor the dead tracker citations to the commits that decided them Stage 9 of the domain:services dead-citation sweep (ruling C+D, form C). Every comment or docblock site under packages/plugins/plugin-audit/src that cited a tracker number answering 404 now cites the commit in this repository's history that decided what the line describes, and says in its own words what that commit decided. Comments only: each touched file keeps its line count, and no code token moves. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude --- ...ctivity-type-vocabulary-enforcement.test.ts | 8 ++++---- .../src/audit-hook-object-scope.test.ts | 8 ++++---- .../plugin-audit/src/audit-writers.test.ts | 14 +++++++------- .../plugins/plugin-audit/src/audit-writers.ts | 18 +++++++++--------- .../src/capability-gate-update-verb.test.ts | 2 +- .../src/comment-access-hooks.test.ts | 8 ++++---- .../plugin-audit/src/comment-access-hooks.ts | 12 ++++++------ .../sys-activity-type-open-vocabulary.test.ts | 6 +++--- .../sys-activity-type-vocabulary.test.ts | 4 ++-- .../src/objects/sys-activity.object.ts | 8 ++++---- .../src/objects/sys-audit-log.object.ts | 4 ++-- .../src/plugin-keyed-text-bounds.test.ts | 6 +++--- ...ew-instant-preservation.integration.test.ts | 2 +- .../plugin-audit/src/read-audit.test.ts | 6 +++--- .../plugins/plugin-audit/src/read-audit.ts | 4 ++-- .../plugin-audit/src/translations/index.ts | 2 +- 16 files changed, 56 insertions(+), 56 deletions(-) diff --git a/packages/plugins/plugin-audit/src/activity-type-vocabulary-enforcement.test.ts b/packages/plugins/plugin-audit/src/activity-type-vocabulary-enforcement.test.ts index 3b4880d8ed6..d4b2b91b5fc 100644 --- a/packages/plugins/plugin-audit/src/activity-type-vocabulary-enforcement.test.ts +++ b/packages/plugins/plugin-audit/src/activity-type-vocabulary-enforcement.test.ts @@ -40,7 +40,7 @@ * red THERE. Breaking a writer is red here and green there. Neither file alone * covers this object. * - * ## 2026-08-24 — what the ruling on #11507 changed about this file + * ## 2026-08-24 — what the open-vocabulary ruling (commit 88b9d749a) changed about this file * * Nothing about the measurements; everything about what they MEAN. #8203 wrote * §3 as "a defect, characterized", with the instruction to delete those cases @@ -319,7 +319,7 @@ describe('[#8203/#11507] an author-contributed type is accepted — the open-voc * instruction is RETIRED, and deleting them now would delete the only * end-to-end measurement of a ruled contract. * - * Maintainer ruling, 2026-08-24, #11507 (direction 4): `sys_activity.type` is + * Maintainer ruling, 2026-08-24, commit 88b9d749a (direction 4): `sys_activity.type` is * an OPEN, author-extensible vocabulary. The declared options are the * platform's built-in set; ADR-0052 §5b.2 `activityMilestones[].type` stays a * sanctioned write path; an author-contributed value landing verbatim is what @@ -329,7 +329,7 @@ describe('[#8203/#11507] an author-contributed type is accepted — the open-voc * So a red here no longer reads "the fix landed". It reads: something has * started REJECTING an author-contributed value — which is direction 3, a * shipped authoring surface turned into a rejection path. Do not adapt these - * cases to it and do not weaken them; re-open #11507, because that is a + * cases to it and do not weaken them; re-open the ruling (commit 88b9d749a), because that is a * maintainer call and not a test-fixing exercise. * * The mechanism is unchanged and still worth knowing: every field on this @@ -362,7 +362,7 @@ describe('[#8203/#11507] an author-contributed type is accepted — the open-voc * in the spec, so any metadata author can name any string and it lands. This * is the authoring-time face of the open vocabulary, and the one an AI-written * metadata app meets first — which is exactly why the declaration now says so - * in its own `description` (#11507), instead of showing that author a list + * in its own `description` (commit 88b9d749a), instead of showing that author a list * that reads closed. */ it('a milestone declaring an undeclared type writes it — the authoring-surface hole', async () => { diff --git a/packages/plugins/plugin-audit/src/audit-hook-object-scope.test.ts b/packages/plugins/plugin-audit/src/audit-hook-object-scope.test.ts index 7cdc231b78d..f16beb53180 100644 --- a/packages/plugins/plugin-audit/src/audit-hook-object-scope.test.ts +++ b/packages/plugins/plugin-audit/src/audit-hook-object-scope.test.ts @@ -16,13 +16,13 @@ * gates bought a `driver.findOne` / matched-row read for a handler that was * going to return on its first line. * - * ## Why an allow list could not fix it (#5928, PR #6575) + * ## Why an allow list could not fix it (#5928, commit 69787f07b) * * `SKIP_OBJECTS` is a DENY list over an OPEN universe: `/meta` PUT registers new * objects into a running engine with no event a plugin could subscribe to, so a * registrant that enumerated the complement would freeze its list at boot and * silently stop auditing everything created afterwards — a compliance - * regression, and a quiet one. The `excludeObjects` face #6575 added is the + * regression, and a quiet one. The `excludeObjects` face commit 69787f07b added is the * expression this plugin was missing; `test 3` below is the pin that the deny * direction is preserved. * @@ -462,7 +462,7 @@ describe('[#5860] the skip list is declared on the registration face', () => { // invariant, and it is what this now asserts. An object-SCOPED gate costs // the demand gate nothing beyond its own object — and on these two // objects nothing at all: `comment-access-hooks.ts` (#4630) and - // service-storage's `attachment-access-hooks.ts` (#10091) already declare + // service-storage's `attachment-access-hooks.ts` (commit da891e0ef) already declare // `beforeUpdate` scoped to `sys_comment` / `sys_attachment`, so // `hasHooksFor` is already true for both wherever the access kits install. const globalPreImage = registrations @@ -524,7 +524,7 @@ describe('[#5860] the skip list is declared on the registration face', () => { expect(excluded).toContain('sys_comment'); expect(excluded).toContain('sys_job_queue'); expect(excluded).not.toContain('biz_task'); - // #6575 refuses both of these at registration; a spread of the real skip + // Commit 69787f07b refuses both of these at registration; a spread of the real skip // list can never produce them, and this says so out loud. expect(excluded).not.toContain('*'); expect(excluded.every((n) => typeof n === 'string' && n.trim().length > 0)).toBe(true); diff --git a/packages/plugins/plugin-audit/src/audit-writers.test.ts b/packages/plugins/plugin-audit/src/audit-writers.test.ts index 222423fe250..8ec28790da2 100644 --- a/packages/plugins/plugin-audit/src/audit-writers.test.ts +++ b/packages/plugins/plugin-audit/src/audit-writers.test.ts @@ -1208,7 +1208,7 @@ describe('audit writers — a lost audit row is reported at error (#5226)', () = * keep losing rows for hours to a second fault with one `error` line at the * top of the log describing the first; * 2. that one line named the telemetry-datasource remedy unconditionally. The - * cause measured on #14927 was `ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED` and + * cause commit ab489388b records was `ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED` and * the text said "datasource" — the operator was sent to check something * that was not broken. * @@ -1367,7 +1367,7 @@ describe('audit writers — reported once per CAUSE, not once per process (#1516 expect(forMissingTable).toMatch(/telemetry/); expect(forMissingTable).toMatch(/OS_TELEMETRY_DB=0/); - // The measured #14927 misdirection: the cause was an organization refusal + // The misdirection commit ab489388b records: the cause was an organization refusal // and the text said "datasource". const refused = makeCauseEngine(() => ORG_REQUIRED()); await refused.fire('crm_lead', 'l-1'); @@ -1407,7 +1407,7 @@ describe('audit writers — reported once per CAUSE, not once per process (#1516 }); /** - * [#8707] Which organization an audit row is stamped with — the RECORD'S own, + * [commit 1408fe385] Which organization an audit row is stamped with — the RECORD'S own, * honouring the maintainer's ruling on #8287. * * The precedence these cases pin is `recordOrgId ?? sess.organizationId`. Read the @@ -1645,12 +1645,12 @@ describe('audit writers — the record\'s own organization stamps the row (#8707 expect(stampOf(created).audit?.organization_id).not.toBe('org-parent'); }); - // ── the platform stamp column — `sys_api_key` (#8778, #19054) ────────── + // ── the platform stamp column — `sys_api_key` (commit 7901b2dd2, #19054) ── // // The former ⛔ KNOWN GAP case lived here: it pinned that // `sys_api_key.active_organization_id` was UNREACHABLE and stamped the // ACTOR's org, and was written to go red the day the divergence became - // expressible. That day is #8778 (maintainer-ruled option A); the cases + // expressible. That day came with commit 7901b2dd2 (maintainer-ruled option A); the cases // below are its rewrite, expecting `org-key`. #19054 moved the divergence // off the authorable `tenancy.organizationField` key and into // `PLATFORM_STAMP_ORGANIZATION_COLUMNS`, keyed by object name — so these @@ -1879,7 +1879,7 @@ describe('audit writers — the writer reads the session key the engine emits (# // This case is GREEN before and after the #9516 fix on purpose: it pins // that fixing WHICH KEY the fallback arm reads did not disturb the ORDER - // the #8707 ruling set (honouring the maintainer's ruling on #8287). + // commit 1408fe385 set (honouring the maintainer's ruling on #8287). await fire('afterInsert', { object: 'crm_lead', input: { id: 'lead-1' }, @@ -1919,7 +1919,7 @@ describe('audit writers — the writer reads the session key the engine emits (# // Lower stakes than the audit stamp — it feeds `resolveWriteLocale` and the // emitted envelope's `organizationId` rather than a row behind an RLS wall — // but the same removed key, dead the same way. Note the ORDER here is - // session-first and stays that way: #8707's ruling reasons about an AUDIT + // session-first and stays that way: commit 1408fe385 reasons about an AUDIT // ROW read through the record's own tenant wall, which is not what a mention // notification is. Only the key changes at this site. const setupMentions = (schemas: Record> = SINGLE_TENANT) => { diff --git a/packages/plugins/plugin-audit/src/audit-writers.ts b/packages/plugins/plugin-audit/src/audit-writers.ts index 9123759bc8e..2dbd2059e8f 100644 --- a/packages/plugins/plugin-audit/src/audit-writers.ts +++ b/packages/plugins/plugin-audit/src/audit-writers.ts @@ -20,8 +20,8 @@ import { SECRET_MASK, collectMaskedReadFields } from '@objectstack/objectql/core // picker, the search companion and the approval inbox the day an author sets // `nameField` — the same argument the SECRET_MASK import above makes. import { referenceTargetOf, resolveDisplayField } from '@objectstack/spec/data'; -// [#8707 / #10101] The platform-row organization resolver, imported rather -// than owned. It started life in THIS file (#8707, honouring #8287's ruling) +// [commit 1408fe385 / #10101] The platform-row organization resolver, imported rather +// than owned. It started life in THIS file (commit 1408fe385, honouring #8287's ruling) // and was promoted to `@objectstack/metadata-core` by the maintainer ruling // recorded on cloud#1395: ONE shared resolver for all three platform-row // writers (audit, approvals, automation runs) — a per-writer copy of the @@ -190,7 +190,7 @@ const SKIP_OBJECTS = new Set([ * #5038's bulk equivalents) had to answer "yes, a hook covers this object" for * every one of these tables and buy a row read for a handler that returns on * its first line. The knowledge existed; the contract had nowhere to put it - * until #5928 / PR #6575 added `excludeObjects`. + * until #5928 / commit 69787f07b added `excludeObjects`. * * Why the negative face and not `object: [...]` with the complement: the object * universe is OPEN. `/meta` PUT registers new objects into a running engine and @@ -223,7 +223,7 @@ const NOISE_FIELDS = new Set([ ]); /** - * [#8144 / #8707 / #10101] `createFieldPresenceProbe` and + * [#8144 / commit 1408fe385 / #10101] `createFieldPresenceProbe` and * `resolveRecordOrganizationField` were defined HERE until #10101 promoted * them to `@objectstack/metadata-core` (the cloud#1395 ruling: one shared * platform-row organization resolver for audit, approvals and automation @@ -786,7 +786,7 @@ function renderMilestoneSummary( * puts a CLOSED vocabulary there — SQLSTATE (`42P01`, `23505`), mysql2's * symbolic names (`ER_NO_SUCH_TABLE`), SQLite's `SQLITE_*` — and ADR-0112 does * the same for the engine's own refusals (`ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED`, - * the cause measured on #14927). None of them varies per row. + * the cause commit ab489388b records). None of them varies per row. * * So the key is bounded by two sets fixed at BOOT — the declared object * registry and the driver's code vocabulary — and by nothing that grows with @@ -1030,7 +1030,7 @@ export function installAuditWriters( return def; }; - // [#8707 / #10101] The object's own organization COLUMN and value, through + // [commit 1408fe385 / #10101] The object's own organization COLUMN and value, through // the SHARED platform-row resolver (`@objectstack/metadata-core`) — one // memoized instance per installation, the same instance shape the approval // writer and the automation-run recorder hold. See @@ -1347,7 +1347,7 @@ export function installAuditWriters( // a strict sys_user lookup); the service principal lands on `actor`. const actorLabel: string | null = userId ?? (typeof sess.actor === 'string' && sess.actor.trim() ? sess.actor.trim() : null); - // [#8707, honouring #8287's ruling] The audited RECORD'S OWN organization + // [commit 1408fe385, honouring #8287's ruling] The audited RECORD'S OWN organization // wins; the acting session's active organization is the fallback. ⛔ Do not // flip this back to `sess.organizationId ?? recordOrgId`. // @@ -1399,7 +1399,7 @@ export function installAuditWriters( // `readonly: true` (so `validateRecord` skips them) and this whole path is // wrapped in swallow-and-report. // - // It survived a careful review of exactly these lines because #8707 + // It survived a careful review of exactly these lines because commit 1408fe385 // reordered the two arms without evaluating either one: reordering two // expressions does not tell you whether they resolve. The pins in // `audit-writers.test.ts` (#9516 block) are what check this comment against @@ -1689,7 +1689,7 @@ export function installAuditWriters( * the declaration whether or not a creation happened. On insert only, a * caller barred from *creating* an attachment on a `files: false` object * could *move* an existing one onto it. `attachment-access-hooks.ts` - * authorizes the re-point (#10091: the new `parent_object`/`parent_id` + * authorizes the re-point (commit da891e0ef: the new `parent_object`/`parent_id` * must be editable) — access, again, not capability. */ const enforceFilesCapability = async (ctx: HookContext) => { diff --git a/packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts b/packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts index aac0f31bed5..872e9f43a97 100644 --- a/packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts +++ b/packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts @@ -10,7 +10,7 @@ * *move* an existing one onto it, and a `sys_comment` could be re-threaded * into a feeds-disabled object's thread. The access kits authorize the * re-point (`comment-access-hooks.ts` since #4630, - * `attachment-access-hooks.ts` since #10091) — those are ACCESS checks, and + * `attachment-access-hooks.ts` since commit da891e0ef) — those are ACCESS checks, and * the capability half was never asked on the update verb. * * This file runs against a REAL `ObjectQL` (a stub driver underneath), not the diff --git a/packages/plugins/plugin-audit/src/comment-access-hooks.test.ts b/packages/plugins/plugin-audit/src/comment-access-hooks.test.ts index 5f4ba3daa7b..5b717547f69 100644 --- a/packages/plugins/plugin-audit/src/comment-access-hooks.test.ts +++ b/packages/plugins/plugin-audit/src/comment-access-hooks.test.ts @@ -261,7 +261,7 @@ describe('comment access — beforeDelete (author or parent editor)', () => { ).rejects.toMatchObject({ code: 'RECORD_NOT_ACCESSIBLE' }); }); - // [#9798] The UNSCOPED multi-write block that used to sit here called the + // [commit c7655d472] The UNSCOPED multi-write block that used to sit here called the // handlers DIRECTLY with a whole-operation context of this file's own // construction — a shape the engine's per-row dispatch (#5038/#5574) never // produced on either verb, so it stayed green for a behaviour the wired @@ -401,8 +401,8 @@ describe('#7141 — caller envelope forwarded to the sharing gate', () => { await beforeDelete(envelopeWriteCtx('beforeDelete', { id: 'c1' }, { ...DELEGATED_ENVELOPE })); const forwarded = canEdit.mock.calls[0]![2] as unknown as Record; - // Every principal field survives — the #6523 contract's unit is the envelope - // and #6206 forbids rebuilding a subset of it. + // Every principal field survives — the unit of commit aa4b90d9a's contract is the envelope + // and the full-envelope ruling forbids rebuilding a subset of it. expect(forwarded).toEqual({ userId: 'human_1', tenantId: 'org_1', @@ -534,7 +534,7 @@ describe('#7141 — caller envelope forwarded to the sharing gate', () => { }); // ───────────────────────────────────────────────────────────────────────── -// #4630's unscoped multi-write refusals through the WIRED engine (#9798) +// #4630's unscoped multi-write refusals through the WIRED engine (commit c7655d472) // // A real `ObjectQL` + in-memory driver + this module's installer — the exact // path `ql.delete('sys_comment', …)` / `ql.update('sys_comment', …)` take in diff --git a/packages/plugins/plugin-audit/src/comment-access-hooks.ts b/packages/plugins/plugin-audit/src/comment-access-hooks.ts index 114606ec77f..058f4919b0a 100644 --- a/packages/plugins/plugin-audit/src/comment-access-hooks.ts +++ b/packages/plugins/plugin-audit/src/comment-access-hooks.ts @@ -32,7 +32,7 @@ * carrying NEITHER an id NOR a `where` is refused outright rather than * authorizing the whole table by resolving zero rows — on BOTH verbs that * refusal reaches this handler through the `dispatchUnscopedMultiWrite` - * whole-operation dispatch both registrations declare (#9719/#9798 built + * whole-operation dispatch both registrations declare (#9719/commit c7655d472 built * it for delete; #9974 ruled it onto update). * - {@link installCommentReadVisibility} — the read side: a * `find`/`findOne`/`count`/`aggregate` middleware that intersects the query @@ -74,7 +74,7 @@ export interface CommentAccessEngine { options?: { object?: string; packageId?: string; - /** [#9798, both verbs since #9974] Opt-in whole-operation `beforeUpdate` / + /** [commit c7655d472, both verbs since #9974] Opt-in whole-operation `beforeUpdate` / * `beforeDelete` dispatch for an UNSCOPED predicate write * (`multi: true`, no `where`) — the engine declaration added by #9719. * Declared here because this file's registrations pass it; the mechanism, @@ -219,7 +219,7 @@ function asIdList(id: unknown): Array | null { * snapshot lacks `permissions`, which sharing bypasses need. * * [#7136] Typed as the full envelope, which is what `ISharingService` declares - * for every parameter this value is handed to (#6523 / the #6206 ruling). + * for every parameter this value is handed to (commit aa4b90d9a / the full-envelope ruling). * * [#7141] And FORWARDED as the full envelope, which is the other half of that * ruling: a caller "MUST NOT rebuild a subset of it". The five-field projection @@ -369,7 +369,7 @@ export function installCommentAccessHooks( // authorize row-by-row, and "nothing to authorize" must never read as // "allowed" (the engine would hand an unscoped AST to deleteMany). // - // [#9798/#9974] This branch is verb-neutral in what it says AND, since + // [commit c7655d472/#9974] This branch is verb-neutral in what it says AND, since // #9974, in what reaches it. On BOTH verbs the only dispatch that can // deliver this shape is the `dispatchUnscopedMultiWrite` whole-operation // dispatch this module's two `before*` registrations declare (see below): @@ -472,7 +472,7 @@ export function installCommentAccessHooks( } }, // [#9974] `dispatchUnscopedMultiWrite` is what makes the #4630 unscoped - // refusal in `resolveTargetRows` REACHABLE ON UPDATE — the half #9798 could + // refusal in `resolveTargetRows` REACHABLE ON UPDATE — the half commit c7655d472 could // not land, ruled in on 2026-08-19. Without it the predicate path dispatches // per row with `input.id` bound (so the by-id branch shadows the shape // check) and a zero-match predicate dispatches nothing, leaving the declared @@ -491,7 +491,7 @@ export function installCommentAccessHooks( if (!rows.length) return; // nothing matched — nothing to authorize await authorizeRows(ctx, rows, 'delete'); }, - // [#9798] `dispatchUnscopedMultiWrite` is what makes the #4630 unscoped + // [commit c7655d472] `dispatchUnscopedMultiWrite` is what makes the #4630 unscoped // refusal in `resolveTargetRows` REACHABLE through the wired engine: the // predicate path dispatches per row with `input.id` bound (so the by-id // branch shadows the check), and a zero-match predicate dispatches nothing diff --git a/packages/plugins/plugin-audit/src/objects/sys-activity-type-open-vocabulary.test.ts b/packages/plugins/plugin-audit/src/objects/sys-activity-type-open-vocabulary.test.ts index 5f1abcb5c45..801b387ea96 100644 --- a/packages/plugins/plugin-audit/src/objects/sys-activity-type-open-vocabulary.test.ts +++ b/packages/plugins/plugin-audit/src/objects/sys-activity-type-open-vocabulary.test.ts @@ -5,13 +5,13 @@ import { ObjectSchema } from '@objectstack/spec/data'; import { SysActivity } from './index.js'; /** - * #11507 — the declaration of `sys_activity.type` must say what the column + * Commit 88b9d749a — the declaration of `sys_activity.type` must say what the column * actually is: an OPEN, author-extensible vocabulary whose declared options are * the platform's BUILT-IN set. * * ## The ruling this file executes * - * Maintainer, 2026-08-24, on #11507 (direction 4 of the four the card framed), + * Maintainer, 2026-08-24, on the card behind commit 88b9d749a (direction 4 of the four it framed), * verbatim: 「四维分析一致的,接手你的建议。」 Recorded on the card as: * * > the column is an open, author-extensible vocabulary. […] make the @@ -92,7 +92,7 @@ describe('[#11507] sys_activity.type is an OPEN vocabulary and the declaration s }); /** - * The load-bearing assertion, and the deliverable of #11507. The three + * The load-bearing assertion, and the deliverable of commit 88b9d749a. The three * markers are the three things an author must be able to learn FROM THE * DECLARATION ITSELF: * - the declared list is the BUILT-IN set (not the whole legal set); diff --git a/packages/plugins/plugin-audit/src/objects/sys-activity-type-vocabulary.test.ts b/packages/plugins/plugin-audit/src/objects/sys-activity-type-vocabulary.test.ts index b3fbdabdeb1..19ac38bf6f4 100644 --- a/packages/plugins/plugin-audit/src/objects/sys-activity-type-vocabulary.test.ts +++ b/packages/plugins/plugin-audit/src/objects/sys-activity-type-vocabulary.test.ts @@ -24,7 +24,7 @@ import { SysActivity } from './index.js'; * shows both halves, against a control that proves the measurement can fail. * This file is the DECLARATIVE half: the writer census, written as literals. * - * ## 2026-08-24 — the #11507 ruling, and what this census now inventories + * ## 2026-08-24 — the open-vocabulary ruling (commit 88b9d749a), and what this census now inventories * * The paragraph above described the state of the code; the maintainer then * ruled what it MEANS (direction 4): `sys_activity.type` is an OPEN, @@ -88,7 +88,7 @@ import { SysActivity } from './index.js'; * * That mirror is unguarded in both directions — objectui pins its key set * against a hardcoded literal rather than against this declaration, so an - * addition here does not reach it. Filed as #8852; deliberately NOT asserted + * addition here does not reach it. Commit 51bb277ef recorded it; deliberately NOT asserted * here, since this package cannot import objectui. Per objectstack-ai/objectui#5840 * that map has since been widened past the declaration to cover values a shipped * producer measurably writes, so the two key sets are no longer set-equal — diff --git a/packages/plugins/plugin-audit/src/objects/sys-activity.object.ts b/packages/plugins/plugin-audit/src/objects/sys-activity.object.ts index f93e685fd89..b0db4ce282e 100644 --- a/packages/plugins/plugin-audit/src/objects/sys-activity.object.ts +++ b/packages/plugins/plugin-audit/src/objects/sys-activity.object.ts @@ -56,8 +56,8 @@ export const SysActivity = ObjectSchema.create({ /** * The activity kind — an OPEN, author-extensible vocabulary whose declared - * options are the platform's BUILT-IN set. Maintainer ruling 2026-08-24 on - * #11507 (direction 4 of the four that card framed), which the `description` + * options are the platform's BUILT-IN set. Maintainer ruling 2026-08-24, + * executed by commit 88b9d749a (direction 4 of the four weighed), which the `description` * below carries into the contract; this comment carries the reasoning. * * ## Why the declaration used to lie @@ -89,7 +89,7 @@ export const SysActivity = ObjectSchema.create({ * * - Do not "fix" this by enforcing the enum on system-owned writes, and do * not narrow `activityMilestones[].type`. Either is direction 3; re-open - * #11507 first. + * the ruling (commit 88b9d749a) first. * - Keep the built-in set declared and censused — open is not undeclared. * The writer census lives in `sys-activity-type-vocabulary.test.ts`, and * it inventories BUILT-IN values only; an author's value belongs to the @@ -170,7 +170,7 @@ export const SysActivity = ObjectSchema.create({ group: 'Target', }), - // [#11374 route A] The value is a record id of the object `object_name` + // [commit f64668d3c, route A] The value is a record id of the object `object_name` // names — written by `audit-writers.ts` (`record_id: recordId`, the id of // the very row the mutation touched). The bound is derived by // referenced-column transitivity from the id itself, never guessed: diff --git a/packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts b/packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts index 7e240d4c297..118f2b636eb 100644 --- a/packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts +++ b/packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts @@ -256,7 +256,7 @@ export const SysAuditLog = ObjectSchema.create({ group: 'Target', }), - // [#11374 route A] The bound is derived by referenced-column transitivity + // [commit f64668d3c, route A] The bound is derived by referenced-column transitivity // from the id this column holds, never guessed: `driver-sql` creates every // table's primary key as `table.string('id').primary()` — knex's // `varchar(255)`, which the driver spells out as @@ -298,7 +298,7 @@ export const SysAuditLog = ObjectSchema.create({ // internal-id-shaped value passes through untouched. // // ⚠️ ORDERING, and why this object differs from its three siblings - // (#11674): this id half is OPTIONAL, so a seed that names a target + // (commit 1cba33f16): this id half is OPTIONAL, so a seed that names a target // loaded later is genuinely order-independent — pass 1 inserts without // the column and pass 2 back-fills it through the internal id captured at // insert time, measured end-to-end against the real engine in diff --git a/packages/plugins/plugin-audit/src/plugin-keyed-text-bounds.test.ts b/packages/plugins/plugin-audit/src/plugin-keyed-text-bounds.test.ts index 03e527efc81..d1be0248eb9 100644 --- a/packages/plugins/plugin-audit/src/plugin-keyed-text-bounds.test.ts +++ b/packages/plugins/plugin-audit/src/plugin-keyed-text-bounds.test.ts @@ -6,10 +6,10 @@ import { AuditPlugin } from './audit-plugin.js'; /** * The ActivityPointer id columns carry the REFERENCED column's bound. * - * ## What used to be here, and where it went (#12147) + * ## What used to be here, and where it went (commit 945e91a13) * * This file carried route A's rule — "every text-family column a declared index - * keys on declares a `maxLength`" (#11374) — enumerated over the objects this + * keys on declares a `maxLength`" (commit 3954fb7df) — enumerated over the objects this * plugin registers, with a vacuity control and an `UNBOUNDABLE` allowlist. That * is now `scripts/check-keyed-text-bounds.mjs`, a source scan over EVERY * `*.object.ts` in the repository. @@ -18,7 +18,7 @@ import { AuditPlugin } from './audit-plugin.js'; * `@objectstack/platform-objects`' pin enumerates that package's exports and * cannot reach a plugin's objects — this package's `package.json` declares only * the `.` export and the root barrel does not re-export `./objects`, and making - * it importable would invert the dependency graph (measured on PR #12143: + * it importable would invert the dependency graph (measured on commit f64668d3c: * `platform-objects` depends only on `metadata-core` + `spec`, while this * plugin depends on `platform-objects`). So each shipping package carried its * own copy until a class-level instrument existed. It exists now. diff --git a/packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts b/packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts index a9853933635..3a9eb5e5c78 100644 --- a/packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts +++ b/packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. /** - * [#16829] The record-view ledger keeps the VIEW instant, measured through the + * [commit 8d4690b8f] The record-view ledger keeps the VIEW instant, measured through the * REAL `sys_stamp_audit_insert` hook. * * ## Why this file exists next to a suite that already claims this diff --git a/packages/plugins/plugin-audit/src/read-audit.test.ts b/packages/plugins/plugin-audit/src/read-audit.test.ts index c1ec449ab61..2603b9cabd1 100644 --- a/packages/plugins/plugin-audit/src/read-audit.test.ts +++ b/packages/plugins/plugin-audit/src/read-audit.test.ts @@ -19,7 +19,7 @@ * - "record-detail views only" turns on the real shapes `find` and `findOne` * leave on `ctx.result` and `ctx.input.ast.where`. * - * ⚠️ [#16829] A THIRD pin used to be claimed here — "the row keeps the VIEW + * ⚠️ [commit 8d4690b8f] A THIRD pin used to be claimed here — "the row keeps the VIEW * instant, which depends on the real engine's `created_at` strip and its * system-context exemption (#4447)". This file CANNOT make that one, and the * claim was false in both of its halves. @@ -40,7 +40,7 @@ * — a real kernel, the real `ObjectQLPlugin`, a real driver. ⛔ Do not restate * an engine-behaviour guarantee here: a green reading from an instrument that * cannot fail is indistinguishable from a pass, and that is precisely how - * #16829 shipped. + * the defect fixed by commit 8d4690b8f shipped. */ import { describe, it, expect, beforeEach } from 'vitest'; @@ -542,7 +542,7 @@ describe('#8992 what the row must NOT contain, and when it says it happened', () * row itself rather than leaving the column to the engine — and that, the * writer's own behaviour, is the whole of what this case pins. * - * ⛔ [#16829] It does NOT pin that the engine keeps the value. This harness's + * ⛔ [commit 8d4690b8f] It does NOT pin that the engine keeps the value. This harness's * engine registers no audit stamp hook at all (see this file's header), so * this case reads green whether the ledger write declares `preserveAudit` or * not. The engine half is pinned by diff --git a/packages/plugins/plugin-audit/src/read-audit.ts b/packages/plugins/plugin-audit/src/read-audit.ts index ae1e1b9a217..fe7789f78ce 100644 --- a/packages/plugins/plugin-audit/src/read-audit.ts +++ b/packages/plugins/plugin-audit/src/read-audit.ts @@ -469,7 +469,7 @@ export function installReadAuditWriter( */ const persistReadAuditRows = async (rows: Record[]): Promise => { // TWO context keys, for two different layers. ⛔ Neither substitutes for - // the other, and dropping either one breaks a different thing (#16829). + // the other, and dropping either one breaks a different thing (commit 8d4690b8f). // // - `isSystem` → the READONLY STRIP. `sys_audit_log` exposes only // `get`/`list` on the API and every field is `readonly: true`, so a @@ -611,7 +611,7 @@ export function installReadAuditWriter( // on `persistReadAuditRows`'s write. ⛔ Read that call site before // touching this field: the two are one mechanism split over two places. // - // ⚠️ [#16829] This comment used to name `isSystem` as that mechanism, on + // ⚠️ [commit 8d4690b8f] This comment used to name `isSystem` as that mechanism, on // the authority of `engine-audit-anchor-write.test.ts`'s "a system-context // write is still exempt". Both halves were wrong, and the citation is why // nobody re-checked them: diff --git a/packages/plugins/plugin-audit/src/translations/index.ts b/packages/plugins/plugin-audit/src/translations/index.ts index 609a0ba848b..05fcda15bd8 100644 --- a/packages/plugins/plugin-audit/src/translations/index.ts +++ b/packages/plugins/plugin-audit/src/translations/index.ts @@ -25,7 +25,7 @@ import { enMessages, zhCNMessages, jaJPMessages, esESMessages } from './messages * ## The provenance companions are READ here, not merely recorded * * `os i18n extract --source-hashes` writes `.source-hashes.generated.ts` - * beside these bundles (maintainer ruling #12069 Option A, #11671). A record + * beside these bundles (maintainer ruling #12069 Option A, commit 09b4f4e4e). A record * says: "this locale's leaf at that path is still a byte copy of THAT source * revision". Recording alone changes nothing a user sees — the substitution is * what {@link withSourceFallback} does, and until it was wired here this set From d6e67afa539247334a8c1867e0128efd39acd6c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 29 Sep 2026 23:35:22 +0000 Subject: [PATCH 2/2] chore(changeset): patch for the plugin-audit provenance re-anchoring The rewritten docblocks and inline comments reach the published dist entry files, so the package ships changed bytes. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude --- .changeset/20596-plugin-audit-provenance-anchors.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/20596-plugin-audit-provenance-anchors.md diff --git a/.changeset/20596-plugin-audit-provenance-anchors.md b/.changeset/20596-plugin-audit-provenance-anchors.md new file mode 100644 index 00000000000..97d9e7dcaa7 --- /dev/null +++ b/.changeset/20596-plugin-audit-provenance-anchors.md @@ -0,0 +1,10 @@ +--- +'@objectstack/plugin-audit': patch +--- + +Provenance comments in `plugin-audit` were re-anchored + +Comment and docblock lines under `src/` that cited tracker numbers which no +longer resolve on GitHub now cite the commit in this repository's history that +decided the matter, and say in their own words what was decided. Comments +only: no type, schema, export, log or refusal text, or runtime behaviour changes.