{"version":3,"file":"totp-native.mjs","names":[],"sources":["../../src/internal/totp-native.ts"],"sourcesContent":["import type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport {\n  TotpUnavailable,\n  TotpMutation,\n  TotpPolicy,\n  TotpRecord,\n  TotpSnapshot,\n  type TotpDecision,\n  type TotpPersistence,\n} from \"@yielded/auth/Totp\";\nimport * as Cause from \"effect/Cause\";\nimport * as Digest from \"effect/crypto/Digest\";\nimport * as SecureRandom from \"effect/crypto/SecureRandom\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\nimport * as SqlClient from \"effect/sql/SqlClient\";\nimport type * as Statement from \"effect/sql/Statement\";\n\nimport { digest, randomId } from \"./crypto\";\nimport { sqlBatchAssertion } from \"./d1-planning\";\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport type { TotpMapping } from \"./models/totp-model\";\nimport type { NativeSqlTables, SqlTable } from \"./native-sql-table\";\nimport { makeNativeSessionPending, prepareNativeSession } from \"./session-native-pending\";\nimport { makeConditionalSqlInsert } from \"./session-native-record\";\nimport { assessSessionAt, sameSessionRevision } from \"./session-native-state\";\nimport { exactSqlText, executeSqlChange } from \"./sql-change\";\nimport {\n  CurrentSqlCommit,\n  makeSqlCommitExecutor,\n  SqlBatchCommit,\n  appendSqlBatchStatement,\n  registerSqlBatchPostcondition,\n  registerSqlPostcondition,\n} from \"./sql-commit\";\nimport type { AnyTableModel } from \"./table-model\";\n\nexport type NativeTotpMapping = TotpMapping<\n  AnyTableModel,\n  AnyTableModel,\n  AnyTableModel,\n  unknown,\n  AnyTableModel\n>;\n\nconst unavailable = () => TotpUnavailable.make({});\n\nconst invalidState = () =>\n  PersistenceMappingError.make({ operation: \"decode\", cause: \"Invalid TOTP authority\" });\n\nconst codec = Schema.fromJsonString(TotpRecord);\nconst encodeTotpRecord = Schema.encodeSync(codec);\nconst reject: TotpDecision = { _tag: \"Rejected\" };\n\nexport const makeNativeTotpServices = Effect.fnUntraced(function* (\n  tables: NativeSqlTables,\n  mapping: NativeTotpMapping,\n): Effect.fn.Return<\n  { readonly totpPersistence: TotpPersistence[\"Service\"] },\n  never,\n  | SqlClient.SqlClient\n  | LifecycleHooks\n  | (SecureRandom.SecureRandom | Digest.Digest)\n  | SqlBatchCommit\n> {\n  const batch = yield* SqlBatchCommit;\n  const conditionalInsert = yield* makeConditionalSqlInsert();\n\n  const sql = (yield* SqlClient.SqlClient).withoutTransforms(),\n    crypto = yield* SecureRandom.SecureRandom,\n    digests = yield* Digest.Digest,\n    executor = yield* makeSqlCommitExecutor(unavailable),\n    external = yield* Effect.serviceOption(CurrentSqlCommit);\n\n  const s = mapping.subject,\n    f = mapping.factor,\n    c = mapping.credential,\n    subject = tables(s.table),\n    factor = tables(f.table),\n    credential = tables(c.table),\n    engineNow = tables.expression(mapping.engineNowMillis);\n\n  const active = tables.expression(s.activeCondition),\n    activeCredential = tables.expression(c.activeCondition);\n\n  const lock = sql.onDialectOrElse({ sqlite: () => sql``, orElse: () => sql`for update` });\n\n  const nativeLocks =\n    batch === undefined && sql.onDialectOrElse({ sqlite: () => false, orElse: () => true });\n\n  const exact = (table: SqlTable, key: string, value: unknown) =>\n    exactSqlText(sql, table.column(key), table.value(key, value));\n\n  const id = (table: SqlTable, key: string, value: unknown) =>\n    sql`${table.column(key)} = ${table.value(key, value)}`;\n\n  const pending =\n    mapping.pending === undefined\n      ? undefined\n      : yield* makeNativeSessionPending(\n          tables,\n          {\n            ...mapping.pending,\n            subjectId: {\n              toNative: (id) => Effect.sync(() => mapping.subjectIds.toNative(id)),\n              toSubject: (id) => Effect.sync(() => mapping.subjectIds.toSubject(id)),\n              equals: Object.is,\n            },\n          },\n          batch !== undefined,\n        );\n\n  const provide = <A, E, R>(work: Effect.Effect<A, E, R>) =>\n    work.pipe(\n      Effect.provideService(SecureRandom.SecureRandom, crypto),\n      Effect.provideService(Digest.Digest, digests),\n    );\n\n  const run = <A, E, R>(work: Effect.Effect<A, E, R>) =>\n    batch === undefined\n      ? executor.run(provide(work))\n      : executor.batch(provide(work)).pipe(Effect.provideService(SqlBatchCommit, batch));\n\n  const stage = Effect.fnUntraced(function* (statement: Statement.Fragment, expected = 1) {\n    if (batch !== undefined) {\n      yield* appendSqlBatchStatement(sql`${statement}`);\n      yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`changes() = ${expected}`));\n    } else {\n      if (!((yield* executeSqlChange(sql, statement)) === expected)) return yield* invalidState();\n    }\n  });\n\n  const capture = Effect.fnUntraced(function* (\n    subjectId: TotpRecord[\"subjectId\"],\n    locking = false,\n  ) {\n    const nativeId = mapping.subjectIds.toNative(subjectId);\n\n    if (!(mapping.subjectIds.toSubject(nativeId) === subjectId)) return yield* invalidState();\n\n    const scope = yield* digest(\n      `effect-auth/totp/scope/v1/${mapping.moduleId.length}:${mapping.moduleId}/${subjectId}`,\n    );\n\n    if (locking && nativeLocks) {\n      const owners =\n        yield* sql`select ${subject.column(s.id)} from ${subject.name} where ${id(subject, s.id, nativeId)} and ${active} limit 2 ${lock}`;\n\n      if (!(owners.length <= 1)) return yield* invalidState();\n      if (owners[0] === undefined) return undefined;\n    }\n    // The distinct subject lock always precedes the ordered authority locks.\n    // Advisory snapshots use this same bounded join without transaction control.\n    const currentCredentials = sql`select ${credential.fields(\"c_\")} from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${activeCredential} order by ${credential.column(c.id)} limit 65 ${locking && nativeLocks ? lock : sql``}`;\n\n    const rows =\n      yield* sql`with current_credentials as ${sql.onDialectOrElse({ pg: () => sql`materialized`, orElse: () => sql`` })} (${currentCredentials})\n      select ${subject.fields(\"s_\")}, ${factor.fields(\"f_\")}, current_credentials.*, ${engineNow} as engine_now\n      from ${subject.name} left join ${factor.name} on ${exact(factor, f.scope, scope)} left join current_credentials on 1 = 1\n      where ${id(subject, s.id, nativeId)} and ${active} limit 65`;\n\n    if (!(rows.length <= 64)) return yield* invalidState();\n    if (rows[0] === undefined) return undefined;\n\n    const subjectRow = subject.decode(rows[0], \"s_\"),\n      decoded = factor.decode(rows[0], \"f_\");\n\n    const factorRow =\n      decoded[f.scope] === null || decoded[f.scope] === undefined ? undefined : decoded;\n\n    const now = Number(rows[0].engine_now);\n    const credentials: { credentialId: unknown; revision: unknown }[] = [];\n\n    for (const row of rows) {\n      const value = credential.decode(row, \"c_\");\n\n      if (value[c.id] === null || value[c.id] === undefined) continue;\n      if (!(mapping.subjectIds.toSubject(value[c.subjectId]) === subjectId))\n        return yield* invalidState();\n      if (credentials.some((entry) => entry.credentialId === value[c.id]))\n        return yield* invalidState();\n      credentials.push({ credentialId: value[c.id], revision: value[c.revision] });\n    }\n\n    const revision = yield* Schema.decodeUnknownEffect(TotpSnapshot.fields.revision)({\n      subjectId,\n      securityRevision: subjectRow[s.securityRevision],\n      credentials,\n    });\n\n    const ordered = {\n      ...revision,\n      credentials: [...revision.credentials].sort((left, right) =>\n        left.credentialId.localeCompare(right.credentialId),\n      ),\n    };\n\n    if (\n      !(mapping.subjectIds.toSubject(subjectRow[s.id]) === subjectId && Number.isSafeInteger(now))\n    )\n      return yield* invalidState();\n\n    const record =\n      factorRow === undefined ? null : yield* Schema.decodeUnknownEffect(codec)(factorRow[f.state]);\n\n    if (\n      !(\n        record === null ||\n        (record.moduleId === mapping.moduleId &&\n          record.subjectId === subjectId &&\n          record.version === factorRow?.[f.version] &&\n          (record.secret === null || record.secret.revision === record.revision) &&\n          (record.pending === null || record.pending.secret.revision === record.pending.revision))\n      )\n    )\n      return yield* invalidState();\n\n    if (\n      !(\n        record === null ||\n        record.secret === null ||\n        ordered.credentials.some(\n          (entry) =>\n            entry.credentialId === record.credentialId && entry.revision === record.revision,\n        )\n      )\n    )\n      return yield* invalidState();\n\n    const snapshot = yield* Schema.decodeEffect(Schema.toType(TotpSnapshot))({\n      revision: ordered,\n      requirement: mapping.subject.decodeRequirement(subjectRow),\n      record,\n    });\n\n    return { nativeId, subjectRow, factorRow, scope, snapshot, now };\n  });\n\n  const mutate = Effect.fnUntraced(function* (input: TotpMutation) {\n    if (\n      !(\n        input.moduleId === mapping.moduleId &&\n        (yield* Schema.encodeEffect(Schema.fromJsonString(TotpPolicy))(input.policy).pipe(\n          Effect.orDie,\n        )) ===\n          (yield* Schema.encodeEffect(Schema.fromJsonString(TotpPolicy))(mapping.policy).pipe(\n            Effect.orDie,\n          ))\n      )\n    )\n      return yield* invalidState();\n    const captured = yield* capture(input.subjectId, true);\n\n    if (captured === undefined) return reject;\n\n    const { snapshot, subjectRow, factorRow, scope, nativeId, now } = captured,\n      current = snapshot.record,\n      policy = input.policy,\n      action = input.action;\n\n    if (\n      snapshot.revision.securityRevision !== input.snapshot.revision.securityRevision ||\n      (current?.version ?? null) !== (input.snapshot.record?.version ?? null) ||\n      (current === null) !== (input.snapshot.record === null) ||\n      (current !== null && encodeTotpRecord(current) !== encodeTotpRecord(input.snapshot.record!))\n    )\n      return reject;\n\n    let expectedCount: number | undefined,\n      countGuardIndex = -1;\n\n    const guards: Statement.Fragment[] = [],\n      timeGuards: Statement.Fragment[] = [],\n      credentialGuards: { credentialId: string; condition: Statement.Fragment }[] = [];\n\n    const timeBound = (start: number, end: number) => {\n      timeGuards.push(sql`${engineNow} >= ${start} and ${engineNow} < ${end}`);\n    };\n\n    if (\n      action._tag === \"Enroll\" ||\n      action._tag === \"Confirm\" ||\n      action._tag === \"Disable\" ||\n      action._tag === \"Regenerate\"\n    ) {\n      const authorization = input.authorization;\n\n      if (authorization === undefined) return reject;\n      const { challenge, evidence } = authorization;\n\n      const expectedAction = {\n        Enroll: \"enroll\",\n        Confirm: \"confirm\",\n        Disable: \"disable\",\n        Regenerate: \"regenerate\",\n      }[action._tag];\n\n      if (\n        challenge.action !== expectedAction ||\n        challenge.moduleId !== mapping.moduleId ||\n        challenge.revision.subjectId !== input.subjectId ||\n        challenge.revision.securityRevision !== snapshot.revision.securityRevision ||\n        evidence.flowId !== challenge.flowId ||\n        evidence.bindingDigest !== challenge.bindingDigest ||\n        evidence.revision.subjectId !== input.subjectId ||\n        evidence.revision.securityRevision !== snapshot.revision.securityRevision\n      )\n        return reject;\n      for (const revision of evidence.revision.credentials)\n        credentialGuards.push({\n          credentialId: revision.credentialId,\n          condition: sql`exists(select 1 from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${exact(credential, c.id, revision.credentialId)} and ${exact(credential, c.revision, revision.revision)} and ${activeCredential})`,\n        });\n      expectedCount = evidence.revision.credentials.length;\n      countGuardIndex = guards.length;\n      guards.push(\n        sql`(select count(*) from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${activeCredential}) = ${evidence.revision.credentials.length}`,\n      );\n\n      const requirements = [authorization.requirement, snapshot.requirement],\n        maximumAge = Math.min(\n          policy.maximumEvidenceAgeMillis,\n          ...requirements.map((r) => r.maximumAgeMillis),\n        );\n\n      for (const requirement of requirements) {\n        const assessed = yield* assessSessionAt(\n          evidence,\n          { ...requirement, maximumAgeMillis: maximumAge },\n          now,\n        ).pipe(Effect.result);\n\n        if (assessed._tag === \"Failure\" || !assessed.success.satisfied) return reject;\n      }\n      for (const proof of evidence.proofs) {\n        const verified = DateTime.toEpochMillis(proof.verifiedAt);\n\n        if (verified > now || now - verified >= maximumAge) return reject;\n        timeBound(verified, verified + maximumAge);\n      }\n      if (\n        (current !== null && current.secret !== null) ||\n        action._tag === \"Disable\" ||\n        action._tag === \"Regenerate\"\n      ) {\n        const factors = new Set(evidence.proofs.flatMap((p) => p.factors));\n\n        if (\n          !(\n            evidence.proofs.some(\n              (p) => p.userVerified && p.phishingResistant && p.factors.includes(\"possession\"),\n            ) ||\n            (factors.has(\"knowledge\") &&\n              factors.has(\"possession\") &&\n              new Set(evidence.proofs.map((p) => p.credentialId)).size >= 2)\n          )\n        )\n          return reject;\n      }\n    }\n    if (action._tag === \"Recovery\" && action.reset) {\n      const target = action.pending;\n\n      if (\n        target === undefined ||\n        pending === undefined ||\n        mapping.pending === undefined ||\n        target.revision.subjectId !== input.subjectId ||\n        target.revision.securityRevision !== snapshot.revision.securityRevision ||\n        target.expiresAtMillis <= now\n      )\n        return reject;\n      const selected = yield* pending.read(\"Login\", target.digest);\n\n      if (selected === undefined) return reject;\n      const original = yield* mapping.pending.login.decode(selected.record.snapshot);\n\n      if (\n        selected.record.flowId !== target.flowId ||\n        selected.record.bindingDigest !== target.bindingDigest ||\n        selected.record.subjectId !== input.subjectId ||\n        selected.record.expiresAtMillis !== target.expiresAtMillis ||\n        original.digest !== target.digest ||\n        !sameSessionRevision(original.evidence.revision, target.revision)\n      )\n        return reject;\n      guards.push(\n        sql`exists(select 1 from ${pending.table.name} where ${pending.predicate(pending.table, \"Login\", target.digest)} and ${exact(pending.table, pending.p.snapshot, selected.record.snapshot)} and ${exact(pending.table, pending.p.version, original.version)})`,\n      );\n      for (const revision of target.revision.credentials)\n        credentialGuards.push({\n          credentialId: revision.credentialId,\n          condition: sql`exists(select 1 from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${exact(credential, c.id, revision.credentialId)} and ${exact(credential, c.revision, revision.revision)} and ${activeCredential})`,\n        });\n      timeBound(0, target.expiresAtMillis);\n    }\n\n    let next: TotpRecord,\n      semantic = false,\n      accepted = true;\n\n    if (action._tag === \"Enroll\") {\n      const candidate = action.record;\n\n      if (\n        candidate.subjectId !== input.subjectId ||\n        candidate.moduleId !== input.moduleId ||\n        candidate.pending === null ||\n        candidate.pending.expiresAtMillis <= now ||\n        candidate.pending.expiresAtMillis > now + policy.enrollmentLifetimeMillis ||\n        candidate.pending.failedAttempts !== 0 ||\n        candidate.pending.secret.revision !== candidate.pending.revision\n      )\n        return reject;\n      // Reissuing cannot erase the confirmation budget during its current enrollment lifetime.\n      if (current !== null && current.pending !== null && current.pending.expiresAtMillis > now)\n        return reject;\n      if (\n        current !== null &&\n        (candidate.credentialId !== current.credentialId ||\n          encodeTotpRecord({ ...candidate, pending: current.pending }) !==\n            encodeTotpRecord(current))\n      )\n        return reject;\n      if (\n        current === null &&\n        (candidate.secret !== null ||\n          candidate.recoveryDigests.length !== 0 ||\n          candidate.acceptedStep !== -1 ||\n          candidate.failedAttempts !== 0)\n      )\n        return reject;\n      next = candidate;\n      timeBound(0, candidate.pending.expiresAtMillis);\n    } else {\n      if (current === null) return reject;\n      next = { ...current };\n      if (action._tag === \"Confirm\") {\n        const pending = current.pending;\n\n        if (\n          pending === null ||\n          pending.enrollmentId !== action.enrollmentId ||\n          pending.expiresAtMillis <= now ||\n          pending.failedAttempts >= policy.attemptLimit\n        )\n          return reject;\n        timeBound(0, pending.expiresAtMillis);\n        if (\n          action.matchedStep === null ||\n          Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n        ) {\n          next = {\n            ...current,\n            pending: { ...pending, failedAttempts: pending.failedAttempts + 1 },\n          };\n          accepted = false;\n        } else {\n          if (new Set(action.recoveryDigests).size !== 10) return reject;\n          next = {\n            ...current,\n            secret: pending.secret,\n            revision: pending.secret.revision,\n            pending: null,\n            recoveryDigests: action.recoveryDigests,\n            acceptedStep: action.matchedStep,\n            attemptWindow: now,\n            failedAttempts: 0,\n          };\n          semantic = true;\n          timeBound(\n            Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n            (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n          );\n        }\n      } else if (action._tag === \"Verify\" || action._tag === \"Recovery\") {\n        if (current.secret === null) return reject;\n\n        const expired = now >= current.attemptWindow + policy.attemptWindowMillis,\n          attempts = expired ? 0 : current.failedAttempts,\n          start = expired ? now : current.attemptWindow;\n\n        if (attempts >= policy.attemptLimit) return reject;\n        next = { ...current, attemptWindow: start, failedAttempts: attempts + 1 };\n        if (action._tag === \"Verify\") {\n          if (\n            action.matchedStep === null ||\n            action.matchedStep <= current.acceptedStep ||\n            Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n          )\n            accepted = false;\n          else {\n            next = { ...next, acceptedStep: action.matchedStep, failedAttempts: 0 };\n            timeBound(\n              Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n              (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n            );\n          }\n        } else {\n          if (\n            (action.reset\n              ? policy.lostFactorRecovery !== \"reset-with-recovery-code\"\n              : !policy.allowRecoveryCodeForPending) ||\n            !current.recoveryDigests.includes(action.digest)\n          )\n            accepted = false;\n          else {\n            next = {\n              ...next,\n              recoveryDigests: current.recoveryDigests.filter((value) => value !== action.digest),\n              failedAttempts: 0,\n            };\n            if (action.reset) {\n              next = {\n                ...next,\n                secret: null,\n                pending: null,\n                recoveryDigests: [],\n                revision: yield* randomId,\n              };\n              semantic = true;\n            }\n          }\n        }\n      } else {\n        if (current.secret === null) return reject;\n        semantic = action._tag === \"Disable\";\n        if (action._tag === \"Disable\")\n          next = {\n            ...current,\n            secret: null,\n            pending: null,\n            recoveryDigests: [],\n            revision: yield* randomId,\n          };\n        else {\n          if (new Set(action.recoveryDigests).size !== 10) return reject;\n          next = { ...current, recoveryDigests: action.recoveryDigests };\n        }\n      }\n    }\n    next = { ...next, version: yield* randomId };\n\n    const ownerKey = id(subject, s.id, nativeId);\n    const initialAuthority = sql`exists(select 1 from ${subject.name} where ${ownerKey} and ${exact(subject, s.securityRevision, snapshot.revision.securityRevision)} and ${active})`;\n\n    const initialFactor =\n      factorRow === undefined\n        ? sql`not exists(select 1 from ${factor.name} where ${exact(factor, f.scope, scope)})`\n        : sql`exists(select 1 from ${factor.name} where ${exact(factor, f.scope, scope)} and ${exact(factor, f.version, current!.version)})`;\n\n    const policyGuard = sql.and(\n      (s.requirementColumns ?? []).map((key) =>\n        subjectRow[key] === null\n          ? sql`${subject.column(key)} is null`\n          : sql`${subject.column(key)} = ${subject.value(key, subjectRow[key])}`,\n      ),\n    );\n\n    const policyCondition = sql`exists(select 1 from ${subject.name} where ${ownerKey} and ${policyGuard})`;\n    const fresh = sql.and([...timeGuards, sql`${engineNow} >= ${now}`]);\n\n    // A factor UPDATE pins scope and version itself, and MySQL rejects a subquery\n    // on the table being updated (error 1093), so only inserts add initialFactor.\n    const unchangedFactor = sql.and([\n      initialAuthority,\n      policyCondition,\n      fresh,\n      ...guards,\n      ...credentialGuards.map((g) => g.condition),\n    ]);\n\n    let nextRevision = snapshot.revision.securityRevision;\n\n    if (semantic) {\n      nextRevision = SecurityRevision.make(yield* randomId);\n      // Subject is the first lock and first graph mutation. The conditional write\n      // validates original evidence before changing the TOTP authority vector.\n      yield* stage(\n        sql`${subject.update({ [s.securityRevision]: nextRevision, [s.factorEnabled]: s.encodeEnabled(next.secret !== null) })} where ${ownerKey} and ${exact(subject, s.securityRevision, snapshot.revision.securityRevision)} and ${active} and ${fresh} and ${initialFactor} and ${policyGuard} and ${sql.and([...guards, ...credentialGuards.map((g) => g.condition)])}`,\n      );\n\n      const values = {\n        ...c.encodeInsert({\n          credentialId: next.credentialId,\n          subjectId: nativeId,\n          revision: next.revision,\n          active: next.secret !== null,\n        }),\n        [c.id]: next.credentialId,\n        [c.subjectId]: nativeId,\n        [c.revision]: next.revision,\n        [c.status]: c.encodeStatus(next.secret !== null),\n      };\n\n      const insert = credential.insert(values);\n\n      const changes = {\n        [c.revision]: next.revision,\n        [c.status]: c.encodeStatus(next.secret !== null),\n      };\n\n      const upsert = sql.onDialectOrElse({\n        mysql: () =>\n          sql`${insert} on duplicate key update ${credential.columnName(c.revision)} = case when ${id(credential, c.subjectId, nativeId)} then ${credential.value(c.revision, next.revision)} else ${credential.column(c.revision)} end, ${credential.columnName(c.status)} = case when ${id(credential, c.subjectId, nativeId)} then ${credential.value(c.status, c.encodeStatus(next.secret !== null))} else ${credential.column(c.status)} end`,\n        orElse: () =>\n          sql`${insert} on conflict (${credential.columnName(c.id)}) do update set ${sql.join(\", \", false)(Object.entries(changes).map(([key, value]) => sql`${credential.columnName(key)} = ${credential.value(key, value)}`))} where ${id(credential, c.subjectId, nativeId)}`,\n      });\n\n      if (sql.onDialectOrElse({ mysql: () => true, orElse: () => false }) && batch === undefined) {\n        yield* sql`${upsert}`;\n        if (\n          !(\n            (yield* sql`select 1 from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${exact(credential, c.id, next.credentialId)} and ${exact(credential, c.revision, next.revision)} and ${id(credential, c.status, c.encodeStatus(next.secret !== null))}`)\n              .length === 1\n          )\n        )\n          return yield* invalidState();\n      } else yield* stage(upsert);\n    }\n\n    const encoded = encodeTotpRecord(next),\n      values = { [f.state]: encoded, [f.version]: next.version };\n\n    const afterAuthority = sql`exists(select 1 from ${subject.name} where ${ownerKey} and ${exact(subject, s.securityRevision, nextRevision)} and ${active})`;\n    const writeGuard = semantic ? sql`${afterAuthority} and ${fresh}` : unchangedFactor;\n\n    if (factorRow === undefined) {\n      const insert = {\n        ...f.encodeInsert({ scope, state: encoded, version: next.version }),\n        [f.scope]: scope,\n        ...values,\n      };\n\n      yield* stage(\n        yield* conditionalInsert(\n          factor,\n          insert,\n          semantic ? writeGuard : sql.and([writeGuard, initialFactor]),\n        ),\n      );\n    } else\n      yield* stage(\n        sql`${factor.update(values)} where ${exact(factor, f.scope, scope)} and ${exact(factor, f.version, current!.version)} and ${writeGuard}`,\n      );\n\n    const expectedPolicy = semantic\n      ? { ...subjectRow, [s.factorEnabled]: s.encodeEnabled(next.secret !== null) }\n      : subjectRow;\n\n    const finalPolicy = sql`exists(select 1 from ${subject.name} where ${ownerKey} and ${sql.and((s.requirementColumns ?? []).map((key) => (expectedPolicy[key] === null ? sql`${subject.column(key)} is null` : sql`${subject.column(key)} = ${subject.value(key, expectedPolicy[key])}`)))})`;\n\n    const finalCondition = sql.and([\n      afterAuthority,\n      finalPolicy,\n      fresh,\n      sql`exists(select 1 from ${factor.name} where ${exact(factor, f.scope, scope)} and ${exact(factor, f.version, next.version)} and ${exact(factor, f.state, encoded)})`,\n      ...guards.filter((_, index) => expectedCount === undefined || index !== countGuardIndex),\n      ...credentialGuards\n        .filter((g) => !semantic || g.credentialId !== next.credentialId)\n        .map((g) => g.condition),\n      ...(semantic\n        ? [\n            sql`exists(select 1 from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${exact(credential, c.id, next.credentialId)} and ${exact(credential, c.revision, next.revision)} and ${id(credential, c.status, c.encodeStatus(next.secret !== null))})`,\n          ]\n        : []),\n      ...(expectedCount === undefined\n        ? []\n        : [\n            sql`(select count(*) from ${credential.name} where ${id(credential, c.subjectId, nativeId)} and ${activeCredential}) = ${expectedCount + (semantic ? (next.secret === null ? 0 : 1) - (current?.secret === null || current === null ? 0 : 1) : 0)}`,\n          ]),\n    ]);\n\n    if (batch !== undefined)\n      yield* registerSqlBatchPostcondition({\n        name: \"totp-factor-and-authority\",\n        statement: sqlBatchAssertion(sql, finalCondition),\n      });\n    else if (Option.isSome(external))\n      yield* registerSqlPostcondition({\n        name: \"totp-factor-and-authority\",\n        check: Effect.gen(function* () {\n          if (!((yield* sql`select 1 where ${finalCondition}`).length === 1))\n            return yield* invalidState();\n          if (input.authorization !== undefined) {\n            const final = yield* capture(input.subjectId);\n\n            if (!(final !== undefined && final.now >= now)) return yield* invalidState();\n            const expected = mapping.subject.decodeRequirement(expectedPolicy);\n\n            const encodedRequirement = Schema.encodeEffect(\n              Schema.fromJsonString(AuthenticationRequirement),\n            );\n\n            if (\n              !(\n                (yield* encodedRequirement(final.snapshot.requirement).pipe(Effect.orDie)) ===\n                (yield* encodedRequirement(expected).pipe(Effect.orDie))\n              )\n            )\n              return yield* invalidState();\n          }\n        }).pipe(\n          Effect.provideService(SecureRandom.SecureRandom, crypto),\n          Effect.provideService(Digest.Digest, digests),\n          Effect.catchCause((cause) =>\n            Effect.failCause(\n              Cause.map(cause, (error) =>\n                PersistenceMappingError.make({ operation: \"decode\", cause: error }),\n              ),\n            ),\n          ),\n        ),\n      });\n\n    return accepted ? { _tag: \"Accepted\" as const, record: next } : reject;\n  });\n\n  const totpPersistence: TotpPersistence[\"Service\"] = {\n    snapshot: (input) =>\n      executor.read(\n        provide(\n          Effect.gen(function* () {\n            if (!(input.moduleId === mapping.moduleId)) return yield* invalidState();\n\n            return (yield* capture(input.subjectId))?.snapshot;\n          }),\n        ),\n      ),\n    mutate: (original, project) =>\n      run(\n        Effect.gen(function* () {\n          const input = yield* Schema.decodeEffect(Schema.toType(TotpMutation))(original);\n          const decision = yield* mutate(input);\n\n          return yield* prepareNativeSession(decision, project);\n        }),\n      ),\n  };\n\n  return { totpPersistence };\n});\n"],"mappings":"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"}