Skip to content

Commit 06b8fbc

Browse files
committed
Merge commit 'cbaf04c1fd' into claude/issue-20594-qa-dead-citations
2 parents 527d5dc + cbaf04c commit 06b8fbc

14 files changed

Lines changed: 51 additions & 41 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/plugin-approvals': patch
3+
---
4+
5+
Provenance comments in `plugin-approvals` were re-anchored
6+
7+
Comment and docblock lines under `src/` that cited tracker numbers which no
8+
longer resolve on GitHub now cite the commit in this repository's history that
9+
decided the matter, and say in their own words what was decided. Comments
10+
only: no type, schema, export, log or refusal text, or runtime behaviour changes.

‎packages/plugins/plugin-approvals/src/approval-node.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ describe('openNodeRequest — organization attribution (cloud#1395, #10101)', ()
459459
});
460460

461461
it('⛔ pins the sys_api_key divergence: stamps the DECLARED active_organization_id, and never treats an ADR-0066 org FK as the stamp', async () => {
462-
// The credential table (#8287/#8778): unwalled by necessity, rows still
462+
// The credential table (#8287, commit 7901b2dd2): unwalled by necessity, rows still
463463
// ABOUT one organization under `tenancy.organizationField` — limb 0 wins
464464
// over the disabled-tenancy opt-out.
465465
const apiKey = makeFakeEngine({

‎packages/plugins/plugin-approvals/src/approval-node.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
} from '@objectstack/spec/automation';
2727
// [#7135] The full `resolveAuthzContext` envelope — what
2828
// `IApprovalService.openNodeRequest` declares for its context parameter since
29-
// #6523 (the #6206 ruling: no per-site subset contracts).
29+
// commit aa4b90d9a (the full-envelope ruling: no per-site subset contracts).
3030
import type { ExecutionContext } from '@objectstack/spec/kernel';
3131
import type { ApprovalService } from './approval-service.js';
3232
import { registerApprovalReviseNode } from './approval-revise-node.js';

‎packages/plugins/plugin-approvals/src/approval-service.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,9 @@ describe('ApprovalService (node era)', () => {
746746
expect(req.pending_approvers).toEqual(['position:sales_manager']);
747747
});
748748

749-
// ── the #8710 carve-out, asserted on THIS side (#8863) ──────────────────
749+
// ── the commit 04d03c3a0 carve-out, asserted on THIS side (commit d200b016b) ──
750750
//
751-
// Maintainer ruling, 2026-08-15 (#8710, inheriting #8613), verbatim:
751+
// Maintainer ruling, 2026-08-15 (commit 04d03c3a0, inheriting #8613), verbatim:
752752
//
753753
// > Access-conferring paths filter deactivated positions; addressing
754754
// > paths do not.

‎packages/plugins/plugin-approvals/src/approval-service.ts‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ import type {
4949
ResumeFailureReport,
5050
} from '@objectstack/spec/contracts';
5151
// [#7135] The full `resolveAuthzContext` envelope — what `IApprovalService`
52-
// declares for every one of these context parameters since #6523 (the #6206
53-
// ruling: enforcement adjudicates on the whole envelope, never a per-site
52+
// declares for every one of these context parameters since commit aa4b90d9a (the
53+
// full-envelope ruling: enforcement adjudicates on the whole envelope, never a per-site
5454
// subset). Annotating the implementation with the retired six-field shape is
5555
// what forced this file to cast its way out of its own contract to read
5656
// fields the caller had already supplied.
@@ -60,7 +60,7 @@ import { isFileIdToken, referenceTargetOf } from '@objectstack/spec/data';
6060
// [#11993] The SANCTIONED renderer for OPERATION-level refusal copy. The
6161
// Operation Message Catalog is the ONE seat for these sentences — its own
6262
// header bars both a package-local string table and a second rendering
63-
// mechanism for a second producer, and #12493 landed this service's key
63+
// mechanism for a second producer, and commit aa5994e17 landed this service's key
6464
// (`approval_recall_not_submitter`) into it ahead of this consumer half.
6565
import { renderOperationMessage, type ValidationMessageTranslator } from '@objectstack/spec/system';
6666
import { isGrantActive } from '@objectstack/core';
@@ -218,7 +218,7 @@ export interface ApprovalResumeSurface {
218218
* evidence of anything. Rejects when a store cannot be read; the inspection
219219
* counts such a row `undetermined` — but ⛔ unlike a thrown
220220
* {@link hasSuspendedRun} it does NOT drop the row, because this oracle is
221-
* asked only WHICH shape a row already known to be stranded is (#16709).
221+
* asked only WHICH shape a row already known to be stranded is (commit 8c7cca1ce).
222222
* A host that resolves a malformed verdict is treated the same way, and
223223
* costs no OTHER row its answer.
224224
*/
@@ -657,7 +657,7 @@ function refineFailedRunState(verdict: ConsumedSuspensionVerdict): StrandedRunSt
657657
* was asked and could not answer. Three ways in: the attached surface has
658658
* no `inspectConsumedSuspension` (an engine build older than this plugin,
659659
* or a test double); the read THREW (a store outage); or the host resolved
660-
* a malformed verdict, violating its own declared surface (#16709). Today's
660+
* a malformed verdict, violating its own declared surface (commit 8c7cca1ce). Today's
661661
* undifferentiated label, kept on purpose as the fail-closed fallback
662662
* (#15358 ruling, item 1): a failure to differentiate is not evidence, so
663663
* the row is reported and its repairability left unstated — ⛔ never
@@ -1378,7 +1378,7 @@ export class ApprovalService implements IApprovalService {
13781378
const perms = Array.isArray(context.permissions) ? context.permissions : [];
13791379
// [#7135] A DECLARED read. `posture` (ADR-0095 D2) is resolved by
13801380
// `resolveAuthzContext` and is a field of the envelope the contract has
1381-
// named here since #6523 — the doc block above already says it is the
1381+
// named here since commit aa4b90d9a — the doc block above already says it is the
13821382
// intended signal. Until this parameter widened, reading it meant an
13831383
// unchecked `as any` on an enforcement input: a typo (`postures`,
13841384
// `'PLATFORM-ADMIN'`) would have compiled and silently denied every
@@ -2292,7 +2292,7 @@ export class ApprovalService implements IApprovalService {
22922292
* `plugin-sharing`, whatever the shared method name suggests. Both answer
22932293
* "who holds position P"; this one reads the directory RAW — neither the
22942294
* ADR-0091 D2 validity window nor the `sys_position.active` catalogue flag is
2295-
* applied. Maintainer ruling, 2026-08-15 (#8710, inheriting #8613), verbatim:
2295+
* applied. Maintainer ruling, 2026-08-15 (commit 04d03c3a0, inheriting #8613), verbatim:
22962296
*
22972297
* > Access-conferring paths filter deactivated positions; addressing paths
22982298
* > do not.
@@ -2315,7 +2315,7 @@ export class ApprovalService implements IApprovalService {
23152315
* projects `user_id` too). The table carries no window columns at all and
23162316
* `isGrantActive` reads an absent bound as unbounded, so there is nothing
23172317
* a filter could do here; membership tier names have no `sys_position`
2318-
* row either (#8710's "a name with no row is untouched" fallback), so no
2318+
* row either (commit 04d03c3a0's "a name with no row is untouched" fallback), so no
23192319
* catalogue flag either. This limb cannot be brought into parity by
23202320
* adding a filter — see {@link expandMembershipTierUsers}.
23212321
* 3. `sys_position.active` — the sharing engine's gate for it lives at the
@@ -2326,7 +2326,7 @@ export class ApprovalService implements IApprovalService {
23262326
* The omission is per-READ, not a missing dependency: `isGrantActive` is
23272327
* imported in this file and IS applied to `sys_approval_delegation` in
23282328
* {@link lookupActiveDelegation}. ⛔ So do not "fix" this by adding the window
2329-
* filter here — that is the option #8710 rejected, on the reasoning above.
2329+
* filter here — that is the option the ruling (commit 04d03c3a0) rejected, on the reasoning above.
23302330
*/
23312331
private async expandPositionUsers(positionName: string, organizationId?: string | null): Promise<string[]> {
23322332
if (!positionName) return [];
@@ -2360,7 +2360,7 @@ export class ApprovalService implements IApprovalService {
23602360
* filter even if it were not: `sys_member` carries no ADR-0091 D2 window
23612361
* columns, and a tier name has no `sys_position` row to read `active` off.
23622362
* {@link expandPositionUsers} carries the ruling both reads inherit
2363-
* (#8613 / #8710) — this method is also the second limb of that union, so a
2363+
* (#8613 / commit 04d03c3a0) — this method is also the second limb of that union, so a
23642364
* change here changes position routing too.
23652365
*/
23662366
private async expandMembershipTierUsers(tier: string, organizationId?: string | null): Promise<string[]> {
@@ -4793,7 +4793,7 @@ export class ApprovalService implements IApprovalService {
47934793
* A surface without that member leaves the row `'failed'` — reported,
47944794
* undifferentiated — because absence of the discriminator is not evidence
47954795
* of anything. So does a read that THREW or answered a malformed verdict
4796-
* (#16709): by the time this oracle is asked the row is already known to be
4796+
* (commit 8c7cca1ce): by the time this oracle is asked the row is already known to be
47974797
* stranded, so a failure to differentiate it is not a reason to drop it from
47984798
* a report — it is counted `undetermined` as telemetry AND reported.
47994799
*
@@ -4820,7 +4820,7 @@ export class ApprovalService implements IApprovalService {
48204820
* outage must not be published as a lost run); a thrown or malformed THIRD
48214821
* read leaves its row in `stranded` as the undifferentiated `'failed'` and
48224822
* is counted here as well — the row is known to be stranded, only its
4823-
* shape could not be told (#16709). So this counter and `stranded.length`
4823+
* shape could not be told (commit 8c7cca1ce). So this counter and `stranded.length`
48244824
* overlap on purpose, and neither one alone sizes the scan's blind spot.
48254825
*/
48264826
undetermined: number;
@@ -4890,7 +4890,7 @@ export class ApprovalService implements IApprovalService {
48904890
// the other two oracles. See `refineFailedRunState` and
48914891
// `StrandedRunState` for the three answers and why none is folded.
48924892
if (runState === 'failed' && typeof this.automation.inspectConsumedSuspension === 'function') {
4893-
// ⚠️ [#16709 item 3] The REFINEMENT runs inside this `try`, with the
4893+
// ⚠️ [commit 8c7cca1ce, item 3] The REFINEMENT runs inside this `try`, with the
48944894
// read it refines. `refineFailedRunState` dereferences the verdict, so
48954895
// a host that violates the declared surface — resolving `undefined`
48964896
// where a verdict is declared — used to throw a `TypeError` out of
@@ -4903,7 +4903,7 @@ export class ApprovalService implements IApprovalService {
49034903
try {
49044904
refined = refineFailedRunState(await this.automation.inspectConsumedSuspension(runId));
49054905
} catch (err: any) {
4906-
// [#16709 item 2 — PM ruling, 2026-09-08] The row STAYS in the
4906+
// [commit 8c7cca1ce, item 2 — PM ruling, 2026-09-08] The row STAYS in the
49074907
// report, as the undifferentiated `'failed'`. This oracle is not
49084908
// asked WHETHER the row is stranded: the first two already answered
49094909
// that (no live pause, terminal `failed`). It is asked only WHICH of

‎packages/plugins/plugin-approvals/src/backfill-platform-row-organizations.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* The one-off platform-row organization backfill (#11308) — dry run and write.
4+
* The one-off platform-row organization backfill (commit 5a916c4d4) — dry run and write.
55
*
66
* The three properties the 2026-08-23 maintainer ruling names are asserted
77
* here rather than described anywhere:
@@ -14,9 +14,9 @@
1414
* 3. **Idempotent** — the sweep runs twice against the same engine and the
1515
* second run's write count is asserted to be 0.
1616
*
17-
* Plus the one thing this card must not do: a platform row about a
17+
* Plus the one thing this sweep must not do: a platform row about a
1818
* `sys_api_key` is repaired from `active_organization_id` (limb 0,
19-
* stamp-only, #8778), and the credential table is never written to. A sweep
19+
* stamp-only, commit 7901b2dd2), and the credential table is never written to. A sweep
2020
* that "unified everything onto one organization field" would flatten that
2121
* fork, so it is pinned rather than trusted.
2222
*/

‎packages/plugins/plugin-approvals/src/backfill-platform-row-organizations.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* ## What this repairs, and what it deliberately does not
88
*
9-
* #10101 (landed as PR #11311) fixed the WRITERS: a `sys_approval_request` and
9+
* #10101 (landed as commit 1272f0a6b) fixed the WRITERS: a `sys_approval_request` and
1010
* a `sys_automation_run` are now stamped from the SUBJECT record's own
1111
* organization, with the acting context as the ruled fallback. It wrote
1212
* nothing to existing rows, so the population produced before it persists —
@@ -32,7 +32,7 @@
3232
* ONE shared resolver (`createRecordOrganizationResolver`,
3333
* `@objectstack/metadata-core`) — never hard-coded to `organization_id`. That
3434
* is what keeps `sys_api_key`'s deliberate divergence intact: its
35-
* `tenancy.organizationField: 'active_organization_id'` (stamp-only, #8778)
35+
* `tenancy.organizationField: 'active_organization_id'` (stamp-only, commit 7901b2dd2)
3636
* wins limb 0 of the resolver, so a platform row ABOUT an API key is repaired
3737
* from that column, and the credential table itself is never written to. A
3838
* sweep written on the intuition "unify everything onto one organization

‎packages/plugins/plugin-approvals/src/exec-context-annotation.pin.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* #7135 — compile-time pin for the CONTEXT type this plugin's enforcement
55
* methods accept.
66
*
7-
* #6523 converged 36 contract signatures onto the full `ExecutionContext` (the
8-
* #6206 ruling: enforcement adjudicates on the whole `resolveAuthzContext`
7+
* Commit aa4b90d9a converged 36 contract signatures onto the full `ExecutionContext` (the
8+
* full-envelope ruling: enforcement adjudicates on the whole `resolveAuthzContext`
99
* envelope, never a per-site subset). #7135 is the services half of the #7070
1010
* consumer split — the implementations here now annotate their own parameters
1111
* with that same envelope instead of the six-field shape they used to name.

‎packages/plugins/plugin-approvals/src/manager-org-screen-parity.contract.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22
/**
3-
* #11286 — CONTRACT: the two `managerIsProvablyOutsideOrg` screens are EQUAL.
3+
* Commit b019891cd — CONTRACT: the two `managerIsProvablyOutsideOrg` screens are EQUAL.
44
*
55
* `sys_user.manager_id` is read by two packages, and each screens the manager
66
* it finds against the caller's organization with its OWN implementation:
@@ -55,10 +55,10 @@
5555
*/
5656
import { describe, it, expect } from 'vitest';
5757
import { ApprovalService } from './approval-service.js';
58-
// [#11286] plugin-sharing's screen is reached by RELATIVE SOURCE PATH, and that
58+
// [commit b019891cd] plugin-sharing's screen is reached by RELATIVE SOURCE PATH, and that
5959
// is the only way in: it is deliberately NOT exported from that package's index
6060
// (exporting it would hoist a security screen into another plugin's public API
61-
// surface — the very decision this card is fenced out of), and the package's
61+
// surface — the very decision this pin is fenced out of), and the package's
6262
// `exports` map publishes `.` only, so there is no subpath to import. The read
6363
// escapes this package, so it is declared in `CROSS_PACKAGE_TEST_INPUTS` in
6464
// scripts/check-cross-package-test-inputs.mjs and mirrored into the

‎packages/plugins/plugin-approvals/src/recall-refusal-user-copy.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
* The refusal now renders through the shared Operation Message Catalog
1313
* (`@objectstack/spec/system`, key `approval_recall_not_submitter`, landed by
14-
* #12493) instead of a package-local string.
14+
* commit aa5994e17) instead of a package-local string.
1515
*
1616
* ⚠️ These tests assert the SENTENCE AN OPERATOR READS, in zh-CN specifically.
1717
* Asserting only that a catalog key was passed would pass against a message

0 commit comments

Comments
 (0)