Skip to content

docs(spec): tenancy-posture names @objectstack/organizations as open code, the licence as the commercial entitlement - #29239

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-66mu3h
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-66mu3h

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Fixes #28826

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:packages/spec/src/security/tenancy-posture.ts 里四处注释不再把 @objectstack/organizations 称为 "enterprise";指许可证的地方改称「商业授权(commercial entitlement)」。只改注释,外加一条 spec patch changeset。
  • 为什么改:ADR-0132 之后该运行时已在本仓以 Apache-2.0 开源,商业仓只是同名子类加上许可证门。旧注释会让读者和 AI 以为组织隔离或写入盖章是闭源代码。
  • 风险与回滚:零行为变化,没有 schema、类型或 .describe() 改动,生成的参考文档不动。回滚即 revert 本 PR。
  • 先看:packages/spec/src/security/tenancy-posture.ts(文件头 "Open code, entitled activation" 一节,以及 OrgScopingEntitlement 的说明)。
  • 两分钟验证:grep -n -i enterprise packages/spec/src/security/tenancy-posture.ts,预期无输出(main 上有 4 处)。
  • 需要你做的:无,席位落地。

What changes

Each of the four enterprise hits on main was read for whether it meant the package or the commercial licence:

  • File header, "Open code, entitled activation" (L27 on main): meant both. It now says that enabling group or isolated needs the @objectstack/organizations runtime mounted (ADR-0105 D12, ADR-0093 D5), that this runtime is open code from this repository under Apache-2.0 (ADR-0132 D1), and that what stays commercial is the entitlement: the licence gate that the same-named commercial package adds by subclassing the open one (ADR-0132 D2, D3). "Open code does not mean free activation" is kept: ADR-0105 D12 as amended by ADR-0132 still states the code-vs-activation split.
  • postureStampsOrganization docblock (L70): meant the package. Now "The @objectstack/organizations runtime (open code, ADR-0132 D1) fills an absent value too".
  • OrgScopingEntitlement docblock (L99): meant the commercial package. Now "the commercial package of the same name ... under its commercial entitlement", plus one sentence that the open package entitles both walled postures by construction (ADR-0132 D4).
  • Same docblock, per-deployment wall shaping (L114): meant any mounted runtime. Now "only a mounted org-scoping runtime may declare anything here, and on a commercial host that is the licence-gated one".
  • .changeset/28826-tenancy-posture-open-runtime-wording.md: @objectstack/spec patch, with the two declaration lines.

No .describe() in the file says "enterprise" (the file has none at all), so nothing generated moves. check:generated confirms it.

Tests

No forced test edits and no new tests: comment-only change. No ablation, because no tested behaviour changed.

Readings on e6a8c4d
  • pnpm --filter @objectstack/spec build: VERDICT command-exit 0.
  • pnpm --filter @objectstack/spec check:generated: VERDICT command-exit 0, "All 14 generated artifacts are up to date".
  • pnpm --filter @objectstack/spec test: VERDICT command-exit 0, Test Files 790 passed (790), Tests 23370 passed, 1 todo.
  • pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0.

Acceptance notes

  • Not changed, on purpose: the next header paragraph ("Cloud ADR-0016's 铁律 ... not by giving the posture away") does not say "enterprise", so it is outside this card. It predates ADR-0132, which reads the same iron rule as "a wall is enforcement". Noted here, not filed.
  • No consumer tests: the claim is Clause-②: no / Metadata-protocol: none, and the published surface is unchanged apart from comment text in the emitted declarations.

Verification

