Skip to main content
Version: v5.7.0

opschain admin identity convert-username-subjects

Included from Basic tier

Converts every subject and approver entry still stored as a username into the principal id it names. Transport grants with a user subject and the approver lines of approval policies match on the principal id — a username is a mapped claim one account per provider may hold, so matching on it would let a federated sign-in inherit a same-named local account's authority. Records written before that rule carried usernames; this command rewrites them, directly against the database (no server, no login), after a dry run.

The sweep covers every record family that names people:

recordfield
transport grantsubject_id (user subjects) and approvers
approval policyapprovers.users
subtree owner declarationowners.users
open approval checklist lineapprovers.users (the frozen copy a pending or approved checklist still decides on)

Each stored username resolves exactly as the write seams resolve a typed one:

  • a username one account holds becomes that account's principal id (converted);
  • a username several accounts hold — a local sam beside a federated sam — is refused by name (ambiguous) and left as stored, with the remedy: rewrite the entry as <provider>:<username> (local:sam, ldap:corp:sam, oidc:okta:sam — the account's auth_provider value, which is what opschain admin users list shows) and re-run;
  • a username no account holds is reported (unknown) and left as stored: re-point the record at an existing principal or remove the entry.

The resolvable rows are rewritten set-based in one transaction; a run with refusals still converts everything it could, prints them, and exits non-zero so they are not missed. Until every row converts, a stored username keeps matching through the dual-read window and every such hit records warn:identity:username_match naming the record (never the username) with this command as the remedy; once the sweep finds nothing to do the username leg is inert. The run records audit:identity:username_subjects_conversion with its counts.

opschain admin identity convert-username-subjects --store postgres://… --dry-run
Username-subject conversion (dry run — nothing written): converted=5 ambiguous=2 unknown=1

RECORD ID FIELD VALUE OUTCOME PRINCIPAL REMEDY
transport_grant 019a… subject_id priya converted 019a… -
transport_grant 019a… approvers sam ambiguous - held by several accounts: rewrite the entry as one of ldap:corp:sam, local:sam
approval_policy 019a… approvers.users nobody unknown - no account holds this username: re-point the record at an existing principal, or remove the entry
…

Re-run without --dry-run to apply. The command is idempotent: a rerun finds only the rows it could not convert.

Flags​

FlagMeaning
--store <dsn>Required. A postgres:// (or postgresql://) DSN over the adopted governance tables.
--dry-runCompute and print the conversion plan without writing anything.

Global -o, --output json|yaml switches to the machine document (the rows and the counts map).

See also​

  • opschain docs cli/admin-transport-grants-create — the subject and approver inputs take a principal id, a username or <provider>:<username>.
  • opschain docs cli/approval-policies-create — the approver-user input likewise.
  • opschain docs identity — same username in two providers.
  • opschain docs events — warn:identity:username_match.