Commit 5a916c4
* feat(approvals): plan the org-less platform-row backfill — dry run only
The DRY-RUN half of the #11308 one-off repair sweep, landed on its own so the
write path cannot be what defines the plan: for a script that touches existing
data the dry run has to exist first, and be a deliverable in its own right.
`planPlatformRowOrganizationBackfill` reads only. It scans each stranded
platform table for rows whose organization column is unset, re-reads each row's
SUBJECT record, and reports — broken out per object — what it would write, plus
the rows it deliberately would not: a subject with no organization of its own is
counted and NAMED (out of the ruling), never given an invented one.
Both the column read on the subject and the column written on the platform row
come from the shared `createRecordOrganizationResolver`, so `sys_api_key`'s
stamp-only `active_organization_id` fork is honoured rather than flattened.
Refs #11308
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
* feat(approvals): write the org-less platform-row backfill, on the plan the dry run printed
The write half, on top of the dry run rather than beside it:
`applyPlatformRowOrganizationBackfill` takes the PLAN a human already read and
issues one update per planned row carrying its id and its resolved organization
column — nothing else on the row, which is what makes the undo expressible as
"write NULL back to these ids".
`runPlatformRowOrganizationBackfill` defaults to `dryRun: true`; writing is
opt-in. A row whose update throws is recorded on its object's plan and the
sweep continues — a driver rejecting one row must not cost the other N-1 their
repair, and a half-done sweep is safe because the next run picks up exactly
what is still unstamped.
Idempotency is asserted, not claimed: the suite runs the sweep twice against
the same engine and pins the second run at zero planned and zero written, with
the deliberately-skipped rows re-REPORTED at the same count.
Refs #11308
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
* test(approvals): hold the backfill's fake engine to the platform's own write contracts
Two gate findings, both real and both about the DOUBLE rather than the sweep:
- its `update()` was looser than `ObjectQL.update` — now opened with
`assertEngineUpdateDispatch(data, options)` from `@objectstack/metadata-core`,
and the pinned ledger learns the file;
- its WHERE matcher read a `$`-combinator as a field name, and sat inside a
closure the conformance gate could not lift. It now refuses the combinators
it does not implement, at module scope where the gate can judge it.
Refs #11308
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
---------
Co-authored-by: os-sam <sam@objectstack.ai>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent a41069b commit 5a916c4
4 files changed
Lines changed: 1085 additions & 0 deletions
File tree
- .changeset
- packages/plugins/plugin-approvals/src
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
0 commit comments