Repository navigation
docs(skills, spec): every published package declares one anchor-safe isDefault permission set - #25930
Conversation
…isDefault permission set The objectstack-data security rule and the Marketplace Protocol header now state the requirement: exactly one `isDefault: true` set for which `describeAnchorForbiddenBits(set, 'everyone')` returns null. The new text is paid for by trimming the same skill file, which stays under its token ceiling. Claude-Session: https://claude.ai/code/session_014LdiGPrydHj5PHTzYQUvoW Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LdiGPrydHj5PHTzYQUvoW Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift Check
What this run could not see
Coarse fallback — 144 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contract reviewServed-tier: Face: governed rule text ( ① Derived judgments
② Semver level
③ Boundary flags
Check-runs on Implemented-by: VERDICT: PASS Isolated contract reviewer (pm-dispatch |
Requested by Leehom · project thread
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: truepermission 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
skills/objectstack-data/rules/security.md, theisDefault: truebullet under the RBAC section. It keeps the semantics (theeveryonebaseline, ADR-0090 D5) and adds the requirement as a check an author can run: exactly one such set, anchor-safe, meaningdescribeAnchorForbiddenBits(set, 'everyone')from@objectstack/spec/securityreturnsnull. It names the two refusals that already exist (lint rulesecurity-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 insystemPermissions, so the bullet now says the set'ssystemPermissionsmay name only app capabilities declared undercapabilities:.packages/spec/src/marketplace/marketplace.zod.ts, whichbuild-docs.tsrenders ascontent/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, anddescribeAnchorForbiddenBits(set, 'everyone')from@objectstack/spec/securityreturnsnull." The section then gives the reason and the enforcement facts. Regenerated withpnpm --filter @objectstack/spec gen:docs; the only regenerated diff is the new 9-line "What a published package declares" section inmarketplace.mdx(commit f1340f3)..changeset/25773-published-package-default-permission-set.md:patchfor@objectstack/skills(shipsskills/**) and@objectstack/spec(shipssrc/**/*.zod.ts, so the edited doc block is published text).Where the predicate and the refusals live (read at
cb0a2fcf)describeAnchorForbiddenBitsinpackages/spec/src/security/high-privilege.ts, exported from@objectstack/spec/security. Foreveryoneit isdescribeHighPrivilegeBitswith the stack's declared capabilities as context: no platform or undeclaredsystemPermissions, noviewAllRecords/modifyAllRecords, noallowDelete/allowTransfer/allowExporton any object.packages/lint/src/validate-security-posture.ts, ruleSECURITY_ANCHOR_HIGH_PRIVILEGE=security-anchor-high-privilege(error), run on everyisDefault: trueset.confirmAudienceBindingSuggestioninpackages/plugins/plugin-security/src/suggested-audience-bindings.tsruns the same predicate; at booteveryoneBaselineinsecurity-plugin.tswithholds a high-privilege set fromeveryone.appDefaultPermissionSetName(plugin-security/src/app-default-permission-set.ts) takes the firstisDefaultset and returnsundefinedwhen there is none, with no diagnostic. The text says "no gate counts them" for that reason.Token ratchet (
skills/**)cb0a2fcf)f1340f32)rules/security.mdtokens (ceiling 2563, not raised)rules/security.mdlinesskills/objectstack-data/**linesskills/*/SKILL.mdlines (untouched)check-skills-token-ratchet; before = after + 2, only this file moved)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.tspath aside on thepermissionSets:bullet; the parenthetical after therls.zod.tssource line; the parenthetical after thefield.zod.tssource 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 fullpnpm turbo run buildunder the verify lock.dispatch-gates --ran: "113 derived famil(ies) accounted for — 113 run, 0 NOT-MEASURED". Alsopnpm --filter @objectstack/spec buildexit 0,pnpm --filter @objectstack/spec typecheckexit 0,check:generatedexit 0 aftergen: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)。只改文字,不加门禁、不改代码行为。skills/**),需要你批准后由席位落地。Acceptance notes
isDefaultset or more than one; the app-level readerappDefaultPermissionSetNamesilently 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.ai/code/session_014LdiGPrydHj5PHTzYQUvoW
Generated by Claude Code