From 226be805072eff7d2940b1b8aa86e1d13d29b0f8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 03:37:40 +0000 Subject: [PATCH 1/2] docs(trigger-schedule): re-anchor the dead tracker citations to the commits that decided them Thirty-two comment and docblock sites under packages/triggers/trigger-schedule/src cited tracker numbers that no longer resolve. Each now cites the commit in this repository's history that decided what the line describes: - #16659 -> ecdfc9411 (a time-triggered flow declares its acting organization; the run executes as it, the time-relative sweep selects inside it, and a flow declaring none is refused with a throw so the engine records it) - #16589 -> 555a89cbd (driver-memory refuses a call the engine scoped to a tenant instead of answering every organization's rows) Comments only: 32 lines out, 32 in, every file keeps its line count, and no code token moves. Test titles carrying these numbers are string tokens and are left, as is the one comment that quotes such a title verbatim. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude --- .../src/schedule-dispatch-claim.test.ts | 2 +- .../src/schedule-runas-e2e.test.ts | 2 +- .../src/schedule-trigger.test.ts | 8 +++--- .../trigger-schedule/src/schedule-trigger.ts | 10 +++---- .../src/time-relative-trigger.test.ts | 16 ++++++------ .../src/time-relative-trigger.ts | 26 +++++++++---------- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/triggers/trigger-schedule/src/schedule-dispatch-claim.test.ts b/packages/triggers/trigger-schedule/src/schedule-dispatch-claim.test.ts index 66285b3c679..7591406001a 100644 --- a/packages/triggers/trigger-schedule/src/schedule-dispatch-claim.test.ts +++ b/packages/triggers/trigger-schedule/src/schedule-dispatch-claim.test.ts @@ -43,7 +43,7 @@ const JOB = `flow-schedule:${FLOW}`; const CRON: FlowTriggerBinding = { flowName: FLOW, schedule: { type: 'cron', expression: '0 1 * * *', timezone: 'UTC' }, - // [#16659] the acting organization every tick of this flow runs as. + // [commit ecdfc9411] the acting organization every tick of this flow runs as. organization: 'org_2mtx1w9d0k4bqf7v', }; diff --git a/packages/triggers/trigger-schedule/src/schedule-runas-e2e.test.ts b/packages/triggers/trigger-schedule/src/schedule-runas-e2e.test.ts index c12ae7bbf70..a8e3513169b 100644 --- a/packages/triggers/trigger-schedule/src/schedule-runas-e2e.test.ts +++ b/packages/triggers/trigger-schedule/src/schedule-runas-e2e.test.ts @@ -59,7 +59,7 @@ function scheduledDataFlow(name: string, runAs?: 'system' | 'user') { type: 'schedule', ...(runAs ? { runAs } : {}), nodes: [ - // [#16659] The acting organization a time-triggered flow declares. The + // [commit ecdfc9411] The acting organization a time-triggered flow declares. The // engine lifts it onto the binding and the trigger threads it onto the // run as `tenantId`; a flow without it is refused at bind. { id: 'start', type: 'start', label: 'Start', config: { schedule: { type: 'interval', intervalMs: 1000 }, organization: 'org_2mtx1w9d0k4bqf7v' } }, diff --git a/packages/triggers/trigger-schedule/src/schedule-trigger.test.ts b/packages/triggers/trigger-schedule/src/schedule-trigger.test.ts index af7373481e0..78a5dea4a46 100644 --- a/packages/triggers/trigger-schedule/src/schedule-trigger.test.ts +++ b/packages/triggers/trigger-schedule/src/schedule-trigger.test.ts @@ -66,7 +66,7 @@ function binding(overrides: Partial = {}): FlowTriggerBindin return { flowName: 'nightly_health_sweep', schedule: { type: 'cron', expression: '0 1 * * *', timezone: 'UTC' }, - // [#16659] A time-triggered binding carries its acting organization; a + // [commit ecdfc9411] A time-triggered binding carries its acting organization; a // binding without one is refused — see // `ScheduleTrigger — the acting-organization refusal (#16659)` below. organization: 'org_2mtx1w9d0k4bqf7v', @@ -324,7 +324,7 @@ describe('ScheduleTriggerPlugin', () => { }); }); -// ─── The acting-organization refusal (#16659) ─────────────────────── +// ─── The acting-organization refusal (commit ecdfc9411) ───────────── // // The unit half of the card's consequence (3): a time-triggered flow that // declares no acting organization is REFUSED at bind, and the refusal reaches @@ -509,7 +509,7 @@ describe('resolveBindingOrganization (#16659)', () => { // // Three states, three suites, and each one asserts what BINDS rather than only // what is logged: a refusal that logs correctly and arms the job anyway is the -// exact defect #16659's own refusal was shaped to avoid. +// exact defect commit ecdfc9411's own refusal was shaped to avoid. describe('ScheduleTrigger — the deployment switch is OFF (#17396)', () => { withScheduledWorkOff(); @@ -585,7 +585,7 @@ describe('ScheduleTrigger — switched ON under `single` (#17396)', () => { const trigger = new ScheduleTrigger(() => job.service, silentLogger()); // ⭐ The widening the whole card turns on: this exact binding is - // REFUSED under a wall (the #16659 suite above) and armed here. + // REFUSED under a wall (commit ecdfc9411's refusal suite above) and armed here. trigger.start(orgLess(), async () => {}); expect(job.jobs.size).toBe(1); }); diff --git a/packages/triggers/trigger-schedule/src/schedule-trigger.ts b/packages/triggers/trigger-schedule/src/schedule-trigger.ts index 5d67f8394de..65117048385 100644 --- a/packages/triggers/trigger-schedule/src/schedule-trigger.ts +++ b/packages/triggers/trigger-schedule/src/schedule-trigger.ts @@ -29,7 +29,7 @@ export interface FlowTriggerBinding { readonly condition?: string | { dialect?: string; source?: string; ast?: unknown }; readonly schedule?: unknown; /** - * [#16659] The ACTING ORGANIZATION a time-triggered flow declares on its + * [commit ecdfc9411] The ACTING ORGANIZATION a time-triggered flow declares on its * start node (`config.organization`), lifted onto the binding by the * engine's `resolveTriggerBinding` the same way `schedule` is. * @@ -248,7 +248,7 @@ export interface TriggerLogger { const JOB_PREFIX = 'flow-schedule'; /** - * Resolve the acting organization of a time-triggered binding (#16659), or + * Resolve the acting organization of a time-triggered binding (commit ecdfc9411), or * `null` when the flow declared none. * * Reads the binding's lifted `organization` first and the raw start-node @@ -369,7 +369,7 @@ export function refuseScheduledWorkDisabled( /** * Refuse to bind a time-triggered flow that declares no acting organization - * (#16659): say why at `error`, then THROW so the engine records the refusal. + * (commit ecdfc9411): say why at `error`, then THROW so the engine records the refusal. * * ## When this fires, after #17396 and #18378 * @@ -700,7 +700,7 @@ export class ScheduleTrigger implements FlowTrigger { return; } - // [#16659] The acting organization is part of the BINDING, so it is + // [commit ecdfc9411] The acting organization is part of the BINDING, so it is // checked before the job service is even resolved: a flow that cannot // legally run must not be reported as "not scheduled because the job // service is missing", which is a different defect with a different @@ -774,7 +774,7 @@ export class ScheduleTrigger implements FlowTrigger { try { const ctx: AutomationContext = { event: 'schedule', - // [#16659] When the flow declares one, the run executes AS + // [commit ecdfc9411] When the flow declares one, the run executes AS // that organization: `tenantId` is the acting run's // organization, and every consumer already reads it — // `notify-node.ts` threads it onto the notification it diff --git a/packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts b/packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts index 712fb53fcf1..655747ac91c 100644 --- a/packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts +++ b/packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts @@ -77,7 +77,7 @@ function fakeDataEngine(rows: Row[], knownObjects: string[] = ['contracts']) { } /** - * [#16659] A fake ObjectQL surface that HONOURS `context.tenantId`, so the + * [commit ecdfc9411] A fake ObjectQL surface that HONOURS `context.tenantId`, so the * differential control can put matching rows in two organizations and observe * which ones come back. * @@ -134,7 +134,7 @@ function silentLogger(): TriggerLogger { const NOW = () => new Date('2026-07-18T12:00:00.000Z'); /** - * [#16659] The organization every fixture binding declares. Named rather than + * [commit ecdfc9411] The organization every fixture binding declares. Named rather than * inlined because it is now asserted from two directions — the sweep's query * scope and the launched run's identity — and a literal repeated at both ends * of that pair can drift into agreeing with itself. @@ -146,7 +146,7 @@ function binding(timeRelative: unknown, overrides: Partial = flowName: 'renewal_alert', object: 'contracts', config: { timeRelative }, - // [#16659] see the schedule trigger's fixture note. + // [commit ecdfc9411] see the schedule trigger's fixture note. organization: TEST_ORG, ...overrides, }; @@ -275,7 +275,7 @@ describe('TimeRelativeTrigger', () => { expect(seen[0]).toMatchObject({ object: 'contracts', event: 'time_relative' }); expect(seen[0].record).toBe(seen[0].params); // The sweep queries as a system op (sees all rows, RLS-bypassing) AND - // inside its declared organization. [#16659] This assertion used to + // inside its declared organization. [commit ecdfc9411] This assertion used to // read `{ isSystem: true }` and it was pinning the defect: `isSystem` // is AUTHORIZATION and `tenantId` is TENANCY, and a sweep carrying only // the first selects across every tenant while its runs act as one. @@ -791,7 +791,7 @@ describe('TimeRelativeTriggerPlugin', () => { }); }); -// ─── The acting-organization refusal (#16659) ─────────────────────── +// ─── The acting-organization refusal (commit ecdfc9411) ───────────── // // The time-relative sweep is NOT the weaker case for carrying an organization, // it is the stronger one: it runs ELEVATED on purpose (`isSystem` — a @@ -859,7 +859,7 @@ describe('TimeRelativeTrigger — the acting-organization refusal (#16659)', () expect(job.jobs.size).toBe(0); }); - // ── the SELECTION half (#16659, F2) ─────────────────────────────────── + // ── the SELECTION half (commit ecdfc9411, F2) ───────────────────────── // // Declaring an organization bounded the RUN and left the QUERY unbounded, // so a sweep declared for A matched rows in every tenant and launched runs @@ -985,7 +985,7 @@ describe('TimeRelativeTrigger — the acting-organization refusal (#16659)', () }); it('a store that CANNOT honour the scope is reported at `error`, never answered unscoped', async () => { - // `driver-memory` refuses any call handed a tenant scope (#16589). A + // `driver-memory` refuses any call handed a tenant scope (commit 555a89cbd). A // sweep required to stay inside one organization, talking to a store // that cannot keep it there, must be LOUD — "selected nothing this // tick" and "cannot select at all" are different facts. @@ -1368,7 +1368,7 @@ describe('TimeRelativeTrigger — switched ON under `group` (#18378)', () => { it('a DECLARED organization still outranks the record — declaring narrows, it does not widen', async () => { // A declaration bounds SELECTION as well as identity, so honouring the // record over it would silently widen a flow the author scoped — the - // #16659 defect. Declaration wins, and the sweep sees one plant only. + // defect commit ecdfc9411 fixed. Declaration wins, and the sweep sees one plant only. const job = fakeJobService(); const base = tenantScopedDataEngine(twoPlants()); const engine = { diff --git a/packages/triggers/trigger-schedule/src/time-relative-trigger.ts b/packages/triggers/trigger-schedule/src/time-relative-trigger.ts index 714341b2f17..c85aadbd168 100644 --- a/packages/triggers/trigger-schedule/src/time-relative-trigger.ts +++ b/packages/triggers/trigger-schedule/src/time-relative-trigger.ts @@ -47,7 +47,7 @@ export interface TimeRelativeDataEngine { limit?: number; /** * The sweep's execution context. Two INDEPENDENT axes, and this - * sweep sets both (#16659): + * sweep sets both (commit ecdfc9411): * * - `isSystem` is AUTHORIZATION — a background sweep must see * every row the organization holds, not the RLS-scoped subset @@ -215,7 +215,7 @@ export function buildWindowWhere(desc: TimeRelativeDescriptor, window: DateWindo } /** - * [#16659] Why the engine will DROP this sweep's tenant scope for `schema`, or + * [commit ecdfc9411] Why the engine will DROP this sweep's tenant scope for `schema`, or * `null` when it will apply it. * * `Engine.buildDriverOptions` scopes a read by `context.tenantId` unless the @@ -343,7 +343,7 @@ export class TimeRelativeTrigger implements FlowTrigger { } const desc = parsed.data; - // [#16659] A time-relative sweep launches from a clock, exactly as a + // [commit ecdfc9411] A time-relative sweep launches from a clock, exactly as a // plain schedule flow does, so it owes the same declaration and takes // the same refusal. It is NOT the weaker case for carrying an // organization, it is the stronger one: the sweep runs ELEVATED @@ -362,7 +362,7 @@ export class TimeRelativeTrigger implements FlowTrigger { // elevation argument above is why the `single` case is still safe: an // unscoped `isSystem` read on a one-organization install selects that // organization's rows and the platform's NULL-tenant rows, which is - // exactly what it selected before #16659 and what the #8844 guard + // exactly what it selected before commit ecdfc9411 and what the #8844 guard // resolves beneath it. const organization = resolveBindingOrganization(binding); if (policy.requiresActingOrganization && organization === null) { @@ -415,7 +415,7 @@ export class TimeRelativeTrigger implements FlowTrigger { // author never made. const inertBecause = organization !== null ? organizationScopeIsInertFor(known) : null; if (inertBecause) { - // [#16659] ⛔ A DISCLOSURE, never a narrowing. The sweep + // [commit ecdfc9411] ⛔ A DISCLOSURE, never a narrowing. The sweep // passes `context.tenantId` unconditionally and the ENGINE // decides whether it applies; this branch re-reads the two // declarations the engine documents as its exemptions @@ -460,7 +460,7 @@ export class TimeRelativeTrigger implements FlowTrigger { // Error isolation: a sweep failure must not crash the job // runner / ticker. Log and swallow. // - // [#16659] At `error` when the logger has one, for the reason + // [commit ecdfc9411] At `error` when the logger has one, for the reason // {@link TriggerLogger.error} already states: the CLI's // boot-quiet window swallows stdout, so a `warn` here can be // the whole of what a broken sweep says and still be invisible. @@ -484,7 +484,7 @@ export class TimeRelativeTrigger implements FlowTrigger { const mode = desc.offsetDays ? `offsets [${desc.offsetDays.join(', ')}]d` : `within ${desc.withinDays}d`; - // [#16659] The organization is on the BIND line, not only in + // [commit ecdfc9411] The organization is on the BIND line, not only in // the refusal: it is now the sweep's selection scope as well as // the run's identity, so "which rows can this flow ever see" is // answerable from the boot log instead of from the metadata. @@ -524,7 +524,7 @@ export class TimeRelativeTrigger implements FlowTrigger { desc: TimeRelativeDescriptor, maxRecords: number, /** - * [#16659] The declared organization, or `null`. + * [commit ecdfc9411] The declared organization, or `null`. * * When declared it bounds this sweep TWICE, and both halves are * load-bearing: @@ -540,7 +540,7 @@ export class TimeRelativeTrigger implements FlowTrigger { * second organization to cross to there (plugin-auth's org-create * posture gate refuses one), so an * unscoped sweep is not the cross-organization task the ruling forbids - * — it is the shape a single-organization install had before #16659. + * — it is the shape a single-organization install had before commit ecdfc9411. * Under `isolated` `start()` still refuses an undeclared binding, and * with the switch off nothing binds, so `null` cannot arrive from * either. @@ -558,7 +558,7 @@ export class TimeRelativeTrigger implements FlowTrigger { * Only `'per-record'` changes behaviour here, and only while * `organization === null`: an explicit declaration outranks it, because * a declaration bounds SELECTION as well as identity and silently - * widening a flow the author scoped would be the #16659 defect again. + * widening a flow the author scoped would be the defect commit ecdfc9411 fixed, again. */ ownership: ScheduledRunOwnership, callback: (ctx: AutomationContext) => Promise, @@ -582,7 +582,7 @@ export class TimeRelativeTrigger implements FlowTrigger { (await engine.find(desc.object, { where, limit: maxRecords, - // [#16659] SELECTION is scoped to the declared organization, + // [commit ecdfc9411] SELECTION is scoped to the declared organization, // not just the run that follows it. // // `isSystem` alone was the whole context here, and it made @@ -612,7 +612,7 @@ export class TimeRelativeTrigger implements FlowTrigger { // (`tenancy.enabled: false`, ADR-0066; federated, ADR-0015), // and every driver that CAN isolate then scopes, while // `driver-memory` — which cannot — refuses the call by name - // (#16589). Refusal is the correct answer for a sweep that + // (commit 555a89cbd). Refusal is the correct answer for a sweep that // is required to stay inside one organization and is talking // to a store that cannot keep it there, and it arrives as a // logged sweep failure rather than as silence. @@ -699,7 +699,7 @@ export class TimeRelativeTrigger implements FlowTrigger { record, object: desc.object, event: 'time_relative', - // [#16659] The acting organization — the same key a + // [commit ecdfc9411] The acting organization — the same key a // record-change run inherits from its triggering session, // and the one `notify-node.ts` and the run-history writer // already read. From 14314f49cbb67bf00febd9e3012662a786ec7c41 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 03:50:11 +0000 Subject: [PATCH 2/2] chore(changeset): patch for the trigger-schedule provenance re-anchoring The rewritten docblocks and inline comments ship: the anchors reach the package's JavaScript entries and its declaration files, so the change publishes bytes and takes a patch changeset. Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H Co-authored-by: Claude --- .../20596-trigger-schedule-provenance-anchors.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/20596-trigger-schedule-provenance-anchors.md diff --git a/.changeset/20596-trigger-schedule-provenance-anchors.md b/.changeset/20596-trigger-schedule-provenance-anchors.md new file mode 100644 index 00000000000..7d25f06447f --- /dev/null +++ b/.changeset/20596-trigger-schedule-provenance-anchors.md @@ -0,0 +1,10 @@ +--- +'@objectstack/trigger-schedule': patch +--- + +Provenance comments in `trigger-schedule` 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.