fix(cli,plugin-security): os meta resync to re-materialize default permission sets (#2705)#2740
Merged
Merged
Conversation
chore: release packages (#2304) objectui@7a68d78f2a0c3c1f99dafd39b75b4f117a24917b
…rmission sets (#2705) Default permission sets (admin_full_access / member_default / viewer_readonly …) were seeded INSERT-ONCE at boot: bootstrapPlatformAdmin skipped any existing row and never wrote the shipped declaration back. So editing a default set's source, recompiling, and restarting `os dev` WITHOUT `--fresh` left the runtime serving the OLD value — silently, because the runtime authz resolver hydrates permission sets from the sys_permission_set row (resolve-authz-context.ts), not from the in-memory dist. Every OTHER metadata seed (declared sets, positions, built-in roles, capabilities) already upserts on boot, leaving the platform-default path the lone insert-once holdout — a gap ADR-0090 widened by persisting more facets (system_permissions, delegated-admin admin_scope) onto the same row. Insert-once is deliberate for prod (it protects an admin's Setup edits and keeps the defaults env-authored), so this is NOT a blind upsert: - bootstrapPlatformAdmin gains a `resync` option. Default boot behavior is unchanged. Under resync an existing row is reconciled to the shipped dist only when the platform still owns it (managed_by absent or 'platform'); a row an admin took over ('user') or a package owns ('package') is left untouched. - New `os meta resync` command boots the runtime, reconciles the default permission-set rows to the compiled dist, and reports reconciled / preserved / newly-seeded — without touching business data and without a `--fresh` wipe. Confirmation-gated (--yes to skip; --json for scripting). Verified: plugin-security 240/240, cli 466/466, and end-to-end `os meta resync` against examples/app-todo — insert path (seeded 4 new), overwrite path (resynced 4), and clean process exit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 22 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2705 — implements the re-evaluated fix (Option B), not a blind upsert.
Problem
Default permission sets (
admin_full_access/member_default/viewer_readonly…) are seeded insert-once at boot:bootstrapPlatformAdminskips any row that already exists and never writes the shipped declaration back. So editing a default set's source, recompiling, and restartingos devwithout--freshleaves the runtime serving the old value — silently, because the runtime authz resolver hydrates permission sets from thesys_permission_setrow (resolve-authz-context.ts:230), not the in-memory dist. A permission-gated surface (e.g.setup.access) keeps its stale behavior with no error, which repeatedly misled debugging.Every other metadata seed (declared sets, positions, built-in roles, capabilities) already upserts on boot — the platform-default path was the lone insert-once holdout, a gap ADR-0090 widened by persisting more facets (
system_permissions, delegated-adminadmin_scope) onto the same row.Why not a blind upsert
Insert-once is deliberate for prod: an existing row is env-authored config and must not be clobbered on restart — it protects an admin's Setup edits and keeps the defaults env-authored (the posture
bootstrapDeclaredPermissionsrelies on). This is a dev-experience gap, not a prod-correctness gap, so the fix is opt-in rather than a change to boot semantics.Change
bootstrapPlatformAdmingains aresyncoption. Default boot is unchanged (insert-once). Underresync, an existing row is reconciled to the shipped dist only when the platform still owns it (managed_byabsent or'platform'); a row an admin took over ('user') or a package owns ('package') is an intentional override and is left alone.os meta resynccommand boots the runtime, reconciles the default permission-set rows to the compiled dist, and reports reconciled / preserved / newly-seeded — without touching business data and without a--freshwipe. Confirmation-gated (--yesto skip;--jsonfor scripting).Prod boot is unaffected.
Verification
plugin-security240/240,cli466/466.os meta resyncagainstexamples/app-todo: insert path (seeded 4 new), overwrite path (resynced 4), and clean process exit (a one-shot command over the app stack;process.exiton the way out, matching the other one-shot CLI commands).🤖 Generated with Claude Code