Skip to content

[field report] rc→GA upgraded envs: package-declared permission sets frozen at first-boot snapshot — provenance skip is silent and has no adoption/migration path #9952

Description

@baozhoutao

Part of steedos-labs/os-project-titanwind-ehr#1606 (and steedos-labs/os-project-titanwind-ehr#1613).

Field report from a production-test deployment. Related but not covered by: #8692 (closed — platform-default seeder / os meta resync path), #8672 (open — org-less materialization; measured-harm follow-up posted there), #2705 (the resync intent this violates in spirit).

Summary

An environment whose database was first initialized on an earlier 17-rc line and then upgraded in place to GA 17.0.0 ends up with sys_permission_set rows that bootstrapDeclaredPermissions / upsertPackagePermissionSetpermanently refuses to reconcile: the legacy rows do not carry managed_by: 'package' + the current package_id, so every boot takes the skippedEnvAuthored / skippedForeign branch. Result: every permission change shipped in the package after the env's first boot silently never takes effect — grants stay frozen at the first-boot snapshot while the deployed artifact moves on. The only signal is a log counter; nothing in Setup shows that a package-declared set has diverged from the package.

There is also no adoption/migration path: no migration, no os command, and (in our deployment — see #8672 follow-up) not even a Setup surface that can see the rows. The only remediation we found is direct SQL against sys_permission_set.

Pinned versions

  • @objectstack/*17.0.0 (GA) — core, runtime, objectql, plugin-auth, spec, types, cli
  • vendor packs: @objectstack/organizations@1.0.0, @objectstack/security-enterprise@1.0.0
  • driver: postgres (postgres:16), single organization
  • Env DB first booted ~2026-07-30 on the then-current 17-rc; app image rebuilt/redeployed multiple times since, most recently 2026-08-19 with the current package.

Measured on the live env (2026-08-19, admin session)

  • sys_user_permission_set holds 13 assignment rows referencing sys_permission_set ids whose id timestamps date to the env's first boot (2026-07-30). The rows exist and are still enforced by authz.
  • The package's permission set (ehr_quality_inspector) currently declares 49 object grants in the built artifact; the env enforces the 41-object first-boot snapshot. Grants added to the package after 07-30 (e.g. CRU on a child object, read on another) return 403 for real users — this is how the freeze was discovered (app issue steedos-labs/os-project-titanwind-ehr#1606).
  • Redeploying the current artifact and restarting does not change the snapshot — consistent with the provenance skip in upsertPackagePermissionSet (packages/plugins/plugin-security/src/bootstrap-declared-permissions.ts): update only when existing.managed_by === 'package' && existing.package_id === packageId, else counted as skipped with a log line only.
  • Control: a fresh GA 17.0.0 env materializes the same package correctly (49 objects, managed_by: 'package', package_id set, active: true).

Expected vs actual

What we did NOT do

No app-side workaround was added. We are remediating the env with one-off SQL (UPDATE sys_permission_set SET managed_by='package', package_id='<pkg>', organization_id='<org>' WHERE name LIKE '<prefix>%' + restart), recorded in the app issue. Every other env upgraded along the same rc→GA line will need the same surgery until an adoption/migration path exists.

Asks

  1. An adoption/migration for legacy sys_permission_set rows whose name matches a currently-declared package set but whose provenance columns predate the current scheme (one-time migration, or an explicit os command an operator can run).
  2. Surface the skip: when boot sync skips a package-declared set because of provenance, show it somewhere an admin can see (Setup badge / warning on the set), not only a log counter — the failure mode is "declared ≠ enforced" drifting for weeks with 403s as the only symptom.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions