0.5.1 Schema-Versioned Migration Admin Tab
Goal
Add a guarded Admin UI migration tab for the entire 0.5.1 upgrade from main. Admins should be able to discover legacy data shape issues, preview collection/schema changes, confirm each migration, and apply migration runs with audit/provenance. The framework should support both:
- Implicit migrations for high-cardinality records where Mongo ownership remains the source of truth, starting with conversations.
- Explicit ReBAC migrations for lower-cardinality resources where OpenFGA tuples are the source of truth, such as teams, agents, KB grants, skills, Slack channel routes, AgentGateway MCP resources, and platform settings.
The branch is release/0.5.1; the migration inventory should be derived from changes since main.
Recommended Authorization Model
Use implicit ownership for high-cardinality private objects and explicit OpenFGA for shared/admin/resource grants:
For 0.5.1, this means private conversations should not create one OpenFGA owner tuple per conversation. Mongo already stores the owner and should remain authoritative for private owner access. OpenFGA should represent explicit sharing, team access, admin/audit access, and lower-cardinality resource grants.
0.5.1 Migration Domains
Create a release manifest that groups migrations by domain. Initial domains:
conversations: implicit owner identity normalization fromowner_idemail toowner_subjectwhile preservingowner_id.conversation_shares: optional explicit migration for direct/team shares into OpenFGAreaderorwritertuples.teams: team membership source normalization, identity group sync provenance, and team slug consistency.team_resources: team-to-agent/tool/skill/task grants already covered by universal ReBAC backfill; expose it in the UI migration tab.team_kb_ownership: explicit OpenFGAknowledge_basereader/ingestor/manager tuple reconciliation.skill_hubs: stable hub skill ids and explicitskill:<id>grants for team resources.slack_channel_routes: OpenFGA-backed Slack channel-agent associations with Mongo retained only for listen mode and priority metadata.dynamic_agents: agent tool caller tuple reconciliation and generated-agent write ownership consistency.agentgateway_mcp: AgentGateway-discovered MCP server records andmcp_server:agentgatewayadmin/discover gates.platform_config: schema version record for default agent/system settings.audit_events: ensure RBAC audit/event indexes and version metadata exist.
Data Schema Versioning
Maintain schema versions in Mongo so all 0.5.1 migrations are explicit and auditable:
- Add a
schema_migrationscollection for migration execution state:_id: stable migration id, for exampleconversation_owner_identity_v1release:0.5.1schema_area:conversationsfrom_version,to_versionstatus:planned,running,completed,failed,rolled_backplanned_counts,applied_counts,warnings,sample_diffscollections,indexes,tuple_writes_planned,tuple_writes_appliedstarted_by,started_at,completed_at
- Add a lightweight
data_schema_versionscollection:_id: schema area, for exampleconversationsversion: current version, for example2updated_by,updated_at,last_migration_id
- Add a
migration_manifestscollection or code-backed manifest response:release:0.5.1domains: migration ids, descriptions, required/optional flags, dependencies, and rollback support.
- For conversations, version
1is legacy email-only ownership; version2adds normalized subject metadata while keeping backwards-compatible email fields.
Conversation Schema Change
Keep existing fields and add normalized identity fields:
- Existing:
owner_id: stringremains the legacy email owner field. - New:
owner_subject?: stringstores Keycloaksubwhen resolvable. - New:
owner_identity_version?: 2marks records normalized by migration or new writes. - New optional provenance under metadata, such as
metadata.owner_identity_migration, records migration id and timestamp.
This avoids breaking old code and avoids per-conversation OpenFGA owner tuples.
Backend Migration Framework
Add a server-side migration registry in the UI backend:
- Migration definition includes
id,schema_area,from_version,to_version,description,plan(), andapply(). plan()is read-only and returns counts, unresolved owners, sample diffs, and target collection changes.apply()requires admin plussystem_config:platform_settingsadminpermission and writes only after confirmation.- Execution should be idempotent: reruns skip already-normalized records.
- Migrations should be chunked/batched to avoid long API timeouts.
- Migrations should declare whether they are:
implicit: Mongo/schema-only, no OpenFGA owner tuple expansion.explicit: writes or reconciles OpenFGA base tuples.index: creates Mongo indexes or schema metadata.
- The registry should enforce dependencies, for example
users.keycloak_submappings beforeconversations.owner_subject.
Admin UI Tab
Add a Migration tab under Admin settings or ReBAC admin:
- Show the
0.5.1 from mainmigration manifest with current schema version and status for each domain. - Admin clicks a migration to run a dry-run preview.
- Preview displays affected collections, proposed schema version, counts, unresolved identities, tuple write counts, index changes, and sample before/after rows with sensitive fields minimized.
- Admin must confirm with a typed confirmation string, for example
MIGRATE conversations TO v2. - Apply endpoint records a migration run, applies batches, stores results, and surfaces errors.
- The tab should support:
Dry RunApplyResume failed runView detailsDownload JSON reportRollbackonly for migrations with a safe rollback contract.
First Migration: Implicit Conversation Ownership
Implement conversation_owner_identity_v1:
- Read distinct
conversations.owner_idemails. - Resolve
owner_idtousers.keycloak_suborusers.metadata.keycloak_sub. - For resolvable owners, update conversations with
owner_subjectandowner_identity_version: 2. - For unresolved owners, leave
owner_iduntouched and report warnings. - Do not write
user:<sub> owner conversation:<id>tuples. - Update chat authorization to allow implicit owner access from
owner_subject === session.subor legacyowner_id === session.user.email; only call OpenFGA for non-owner explicit shares/admin checks.
Release-Wide Migration Behavior
For the rest of 0.5.1:
- Reuse existing
scripts/backfill-universal-rebac.tslogic as a backend migration, not just a CLI script, for teams/resources/default-agent relationships. - Reuse
scripts/backfill-agent-tool-openfga.tslogic for dynamic-agent tool caller tuples. - Add migration implementations for KB ownership, skill hub grants, Slack channel-agent route tuples, and AgentGateway MCP onboarding if the corresponding Mongo state exists.
- Avoid writing explicit tuples for high-cardinality private documents unless the tuple represents sharing or delegation.
- Store provenance in
rebac_relationshipsfor explicit relationships, but do not require onerebac_relationshipsrow for every private conversation owner.
Files To Change Later
Likely implementation surface:
ui/src/types/mongodb.tsfor conversation schema fields and migration collection types.ui/src/lib/api-middleware.tsfor identity-aware conversation ownership/access helpers.ui/src/app/api/chat/**/route.tsto use implicit owner access before OpenFGA checks.- New
ui/src/lib/rbac/migrations/registry and conversation migration implementation. - New
ui/src/app/api/admin/rebac/migrations/orui/src/app/api/admin/migrations/endpoints. - New Admin UI tab component, likely under
ui/src/components/admin/. - Existing migration scripts to adapt or wrap:
scripts/backfill-universal-rebac.ts,scripts/backfill-agent-tool-openfga.ts, andscripts/init-rbac-mongo-indexes.ts. - Update
docs/docs/security/rbac/architecture.md,docs/docs/security/rbac/workflows.md, anddocs/docs/security/rbac/file-map.md.
Verification
Add tests for:
- Migration dry-run counts and sample diffs.
- Apply idempotency and unresolved owner warnings.
data_schema_versionsandschema_migrationsupdates.- Release manifest dependency ordering for
0.5.1. - Existing backfill script behavior when invoked through the migration registry.
- Conversation list/read/write behavior for
owner_subject, legacyowner_id, explicit OpenFGA share, and denial. - Explicit low-cardinality migrations write base tuples and never derived
can_*tuples. - Admin UI confirmation flow.
Non-Goals
Do not write per-conversation owner OpenFGA tuples for private conversations. Do not make Task Builder a 0.5.1 migration target because it is scheduled for a separate refactor. Do not require every historical record to be fully migratable before the UI is usable; unresolved identities should remain legacy-compatible and visible to their email owner while flagged in migration warnings.