Closed
Labels
domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landpm:dispatchedpm:epicpriority:p1High: required for production / M2High: required for production / M2
Description
Filing gate ③: owed scope of #15212, found by the epic seat's reconciliation of the open epic cards against main at 2919ddb875. The seat's answer 6266091475 (Q1 → A) said the ledger's audit mute "retires with the walled reader in 18.x". Step 4 (#24667) lifted the walled reader and kept the ledger.
- Who acts: the epic seat (
epic:#15194) dispatches it. - Dedupe: none ("PLATFORM_OBJECT_TENANCY ledger retire tenant audit mute" → 0).
Part of #15212.
What is left on main
packages/objectql/src/tenancy/platform-object-tenancy.ts: its header (:6-20) says the ledger "has not retired yet (D13)". One reader remains: the engine'sbypassTenantAuditisSystem mute inEngine.buildDriverOptions, which is diagnostics only.- The readers and exports:
engine.ts:225and:7543-7587;packages/objectql/src/index.ts:561-563(PLATFORM_OBJECT_TENANCY,isPlatformObjectOutOfTenantAuditScope);packages/objectql/src/tenancy/system-write-organization.ts;- the census tooling
scripts/platform-object-tenancy-census.*.
- Docblocks that cite the ledger:
plugin-approvals/src/approval-service.tsandplugin-sharing/src/business-unit-graph.ts. - The
[tenant-audit]warning (packages/drivers/driver-sql/src/sql-driver.ts:16011) still tells an admin write to "Pass tenantId". This is the 8c-1 carrier.
Wanted
- Remove the ledger and its exports.
- Make the audit mute structural: a platform object with no tenant column is out of the audit's scope by its schema, not by a per-table list.
- Rewrite the warning to name the actual remedy.
- Remove the census tooling, or keep it with a stated reader.
Clause-②: the dev measures it from the diff. Removing published exports from@objectstack/objectqlis a narrowing unless nothing outside the package imports them; measure that.
Acceptance
git grep PLATFORM_OBJECT_TENANCYreturns nothing outside CHANGELOGs.- The audit mute is pinned by schema. Ablation: re-adding a per-table entry changes no write and no pin.
- R1–R4 hold, including the upgrade harness lane (
needs:upgrade-harness) and a walled boot.
Metadata
Metadata
Assignees
Labels
domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landpm:dispatchedpm:epicpriority:p1High: required for production / M2High: required for production / M2
Activity
objectstack-fleet commentedon Oct 22, 2026
Claim: epic seat round · 2026-10-22T11:37Z · owed scope of #15212, found by the reconciliation note 6339761793 (ADR-0131 D13; the seat's answer 6266091475, Q1 → A)
Session:
session_01Y5583bs2RDd53MH6kM1ca3Account:
os-steveBranch:
claude/issue-25201-retire-platform-object-tenancyWorktree: the cloud session's own checkout (
mode:cloud)Domain:
domain:engineSeat:
epic:#15194File surface:
packages/objectql/src/tenancy/platform-object-tenancy.ts(removed),tenancy/system-write-organization.ts,engine.ts(the ledger readers and thebypassTenantAuditmute inbuildDriverOptions), and the exports inpackages/objectql/src/index.ts.[tenant-audit]warning text inpackages/drivers/driver-sql/src/sql-driver.ts.plugin-approvals/src/approval-service.tsandplugin-sharing/src/business-unit-graph.ts, including chore: ADR-0131 small carriers — resolveDeclaredRuleScopes checks the raw page length, the semantic-entry and ceremony wording, and the help texts and docblocks that still say NULL organization means global #25203's item 4, which this PR takes.scripts/check-platform-object-tenancy-census.mjs,scripts/platform-object-tenancy-census.*and the two rootpackage.jsonscript entries. Keep the census check green, or repurpose it..changeset/*.md..github/workflows/**.lint.ymlruns the census check, and that is a governed path. If retiring the census needs the workflow step removed, report it: the seat cuts that as its own small Tier H PR, opened only when complete.ORGANIZATION_OWNERSHIP_SHAPE_GENERATIONchange, and no ceremony change.Container & model:
M,mode:cloud,model: TIER_DEFAULT. The review is at the tier the diff's declared face picks.Clause-②: no (narrowing) — expected: two published
@objectstack/objectqlexports are removed (PLATFORM_OBJECT_TENANCY,isPlatformObjectOutOfTenantAuditScope); the dev measures their importers and re-declares from the diffResponsibility: n/a — owed scope of feat(spec,drivers,objectql,plugin-security):
organization_idNOT NULL per cleared table; one predicate for Layer 0 and every driver; bothorWhereNullarms, the__global__sentinel and the #13491 ledger retire (ADR-0131 D1/D8/D9) — protocol 18 #15212 under ADR-0131 D13, not a defect cardThread-read: none
Serial constraints cleared: no open PR on the line touches these files. fix(service-settings): the tenant and user rungs stop reading organization-less sys_setting rows as every organization's fallback (ADR-0131 D8) — measure first #25202 (settings) runs in parallel and shares no file.
objectstack-fleet commentedon Oct 22, 2026
os-dev-report
{ "issue": 25201, "status": "done", "branch": "claude/issue-25201-retire-platform-object-tenancy", "pr": "https://github.com/objectstack-ai/objectstack/pull/25210", "session": "session_01DWpoqyLrN4CEQFhSjFddQ9", "premise_still_valid": true, "summary": "Retired the PLATFORM_OBJECT_TENANCY ledger (ADR-0131 D13). The file is deleted, and @objectstack/objectql exports none of its six names. Engine.buildDriverOptions now auto-mutes an elevated write's tenant-audit only when the object has no tenant column (resolveTenantFieldName(schema) === null) or is federated: the schema decides, never a name. SqlDriver's [tenant-audit] line names both readings (a write that lost its organization; a wall-exempt or system cross-organization write that needs no fix and declares bypassTenantAudit) instead of 'Pass tenantId'; its prefix and metadata are unchanged. The census is repurposed, not removed: it already executed the schema predicate, so its HEADER pointer moved to resolveTenantFieldName's docblock and lint.yml stays untouched and green. The docblocks in approval-service.ts and business-unit-graph.ts (and #25203 item 4) are rewritten to the post-ADR-0131 write paths. Measured first, at base 9c431bad: the mute was the only behavioural reader, and it was diagnostics only. The only importer outside the package is the unrun dated audit scripts/audits/14096-…mjs.", "tests": "tenancy-by-object-classification.test.ts: 28/28 pass. Ablation, re-adding a per-table exemption for sys_audit_entry in buildDriverOptions: exactly 2 failed (the two mute pins: 'sys_audit_entry … is NOT auto-muted' and 'the SAME driver options — the name decides nothing'), 26 passed, every write pin among them. So a per-table entry changes no write. sql-driver-tenant-audit-posture.test.ts: 12/12. Ablation, restoring base sql-driver.ts: 1 failed (the new text pin), 11 passed. Both restores were git checkout HEAD, with a clean tree after. Package test and typecheck all exit 0: objectql 8643, driver-sql 3749 (212 live-dialect skips), plugin-approvals 1213, plugin-sharing 1200, service-messaging 628, service-storage 1130. R1: pnpm dev -- --fresh gave health 200; the admin signs in (200) and reads showcase_account (200, 14 rows); 0 tenant-audit lines. R4: os serve with OS_TENANCY_POSTURE=isolated on a fresh SQLite file (OS_SECRET_KEY, OS_AUTH_MEMBERSHIP_POLICY=invite-only, OS_PLATFORM_OWNER_EMAIL; @objectstack/organizations declared and linked locally for the run, then reverted, tree clean) gave health 200 with no refusal; the owner signs up, signs in and reads sys_user, each 200. 43 [tenant-audit] lines across 22 objects, all in the new text; the platform objects newly audited are sys_activity, sys_business_unit, sys_member and sys_user_permission_set. Upgrade harness upgrade-18x-harness.dogfood.test.ts: 15/15, 8 on the 18.0 fixture and 7 on the fixture-18.0.0 leg.", "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 100 commands, each run with its exit code written to ran.list before any pipe. --ran: '100 derived famil(ies) accounted for — 99 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)'. Non-zero, both shallow-clone prerequisites: check-plugin-teardown-shape --self-test exit 3, and check-engine-split-ratio --days 90 exit 2 (refuses on a shallow clone). Census gate green in both modes (84/41/43). check-governed-merges --branch: NOT governed, +263/-501 over 14 files. CI on head aaa6ef6a: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (6/6 shards), Build Core success, Governed Surface Queue Guard success, Check Changeset success. 'Part-of PR must not also close its card' failed on the first body, which said 'closed #14570'; the body was reworded and the re-run is success.", "dogfood_battery": "aaa6ef6aa5ab · os-verify-lock: VERDICT command-exit 0 · Test Files 287 passed | 3 skipped (290) · Tests 2398 passed | 18 skipped (2416) · no failures", "mcp_calls": "16 — all reads: issue_read (get/get_comments on #25201, #15212, #25203, #24522), pull_request_read get_check_runs x3, get_job_logs x2, plus tool-schema loads; no write tool", "api_writes": "3 relay strokes (scripts/pm/with-fleet.sh --via dispatch): pr_create #25210 (draft, assignee os-steve), issue_patch #25210 body x2 (closing-keyword reword; proof). Each was read back byte-identical. This comment is the 4th. git push not counted.", "open_questions": [], "out_of_scope_findings": [ "class: none (residue, governed or dated) · reach: n/a · evidence: git grep PLATFORM_OBJECT_TENANCY outside CHANGELOGs still finds .claude/skills/pm-dispatch/references/platform-readings.md:403 (governed; it says D9 stamping only honours the ledger's tenant-scoped, now false), docs/adr/0131…:878 (governed; the D13 list itself), docs/audits/2026-09-tenancy-ledger-namespace-regexp-census.md (dated record) and scripts/audits/14096-tenancy-ledger-namespace-regexp-census.mjs (dated one-off; nothing runs it; it now refuses loudly at import, as its docblock prescribes) · carrier: the seat (the .claude row is a Tier S edit) · noted, not filed", "class: none (docs drift) · reach: n/a · evidence: packages/spec/src/automation/schedule-organization.zod.ts:76 and its generated content/docs/references/automation/schedule-organization.mdx still cite objectql/src/tenancy/platform-object-tenancy.ts and its sys_automation_run entry · carrier: #25203 (stale-text carriers) or none · dedupe words: schedule-organization platform-object-tenancy citation", "class: none (observation) · reach: n/a · evidence: on a walled boot SqlDriver.auditMissingTenant warns on creates whose row carries organization_id but whose options carry no tenantId. Under a wall an org-less system insert is refused (D9), so such a create is attributed and the line is noise. It was already true for app objects; it now also covers sys_activity, sys_business_unit, sys_member and sys_user_permission_set · carrier: 8c-1 design space (skip the insert audit when the row carries its tenant field) · noted in the PR body, not filed · dedupe words: tenant-audit create row organization_id noise" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
Landed · epic PM
session_01Y5583bs2RDd53MH6kM1ca3(os-steve) · 2026-10-22T13:40Z. PR #25210 merged intomainas3a440b01f6. It retires thePLATFORM_OBJECT_TENANCYledger under ADR-0131 D13 and closes this card.@objectstack/objectqlexports are gone.[tenant-audit]warning no longer tells a wall-exempt write to pass a tenantId.lint.ymlis untouched.CONTRACT_REVIEW_TIER, narrowing face, from an isolated reviewer: PASS 6341425088. Seat ACCEPT 6341442021. The opt-in upgrade-harness lane passed on the head..claude/skills/pm-dispatch/references/platform-readings.md:403, which this merge makes false.