Skip to content

docs(spec): postureStampsOrganization docblock names the open stampers - #28823

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

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

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Fixes #28761

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:只改 packages/spec/src/security/tenancy-posture.ts 中 postureStampsOrganization 上方的注释,外加一条 @objectstack/spec patch changeset;不改任何代码。
  • 为什么改:旧注释说"打 organization_id 的是企业版 organizations 运行时,不是开源引擎",与代码相反:开源引擎在写入时把记录落到当前组织,SQL 驱动补上缺省的 organization_id。保留真实的一半:启用多组织姿态仍需企业版运行时。
  • 风险与回滚:零运行时风险(仅注释,随 dist 的 .d.ts 发布);回滚即 revert 本 PR。
  • 先看:packages/spec/src/security/tenancy-posture.ts 的 postureStampsOrganization 文档块。
  • 两分钟验证:git diff origin/main...HEAD -- packages/spec/src/security/tenancy-posture.ts,预期只见注释行变动、无一行代码变化。
  • 需要你做的:无,席位落地。

What changes

Comments only, plus a patch changeset for @objectstack/spec (the JSDoc ships in the built declaration chunk, so the published bytes change).

The postureStampsOrganization docblock said "The STAMPER, however, is the enterprise @objectstack/organizations runtime, not the open engine … the open engine only VALIDATES supplied values". It now says:

Tests

No behaviour changes, so no test was added or changed.

Local runs at head 021a3cf
  • pnpm --filter @objectstack/spec build (under os-verify-lock): 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 typecheck: VERDICT command-exit 0.
  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2: Test Files 875 passed (875), Tests 24715 passed | 1 todo (24716), VERDICT command-exit 0.
  • Published-surface check after the build: the new docblock (with "but it is not the only stamper") is in packages/spec/dist/queue.zod-IH5GXQGp.d.ts / .d.mts, directly above declare function postureStampsOrganization; "not the open engine" has 0 matches in dist/security/index.d.ts. files includes dist.

Acceptance notes

  • Where the JSDoc ships. The card and triage said dist/security/index.d.ts. After the build the declaration lives in a shared chunk (dist/queue.zod-IH5GXQGp.d.ts) that the security entry re-exports. It still ships, so the changeset level (patch) holds.
  • No consumers. postureStampsOrganization has no caller in this repo (grep at 1617b7f); only api-surface/security.json and export-origins/security.json name it, and those record names only, so they did not move.

Verification

Derived gate families (dispatch-gates --commands, head 021a3cf)
  • 73 derived families. 72 exited 0 (three after clearing their prerequisites: --unshallow for check-plugin-teardown-shape --self-test, an objectql + lint closure build for check:lean-entry-closure and check:doc-formula-expressions).
  • 1 is NOT MEASURED: pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET, needs a full pnpm build). CI runs it.
  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE: "73 derived famil(ies) accounted for — 72 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)", exit 0.

🤖 Generated with Claude Code


Generated by Claude Code

The docblock said the stamper is the enterprise organizations runtime,
not the open engine. The engine lands an insert in the active
organization (ObjectQL#driverWriteTarget) and the SQL driver fills an
absent organization_id (SqlDriver#injectTenantOnInsert). Keep the true
half: activating a walled posture needs the enterprise runtime
(ADR-0105 D12). Comment only.

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

github-actions Bot commented Nov 1, 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 663b7c08eedd61a3a492a425ced0dbbd57676415 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

Head-sha: 021a3cf90592328cd987d5b17e2f02eb7dec6a28 · read 2026-11-01T21:51Z

维护者速读

  • 改了什么:只改 postureStampsOrganization 上方的注释,外加一条 spec patch changeset,不改代码。
  • 为什么改:旧注释说给记录打 organization_id 的只有企业版运行时,开源引擎不打,这与代码相反:开源引擎把插入落到当前组织,SQL 驱动补上缺省值。
  • 风险与回滚:只是注释,没有运行行为变化。回滚即撤销本 PR。
  • 先看:packages/spec/src/security/tenancy-posture.ts 中 postureStampsOrganization 的注释。
  • 两分钟验证:读新注释,对照 packages/objectql/src/engine.ts 的 driverWriteTarget 和 packages/drivers/driver-sql/src/sql-driver.ts 的 injectTenantOnInsert。
  • 需要你做的:无。这个文件在 packages/spec/src 下,按规矩要过一次契约复审档复核,已交分诊;PASS 且 CI 全绿后席位落地。

席位意见:可落地,等契约复审。新注释点名的两个开源写入点在 main 上都存在,并保留了「启用多组织姿态需要企业版运行时」这一半真话。

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

  1. Shape: draft, base main, first line Fixes #28761, no other closing keyword. 2 files (+24/-7): the docblock in packages/spec/src/security/tenancy-posture.ts and .changeset/28761-posture-stamps-organization-docblock.md (@objectstack/spec patch, Clause-②: no, Metadata-protocol: none). Comment only: the function body is unchanged. Not governed.
  2. Premise, measured on origin/main: ObjectQL#driverWriteTarget exists (packages/objectql/src/engine.ts, docblock: "the active organization, in every posture"); SqlDriver#injectTenantOnInsert exists and runs on insert, upsert and bulk insert (packages/drivers/driver-sql/src/sql-driver.ts). The old sentence ("The STAMPER, however, is the enterprise @objectstack/organizations runtime, not the open engine") is gone, and the true half (activation needs that runtime, ADR-0105 D12) is kept.
  3. Gate check-runs (pinned to head 021a3cf9): at reading 11 success, 8 skipped, 22 running, 0 failed. Landing needs every check green or an expected skip. Dev's local readings: spec build, check:generated and typecheck exit 0; spec vitest 875/875 files; dispatch-gates 72/73 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads, needs a full build; CI runs it).
  4. Accepted deviations: the JSDoc ships in a shared dist chunk rather than dist/security/index.d.ts; it still ships, so the patch changeset stands. The changeset sentence was read against the diff and matches it.
  5. Out of scope: none. The new docblock's claims about @objectstack/plugin-security (an explicit value held to the Layer 0 verdict) and the organizations runtime's write middleware are left to the contract review to read against code.
  6. Landing: packages/spec/src/** non-test is a contract-review face, so one CONTRACT_REVIEW_TIER review is owed on this head; handed to triage (line below). After a PASS and all checks green, the seat readies and queues it through the relay. A head move voids this record.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (maintainer standing word 2026-10-28T15:04Z: the Fable quota is short, so contract reviews wait for triage) · head 021a3cf

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 021a3cf90592328cd987d5b17e2f02eb7dec6a28 · 2026-11-01T21:53Z

Taken under references/contract-review.md (a): the hand-off line in 6564403548 names this head. Face schema (a docblock in packages/spec/src), at CONTRACT_REVIEW_TIER.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 021a3cf90592328cd987d5b17e2f02eb7dec6a28
Local-runs: none
Scope: packages/spec/src/security/tenancy-posture.ts + packages/objectql/src/engine.ts, packages/objectql/src/engine-driver-options.ts, packages/drivers/driver-sql/src/sql-driver.ts, packages/plugins/plugin-security/src/security-plugin-write-tenant-wall.ts, packages/plugins/organizations/src/organizations-plugin.ts, docs/adr/0105-group-tenancy-posture-and-first-class-org-scope.md, docs/adr/0132-multi-organization-runtime-is-open-core.md, packages/spec/package.json, packages/spec/api-surface/security.json

PR #28823 for card #28761. Face schema: the hit is a non-test file under packages/spec/src. Read at 2026-11-01T22:00Z. Inputs: the card and its comments, the sibling card #28703, the PR body, its two files, its comments, the net diff from merge-base 1617b7fb910747ef66695b2f4c545f60a114091b to the head, the cited code on main at 2081a5e58e9f1d5a985cbbaaffe4ad6aa9dc01fc, and the head's check-runs. Nothing was built, run or checked out.

① Derived judgments

  1. Comment-only, confirmed. The net diff is two files: .changeset/28761-posture-stamps-organization-docblock.md (added, 8 lines) and packages/spec/src/security/tenancy-posture.ts (+16/-7). The one hunk in the spec file sits inside the JSDoc block above export function postureStampsOrganization. I stripped every comment from the merge-base and head versions of the file and diffed the rest: identical. No code, type or export changes. The function body, its signature and postureEnforcesWall are untouched. The file is unchanged on main since the merge-base, so the diff reads the same against main.
  2. Published .d.ts can change only in comments. packages/spec/package.json maps ./security to dist/security/index.d.ts and dist/security/index.d.mts, and files includes dist. postureStampsOrganization is exported from the entry's type graph, so its JSDoc ships. Since the source change is comment-only, the declaration output can differ only in that comment. api-surface/security.json and export-origins/security.json record names only, so they do not move. No consumer of the function exists on main in this repo outside those two records. The dev's note that the text lands in a shared chunk re-exported by the security entry is consistent with this and changes nothing. Not re-run locally.
  3. Acceptance set unchanged. No schema, enum, or signature moves. Clause-②: no is correct on both the PR body and the changeset.

② Semver level

patch on @objectstack/spec is right. The JSDoc ships in the published declaration files, so the published bytes change; skip-changeset would be wrong. Nothing is widened or narrowed, so no (widening) or (narrowing) arm applies. Metadata-protocol: none is right: no metadata type or key is touched. The changeset sentence matches the diff: it names the two open stampers, says the enterprise runtime is needed to activate a walled posture, and says comment only. Check Changeset is green on the head.

③ Boundary flags

  • Author is objectstack-fleet[bot], so no login note is owed.
  • The PR is a draft and carries needs:contract-review. The dev report lists no open_questions and no out_of_scope_findings. The one deviation (the docblock ships in a shared chunk, not directly in dist/security/index.d.ts) is accepted in ① item 2.
  • Check-runs on the head at reading time: 25 success, 13 skipped, 28 still in progress, 0 failure. Governed Surface Queue Guard, Check Changeset, Spec property liveness, Lint · ESLint and the PR-body guards are green. Landing still needs every remaining run green; this record does not stand in for that.
  • Non-blocking flag, the word "enterprise". The new docblock says "The enterprise @objectstack/organizations runtime fills an absent value too, in its write middleware" and then "What does need that runtime is ACTIVATING a walled posture (ADR-0105 D12)". Since ADR-0132 D1 (accepted 2026-09-07) @objectstack/organizations ships from this repo as packages/plugins/organizations, Apache-2.0. The middleware that fills organization_id is Middleware A of the open class. The commercial repo keeps a private package of the same name that only subclasses it and adds the licence gate (ADR-0132 D2, D3). So the stamper named here is open code, and the ADR-0105 D12 amendment says its own "enterprise runtime" wording "reads as history". The file header carries the same adjective and the card's own done-when wording uses it too, so the docblock inherits it rather than inventing it. What stays true: the runtime must be present to activate a walled posture (ADR-0093 D5 guard, organizationWallActive in packages/runtime/src/app-plugin.ts), and the entitlement is commercial (ADR-0132 D2), so "open code does not mean free activation" holds. This is a packaging label, not a claim about the wall or about who stamps. Not a must-fix. Worth a follow-up card that re-words the header and the docblock together, since the header is outside this card's file surface.
  • Minor note: "This predicate is the shared vocabulary for the stamping rule" has no caller on main in this repo, and none in the cloud checkout at ce2ed26. It is a vocabulary claim, not a behaviour claim, and the old text made a stronger version of it. Noted, not a finding.

④ Design judgment

Each sentence of the new docblock read against the code on main at 2081a5e5.

  1. "True exactly when a wall is enforced: an absent value would land a row behind a wall that then hides it." Unchanged text. The body returns postureEnforcesWall(posture). True.
  2. "The stamping is open code (ADR-0105 D5, the write half of the wall)." ADR-0105 D5 calls insert stamping "the write-side twin of the read wall". D12 lists "D5 stamping/validation" among what ships open. Every stamper below lives in an Apache-2.0 package in this repo. True.
  3. "The engine lands an insert in the caller's active organization in every posture (ObjectQL#driverWriteTarget, packages/objectql)." The insert path in engine.ts calls buildDriverOptions with writeTarget: true and the comment "The active organization is where the row LANDS, in every posture". The body in engine-driver-options.ts returns tenantId from execCtx.tenantId with no posture branch; only group adds tenantIds. The method's own docblock says "the active organization, in every posture". True. Two caveats the summary omits and need not state: there is no target when the context carries no tenantId, and buildDriverOptions withholds it for tenancy.enabled: false and federated objects.
  4. "The SQL driver fills an absent organization_id from it (SqlDriver#injectTenantOnInsert, packages/drivers/driver-sql)." The method fills the resolved tenant column from options.tenantId when the row's value is undefined, null or ''. It runs on create, upsert and the bulk path. True.
  5. "An explicit value is never overwritten." injectTenantOnInsert only fills an empty slot and its docblock says "Explicit values are never overwritten". Middleware A in the organizations plugin is fill-only and says a supplied value "is never touched here". The system-insert derivation in engine.ts keeps the row's own value first. True.
  6. "Where @objectstack/plugin-security installs the wall on the write, it holds that value to the Layer 0 verdict, storing it where the wall admits it and refusing the write where it does not." composeWriteTenantWall refuses any supplied organization_id outside the caller's Layer 0 (judgePayload, denyTenantPlacement), judges the stored image again (judgeRow), and declares judgesOrganization on the seam. staticReadonlySparesOrganization in engine.ts then leaves the admitted value on the row instead of stripping it. True.
  7. "The enterprise @objectstack/organizations runtime fills an absent value too, in its write middleware, but it is not the only stamper." Middleware A fills data.organization_id from opCtx.context.tenantId when it is null or empty, for non-system single-object inserts. The callerKeySets docblock in engine.ts names this fill. True as behaviour. The adjective "enterprise" is the ③ flag.
  8. "What does need that runtime is ACTIVATING a walled posture (ADR-0105 D12): open code does not mean free activation." D12 as amended by ADR-0132: the runtime must be present or a walled boot is refused (ADR-0093 D5), and the entitlement stays commercial. True, with the same adjective caveat.
  9. "This predicate is the shared vocabulary for the stamping rule, whichever package does the stamping." Vocabulary claim; see ③. Not false.
  10. File header, unchanged by the PR. "The D5 write stamping all ship in open packages" is true (items 3, 4, 7). "ENABLING a multi-organization posture requires the enterprise @objectstack/organizations runtime (ADR-0105 D12)" is true as to presence and entitlement; the adjective is the same inherited imprecision. The card's defect was that the old docblock contradicted this header. The new docblock agrees with it.

No sentence misstates the tenant wall or who stamps. The old false sentence ("the STAMPER, however, is the enterprise runtime, not the open engine") is gone, and the true half (activation needs the runtime) is kept, as the card's done-when asks and as #28703's merged verify docblock (#28760) words it.

Implemented-by: claude/project-thread-ef6d8g
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

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