Skip to content

feat(auth): implement secure account merge intents and atomic migration #662

Description

@XiaoSeS

Parent

Problem

The legacy account merge flow cannot prove independent control of both accounts and therefore remains disabled. Implement the safe Account Merge flow defined in docs/22-secure-account-merge-acceptance-design.md without reopening the legacy token-based endpoints.

Scope

  • Server-side, short-lived primary fresh-reauthentication proof bound to the current Web Session.
  • One-time Merge Intent with TTL, session nonce hash, optimistic/pessimistic concurrency control, and stable reason codes.
  • Independent secondary authentication through local password, Browser Provider, or Credential Provider; request bodies must not accept secondary userId, email, username-as-identity, or provider:subject as proof.
  • Real-time conflict preview with preview_version and server-side digest; confirm recomputes the digest and fails stale previews closed.
  • Atomic PostgreSQL migration policy for active Identity Bindings, local credentials, Namespace memberships, Skill ownership, current social state, profile/transient state, and historical references.
  • Block non-default platform-role escalation and new Namespace OWNER acquisition.
  • Revoke (do not migrate) every active secondary API Token.
  • Mark the secondary account MERGED with merged_to_user_id in the same transaction.
  • Stable per-request account-state guard plus retryable Redis Session revocation task and metrics.
  • New flow disabled by default; legacy initiate/verify/confirm endpoints continue returning 503.
  • Account settings UI, operator documentation, OpenAPI contract, audit events, and low-cardinality metrics.

Required migration inventory

Before implementation is considered complete, classify every database/string/JSON reference to a platform user as one of:

  1. current ownership to migrate;
  2. current authorization to migrate/revoke;
  3. historical fact to preserve on the secondary user;
  4. derived/transient data to rebuild, migrate, invalidate, or delete.

Any unclassified user reference blocks release.

Acceptance

  • Primary and secondary proofs are two independent authentication actions and never appear in URL, response, logs, or audit detail.
  • Same-account, system-account, non-ACTIVE, expired, replayed, session-mismatched, conflicting, and concurrent confirmations fail closed.
  • Two concurrent confirms yield exactly one commit.
  • Injected failure at each migration stage rolls back all PostgreSQL changes.
  • Secondary Web Sessions are rejected immediately after commit even if Redis deletion is delayed; deletion retries are observable.
  • Secondary API Tokens return 401 after commit; primary tokens remain valid.
  • PostgreSQL 16 and Redis integration tests, rolling-upgrade checks, and Hong Kong test-machine deployment all pass on the exact big-main SHA.
  • No server reboot; isolated test resources and images/caches are cleaned after validation.

Delivery

Target a dedicated PR at big-main. Do not merge directly to main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    effort/l大改动或高风险改动,需要 maintainer 负责 / Large or risky change requiring maintainer ownership.enhancementNew feature or requestpriority/p2中优先级 / Medium priority triage bucket.risk/high涉及安全、鉴权、迁移或公共契约 / Touches security, auth, migrations, or public contracts.triage/needs-info需要补充更多信息后才能分流 / Issue needs more detail before it can be routed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions