Skip to content

docs(objectql): Multi-Tenant Schemas says the injected organization_id is stamped on insert and NOT NULL on a table the driver creates - #25322

Queued
objectstack-fleet[bot] wants to merge 1 commit into
mainfrom
claude/project-thread-c1stko
Queued

objectstack-fleet[bot] wants to merge 1 commit into
mainfrom
claude/project-thread-c1stko

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread

Fixes #25137

Clause-②: no
Metadata-protocol: none

What changed

One file, docs only: content/docs/protocol/objectql/schema.mdx, section "Multi-Tenant Schemas" (+19 / -3).

  • The parenthetical that said the injected organization_id "is server-populated on insert and stays NULL where no organization context exists" now says the platform stamps it on insert, so the author never writes it.
  • A new paragraph after the first YAML example says what main does, each claim with its source:
    • required: false is the authoring surface, not the stored value; NULL is not an organization (ADR-0131 D1).
    • An insert is stamped with the writer's organization, under single with the Default Organization, and a write that names none is refused wherever an organization can exist (ADR-0131 D9).
    • A table the SQL or Turso driver creates carries the column NOT NULL at CREATE TABLE, so the database refuses a row with no organization, an upsert included (ADR-0131 D1's driver note, and the tenant-column-not-null-ddl changeset of @objectstack/driver-sql / @objectstack/driver-turso). The in-memory driver enforces no NOT NULL (the same D1 note).
    • A table that already existed keeps a nullable column until os migrate organization-ownership tightens it; the ceremony cannot tighten a rotated shard or a Turso remote table; os migrate plan lists every tenant column still nullable (the changeset's "Unchanged" bullet; ADR-0131 D1 and its 2026-10-22 amendment, item 2). Both are linked to their deployment/cli sections.
    • An object whose rows belong to no organization opts out and has no column (the changeset's remedy; ADR-0131 D1). The opt-out paragraph that already follows is unchanged.

D1's wording, measured before citing it. The card and the changeset both quote D1 as "There is no nullable tenant column anywhere". That sentence is no longer D1: the 2026-10-22 amendment (ruling of record 6328195425) replaced it with a paragraph that says where the column is NOT NULL and which nullable columns remain. So the page cites D1 for what the amended text says (NOT NULL at the engine and at every table the driver creates; NULL is not a state), and does not quote the retired sentence.

Per-hit verdicts (the other pages)

Rule applied: a sentence that describes a database from before the ownership ceremony, or history, stays; only a sentence that claims today's behaviour and is wrong changes. None changed.

Page:line (origin/main 9dc1f42d5) What it says Verdict
deployment/seed-tenancy-repair.mdx:18 the repair stamps business rows that carry NULL stays: the repair acts on rows an existing database already holds
deployment/seed-tenancy-repair.mdx:33 seed rows "land with organization_id = NULL" on a first boot stays: it is in "The defect it repairs", which states it as measured on 17.0.0 GA (:47). See Acceptance notes on its tense
deployment/seed-tenancy-repair.mdx:162 the repair's WHERE organization_id IS NULL stays: the repair's SQL over pre-ceremony rows
deployment/seed-tenancy-repair.mdx:179 colliding rows keep organization_id = NULL stays: what the repair leaves on such a database
deployment/seed-tenancy-repair.mdx:295 NULL is the marker the report reads stays: the ordering rule for a database that holds such rows
deployment/seed-tenancy-repair.mdx:304 colliding rows keep NULL and stay findable stays: same
deployment/seed-tenancy-repair.mdx:344 the manual remedy's WHERE organization_id IS NULL stays: the manual remedy for such a database
deployment/cli.mdx:1904 a seeded row written before any organization existed carries NULL stays: history ("predates the repair"); os migrate duplicates inventories it
deployment/cli.mdx:1934 the repair leaves colliding rows NULL stays: same as seed-tenancy-repair.mdx:304
permissions/permission-sets.mdx:193 an organization-less grant row "an earlier release's promotion wrote" anchors nothing stays: history, and still true of such a row

cli.mdx is not edited, so this PR has no hunk beside draft PR #25212's (its one cli.mdx hunk is at @@ -756).

The PM's readings, measured

Gates

Head 2f9543d: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 41 commands (29 pnpm, 12 direct node) for the one changed path. Each was run with its exit code captured before any pipe and recorded as COMMAND :: exit CODE; --ran reconciles 41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUN. All 41 exit 0. One needed a second run: pnpm --filter @objectstack/spec run check:skill-examples first exited 3 (PREREQUISITE NOT MET: packages/client-react/dist held no declarations in a fresh worktree); after pnpm --filter '@objectstack/client-react...' build it exits 0 (262 prose examples type-check across 3 surfaces). check:doc-anchors resolves all 573 internal fragment links, the two new ones included. Before the gates, @objectstack/lint... and @objectstack/spec were built under the verify lock (VERDICT command-exit 0).

Not measured locally, CI's: the Build Docs and Test Core jobs, the type-check lanes, and the wide-population families the derivation names. No package source moves, so no test or ablation applies.

No published file moves (content/docs/** is in no package's files[]), so this carries skip-changeset and no changeset.

Acceptance notes

  • seed-tenancy-repair.mdx describes its defect in the present tense (:30-34, and :72 "At kernel:ready on a fresh install no organization exists yet"). On main the single posture creates the Default Organization at boot, before seeds load, and the seed loader refuses an organization-less row on an install that registers the organization object (packages/metadata-protocol/src/seed-loader.ts, the unowned branch). The section is anchored to 17.0.0 GA, so this PR leaves it; a reader on 18.x may still take it for today's behaviour. Carrier: none.
  • The page cites the changeset by its name, not its path: a release consumes .changeset/*.md, and the sentence then lives in the two drivers' CHANGELOG.md. ADR-0131 D1's driver note carries the same fact durably.
  • The attribution block's first line is an HTML comment the session requires as the body's first line; os-dev.md forbids HTML comments in GitHub text. It is the same shape PR docs(pm-dispatch): a project-coordinator reference — the cross-lane scheduling rules a Claude Code project runs by, so its instructions name only its lanes #25255 carried through the relay; reported as a deviation.
  • The branch is the harness-pinned claude/project-thread-c1stko, which names no issue; the claim (comment 6354581569) records it as the identity.

Generated by Claude Code

… NOT NULL on a table the driver creates

"Multi-Tenant Schemas" said the column stays NULL where no organization
context exists. Since the driver creates a tenant column NOT NULL, a
table it creates refuses that write. Say what main does: the stamp
(ADR-0131 D9), the NOT NULL at CREATE TABLE (ADR-0131 D1 and the
tenant-column-not-null-ddl changeset), the tables that stay nullable
until the ownership ceremony, and the opt-out for organization-less rows.

Claude-Session: https://claude.ai/code/session_01Er1tmLgRYyGBSrDcDsUMqQ
Co-authored-by: Claude <noreply@anthropic.com>

This branch has not been deployed

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

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants