Skip to content

[finding] The published objectstack-data skill never says what single posture means for the organization count — an AI app author reading it (and the code's exemption list) lands on 「stay single, seed one sys_organization per tenant, bring your own RLS wall」; the sentence that forbids that shape lives only in content/docs/deployment/tenancy-modes.mdx and ADR-0105 §「Today's two postures」, neither linked from the skill #17019

Description

@huangyiirene

Filed by the director seat (summon #18, session_017Js5kTpTtxieBjPyScgxJ3, 2026-09-09) while answering the maintainer's question behind #16934 — 「ats 为什么会搞错,是我们的 skills 或者文档没写清楚吗?」. Skills lane (skills/objectstack-data, published directory), which self-triages its own findings. ⛔ Not graded. Class (c): a metadata/seed shape the runtime accepts and then silently mis-serves; also (b) by omission against a declared contract, cited below.

The contract, and where it is written

Three places state the shape of single; all three predate the ats design:

  • content/docs/deployment/tenancy-modes.mdx (on main since 2026-08-30, 247933ff): postures table row Shape — 「single: one logical tenant; sub-units modelled as business units in one tree」, Default organization — 「one bootstrapped "Default Organization"」, Org-management UI — 「hidden」; line 48 「single is not "multi-org with the walls left standing"」; lines 138–140 「creating additional organizations is refused (403) whenever the effective posture is single」.
  • ADR-0105 line 70 「single (ADR-0093): one logical tenant. Layer 0 inert」; line 153 (posture table, Intended shape) 「one logical tenant; factories as BUs in one tree」; line 512 「Posture: single. One organization; the full structure as one BU tree」.
  • ADR-0093 (the posture ladder itself); ADR-0131 D9 「under single the Default Organization is the only one」.

Where it is not written: the skill an app author actually loads

skills/objectstack-data is what an AI author reads while writing *.object.ts and *.seed.ts. Its every sentence that touches the posture points the other way:

git grep -n -iE "exactly one organization|one logical tenant|Default Organization|sys_organization" origin/main -- skills/ → 0 hits (control: the same grep over content/docs/deployment/ hits tenancy-modes.mdx and seed-tenancy-repair.mdx).

Measured instance (objectstack-ai/ats 446ab44, read-only from this session)

DESIGN.md §「租户墙划分契约(2026-09-07 裁决)」 cites plugin-security/src/security-plugin.ts:2940 (the Layer 0 exemption comment: 「…and the whole single posture all yield null here and are untouched」), ADR-0055, ADR-0090 D3, ADR-0105 D2/D11, ADR-0019 D3 and the objectstack-data skill (§Search Fields). It cites neither tenancy-modes.mdx nor ADR-0105's posture table sixty lines above the D2 it quotes. From those readings it concluded, verbatim, 「今天(single posture,墙惰性)—— 划分成立 … 墙立起来之后 —— 同一套划分不用改」: employers modelled as sys_organization rows under single (src/data/shared/build.ts, organization_id: orgId(e.slug)), isolation by hand-written RLS, walls to be 「stood up later」 — exactly the shape line 48 of the deployment page names and forbids. When the write-side #8844 refusal fired on 09-07 with the reason 「declared single posture yet holds 2 organizations」 (DESIGN line 303), the team read it as a platform inconsistency (reads had worked for days — see #17010 for the silent boot) and filed ats#56 / #16659 / the #16934 card, not a posture change.

The pattern is the mechanism/contract split: the code comment tells an author what single does, the ADR and the deployment page tell them what single means, and the skill — the one text guaranteed to be in context — carries only the first.

What is asked

For the skills seat to triage; ⛔ no wording proposed as a ruling. The shape that closes the gap, for the seat's four-axis pass: one loud sentence in rules/security.md 「## Multi-tenancy」 stating the posture ↔ organization-count contract (single = the bootstrapped Default Organization and nothing else; tenants-as-organizations ⇒ a walled posture, declared on the deployment, open-core since #16215 + #16719), a ⛔ line under §「Seed Data & Fixtures」 that sys_organization is platform-bootstrapped and never seeded, the Sources line extended to ADR-0093 / ADR-0105 §「Today's two postures」 / content/docs/deployment/tenancy-modes.mdx, and references/data-hooks.md line 622 re-read against ADR-0132. Reader of each line, per the lane's own test: an AI author choosing between tenancy on an object and a posture on the deployment. ⛔ Not asked: any change to tenancy-modes.mdx (it already states the contract) or to the runtime (boot-time count is #17010).

Re-check: git grep -n -iE "For SaaS, set .tenancy" origin/main -- skills/objectstack-data/rules/security.md (the sentence still stands alone); git grep -n -iE "needs cloud" origin/main -- skills/objectstack-data/references/data-hooks.md (line 622 still says cloud); git grep -n -iE "one logical tenant" origin/main -- skills/ → 0.

Dedupe: search_issues over this repo for 「objectstack-data skill tenancy posture single organization count seed sys_organization」 and 「skill multi-tenancy section walled posture tenants as organizations app author guidance」 returned #17010 (runtime side, boot count — complementary, not this), #16718 (the 65 stale enterprise mentions — overlaps only data-hooks.md:622), #5887 / #5746 (closed, older doc pages), #12701 (hotcrm isolated-posture epic). None asks the published skill to state the posture ↔ organization-count contract. Related: #16934 (correction comment 5594769261), #17009, #17010, ADR-0093, ADR-0105, ADR-0131 D9/D11, ADR-0132.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions