Skip to content

refactor(plugin-security): make sys_permission_set data record a pure projection (retire the two-store split-brain) #2875

Description

@os-zhuang

Context

sys_permission_set currently has two stores:

  1. Authoritative metadata — the layered metadata overlay (sys_metadata), written by Studio env-scope edits (saveMetaItem / client.layered).
  2. Queryable data record — snake_case JSON-string columns that Setup reads for lists and user assignment.

These were only synced at boot and on publish. Env-scope metadata edits did not project onto the data record, so Setup showed stale facets — the ADR-0056 display-freshness gap (#2857).

What's already done

framework #2867 (closing #2857) added an onMetadataMutation subscriber that projects env-authored permission-set edits onto the data record.

This is a sync band-aid. It re-couples two independent sources of truth after the fact.

The remaining problem

Two authoritative stores can still drift. Any write path that bypasses the subscriber — a bulk import, a future API, a migration, a background job — desyncs metadata from the data record, and the two disagree with no single winner. The projection is eventually-consistent glue, not a cure for having two truths.

Proposed work

Make the data record a pure read-model:

  • The metadata overlay is the only authoritative store.
  • The data record is projected from it (read-only) and never independently authoritative — reads that need SQL/query go through the projection; writes always target metadata.
  • Alternatively, evaluate collapsing to a single store if the query needs can be served from metadata directly.

This needs an ADR (follow-up to ADR-0056) to choose the direction and define the migration/backfill path.

Acceptance criteria

  • One authoritative store; the other is derived and documented as read-only.
  • No write path can desync the two — enforced structurally, not by a subscriber a new path might forget to trigger.
  • Setup reflects Studio edits with no projection race.

References

Follow-up raised after landing the #2867 projection fix — this issue is the durable root-cause fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions