Skip to main content
Version: main 🚧

MongoDB Migration Plan

Migration Type​

Additive MongoDB migration with no collection rename, destructive data movement, or required plaintext credential export in the first release.

The implementation adds new credential collections and indexes, then provides non-destructive migration preview for existing credential-shaped fields. Existing static credentials, MCP inline env records, skill hub credentials_ref, and catalog API key behavior remain compatible while the feature toggle is disabled.

Required Collections​

credential_secret_refs​

Stores non-secret metadata for secrets, connector client secrets, provider token sets, and migration candidates.

Required indexes:

db.credential_secret_refs.createIndex({ secret_id: 1 }, { unique: true })
db.credential_secret_refs.createIndex({ owner_type: 1, owner_id: 1, kind: 1, status: 1 })
db.credential_secret_refs.createIndex({ provider: 1, connector_id: 1, status: 1 })
db.credential_secret_refs.createIndex({ updated_at: -1 })

credential_encrypted_payloads​

Stores ciphertext, encrypted data keys, key metadata, algorithm metadata, and version history.

Required indexes:

db.credential_encrypted_payloads.createIndex({ payload_id: 1 }, { unique: true })
db.credential_encrypted_payloads.createIndex({ secret_id: 1, version: 1 }, { unique: true })
db.credential_encrypted_payloads.createIndex({ secret_id: 1, created_at: -1 })

oauth_connectors​

Stores non-secret OAuth connector configuration and encrypted client-secret references.

Required indexes:

db.oauth_connectors.createIndex({ connector_id: 1 }, { unique: true })
db.oauth_connectors.createIndex({ provider_key: 1, type: 1 }, { unique: true, partialFilterExpression: { status: { $ne: "deleted" } } })
db.oauth_connectors.createIndex({ status: 1, enabled_for: 1 })

provider_connections​

Stores user/provider relationship metadata and encrypted token-set references.

Required indexes:

db.provider_connections.createIndex({ connection_id: 1 }, { unique: true })
db.provider_connections.createIndex({ subject_user_id: 1, provider_key: 1, state: 1 })
db.provider_connections.createIndex({ connector_id: 1, state: 1 })
db.provider_connections.createIndex({ provider_key: 1, provider_resource_id: 1, state: 1 })

credential_audit_events​

Stores non-secret audit events for credential lifecycle, use, denial, refresh, drift, migration, and feature-toggle changes.

Required indexes:

db.credential_audit_events.createIndex({ created_at: -1, event_type: 1 })
db.credential_audit_events.createIndex({ resource_type: 1, resource_id: 1, created_at: -1 })
db.credential_audit_events.createIndex({ subject_user_id: 1, created_at: -1 })
db.credential_audit_events.createIndex({ correlation_id: 1 })

credential_migration_previews​

Stores non-secret migration scan results and operator decisions.

Required indexes:

db.credential_migration_previews.createIndex({ preview_id: 1 }, { unique: true })
db.credential_migration_previews.createIndex({ source_type: 1, source_id: 1, status: 1 })
db.credential_migration_previews.createIndex({ created_at: -1 })

Schema and Data Movement​

First Release​

  • Create new collections and indexes.
  • Add optional credential reference fields to MCP server configuration records only when users opt into the new model.
  • Add optional connector/provider connection collections without modifying existing Keycloak broker config.
  • Add migration preview that scans existing sources and stores only source ids, field names, risk classification, and recommendations.
  • Do not automatically move existing inline credential values.

Later Apply Migration​

When a future task implements explicit migration apply:

  1. Read the existing credential-shaped value in a server-side context.
  2. Create a credential_secret_refs record.
  3. Encrypt value into credential_encrypted_payloads.
  4. Update the source record to reference secret_id.
  5. Remove or mask the plaintext source value.
  6. Record a credential_audit_events migration event.

The apply operation must be idempotent and must not remove plaintext until encrypted payload write and source-reference update both succeed.

Rollback​

Toggle Rollback​

Disable the credential feature toggle. Existing static credential behavior remains active. New credential metadata and encrypted payload collections are left in place but no new UI/API/runtime actions are exposed.

Index Rollback​

Indexes are additive and can remain safely. If removal is required, drop only the indexes created for this feature after verifying no enabled deployment depends on them.

Data Rollback​

For first-release preview-only migration, no source data is modified. Remove preview records if necessary.

For future apply migrations, rollback requires restoring the previous source value from a pre-migration backup or re-entering the credential through an approved create/rotate flow. Raw credential values must not be reconstructed from logs or audit events.

Environment Differences​

Local Development​

  • CREDENTIAL_KEY_PROVIDER=dev-local may use a generated local key file.
  • Development key files must be ignored by git and must not be reused for production data.
  • Health checks must clearly identify development key mode.

Staging and Production​

  • CREDENTIAL_KEY_PROVIDER=aws-kms or equivalent is required.
  • KMS/CMK access must be scoped to the CAIPE runtime identities that need wrapping and unwrapping.
  • dev-local must fail startup or health checks in production mode.
  • Backup and restore procedures must include MongoDB credential collections and KMS key availability.

Operational Validation​

  • Confirm index bootstrap is idempotent.
  • Confirm health endpoint fails closed when MongoDB, KMS, or OpenFGA is unavailable.
  • Confirm audit events contain reason codes and correlation ids but no raw credential material.
  • Confirm browser API responses mask connector client secrets, provider tokens, and BYO secret values.
  • Confirm Helm rendering includes toggle and KMS references but no hardcoded credentials.