{"version":3,"file":"password-credentials.mjs","names":[],"sources":["../../src/internal/password-credentials.ts"],"sourcesContent":["import { CurrentCommitJournal, hasCommitScope } from \"@yielded/auth/Hooks\";\nimport type { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport {\n  EncodedPasswordHash,\n  type PasswordPersistence,\n  PasswordUnavailable,\n  snapshotPasswordCredential,\n  type PasswordCredentialSnapshot,\n} from \"@yielded/auth/Password\";\nimport { reportPersistenceFailure } from \"@yielded/auth/Persistence\";\nimport { SecurityRevision } from \"@yielded/auth/Sessions\";\nimport * as Cause from \"effect/Cause\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport * as SqlClient from \"effect/sql/SqlClient\";\n\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport type { AnyPasswordPersistenceMapping } from \"./models/password-model\";\nimport { sqlMapping, type SqlTable } from \"./native-sql-table\";\nimport type { PasswordWorkflowOptions } from \"./password-policy\";\n\ntype Row = Readonly<Record<string, unknown>>;\nconst unavailable = () => PasswordUnavailable.make({});\n\nconst failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n  reportPersistenceFailure(effect, Schema.is(PasswordUnavailable), { markReported: true }).pipe(\n    Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, unavailable))),\n  );\n\nexport const samePasswordCredentialSnapshot = (\n  a: PasswordCredentialSnapshot,\n  b: PasswordCredentialSnapshot,\n) =>\n  a.moduleId === b.moduleId &&\n  a.revision.subjectId === b.revision.subjectId &&\n  a.revision.securityRevision === b.revision.securityRevision &&\n  a.revision.credentials.length === b.revision.credentials.length &&\n  new Set(a.revision.credentials.map((entry) => entry.credentialId)).size ===\n    a.revision.credentials.length &&\n  new Set(b.revision.credentials.map((entry) => entry.credentialId)).size ===\n    b.revision.credentials.length &&\n  a.revision.credentials.every((entry) =>\n    b.revision.credentials.some(\n      (other) => entry.credentialId === other.credentialId && entry.revision === other.revision,\n    ),\n  ) &&\n  a.credentialId === b.credentialId &&\n  a.credentialRevision === b.credentialRevision &&\n  a.verifierVersion === b.verifierVersion &&\n  Redacted.value(a.verifier) === Redacted.value(b.verifier) &&\n  a.normalization === b.normalization &&\n  a.identifier.namespace === b.identifier.namespace &&\n  a.identifier.value === b.identifier.value &&\n  a.identifierBindingRevision === b.identifierBindingRevision &&\n  a.identifierVerifiedAtMillis === b.identifierVerifiedAtMillis;\n\n/** Lookup is read-only; rehash is one conditional maintenance write, never authentication. */\nexport const makePasswordCredentials = Effect.fnUntraced(function* (\n  table: (table: object) => SqlTable,\n  mapping: AnyPasswordPersistenceMapping,\n  options: PasswordWorkflowOptions,\n): Effect.fn.Return<\n  Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">,\n  PasswordUnavailable,\n  SqlClient.SqlClient\n> {\n  const sql = (yield* SqlClient.SqlClient).withoutTransforms();\n  const parent = yield* Effect.serviceOption(CurrentCommitJournal);\n\n  const [s, i, c, a] = yield* sqlMapping(\n    () =>\n      [\n        table(mapping.subject.table),\n        table(mapping.identifier.table),\n        table(mapping.credential.table),\n        table(mapping.authorityCredential.table),\n      ] as const,\n  ).pipe(failure);\n\n  const standalone = Effect.gen(function* () {\n    if (options.coordinated) {\n      const current = yield* Effect.serviceOption(CurrentCommitJournal);\n\n      if (Option.isNone(parent) || Option.isNone(current) || parent.value !== current.value)\n        return yield* unavailable();\n    } else {\n      if (yield* hasCommitScope) return yield* unavailable();\n      yield* options.standaloneGuard;\n    }\n  });\n\n  const allocate = <A>(\n    asynchronous: Effect.Effect<A, PersistenceMappingError> | undefined,\n    sync: (() => A) | undefined,\n  ) => {\n    if (options.mode !== \"synchronous\" && asynchronous !== undefined) return asynchronous;\n\n    return sync === undefined\n      ? Effect.fail(unavailable())\n      : Effect.try({ try: sync, catch: unavailable });\n  };\n\n  // Bind each native ID through its own column codec. Physical encodings of the\n  // same application ID need not match across subject, identifier and password.\n  const snapshot = Effect.fnUntraced(function* (\n    nativeId: unknown,\n    moduleId: string,\n    identifier: LoginIdentifier,\n  ) {\n    const subjectTable = s.as(\"password_subject\");\n    const identifierTable = i.as(\"password_identifier\");\n    const credentialTable = c.as(\"password_credential\");\n    const authorityTable = a.as(\"password_authority\");\n    const authority = mapping.authorityCredential;\n\n    const rows = yield* sqlMapping(\n      () =>\n        sql<Row>`select ${subjectTable.fields(\"subject_\")}, ${identifierTable.fields(\"identifier_\")}, ${credentialTable.fields(\"credential_\")}, ${authorityTable.fields(\"authority_\")}\n      from ${subjectTable.name}\n      inner join ${identifierTable.name} on ${identifierTable.column(mapping.identifier.namespace)} = ${identifierTable.value(mapping.identifier.namespace, identifier.namespace)}\n        and ${identifierTable.column(mapping.identifier.value)} = ${identifierTable.value(mapping.identifier.value, identifier.value)}\n        and ${identifierTable.column(mapping.identifier.subjectId)} = ${identifierTable.value(mapping.identifier.subjectId, nativeId)}\n      inner join ${credentialTable.name} on ${credentialTable.column(mapping.credential.moduleId)} = ${credentialTable.value(mapping.credential.moduleId, moduleId)}\n        and ${credentialTable.column(mapping.credential.subjectId)} = ${credentialTable.value(mapping.credential.subjectId, nativeId)}\n      left join ${authorityTable.name} on ${authorityTable.column(authority.subjectId)} = ${authorityTable.value(authority.subjectId, nativeId)}\n        ${authority.status === undefined || authority.d1ActiveStatusValue === undefined ? sql`` : sql`and ${authorityTable.column(authority.status)} = ${authorityTable.value(authority.status, authority.d1ActiveStatusValue)}`}\n      where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)} order by ${authorityTable.column(authority.credentialId)} limit 4097\n      `,\n    ).pipe(Effect.flatten);\n\n    if (rows.length === 0) return undefined;\n    if (rows.length > 4096) return yield* unavailable();\n\n    const [subject, identifierRow, credential] = yield* sqlMapping(\n      () =>\n        [\n          s.decode(rows[0]!, \"subject_\"),\n          i.decode(rows[0]!, \"identifier_\"),\n          c.decode(rows[0]!, \"credential_\"),\n        ] as const,\n    );\n\n    if (\n      yield* sqlMapping(\n        () =>\n          !mapping.subject.isActiveStatus(subject[mapping.subject.status]) ||\n          !mapping.identifier.isCurrent(identifierRow) ||\n          !mapping.subjectId.equals(nativeId, identifierRow[mapping.identifier.subjectId]) ||\n          !mapping.subjectId.equals(nativeId, subject[mapping.subject.id]) ||\n          !mapping.subjectId.equals(nativeId, credential[mapping.credential.subjectId]),\n      )\n    )\n      return undefined;\n\n    const captured = yield* sqlMapping(() =>\n      mapping.credential.decode({ moduleId, subject, identifier: identifierRow, credential }),\n    ).pipe(Effect.flatten, Effect.flatMap(snapshotPasswordCredential));\n\n    const factors = new Map<string, SecurityRevision>();\n\n    for (const row of rows) {\n      const factor = yield* sqlMapping(() => a.decode(row, \"authority_\"));\n\n      if (factor[authority.credentialId] === null || factor[authority.credentialId] === undefined)\n        continue;\n      if (!mapping.subjectId.equals(nativeId, factor[authority.subjectId]))\n        return yield* unavailable();\n      if (\n        authority.status !== undefined &&\n        authority.isActiveStatus?.(factor[authority.status]) !== true\n      )\n        continue;\n\n      const credentialId = yield* Schema.decodeUnknownEffect(Schema.String)(\n        factor[authority.credentialId],\n      );\n\n      const revision = yield* Schema.decodeUnknownEffect(SecurityRevision)(\n        factor[authority.revision],\n      );\n\n      if (factors.has(credentialId)) return yield* unavailable();\n      factors.set(credentialId, revision);\n    }\n    if (factors.size > 64 || factors.get(captured.credentialId) !== captured.credentialRevision)\n      return undefined;\n\n    return yield* snapshotPasswordCredential({\n      ...captured,\n      revision: {\n        ...captured.revision,\n        credentials: [...factors].map(([credentialId, revision]) => ({ credentialId, revision })),\n      },\n    });\n  });\n\n  return {\n    findCredential: Effect.fnUntraced(\n      function* (uncaptured) {\n        const input = { ...uncaptured, identifier: { ...uncaptured.identifier } };\n\n        yield* standalone;\n\n        const identifiers = yield* sqlMapping(\n          () => sql<Row>`select ${i.fields(\"i_\")} from ${i.name}\n          where ${i.column(mapping.identifier.namespace)} = ${i.value(mapping.identifier.namespace, input.identifier.namespace)}\n            and ${i.column(mapping.identifier.value)} = ${i.value(mapping.identifier.value, input.identifier.value)}`,\n        ).pipe(Effect.flatten);\n\n        const identifier =\n          identifiers.length === 1\n            ? yield* sqlMapping(() => i.decode(identifiers[0]!, \"i_\"))\n            : undefined;\n\n        if (\n          identifier === undefined ||\n          !(yield* sqlMapping(() => mapping.identifier.isCurrent(identifier)))\n        )\n          return Option.none();\n\n        const credential = yield* snapshot(\n          identifier[mapping.identifier.subjectId],\n          input.moduleId,\n          input.identifier,\n        );\n\n        return credential === undefined ||\n          (input.subjectId !== undefined && credential.revision.subjectId !== input.subjectId)\n          ? Option.none()\n          : Option.some(credential);\n      },\n      (_) => failure(_),\n    ),\n    rehashIfCurrent: Effect.fnUntraced(\n      function* (input) {\n        const nextVerifier = Redacted.make(\n          yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)),\n        );\n\n        const credential = yield* snapshotPasswordCredential(input.credential);\n\n        yield* standalone;\n        const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);\n        const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);\n\n        if (version === credential.verifierVersion) return yield* unavailable();\n\n        // A custom encoder cannot turn maintenance into a semantic credential change.\n        const values = yield* sqlMapping(() => {\n          const encoded = mapping.credential.encodeVerifier(nextVerifier, version);\n\n          return {\n            [mapping.credential.verifier]: encoded[mapping.credential.verifier],\n            [mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion],\n          };\n        });\n\n        if (Object.values(values).some((value) => value === undefined))\n          return yield* PersistenceMappingError.make({\n            operation: \"mapping\",\n            cause: unavailable(),\n          });\n\n        yield* sqlMapping(() => {\n          // Ordinary identity predicates retain index use; the full CAS ignores text collation.\n          const exact = sql.and(\n            Object.entries({\n              [mapping.credential.moduleId]: credential.moduleId,\n              [mapping.credential.subjectId]: nativeId,\n              [mapping.credential.credentialId]: credential.credentialId,\n              [mapping.credential.credentialRevision]: credential.credentialRevision,\n              [mapping.credential.verifierVersion]: credential.verifierVersion,\n              [mapping.credential.verifier]: Redacted.value(credential.verifier),\n              [mapping.credential.normalization]: credential.normalization,\n            }).map(([key, value]) => {\n              const column = c.column(key),\n                bound = c.value(key, value);\n\n              if (typeof value !== \"string\") return sql`${column} = ${bound}`;\n\n              return sql.onDialectOrElse({\n                mysql: () => sql`binary ${column} = binary ${bound}`,\n                pg: () =>\n                  sql`convert_to(cast(${column} as text), 'UTF8') = convert_to(cast(${bound} as text), 'UTF8')`,\n                orElse: () => sql`cast(${column} as blob) = cast(${bound} as blob)`,\n              });\n            }),\n          );\n\n          return sql`${c.update(values)}\n          where ${c.column(mapping.credential.moduleId)} = ${c.value(mapping.credential.moduleId, credential.moduleId)}\n            and ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}\n            and ${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, credential.credentialId)}\n            and ${exact}`;\n        }).pipe(Effect.flatten);\n      },\n      (_) => failure(_),\n    ),\n  } satisfies Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">;\n});\n"],"mappings":"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"}