All readings on head e6a8c4d7 (objectstack-ai/objectstack).

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE: "73 derived famil(ies) accounted for — 73 run, 0 NOT-MEASURED (a DERIVED zero — all 73 recorded an exit code and none of them is 3)". Every one of the 73 exited 0.
  • Four of them first exited 3 (prerequisite not met, not a red): check-plugin-teardown-shape --self-test needed full history, and check:doc-formula-expressions, check:dual-build-cjs-loads, check:lean-entry-closure needed built packages. After git fetch --unshallow and pnpm build (VERDICT command-exit 0, 117/117 tasks) all four exited 0.
  • node scripts/check-changeset-no-major.mjs --base origin/main --event FILE with this body: exit 0, "LEVEL AXIS: this PR declares clause-② no and metadata-protocol none ... a non-protocol change at patch".
  • pnpm check:dev-prereqs (local-only family): exit 0.
  • Not run locally, left to CI: pnpm lint, the repo-wide scans, and consumer packages (none are owed for a comment-only Clause-②: no change).

Generated by Claude Code

…code, the licence as the commercial entitlement

The file header and the postureStampsOrganization / OrgScopingEntitlement
docblocks still called the Apache-2.0 runtime "enterprise" (ADR-0132 D1).
Name the package plainly and say "commercial entitlement" where the licence
gate of the same-named commercial package is meant (ADR-0132 D2, D3).
Comment-only; no behaviour change.

Claude-Session: https://claude.ai/code/session_01ADHkmRYknavAqEfbSsc1GG
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/spec/src/security/tenancy-posture.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/src/security/tenancy-posture.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 45e9b2f14c91f76683296cd33bb1b477cbaef1bb → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

Head-sha: e6a8c4d7c7efae8a0d384d0a2d20e1ae274372a9 · read 2026-11-02T10:29Z

维护者速读

席位意见:可落地(纯注释,不需契约复审)。

席位核对 — ACCEPT · domain:spec#1 · head e6a8c4d7

  1. Shape: draft, base main, Fixes #28826, Clause-②: no / Metadata-protocol: none at line start in the body and the changeset (spec patch). Two files, within claim 6573643827's surface. check-governed-merges: not governed.
  2. Diff: all four "enterprise" hits were read for package vs licence. The header and postureStampsOrganization name the package as open code (ADR-0132 D1); the commercial entitlement is the licence gate the same-named commercial package adds (D2, D3). OrgScopingEntitlement says the open package entitles both walled postures by construction. The seat checked that against ADR-0132 D4, whose heading reads exactly that. The wall-shaping paragraph says "a mounted org-scoping runtime". The file has no .describe(), so nothing generated moves.
  3. Readings (dev): spec 790 files / 23370 tests, typecheck and check:generated 14/14, all exit 0. dispatch-gates: 73 derived, all exit 0, 0 NOT MEASURED. Offline --event exit 0. Check-runs at this reading: 51 success, 9 skipped, 3 still running (Type Check UI, two Test Core shards), 0 failed.
  4. Noted, not filed: the header's "not by giving the posture away" paragraph predates ADR-0132 (the PR's acceptance notes). It's for the next touch of this file.
  5. Landing: comment only, so no CONTRACT_REVIEW_TIER review. The seat readies the PR and arms auto-merge now; the required checks gate the merge.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 2, 2026 10:30
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 2, 2026 10:30
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit 2c3574c Nov 2, 2026
65 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-66mu3h branch November 2, 2026 11:29
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: e6a8c4d7c7efae8a0d384d0a2d20e1ae274372a9
Local-runs: none
Scope: packages/spec/src/security/tenancy-posture.ts + docs/adr/0132-multi-organization-runtime-is-open-core.md (Context, D1–D4, D6), docs/adr/0093-tenancy-mode-and-membership-lifecycle.md (D5), docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md (D12 and its ADR-0132 amendment), packages/plugins/organizations/package.json (license), packages/plugins/organizations/src/index.ts (header), packages/plugins/organizations/src/organizations-plugin.ts (providesServices, supportedPostures, the no-gate constructor, Middleware A insert auto-stamp, registerService('org-scoping', this)), packages/plugins/plugin-auth/src/auth-plugin.ts (probeEntitledPostures), packages/plugins/plugin-auth/src/tenancy-service.ts (the entitlement read at the posture resolution), packages/plugins/plugin-auth/src/auth-manager.ts (effectiveTenancyPosture, the organization/create gate) and .changeset/28826-tenancy-posture-open-runtime-wording.md

