SigilSession

@Singleton
class SigilSession @Inject constructor(passkeyManager: PasskeyManager, sigilIdentityProvider: SigilIdentityProvider, sigilStateStore: SigilStateStore, walletSeedSource: WalletSeedSource)

Single-biometric bootstrap orchestrator for sign-in flows.

The problem this solves. Post-A2, sign-in derives the sigil DID via PRF(passkey, SIGIL_SALT) and the wallet seed via PRF(passkey, SEED_SALT). Each PRF salt is a separate parameter to a separate WebAuthn assertion — two ceremonies, two biometric prompts. After tapping "sign in" the user immediately taps "read balance" and gets prompted again. That's the regression WalletSeedSource.ensureSeedReady inherits from the post-A2 design.

The fix. WebAuthn's PRF extension supports evaluating TWO salts in one assertion (eval.first + eval.second). Modern authenticators (Google Password Manager since Chrome 132, hardware tokens) return both outputs in a single response → one biometric prompt.

Flow:

  1. Single PRF ceremony with prfSaltFirst = SIGIL_SALT and prfSaltSecond = SEED_SALT. One biometric.

  2. Derive sigil DID via SigilIdentityProvider.deriveFromPrfOutput.

  3. Pre-warm SeedVault via WalletSeedSource.acceptPreDerivedSeed so the wallet's first refresh hits cache instead of running its own PRF ceremony.

  4. Persist the sigil triple in SigilStateStore.

Fallback. If the authenticator only evaluates first (older GMS Core, etc.), PasskeyManager.authenticateWithPrf returns prfOutputSecond = null. We then run a second ceremony for SEED_SALT (= two biometrics, same as the pre-SigilSession path). UX degrades gracefully; correctness is unchanged.

Lives in sdk:wallet-seed (not core:identity) because the orchestrator depends on WalletSeedSource for the SeedVault pre-warm — and sdk:wallet-seed already sits above core:identity in the dependency graph, so this is the natural seam.

Constructors

Link copied to clipboard
@Inject
constructor(passkeyManager: PasskeyManager, sigilIdentityProvider: SigilIdentityProvider, sigilStateStore: SigilStateStore, walletSeedSource: WalletSeedSource)

Functions

Link copied to clipboard
suspend fun forge(activity: FragmentActivity, userName: String): ForgeResult

Forge a NEW sigil — create a fresh passkey AND derive its identity (+ pre-warm the wallet seed) in a single biometric ceremony via PRF-on-create.

Link copied to clipboard
suspend fun signIn(activity: FragmentActivity): SigilDerivation

Sign in with an existing passkey and pre-warm the wallet seed.