Skip to content

Commit 3d6f230

Browse files
docs(spec): tenancy-posture prose says which side of the open/commercial split gates activation (#29454)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9RGv5iq3ShhcQehne7GnJDs)_ Fixes #29318 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:只改 `tenancy-posture.ts` 的两段注释(文件头「开源代码与激活授权」一节、`postureStampsOrganization` 的说明),外加一个 spec patch changeset;无代码、无 schema、无生成物变化。 - 为什么改:原文「open code does not mean free activation」没说是哪一侧,读起来像开源安装也要许可证;按 ADR-0132,开源安装挂上 `@objectstack/organizations` 即可启用 group/isolated,只有商业侧子类才加许可证门。 - 风险与回滚:纯注释,零运行时风险;回滚即 revert 本 PR。 - 先看:`packages/spec/src/security/tenancy-posture.ts` 第 23–48 行(文件头一节)与 `postureStampsOrganization` 的说明块。 - 两分钟验证:`git diff origin/main -- packages/spec/src/security/tenancy-posture.ts`,预期只见注释行变化,且每句激活相关的话都写明是开源侧还是商业侧。 - 需要你做的:无,席位落地。 ## What changes - **Header section** (was "Open code, entitled activation", now "Open code; activation is entitled only on a commercial host"). It keeps the implementation-vs-entitlement separation and now says which side each sentence describes: - On an open install, activation is gate-free: the open runtime carries no licence check (ADR-0132 D2) and entitles both walled postures by construction (ADR-0132 D4), so mounting it is enough. Measured on `origin/main`: `packages/plugins/organizations/src/organizations-plugin.ts` declares `supportedPostures = ['group', 'isolated']` with the "NO LICENCE GATE HERE" note beside it. - On a commercial host, activation is entitled: the package of the same name subclasses the open one and answers its licence gate in its own constructor, and the host's manifest resolves the name to it (ADR-0132 D2, D3). "Open code does not mean free activation" is kept, scoped to that side, matching the ADR-0105 D12 amendment's "on the commercial side". - **Cloud ADR-0016 铁律 paragraph.** The guarantee no longer rests on "not giving the posture away". It now says the iron rule is satisfied by the wall itself on both sides: a multi-org shape never runs unwalled (ADR-0093 D5). Whether switching the posture on is free is the entitlement question, not the iron rule's. The Chinese quotation (强制免费、治理收费) is unchanged. - **`postureStampsOrganization` docblock.** "Open code does not mean free activation" is now scoped the same way: mounting the runtime is enough on an open install, and only a commercial host gates activation. - **Changeset** `.changeset/29318-tenancy-posture-activation-prose.md`: `@objectstack/spec` patch (the docblocks ship in the published `.d.ts`). No forced test edits. ## Tests Comment-only diff. `pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated`: all 14 generated artifacts up to date (the file has no `.describe()`, so nothing generated moves). Spec `typecheck` and `test` were run locally (readings under Verification). ## Acceptance notes - The `OrgScopingEntitlement` docblock further down already scopes its "packaging decision" sentence to the commercial runtime and names ADR-0132 D4 for the open package, so it is left as it is. ## Verification All readings at head `e82aa69a` (the only commit), in `objectstack-ai/objectstack`. <details><summary>Spec build, generated artifacts, typecheck, test</summary> - `pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated` under the verify lock: `VERDICT command-exit 0`, "All 14 generated artifacts are up to date". - `pnpm --filter @objectstack/spec typecheck`: exit 0. - `pnpm --filter @objectstack/spec test`: `VERDICT command-exit 0`, Test Files 791 passed (791), Tests 23469 passed, 1 todo. </details> <details><summary>Derived gates (dispatch-gates --commands, 73 families)</summary> - All 73 derived commands exit 0. Four first answered exit 3 (prerequisite not met, nothing measured): the teardown-shape self-test on the shallow clone, and `check:doc-formula-expressions`, `check:dual-build-cjs-loads`, `check:lean-entry-closure` on unbuilt packages. After fetching the self-test's control commit and `turbo run build --filter=./packages/**` (VERDICT command-exit 0), all four exit 0. - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE`: "73 derived, 73 run, 0 NOT-MEASURED, 0 UNRUN", exit 0. - `check-changeset-no-major.mjs --base origin/main --event FILE` on this body, offline: exit 0, level axis "clause-② `no` and metadata-protocol `none` ... a non-protocol change at `patch`". - Local-only `check:dev-prereqs`: its self-test passes; the scan exits 1 because 35 `ui/` workspace packages are not built in this container (an unmet local precondition, not a finding on this diff). NOT MEASURED for that half. </details> Dogfood: n/a, no `!` in the title and no (narrowing) arm. --- _Generated by [Claude Code](https://claude.ai/code/session_01ADHkmPErSzAW8P6oQg3W1k)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7eb0b19 commit 3d6f230

2 files changed

Lines changed: 36 additions & 14 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
docs(spec): the tenancy-posture docblocks say which side of the open/commercial split each activation sentence describes
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
Comment-only. The header of `@objectstack/spec`'s tenancy-posture module and the `postureStampsOrganization` docblock said "open code does not mean free activation" without saying where, which read as if a multi-organization posture were licence-gated everywhere. It is not: on an open install `@objectstack/organizations` ships under Apache-2.0 with no licence check and entitles both walled postures by construction (ADR-0132 D1, D2, D4), so mounting it is enough. Only on a commercial host, where the package of the same name subclasses the open one and adds its licence gate (ADR-0132 D2, D3), does activation need an entitlement. The cloud ADR-0016 iron-rule paragraph no longer says the guarantee comes from not "giving the posture away": the guarantee is that a multi-organization shape never runs unwalled (ADR-0093 D5), on either side of the split. No schema, type, export or runtime behaviour changes.

‎packages/spec/src/security/tenancy-posture.ts‎

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,32 @@
2020
* group-wide visibility and cross-org workflow are inherent to the shape, and
2121
* a hard per-org wall makes both an architecture problem.
2222
*
23-
* ## Open code, entitled activation
23+
* ## Open code; activation is entitled only on a commercial host
2424
*
2525
* The wall's IMPLEMENTATION is open — the Layer 0 compiler, `accessible_org_ids`
26-
* resolution and the D5 write stamping all ship in open packages — but ENABLING
26+
* resolution and the D5 write stamping all ship in open packages — and ENABLING
2727
* a multi-organization posture (`group` or `isolated`) requires the
2828
* `@objectstack/organizations` runtime to be mounted (ADR-0105 D12, ADR-0093 D5).
2929
* That runtime is open code too: it ships from this repository under Apache-2.0
30-
* (ADR-0132 D1). What stays commercial is the entitlement — the licence gate the
31-
* commercial package of the same name adds by subclassing the open one (ADR-0132
32-
* D2, D3). The two are separate questions and must not be conflated: open code
33-
* does not mean free activation.
34-
*
35-
* Cloud ADR-0016's 铁律 (强制免费、治理收费) is satisfied by the first half alone —
36-
* it guarantees that a deployment RUNNING a multi-org shape is safe, which the
37-
* platform delivers by REFUSING to run one unwalled (ADR-0093 D5), not by giving
38-
* the posture away. You never silently get an unenforced organization boundary.
30+
* (ADR-0132 D1). Implementation and entitlement are separate questions and must
31+
* not be conflated, and which side of the split a deployment sits on answers
32+
* the second one:
33+
*
34+
* - On an OPEN install, activation is gate-free. The open runtime carries no
35+
* licence check of any kind (ADR-0132 D2) and entitles both walled postures
36+
* by construction (ADR-0132 D4): mounting it is enough.
37+
* - On a COMMERCIAL host, activation is entitled. The commercial package of the
38+
* same name subclasses the open one and answers its licence gate in its own
39+
* constructor, and the host's manifest resolves the name to that package
40+
* (ADR-0132 D2, D3); it may also narrow which walled postures it entitles.
41+
* There, and only there, open code does not mean free activation.
42+
*
43+
* Cloud ADR-0016's 铁律 (强制免费、治理收费) is satisfied by the wall itself, on
44+
* both sides of the split — it guarantees that a deployment RUNNING a multi-org
45+
* shape is safe, which the platform delivers by REFUSING to run one unwalled
46+
* (ADR-0093 D5). Whether switching the posture on is free is the entitlement
47+
* question above, not the iron rule's. You never silently get an unenforced
48+
* organization boundary.
3949
*/
4050

4151
import { z } from 'zod';
@@ -75,9 +85,11 @@ export function postureEnforcesWall(posture: TenancyPosture): boolean {
7585
* runtime (open code, ADR-0132 D1) fills an absent value too, in its write
7686
* middleware, but it is not the only stamper.
7787
*
78-
* What does need that runtime is ACTIVATING a walled posture (ADR-0105 D12):
79-
* open code does not mean free activation. This predicate is the shared
80-
* vocabulary for the stamping rule, whichever package does the stamping.
88+
* What does need that runtime is ACTIVATING a walled posture (ADR-0105 D12).
89+
* On an open install mounting it is enough (ADR-0132 D4); only on a commercial
90+
* host is that activation licence-gated (ADR-0132 D2), and there open code does
91+
* not mean free activation. This predicate is the shared vocabulary for the
92+
* stamping rule, whichever package does the stamping.
8193
*/
8294
export function postureStampsOrganization(posture: TenancyPosture): boolean {
8395
return postureEnforcesWall(posture);

0 commit comments

Comments
 (0)