Read-only round: the net diff against main at the merge base 104cd1a5 (2 files, +27 / −10, the same two files the PR's file list names), card #28826's body and all five comments, PR #29239's body and file list, and the check-runs on e6a8c4d7 (every required context success; the skipped rows are opt-in or path-filtered legs). The dispatching seat's ACCEPT record and landing note are not inputs. Every cited file was read at e6a8c4d7, never on the working tree.

① Derived judgments

  1. The net change is four docblock hunks and a changeset; no schema, type, export or .describe() moves — right. TenancyPostureSchema, TENANCY_POSTURES, the three predicates and OrgScopingEntitlement are byte-identical below the comments; the file carries no .describe() at all, so nothing under content/docs/references/** is owed. The TypeScript Type Check leg (home of check:generated and check:api-surface) is green on this head.
  2. Each of the four "enterprise" hits on main (L27, L70, L99, L114) was read for package vs licence and reworded accordingly — right. grep -i enterprise on the file at e6a8c4d7 answers nothing; the two that meant the package (header, postureStampsOrganization) now name it as open code with ADR-0132 D1; the one that meant the licence (OrgScopingEntitlement) now says "commercial package of the same name ... under its commercial entitlement"; the one that meant whichever runtime is mounted (wall shaping) now says "a mounted org-scoping runtime ... on a commercial host the licence-gated one".
  3. The ADR citations resolve to the decisions they are used for — right. ADR-0132 D1 (open core, packages/plugins/organizations, Apache-2.0: package.json "license": "Apache-2.0"), D2 (the entitlement alone stays commercial; the commercial class extends the open one and calls its gate in its own constructor), D3 (one name, two packages, the declaring manifest decides), D4 (the open package entitles both walled postures by construction: supportedPostures = ['group', 'isolated'] at organizations-plugin.ts L236). ADR-0105 D12 (activation probes the org-scoping runtime) and ADR-0093 D5 (a walled request with no working runtime refuses to boot) are the two the header cites for "requires the runtime to be mounted", and tenancy-service.ts L480 is the read that makes them one mechanism (probeIsolation plus probeEntitledPostures).
  4. "fills an absent value too, in its write middleware" holds. organizations-plugin.ts Middleware A ("auto-stamp organization_id on insert", L342) is registered on the ObjectQL engine at start(); the predicate's docblock already names the engine and the SQL driver as the other stampers, which PR docs(spec): postureStampsOrganization docblock names the open stampers #28823 established and this change keeps.
  5. "only a mounted org-scoping runtime may declare anything here, and on a commercial host that is the licence-gated one, which is what keeps the org-create gate intact" holds against the reader. auth-plugin.ts probeEntitledPostures reads getService('org-scoping')?.supportedPostures and nothing else; auth-manager.ts derives both the organization/create gate and features.multiOrgEnabled from effectiveTenancyPosture(), which the tenancy service resolves from that probe; on a commercial host the workspace:* declaration resolves the name to the gated subclass (ADR-0132 D3, restated in the open package's own header). A host that declared the set itself would walk the gate open, which is the paywall-bypass sentence the paragraph keeps.
  6. The claim's file surface held — right. No ADR and nothing under packages/plugins/organizations is edited (both named as out of surface in the claim); the dev cited them and left them alone.

② Semver level

.changeset/28826-tenancy-posture-open-runtime-wording.md declares '@objectstack/spec': patch with Clause-②: no and Metadata-protocol: none; the PR body carries the same two lines. The diff publishes changed comment text in the emitted declarations and nothing an author can write, so none is the kind and patch its level. Check Changeset and the PR-body guards are green on this head.

③ Boundary flags

Dev flags, from os-dev-report 6574517488 on the card (head e6a8c4d7) and the PR body:

  • Deviation: "license flag" respelled "licence" inside the reworded sentence. Acceptable: comment-only, and ADR-0132 and the open package's own docblocks spell it that way; the code identifiers (isMultiOrgLicenseError, MULTI_ORG_NOT_LICENSED) are untouched.
  • Deviation: a full pnpm build (~12 min) to satisfy check:dual-build-cjs-loads / check:lean-entry-closure locally. Dev-side cost only; both ride Lint & Repo Gates, green here.
  • Out-of-scope finding, "carrier: none · noted, not filed": the header's next paragraph ("Cloud ADR-0016's 铁律 ... REFUSING to run one unwalled (ADR-0093 D5), not by giving the posture away") predates ADR-0132. The dev's reading is right and the disposition is not: that paragraph now sits directly under a sentence saying the runtime is open code, and ADR-0132's own Context section reads the same iron rule as "a wall is enforcement" and ships the posture in open core, so "not by giving the posture away" is a sentence the next reader of this header meets as a contradiction, in a published @objectstack/spec docblock with a named location. Prime Directive chore: version packages #10 files a defect with a named location; "left for the next touch of the file" is a bury. Carried as ④ should-fix 2, to be filed as a domain:spec prose card rather than left in acceptance notes.
  • files_changed and line_budget match the net diff (2 files, 37 changed lines, no governed path). open_questions: [].

④ Design judgment

packages/spec/src/security/tenancy-posture.ts only, every sentence the change writes against ADR-0132 / ADR-0105 D12 / ADR-0093 D5 and the open package and tenancy reader they govern. No must-fix. Two should-fix items, neither of which changes the verdict.

  • Header, "Open code, entitled activation" (hunk 1) — the three new sentences hold (① items 3 and 5). should-fix 1 — the kept closing sentence, "open code does not mean free activation", is now under-qualified by its new neighbours. On main it followed "requires the enterprise runtime", where "not free" read as the licence. It now follows "That runtime is open code too ... ships from this repository under Apache-2.0", and on an open install activation IS free of any gate: constructing the open OrganizationsPlugin is enough to run multi-org (organizations-plugin.ts L243, "NO LICENCE GATE HERE, and none is to be added"; ADR-0132 D4, "an installation that has the package has the wall"). ADR-0105 D12's amendment carries the qualifier the header dropped: "enabling multi-organization operation is still an entitlement on the commercial side". The same unqualified slogan is repeated, unchanged, in the postureStampsOrganization docblock ("What does need that runtime is ACTIVATING a walled posture (ADR-0105 D12): open code does not mean free activation"). One clause in each place — "on a commercial host" or "where a gate is mounted" — makes both true for both editions. Should-fix because the governing ADR still prints the sentence verbatim, so the spec does not contradict a binding record; it is less precise than the ADR's own amendment.
  • postureStampsOrganization docblock (hunk 2) — holds (① item 4). The sentence names the stamper, the mechanism and the ADR, and keeps "not the only stamper", which the engine and driver call-outs above it carry.
  • OrgScopingEntitlement docblock, entitlement paragraph (hunk 3) — holds (① item 3, D4). "the commercial runtime owns it" is D4's own reservation ("the commercial runtime may still narrow what it entitles"); "the open package entitles both walled postures by construction" is L236. Tried to read "gate group and isolated independently" as a capability the open reader lacks: tenancy-service.ts L481 refuses any requested posture absent from supportedPostures, so a narrowed declaration from the subclass is honoured by the same read.
  • OrgScopingEntitlement docblock, wall-shaping paragraph (hunk 4) — holds (① item 5). Tried to break "only a mounted org-scoping runtime may declare anything here" with a host that registers its own org-scoping service: the reader would accept it, but that is the bypass the sentence names as forbidden, and it was equally reachable under the old "enterprise runtime" wording; the new wording is the more exact of the two because it names the service the reader actually probes.
  • should-fix 2 — the untouched 铁律 paragraph (header L35–38 at e6a8c4d7) now contradicts hunk 1. Carried from ③. Not written by this change, so not a FAIL here; it should be a card, not an acceptance note.

Implemented-by: claude/project-thread-66mu3h
Reviewed-by: session_01ADHkmPi25XXKx92Xmg4viS

VERDICT: PASS

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 tooling

Projects

None yet

1 participant