Skip to content

test(plugin-security,plugin-auth,plugin-approvals): narrow the blanket pre-18 tenant-column relax rigs to the residue tables they model, and correct the last "stays NULL on single-tenant" comments #25128

Closed

Description

@objectstack-fleet

Filing gate ③: this follow-up comes out of 7b-0 (#24940, merged as 5e9b100743). It covers B6 of the seat's contract review 6317931247, and C1 of its delta check 6319612676. Neither blocked the landing.

  • Who acts: the plugin-security lane, with plugin-auth and plugin-approvals for their own rigs, plus spec / objectql for the comments.
  • Dedupe: none found for "relaxEveryRegisteredTenantColumn narrow" or "stays NULL on single-tenant comment".

B6: narrow the blanket relax rigs

Since 7b-0, a table the driver creates has a NOT NULL tenant column. Tests that model a pre-18 store (where the column was nullable) relax it through the pre-18 testkits. About 42 rigs in plugin-security, plugin-auth and plugin-approvals use the blanket form, relaxEveryRegisteredTenantColumn or relaxEveryTenantColumn. A named list of the tables that actually hold the organization-less residue would do the job: sys_permission_set, sys_position, sys_user_permission_set and the holdings.

Each rig is a legitimate pre-18 model, and no assertion is weakened by it. But the blanket form also relaxes tables that hold no residue. So an unstamped production write inside such a rig lands, where it should fail. The rig loses the power to catch exactly the bug 7b-0 exists to refuse.

Fix: replace each blanket call with relaxTenantColumns(engine, [the tables the test seeds organization-less]), and keep the one-line justification comment. Spot-check a rig by removing its relax: only the named tables' seeds should fail.

C1: three more stale comments

These comments still say the tenant column stays NULL on single-tenant stacks. B8 corrected the two it named.

  • packages/objectql/src/registry.ts:777
  • packages/spec/src/data/object.zod.ts:2499-2501. A spec docblock: re-run check:generated after the edit.
  • packages/objectql/src/registry-tenant-index-declaration.test.ts:151-152

Text only. No behavior change.

Activity

  1. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 27 (p3 only, by the maintainer's order 「你后续只处理 p3」) · 2026-10-21T18:04Z · p3, domain:engine (triage's grade), filed from 7b-0's contract review 6317931247 and delta check 6319612676 (#24940, merged as 5e9b100743). Split first: item B6 (narrow the blanket pre-18 relax rigs) is entirely in domain:services packages (plugin-security 27 test files, plugin-auth 11, plugin-approvals 2, measured on origin/main 4e2c42f363). Under the execution rule that a queued card carrying another lane's item is split by the seat that finds it, B6 moved to #25132, which carries no domain:* label for triage to route. This card keeps item C1, and this claim takes C1 only.
    Session: session_01JtSQQ3EWsbNPzyYMug1tXy (the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)
    Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-25128-tenant-column-never-null-comments
    Worktree: objectstack-issue-25128
    Domain: domain:engine
    Seat: domain:engine#1 (seat post #6367)
    File surface:

    • packages/objectql/src/registry.ts: the comment at the organization_id index gate (the census found :777, "it just stays NULL"). Comment only.
    • packages/objectql/src/registry-tenant-index-declaration.test.ts: the comment above expect(def.fields.organization_id).toBeDefined() (:151–:152). Comment only; no assertion moves.
    • packages/spec/src/data/object.zod.ts: the systemFields docblock's organization_id bullet (:2498–:2501, "It stays NULL on single-tenant stacks"). A docblock, not a .describe() string. Whatever the repo's generators emit from it is regenerated with their own tooling, and check:generated is re-run.
    • The wording: the one 7b-0 already used for the sites it corrected, in registry.ts's applySystemFields docblock and system-names.ts's ORGANIZATION_ID: org-scoping stamps it on insert (under single with the Default Organization), and it is never NULL (ADR-0131 D1). The dev confirms that is what main does before writing it.
    • The census: a repo-wide read for "stays NULL" / "NULL on single-tenant" on 4e2c42f363 finds only these three tenant-column sites; the other hits are unrelated (nullable booleans, CHANGELOG history).
    • The changeset: only if the Check Changeset gate asks for one on a comment-only change; then patch for the two packages touched.

    ⛔ Not in scope:

    Container & model: S, mode:cloud (three comment edits and a generator re-run), model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate"; it flags object.zod.ts as a clause-② suspect surface, but the edit is a docblock that widens or narrows no accept set)
    Clause-②: no (comment and docblock text only: no accept set, response, status, error, outcome or export moves)
    Responsibility: a contributor reading objectql's registry, its tenant-index test or the spec's systemFields docblock | three comments still say the tenant column stays NULL on single-tenant stacks, after 7b-0 made it NOT NULL and stamped | every reader of those comments, and any generated reference that carries the spec docblock
    Thread-read: none
    Serial constraints cleared: the 9 open PRs' file lists and the pm:dispatched claims were read at this claim, on origin/main 4e2c42f363. None touches the three files. Cross-lane: packages/spec/src/data/object.zod.ts is domain:spec's file; the seat declares it to the spec seat before the queue.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T18:06Z: mode:cloud. The dev session is session_01Xwr1aPkHuFRqE9RSahyogV. It builds at the default tier on branch claude/issue-25128-tenant-column-never-null-comments, under claim 6323015024 (item C1 only; B6 is #25132).

    • Read first:
      • what main does with the tenant column on a single-tenant stack: the Default Organization stamp on insert, and 7b-0's NOT NULL;
      • whether anything is generated from the spec systemFields docblock;
      • a repo-wide census for "stays NULL" / "NULL on single-tenant".
    • What lands:
      • the three comments say the column is stamped on insert and never NULL (ADR-0131 D1), in the wording 7b-0 already used, with the multi-tenant INDEX gate kept;
      • any generated output regenerated with the repo's tooling, and check:generated re-run;
      • the Clause-②: and Metadata-protocol: none lines on the PR body, and a changeset only if the gate asks.
    • Fork, not widening: if main does not do what the wording says, the dev reports needs_decision instead.
    • Cross-lane: packages/spec/src/data/object.zod.ts is domain:spec's; the seat declares it before the queue.
    • Not built: B6 (test(plugin-security,plugin-auth,plugin-approvals): narrow the blanket pre-18 tenant-column relax rigs to the residue tables they model #25132), any code, assertion, .describe() text or CHANGELOG.
    • Owed: the seat's review of record before the queue.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 25128,
     "status": "done",
     "branch": "claude/issue-25128-tenant-column-never-null-comments",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/25135",
     "session": "session_01Xwr1aPkHuFRqE9RSahyogV",
     "premise_still_valid": true,
     "summary": "Item C1 only; B6 is #25132 and is not addressed here. Three comments that said organization_id stays NULL on single-tenant stacks now use 7b-0's wording: org-scoping stamps it on insert (under `single` with the Default Organization), and it is never NULL (ADR-0131 D1). Each keeps the rest of its content, including the index gate on multi-tenant mode. The sites are objectql registry.ts (the applySystemFields organization_id gate comment), registry-tenant-index-declaration.test.ts (the comment above the organization_id toBeDefined assertion) and spec object.zod.ts (the systemFields docblock bullet, which keeps its multi-tenant attribution to @objectstack/organizations). What main does, read before any edit: NOT NULL comes from driver-sql createColumn's tenantColumn argument on the CREATE TABLE sites (initObjects, ensureShardTable) and from driver-turso buildCreateTableSQL. The single-posture stamp is ObjectQL.resolveSystemInsertOrganization calling core resolveSystemWriteOrganization, which answers derived for exactly one organization under single (the Default Organization). That id is threaded as DriverOptions.tenantId, and the driver stamps it. Generator: nothing committed is generated from the docblock. build-docs renders json-schema (built from .describe()) plus module file headers, never property docblocks. After the spec build git status is clean, and check:generated reports 14/14 up to date. Census over packages/objectql and packages/spec found only the three sites; one stale sentence outside the fence, content/docs/protocol/objectql/schema.mdx 'Multi-Tenant Schemas', is named and not edited. A patch changeset for @objectstack/spec was added because spec's files[] ships src/**/*.zod.ts and dist, both of which carry the docblock. objectql's shipped dist carries no comment text: it holds applySystemFields as a positive control and none of the comment.",
     "tests": "Head ca06c671d (includes the merge of origin/main 1b3b65e64). pnpm exec turbo run build --concurrency=2 under the lock: Tasks 77 successful, 77 total; VERDICT command-exit 0. pnpm --filter @objectstack/objectql typecheck: exit 0 (tsc and check:test-typecheck OK). pnpm --filter @objectstack/spec typecheck: exit 0 (tsc, scripts-typecheck and check:test-typecheck OK). pnpm --filter @objectstack/objectql exec vitest run --maxWorkers=2 src/registry-tenant-index-declaration.test.ts: Test Files 1 passed (1), Tests 12 passed (12). The same three also passed before the merge, on d4311e1ac. pnpm --filter @objectstack/spec check:generated: exit 0, 'All 14 generated artifacts are up to date', no tracked change after the build. No ablation, because no tested behaviour changes (comment-only).",
     "gates": "Local subset on head ca06c671d: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, with no paths, derived 94 commands. All 94 were run, each exit code captured before any pipe, and all 94 exited 0. Reconciled with node scripts/pm/dispatch-gates.mjs --ran ran.txt --repo objectstack-ai/objectstack, exit 0: '94 derived famil(ies) accounted for — 94 run, 0 NOT-MEASURED (a DERIVED zero — all 94 recorded an exit code and none of them is 3)'. On the pre-merge head 3c3a5759b the same 94 ran: 93 exited 0, and pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET, no dist/). It was built for (full turbo build) and re-run, exit 0. The history was deepened with git fetch --shallow-since=2026-07-13 before the derivation; check-engine-split-ratio --days 90 and check-plugin-teardown-shape --self-test both exited 0. CI families (PR #25135 check-runs): in_progress at report time, not waited on per os-dev; NOT MEASURED locally: the path-scheduled CI jobs (Test Core shards, Build Core), the type-check lanes, test:repo and the artifact-roster/wide-population families, which are CI's.",
     "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm (Clause-②: no)",
     "mcp_calls": "0 — no MCP GitHub tool used; reads went through gh api over the proxy",
     "api_writes": "2 relay strokes (fleet-write dispatch, POST /repos/objectstack-ai/objectstack/dispatches each): (1) pr_create, executed as POST /repos/objectstack-ai/objectstack/pulls (draft) plus POST /repos/objectstack-ai/objectstack/issues/25135/assignees [os-project-manager], read back 6184/6184 bytes identical; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/25128/comments. git push (not REST) to the own branch 4 times: the empty branch, the comment commit d4311e1ac, the changeset commit 3c3a5759b and the merge ca06c671d.",
     "line_budget": "none set. Diff vs origin/main: packages/objectql/src/registry.ts +3/-2; packages/objectql/src/registry-tenant-index-declaration.test.ts +2/-1; packages/spec/src/data/object.zod.ts +4/-3; .changeset/25128-tenant-column-never-null-comments.md +10/-0 (dispatch-gates counts 25 changed lines, +19/-6, 4 files)",
     "files_changed": [
      "packages/objectql/src/registry.ts",
      "packages/objectql/src/registry-tenant-index-declaration.test.ts",
      "packages/spec/src/data/object.zod.ts (domain:spec's file; the seat declares it)",
      ".changeset/25128-tenant-column-never-null-comments.md"
     ],
     "deviations": [
      "A changeset was added, outside the claim's file surface. The Check Changeset gate requires a changeset or the skip-changeset label, and skip-changeset is not legitimate: @objectstack/spec ships src/**/*.zod.ts and dist, and both carry the edited docblock. It is patch for @objectstack/spec only, not for objectql. objectql's files[] is dist only, and its built dist carries none of the comment text (positive control: applySystemFields hits), so a release there would ship no change.",
      "The object.zod.ts bullet keeps its multi-tenant attribution ('@objectstack/organizations, the org-scoping service, in multi-tenant mode'), joined to 7b-0's single-tenant wording rather than replaced by it, to keep the comment's other content.",
      "The PR body opens with the C1/B6 lines and puts 'Fixes #25128' on its third line; the dispatch asked for the C1/B6 lines first, and os-dev's DoD asks for Fixes on the first line. The dispatch's ordering was followed.",
      "Commits carry the AGENTS.md model-free trailer pair (Claude-Session plus 'Co-authored-by: Claude'), not the harness's model-named Co-Authored-By trailer; AGENTS.md and the pre-push hook take precedence."
     ],
     "open_questions": [
      {
       "question": "Should the changeset also list @objectstack/objectql?",
       "options": [
        "A: spec only (as shipped): objectql publishes no changed bytes",
        "B: also list objectql as patch"
       ],
       "recommendation": "A. On the axes: business need, objectql's tarball does not move, so a release would ship nothing; long-term, a changeset should name what ships; AI-error, a changeset naming an unchanged package teaches that touching equals publishing; startup focus, no extra release noise."
      }
     ],
     "out_of_scope_findings": [
      "content/docs/protocol/objectql/schema.mdx, section 'Multi-Tenant Schemas', still says the injected organization_id 'stays NULL where no organization context exists'. This is doc drift in a hand-written page outside the fence: not a filing class (none of a/b/c) and not filed; noted in the PR's Acceptance notes. carrier: none (承接者:无). Dedupe words: stays NULL schema.mdx, multi-tenant schemas organization_id NULL, tenant column docs stale."
     ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 21, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T20:47Z

    Probe Reading
    Review TIER_DEFAULT. Record 6324719576 PASS on ca06c671d4. ACCEPT 6325466290. Not governed.
    Queue It entered the merge queue at 2026-10-21T20:12Z and left it merged at 2026-10-21T20:45Z. No gh-readonly-queue/main/pr-25135-* branch remains.
    origin/main 863c580224 is on origin/main, one squash commit carrying PR #25135's 4 files, +19 / −6.
    Card Closed completed through Fixes #25128; pm:dispatched is cleared.

    What main now holds (item C1):

    • Three comments no longer say the tenant column stays NULL on single-tenant stacks. In objectql's registry.ts (applySystemFields' organization_id gate), objectql's registry-tenant-index-declaration.test.ts, and spec's systemFields docblock in object.zod.ts, each now says what main does since 7b-0: org-scoping stamps the column on insert (under single with the Default Organization), and it is never NULL (ADR-0131 D1).
    • Unchanged: the column is provisioned unconditionally, and only its index is gated on multi-tenant mode. No code, assertion, .describe() text or CHANGELOG line moved.
    • Shipped as: patch of @objectstack/spec, Clause-②: no (comment and docblock text only: …), Metadata-protocol: none.

    Beside it:

    The dev session session_01Xwr1aPkHuFRqE9RSahyogV is archived.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions