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 dev without --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-security 240/240, cli 466/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-zhuang and 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

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 10, 2026 11:44am

Request Review

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

github-actions Bot 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 main Jul 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 free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant