Skip to content

fix(cli,plugin-security): os meta resync to re-materialize default permission sets (#2705) - #2740

Merged
os-zhuang merged 3 commits into
mainfrom
fix/meta-resync-default-permission-sets
Jul 10, 2026
Merged

fix(cli,plugin-security): os meta resync to re-materialize default permission sets (#2705)#2740
os-zhuang merged 3 commits into
mainfrom
fix/meta-resync-default-permission-sets

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

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: bootstrapPlatformAdmin skips any row that already exists and never writes the shipped declaration back. So editing a default set's source, recompiling, and restarting os devwithout--fresh leaves 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: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-admin admin_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 bootstrapDeclaredPermissions relies 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

  • bootstrapPlatformAdmin gains a resync option. Default boot is unchanged (insert-once). 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 an intentional override and is left alone.
  • 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).

Prod boot is unaffected.

Verification

  • plugin-security240/240, cli466/466.
  • End-to-end os meta resync against examples/app-todo: insert path (seeded 4 new), overwrite path (resynced 4), and clean process exit (a one-shot command over the app stack; process.exit on the way out, matching the other one-shot CLI commands).

🤖 Generated with Claude Code

os-zhuangand others added 2 commits July 10, 2026 10:30
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>
@vercel

vercelBot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 10, 2026 11:44am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/cli, @objectstack/plugin-security.

22 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx(via packages/cli)
  • content/docs/api/client-sdk.mdx(via @objectstack/cli)
  • content/docs/api/data-flow.mdx(via @objectstack/cli)
  • content/docs/api/environment-routing.mdx(via @objectstack/cli)
  • content/docs/api/error-catalog.mdx(via @objectstack/cli)
  • content/docs/automation/hook-bodies.mdx(via packages/cli)
  • content/docs/getting-started/cli.mdx(via @objectstack/cli, @objectstack/plugin-security)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/cli)
  • content/docs/kernel/runtime-services/index.mdx(via packages/cli)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authentication.mdx(via @objectstack/cli)
  • content/docs/permissions/authorization.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/explain.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/plugin-security)
  • content/docs/plugins/index.mdx(via @objectstack/plugin-security)
  • content/docs/plugins/packages.mdx(via @objectstack/cli, @objectstack/plugin-security)
  • content/docs/protocol/objectos/plugin-spec.mdx(via @objectstack/cli)
  • content/docs/protocol/objectos/realtime-protocol.mdx(via @objectstack/cli)
  • content/docs/releases/implementation-status.mdx(via @objectstack/cli, @objectstack/plugin-security)
  • content/docs/ui/audience-based-interfaces.mdx(via packages/plugins/plugin-security)
  • content/docs/ui/dashboards.mdx(via @objectstack/plugin-security)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 8f0b9df into mainJul 10, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the fix/meta-resync-default-permission-sets branch July 10, 2026 11:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cli/plugin-security] dev 元数据物化不一致:默认权限集 insert-if-not-exists 不重物化(声明集走 upsert)

1 participant

@os-zhuang