Repository navigation
Commit d65cbb6
docs(skills, spec): every published package declares one anchor-safe isDefault permission set (#25930)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XFfzvMqgJHhisBXrtmgA5T9)_
Fixes #25773
Clause-②: no
Metadata-protocol: none
## Summary
Consequence (ii) of maintainer ruling record 6341690661: the published
skill and the marketplace reference now state that every published
package declares exactly one anchor-safe `isDefault: true` permission
set. Text only. No lint rule, schema key or runtime path changes, and no
new gate (the ruling orders the text; a gate needs the maintainer's own
word).
## What changed
1. `skills/objectstack-data/rules/security.md`, the `isDefault: true`
bullet under the RBAC section. It keeps the semantics (the `everyone`
baseline, ADR-0090 D5) and adds the requirement as a check an author can
run: exactly one such set, anchor-safe, meaning
`describeAnchorForbiddenBits(set, 'everyone')` from
`@objectstack/spec/security` returns `null`. It names the two refusals
that already exist (lint rule `security-anchor-high-privilege`, and the
binding), says what happens with none (invited members get nothing until
an admin assigns a set to each), and says that no gate counts the sets.
The old "lint and boot refuse a platform capability or undeclared name"
clause is folded in: it is exactly what the anchor-safe predicate
refuses in `systemPermissions`, so the bullet now says the set's
`systemPermissions` may name only app capabilities declared under
`capabilities:`.
2. Marketplace docs. The source is the Marketplace Protocol module doc
block at the top of `packages/spec/src/marketplace/marketplace.zod.ts`,
which `build-docs.ts` renders as
`content/docs/references/marketplace/marketplace.mdx` (AUTO-GEN, not
hand-edited). That block already carries the "Developer Publishing Flow"
a publisher reads, so the new section sits right after it. The exact
source sentence added: "Exactly one anchor-safe default permission set
(ADR-0090 D5): `isDefault: true`, and `describeAnchorForbiddenBits(set,
'everyone')` from `@objectstack/spec/security` returns `null`." The
section then gives the reason and the enforcement facts. Regenerated
with `pnpm --filter @objectstack/spec gen:docs`; the only regenerated
diff is the new 9-line "What a published package declares" section in
`marketplace.mdx` (commit f1340f3).
3. `.changeset/25773-published-package-default-permission-set.md`:
`patch` for `@objectstack/skills` (ships `skills/**`) and
`@objectstack/spec` (ships `src/**/*.zod.ts`, so the edited doc block is
published text).
## Where the predicate and the refusals live (read at `cb0a2fcf`)
- Predicate: `describeAnchorForbiddenBits` in
`packages/spec/src/security/high-privilege.ts`, exported from
`@objectstack/spec/security`. For `everyone` it is
`describeHighPrivilegeBits` with the stack's declared capabilities as
context: no platform or undeclared `systemPermissions`, no
`viewAllRecords` / `modifyAllRecords`, no `allowDelete` /
`allowTransfer` / `allowExport` on any object.
- Author-time refusal: `packages/lint/src/validate-security-posture.ts`,
rule `SECURITY_ANCHOR_HIGH_PRIVILEGE` = `security-anchor-high-privilege`
(error), run on every `isDefault: true` set.
- Bind-time refusal: `confirmAudienceBindingSuggestion` in
`packages/plugins/plugin-security/src/suggested-audience-bindings.ts`
runs the same predicate; at boot `everyoneBaseline` in
`security-plugin.ts` withholds a high-privilege set from `everyone`.
- Presence and count: nothing enforces them.
`appDefaultPermissionSetName`
(`plugin-security/src/app-default-permission-set.ts`) takes the first
`isDefault` set and returns `undefined` when there is none, with no
diagnostic. The text says "no gate counts them" for that reason.
## Token ratchet (`skills/**`)
| Reading | Before (`cb0a2fcf`) | After (`f1340f32`) |
|:--|--:|--:|
| `rules/security.md` tokens (ceiling 2563, not raised) | 2563 | 2561 |
| `rules/security.md` lines | 220 | 220 |
| `skills/objectstack-data/**` lines | 3806 | 3806 |
| all `skills/*/SKILL.md` lines (untouched) | 4383 | 4383 |
| bundle total tokens (`check-skills-token-ratchet`; before = after + 2,
only this file moved) | 155469 | 155467 |
The new text (+66 tokens on the bullet as first drafted) is paid by
deleting content in the same file, with no re-wrap counted as savings:
the `stack.zod.ts` path aside on the `permissionSets:` bullet; the
parenthetical after the `rls.zod.ts` source line; the parenthetical
after the `field.zod.ts` source line; ADR-0105 §"Today's two postures"
from the multi-tenancy reference (ADR-0093 and the tenancy-modes URL
stay); "plugin-security's FieldMasker enforces it. The real channels
are:" shortened to "(FieldMasker). Two more channels:"; and the
capability clause folded into the anchor-safe sentence as described
above.
## Gates (head `f1340f32`)
Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`: 113 commands. All 113 run with exit codes
captured before any pipe: 113 exit 0. Six first answered exit 3
(PREREQUISITE NOT MET: `check:doc-formula-expressions`,
`check:doc-security-posture`, `check:skill-examples`,
`check:docs-transcript-drift`, `check:dual-build-cjs-loads`,
`check:lean-entry-closure`) and answered exit 0 after a full `pnpm turbo
run build` under the verify lock. `dispatch-gates --ran`: "113 derived
famil(ies) accounted for — 113 run, 0 NOT-MEASURED". Also `pnpm --filter
@objectstack/spec build` exit 0, `pnpm --filter @objectstack/spec
typecheck` exit 0, `check:generated` exit 0 after `gen:docs`. No tests
changed and no tested behaviour changed, so there is no ablation. CI
families (Test Core, Build Core, Build Docs, type-check lanes) are left
to this PR's check-runs.
## 维护者速读(草稿)
- **改了什么**:对外发布的技能文档 `security.md` 和 marketplace
参考文档里,写明"每个发布包必须声明且只声明一个锚安全的默认权限集(`isDefault:
true`)",并给出作者可自查的判据(`describeAnchorForbiddenBits(set, 'everyone')` 返回
`null`)。只改文字,不加门禁、不改代码行为。
- **为什么改**:落实裁决 6341690661 的第 (ii)
项:默认访问只通过一个机制到达组织邀请的成员;包里没有这样的权限集,新成员就什么都看不到,直到管理员逐人分配。原文只讲了含义,没讲要求。
- **风险与代价(含回滚)**:技能文件 token 不增(2563 → 2561),用删掉同文件三处源码路径旁注、一处 ADR
章节引用和一句话来抵账。回滚即还原这两个文件并重生成文档页。
- **席位意见**:
- **你要做的**:这是 Tier H(`skills/**`),需要你批准后由席位落地。
## Acceptance notes
- No gate refuses a package that declares no `isDefault` set or more
than one; the app-level reader `appDefaultPermissionSetName` silently
takes the first. Whether a gate should enforce this at publish time is
left for the maintainer's word, per the card's boundary.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_014LdiGPrydHj5PHTzYQUvoW
---
_Generated by [Claude
Code](https://claude.ai/code/session_014LdiGPrydHj5PHTzYQUvoW)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 493a6c4 commit d65cbb6
4 files changed
Lines changed: 42 additions & 13 deletions
File tree
- .changeset
- content/docs/references/marketplace
- packages/spec/src/marketplace
- skills/objectstack-data/rules
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
34 | 43 | | |
35 | 44 | | |
36 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
32 | 41 | | |
33 | 42 | | |
34 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
25 | | - | |
| 24 | + | |
| 25 | + | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | | - | |
32 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
33 | 36 | | |
34 | 37 | | |
35 | 38 | | |
| |||
108 | 111 | | |
109 | 112 | | |
110 | 113 | | |
111 | | - | |
112 | | - | |
| 114 | + | |
113 | 115 | | |
114 | 116 | | |
115 | 117 | | |
116 | 118 | | |
117 | 119 | | |
118 | 120 | | |
119 | | - | |
120 | | - | |
| 121 | + | |
121 | 122 | | |
122 | 123 | | |
123 | 124 | | |
| |||
147 | 148 | | |
148 | 149 | | |
149 | 150 | | |
150 | | - | |
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | 157 | | |
158 | | - | |
159 | | - | |
| 158 | + | |
| 159 | + | |
160 | 160 | | |
161 | 161 | | |
162 | 162 | | |
| |||
0 commit comments