Repository navigation
feat(plugin-security)!: the boot writes no sys_permission_set row (#15204 stage 6b-2) - #22900
objectstack-fleet[bot] wants to merge 16 commits into
Conversation
…efusal diagnostics and managed_by normalizer (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…log row; os meta resync is retired (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…us retires with its writer (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…ift_status / drift_detail (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…the legacy platform-bucket rows themselves (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…face-only disposition (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…ed seeders (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…new one (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…wn changeset (#15204 stage 6b-2a) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…ermission_set row; existing-database cases write the legacy row themselves (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…places did (#15204 stage 6b-2) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
…r, a command that exists (#15204 stage 6b-2a) Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 5 package(s): 65 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 16 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 152 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 6c1f4a9bb8d33f6f930655c0155c368b7778699d && git checkout 6c1f4a9bb8d33f6f930655c0155c368b7778699d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 63739521d854d49dbb08dbc5370c99fde8a7555c fcaedfdaa187e10c35234ad11ef564fb3c916781 && git checkout -B drift-repro 63739521d854d49dbb08dbc5370c99fde8a7555c && git merge --no-ff fcaedfdaa187e10c35234ad11ef564fb3c916781
node scripts/docs-audit/affected-docs.mjs --json 63739521d854d49dbb08dbc5370c99fde8a7555c
|
… seeder was the only caller of (#15204 stage 6b-2) warnOrganizationLessRows, catalogIsPerOrganization and listSeedOrganizationIds had one caller, bootstrap-declared-permissions.ts, deleted in this PR. Re-measured: no live caller and no test. Internal (never exported from the package index). Also carries T1's buildExistingByName key-set fence byte-for-byte. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49
…15204 stage 6b-2) No assertion changes; keeps the residual under the 3,000-line ruling after the organization-scope deletion. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49
Part of #15204
Clause-②: yes (narrowing)
Stage 6b-2: the boot writes no
sys_permission_setrow. The declared-permission seeder, the platform-default materialization, thepermissionpublish materializer, themetadata:reloadedre-seed and the organization-creation hook are deleted, with drift, the seed refusal diagnostics and themanaged_bynormalizer ("only delete, never fix", batch #310 item 4). This PR leaves #15204 open: stages 7a, 7b, 8, 8-post, C7b and 6c remain.Landing — draft until all of these land
mainwith their pins gone. 6b-2a (feat(cli)!: delete os meta resync and the example position binders (#15204 stage 6b-2a) #22899:os meta resyncand the example binders, Tier H) is independent and goes to the maintainer separately.main: 2,994 changed lines (34 files, +439 / −2,555). That is close to the line, so any growth here needs re-measuring. Until then GitHub shows the whole branch.mainis merged in after the precursors:inert-wirings.test.tsandschema-migrate.lazy-driver-import.test.tsconflict with feat(cli)!: delete os meta resync and the example position binders (#15204 stage 6b-2a) #22899's later comment fixes; take feat(cli)!: delete os meta resync and the example position binders (#15204 stage 6b-2a) #22899's side.scripts/engine-double-contract.pinned.json: regenerate withnode scripts/check-engine-double-contract.mjs --write.*.baseline.jsonledgers: drop every entry for a deleted suite.skills/objectstack-platform/references/operations.md). After feat(cli)!: delete os meta resync and the example position binders (#15204 stage 6b-2a) #22899 lands andmainis merged, this diff touches no governed path, and size alone decides the terminal.What changes
bootstrap-declared-permissions.ts(522 lines)managed_by:'package'row, once per organization under a wallbootstrap-platform-admin.tsresyncreconciled themadmin_full_accessrow only for leg C (a grant written before the name column; restrict-only). A refused read withholds the promotion and says so once. Noresyncoption, noseeded/resynced/resyncSkippedpermissionpublish materializer (SP)everyone's re-derivation only when it materialized and the body carriedisDefaultonMetadataMutation: every landedpermissionpublish, direct save or delete, unconditionally. Drafts and other types do nothing (closes U2 contract flag A, 6109964380)metadata:reloadedre-seed, organization-creation hook (SP)permission-set-drift.ts,normalize-managed-by.ts,seed-refusal-diagnostics.tswarnOrganizationLessRows,catalogIsPerOrganization,listSeedOrganizationIds(organization-scope.ts, internal)sys_permission_set.drift_status/drift_detailand the Needs Attention viewreadDeclareddeclared-capability-context.ts(its two readers: the capability context and the managed-object write denies). It is a read of the registry, the catalog's one home, never of a row, so not a transition piece.createSecurityCatalogReaderdoes not fit: it refuses theobjecttype, and switching the capability read to it would change a fail-closed answer into a throw on the ADR-0090 D5 gateWho still needed the rows: measured, and answered before this stage
Every grant writer and the user-page grant picker write the name since 6b-2-pre (#22863). The remaining row readers on this head:
Pins
builtin-positions.boot.test.ts(real plugin boot, real SQLite, every scenario): zerosys_permission_setrows after boot, with a positive census control. The first platform administrator (single) and the organization administrator are still granted. The grant golden is unchanged, with no row at all.grant-permission-set-name.writers.test.ts: the promotion leaves zero rows and the holder reads by name. The 6b-2-pre pins stay green: organization admins under a wall and undersingleon zero rows; self-registration and the verify persona in their packages.everyone-rederivation-on-permission-mutation.test.ts: one listener even across a bootstrap re-run. Publish and delete of apermissionre-derive; a draft or another type does not.suggested-binding-acceptance.dogfood.test.tsstays green.showcase-permission-seeding.dogfood.test.ts(thedeclarative-permission-seedingauthz row, rewritten): the showcase's sets are served by the catalog with their package, and the boot writes no row.bootstrap-platform-admin-refused-existence-read.test.ts: a refused legacy read withholds the promotion and writes nothing; an empty answer goes on.Also in this PR
permission.packageIdre-points to its surviving reader (the CLI's compile-time collision door).permission.managedByis corrected todead: the retired seeder stamped the column and never read the authored key, so the oldliveverdict was already wrong (see Acceptance notes).tenant-audit-census.mdxare updated.permission-sets.mdx(built-in sets, provenance, the drift section reduced to overlay shadow) andauthorization.mdx.__tests__/legacy-catalog-rows.testkit.ts, dogfoodensureLegacyPermissionSetRow).Changesets
@objectstack/plugin-securityminor, BREAKING,Clause-②: yes (narrowing), ADR-0087not-required (no-migration-prescription).@objectstack/climinor BREAKING;plugin-security,driver-sql,runtimepatch) rides here until it lands.Verification (local, at the head this PR opens with)
turbo run build, 74/74.authz-conformance,authz-probe-blind-spot) are in that run.dispatch-gates --commands: 134 derived families, all run, each recorded with its exit code; reconciled by--ran, 0 not measured. Red:check:platform-checklistonly, with the same 8 absent-symbol anchors on T1 (which touches no checklist file), so they come frommain.Acceptance notes
permission.managedByis an authored key with no reader (pre-existing; the ledger now saysdead). Retiring it is an enforce-or-remove item for the spec seat. It is not done here.scripts/measure-position-name-fold-census.mjs, not a CI gate) refuses to report once 6b-2a deletes the binders: its controls read binder tuples. Carrier: whoever next runs it re-aims its junction scan atPositionSchema.permissionSets.two-doors-permission,showcase-permission-projection) keep their data-door cases on an existing database (the fixture writes the legacy row), because the gate still guards such rows until 7a / stage 8. 块1 (a publish materializes a row) is deleted with the materializer.check:platform-checklistreds onmain(anonymous-form-intake and other symbol anchors) are pre-existing and outside this diff.维护者速读(草稿)
改了什么:启动过程不再向
sys_permission_set表写任何行。删除了:包声明权限集的播种器、平台默认权限集的物化(含os meta resync命令,见 6b-2a)、包发布时的物化器、热安装后的重播种、新建组织时的播种,以及基于这些行的漂移诊断、managed_by归一化和播种拒绝诊断。sys_permission_set上的drift_status/drift_detail两个字段及「需要关注」视图随写入者一并删除。U2 的「接受包默认权限集后重新推导 everyone」从被删的发布物化器挪到元数据变更信号上,且改为对每次权限集发布/保存/删除都执行(不再要求请求体带isDefault)。为什么改:ADR-0131 D3 规定权限集只有一个家——注册表。鉴权解析器从阶段 1 起已从注册表读定义,授权从 6b-2-pre 起按名称写入,这些行已不再决定任何权限。
风险与代价(含回滚):全新数据库上 Setup 的「授予权限集」选择器仍列表行,因此会是空的——这就是本 PR 等 #22865 选择器决定再合并的原因。已有数据库保留旧行(直到 C7b)。删除了若干公开导出和
bootstrapPlatformAdmin的resync选项,changeset 已逐项列出。回滚:直接 revert,无数据迁移。本 PR 需先合入 T1、T2、6b-2a 三个前置 PR,之后合并 main,差异约 2,870 行。席位意见:
你要做的:等 #22865、objectui PR-3、CD(#22881)、objectui PR-4 落地后批准合并;在 6b-2a 落地前,本 PR 因含 skills 文件为 Tier H。
🤖 Generated with Claude Code
https://claude.ai/code/session_013XKtmoR5QCUSTMjiQ3os49