@yielded/auth-persistence-drizzle 0.1.0-beta.22 → 0.1.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/D1.d.mts +11 -11
- package/dist/D1.mjs +2 -1
- package/dist/D1.mjs.map +1 -1
- package/dist/Libsql.d.mts +40 -56
- package/dist/Libsql.mjs +2 -1
- package/dist/Libsql.mjs.map +1 -1
- package/dist/Mysql2.d.mts +16 -17
- package/dist/Pglite.d.mts +18 -18
- package/dist/Pglite.mjs +2 -1
- package/dist/Pglite.mjs.map +1 -1
- package/dist/Postgres.d.mts +24 -24
- package/dist/Postgres.mjs +2 -1
- package/dist/Postgres.mjs.map +1 -1
- package/dist/SqliteBun.d.mts +39 -55
- package/dist/SqliteBun.mjs +2 -1
- package/dist/SqliteBun.mjs.map +1 -1
- package/dist/SqliteDo.d.mts +48 -64
- package/dist/SqliteDo.mjs +2 -1
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +45 -61
- package/dist/SqliteNode.mjs +2 -1
- package/dist/SqliteNode.mjs.map +1 -1
- package/dist/SqliteWasm.d.mts +48 -64
- package/dist/SqliteWasm.mjs +2 -1
- package/dist/SqliteWasm.mjs.map +1 -1
- package/dist/drizzle/crypto.mjs +1 -1
- package/dist/drizzle/d1-emails.d.mts +1 -1
- package/dist/drizzle/d1-oauth.d.mts +14 -14
- package/dist/drizzle/d1-passkey.d.mts +1 -1
- package/dist/drizzle/d1-password-prepared.d.mts +4 -4
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +18 -35
- package/dist/drizzle/d1-passwords.mjs +78 -290
- package/dist/drizzle/d1-passwords.mjs.map +1 -1
- package/dist/drizzle/d1-phone.d.mts +1 -1
- package/dist/drizzle/d1-proofs.d.mts +2 -2
- package/dist/drizzle/d1-sessions.d.mts +3 -3
- package/dist/drizzle/d1-sessions.mjs +11 -6
- package/dist/drizzle/d1-sessions.mjs.map +1 -1
- package/dist/drizzle/d1-totp.d.mts +1 -1
- package/dist/drizzle/mysql-password-prepared.d.mts +5 -5
- package/dist/drizzle/mysql-password-prepared.mjs.map +1 -1
- package/dist/drizzle/mysql-passwords.d.mts +16 -32
- package/dist/drizzle/mysql-passwords.mjs.map +1 -1
- package/dist/drizzle/mysql-sessions.d.mts +1 -1
- package/dist/drizzle/native-sql-table.mjs +135 -0
- package/dist/drizzle/native-sql-table.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-model.d.mts +20 -281
- package/dist/drizzle/oauth-connected-model.mjs +3 -17
- package/dist/drizzle/oauth-connected-model.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-reference.d.mts +1 -3
- package/dist/drizzle/oauth-connected-reference.mjs +4 -53
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-target.d.mts +3 -990
- package/dist/drizzle/oauth-connected-target.mjs +8 -92
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
- package/dist/drizzle/oauth-kernel.mjs +11 -0
- package/dist/drizzle/oauth-kernel.mjs.map +1 -0
- package/dist/drizzle/oauth-model.d.mts +35 -438
- package/dist/drizzle/oauth-model.mjs +6 -44
- package/dist/drizzle/oauth-model.mjs.map +1 -1
- package/dist/drizzle/oauth-mysql.mjs +2 -2
- package/dist/drizzle/oauth-mysql.mjs.map +1 -1
- package/dist/drizzle/oauth-proxy.d.mts +10 -0
- package/dist/drizzle/oauth-proxy.mjs +54 -0
- package/dist/drizzle/oauth-proxy.mjs.map +1 -0
- package/dist/drizzle/oauth-target.d.mts +6 -107
- package/dist/drizzle/oauth-target.mjs +15 -245
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/password-model.d.mts +5 -8
- package/dist/drizzle/password-prepared-model.d.mts +5 -5
- package/dist/drizzle/password-prepared-model.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +1 -1
- package/dist/drizzle/password-sql.mjs +2 -1
- package/dist/drizzle/password-sql.mjs.map +1 -1
- package/dist/drizzle/password-target.mjs +13 -2
- package/dist/drizzle/password-target.mjs.map +1 -1
- package/dist/drizzle/pg-password-prepared.d.mts +5 -5
- package/dist/drizzle/pg-password-prepared.mjs.map +1 -1
- package/dist/drizzle/pg-passwords.d.mts +16 -32
- package/dist/drizzle/pg-passwords.mjs.map +1 -1
- package/dist/drizzle/pg-sessions.d.mts +1 -1
- package/dist/drizzle/phone-target.d.mts +2 -2
- package/dist/drizzle/phone-target.mjs +1 -1
- package/dist/drizzle/query-operations.mjs +3 -1
- package/dist/drizzle/query-operations.mjs.map +1 -1
- package/dist/drizzle/session-sql.mjs +2 -1
- package/dist/drizzle/session-sql.mjs.map +1 -1
- package/dist/drizzle/sqlite-password-prepared.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/storage-validation.mjs +10 -198
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-target.d.mts +3 -3
- package/dist/drizzle/totp-target.mjs +2 -2
- package/dist/drizzle/transaction-execution.d.mts +2 -2
- package/dist/drizzle/transaction-owner.d.mts +1 -2
- package/dist/index.d.mts +3 -2
- package/dist/internal/drizzle-postgres-oauth-proxy.d.mts +138 -0
- package/dist/internal/drizzle-postgres-oauth-proxy.mjs +29 -0
- package/dist/internal/drizzle-postgres-oauth-proxy.mjs.map +1 -0
- package/dist/internal/drizzle-postgres.mjs +2 -0
- package/dist/internal/drizzle-postgres.mjs.map +1 -1
- package/dist/internal/drizzle-sqlite-oauth-proxy.d.mts +146 -0
- package/dist/internal/drizzle-sqlite-oauth-proxy.mjs +29 -0
- package/dist/internal/drizzle-sqlite-oauth-proxy.mjs.map +1 -0
- package/dist/internal/drizzle-sqlite.mjs +2 -0
- package/dist/internal/drizzle-sqlite.mjs.map +1 -1
- package/package.json +1 -1
- package/src/D1.ts +2 -0
- package/src/Libsql.ts +2 -0
- package/src/Pglite.ts +2 -0
- package/src/Postgres.ts +2 -0
- package/src/SqliteBun.ts +2 -0
- package/src/SqliteDo.ts +2 -0
- package/src/SqliteNode.ts +2 -0
- package/src/SqliteWasm.ts +2 -0
- package/src/drizzle/d1-password-prepared.ts +2 -23
- package/src/drizzle/d1-passwords.ts +158 -780
- package/src/drizzle/d1-sessions.ts +21 -6
- package/src/drizzle/mysql-password-prepared.ts +4 -16
- package/src/drizzle/mysql-passwords.ts +5 -20
- package/src/drizzle/native-sql-table.ts +259 -0
- package/src/drizzle/oauth-connected-model.ts +97 -315
- package/src/drizzle/oauth-connected-reference.ts +13 -93
- package/src/drizzle/oauth-connected-target.ts +14 -271
- package/src/drizzle/oauth-kernel.ts +10 -0
- package/src/drizzle/oauth-model.ts +188 -541
- package/src/drizzle/oauth-mysql.ts +2 -2
- package/src/drizzle/oauth-proxy.ts +101 -0
- package/src/drizzle/oauth-target.ts +33 -737
- package/src/drizzle/password-model.ts +0 -33
- package/src/drizzle/password-prepared-model.ts +0 -18
- package/src/drizzle/password-sql.ts +3 -0
- package/src/drizzle/password-target.ts +41 -4
- package/src/drizzle/pg-password-prepared.ts +4 -16
- package/src/drizzle/pg-passwords.ts +5 -20
- package/src/drizzle/query-operations.ts +4 -0
- package/src/drizzle/session-sql.ts +2 -1
- package/src/drizzle/sqlite-password-prepared.ts +4 -52
- package/src/drizzle/sqlite-passwords.ts +7 -28
- package/src/drizzle/storage-validation.ts +13 -222
- package/src/index.ts +2 -8
- package/src/internal/drizzle-postgres-oauth-proxy.ts +37 -0
- package/src/internal/drizzle-postgres.ts +2 -0
- package/src/internal/drizzle-sqlite-oauth-proxy.ts +44 -0
- package/src/internal/drizzle-sqlite.ts +2 -0
- package/dist/_virtual/_rolldown/runtime.mjs +0 -13
- package/dist/drizzle/oauth-accounts.mjs +0 -359
- package/dist/drizzle/oauth-accounts.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-access.mjs +0 -212
- package/dist/drizzle/oauth-connected-access.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-collection.mjs +0 -202
- package/dist/drizzle/oauth-connected-collection.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-custody.mjs +0 -147
- package/dist/drizzle/oauth-connected-custody.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-flow.mjs +0 -297
- package/dist/drizzle/oauth-connected-flow.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-input.mjs +0 -122
- package/dist/drizzle/oauth-connected-input.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-maintenance.mjs +0 -214
- package/dist/drizzle/oauth-connected-maintenance.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-management.mjs +0 -229
- package/dist/drizzle/oauth-connected-management.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-settlement.mjs +0 -128
- package/dist/drizzle/oauth-connected-settlement.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-sign-in.mjs +0 -265
- package/dist/drizzle/oauth-connected-sign-in.mjs.map +0 -1
- package/dist/drizzle/oauth-connected-state.d.mts +0 -2062
- package/dist/drizzle/oauth-connected-state.mjs +0 -430
- package/dist/drizzle/oauth-connected-state.mjs.map +0 -1
- package/dist/drizzle/oauth-flow.d.mts +0 -22
- package/dist/drizzle/oauth-flow.mjs +0 -253
- package/dist/drizzle/oauth-flow.mjs.map +0 -1
- package/dist/drizzle/oauth-input.mjs +0 -127
- package/dist/drizzle/oauth-input.mjs.map +0 -1
- package/dist/drizzle/oauth-owner.d.mts +0 -10
- package/dist/drizzle/oauth-owner.mjs +0 -10
- package/dist/drizzle/oauth-owner.mjs.map +0 -1
- package/dist/drizzle/oauth-registration.d.mts +0 -5
- package/dist/drizzle/oauth-registration.mjs +0 -374
- package/dist/drizzle/oauth-registration.mjs.map +0 -1
- package/dist/drizzle/oauth-state.mjs +0 -107
- package/dist/drizzle/oauth-state.mjs.map +0 -1
- package/src/drizzle/oauth-accounts.ts +0 -805
- package/src/drizzle/oauth-connected-access.ts +0 -361
- package/src/drizzle/oauth-connected-collection.ts +0 -324
- package/src/drizzle/oauth-connected-custody.ts +0 -279
- package/src/drizzle/oauth-connected-flow.ts +0 -529
- package/src/drizzle/oauth-connected-input.ts +0 -147
- package/src/drizzle/oauth-connected-maintenance.ts +0 -346
- package/src/drizzle/oauth-connected-management.ts +0 -365
- package/src/drizzle/oauth-connected-settlement.ts +0 -251
- package/src/drizzle/oauth-connected-sign-in.ts +0 -443
- package/src/drizzle/oauth-connected-state.ts +0 -872
- package/src/drizzle/oauth-flow.ts +0 -462
- package/src/drizzle/oauth-input.ts +0 -201
- package/src/drizzle/oauth-owner.ts +0 -29
- package/src/drizzle/oauth-registration.ts +0 -640
- package/src/drizzle/oauth-state.ts +0 -218
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-management.mjs","names":["S.useAuthority","S.jobTable","A.locked","S.current","S.action","client","S.client","F.inspectTuple","cohort","S.cohort","S.readGrant","C.sameContext","C.fence","C.storeJob","S.nativeCopy","C.clear"],"sources":["../../src/drizzle/oauth-connected-management.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport { snapshotOAuthSync } from \"@yielded/auth/OAuth\";\nimport { asc, eq, gt, lte } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as A from \"./oauth-connected-access\";\nimport * as C from \"./oauth-connected-custody\";\nimport * as F from \"./oauth-connected-flow\";\nimport * as S from \"./oauth-connected-state\";\nimport { both, col, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { digest, invariant } from \"./oauth-state\";\n\nexport const list = Effect.fn(\"oauthConnected.list\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"list\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const found = yield* S.useAuthority(mapping, input.authorization, \"metadata\");\n\n if (found === undefined) return { items: [] };\n invariant(Number.isSafeInteger(input.limit) && input.limit >= 1 && input.limit <= 100);\n\n const g = mapping.grant,\n h = mapping.cohort,\n j = S.jobTable(mapping);\n\n const cursor = input.cursor === undefined ? undefined : M.OAuthGrantId.make(input.cursor);\n\n const where = both(\n equal(g.table, { [g.moduleId]: input.authorization.moduleId, [g.subjectId]: found.nativeId }),\n cursor === undefined ? undefined : gt(col(g.table, g.grantId), cursor),\n input.authorization.grantId === undefined\n ? undefined\n : eq(col(g.table, g.grantId), input.authorization.grantId),\n input.authorization.profileKey === undefined\n ? undefined\n : eq(col(g.table, g.profileKey), input.authorization.profileKey),\n );\n\n const columns = [\n g.moduleId,\n g.grantId,\n g.subjectId,\n g.identityKey,\n g.clientKey,\n g.cohortKey,\n g.cohortGeneration,\n g.profileKey,\n g.state,\n g.summary,\n g.revocationJobId,\n g.version,\n ];\n\n const read = yield* owner.read(g.table, where, {\n columns,\n limit: input.limit + 1,\n takeOnly: true,\n observe: false,\n lock: false,\n orderBy: asc(col(g.table, g.grantId)),\n });\n\n const more = read.rows.length > input.limit,\n rows = read.rows.slice(0, input.limit),\n last = rows.at(-1)?.[g.grantId];\n\n owner.observations.push({\n table: g.table,\n where: more ? both(where, lte(col(g.table, g.grantId), last)) : where,\n rows,\n });\n const items: Array<typeof M.OAuthConnectedSummary.Type> = [];\n\n for (const row of rows) {\n const summary = S.summaryStorage.decode(row[g.summary]);\n\n invariant(\n summary.grantId === row[g.grantId] &&\n summary.profileKey === row[g.profileKey] &&\n mapping.subjectId.equals(found.nativeId, row[g.subjectId]),\n );\n\n const co = yield* owner.read(h.table, equal(h.table, { [h.cohortKey]: row[g.cohortKey] }), {\n limit: 1,\n lock: false,\n });\n\n const cr = co.rows[0];\n\n invariant(\n cr !== undefined &&\n cr[h.clientKey] === row[g.clientKey] &&\n cr[h.identityKey] === row[g.identityKey],\n );\n let status = row[g.state] as (typeof M.OAuthConnectedSummary.Type)[\"status\"];\n\n if (\n status !== \"Disconnected\" &&\n (cr[h.state] !== \"Open\" || cr[h.generation] !== row[g.cohortGeneration])\n )\n status = \"ReauthorizationRequired\";\n let remote = summary.remoteRevocation;\n\n if (row[g.revocationJobId] !== null) {\n if (j === undefined) remote = \"Unknown\";\n else {\n const job = yield* owner.read(\n j.table,\n equal(j.table, { [j.jobId]: row[g.revocationJobId] }),\n {\n limit: 1,\n lock: false,\n columns: [j.jobId, j.moduleId, j.grantId, j.cohortKey, j.state],\n },\n );\n\n const jr = job.rows[0];\n\n invariant(\n jr !== undefined &&\n jr[j.moduleId] === row[g.moduleId] &&\n jr[j.grantId] === row[g.grantId] &&\n jr[j.cohortKey] === row[g.cohortKey],\n );\n remote =\n jr[j.state] === \"Confirmed\"\n ? \"Confirmed\"\n : jr[j.state] === \"Unknown\"\n ? \"Unknown\"\n : \"Pending\";\n }\n }\n items.push(\n snapshotOAuthSync(M.OAuthConnectedSummary, { ...summary, status, remoteRevocation: remote }),\n );\n }\n\n return { items, ...(more ? { cursor: last as string } : {}) };\n});\n\nconst command = Effect.fn(\"oauthConnected.disconnectCommand\")(function* (\n mapping: S.Mapping,\n moduleId: string,\n commandId: string,\n lock = true,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const d = mapping.command,\n read = yield* owner.read(\n d.table,\n equal(d.table, { [d.moduleId]: moduleId, [d.commandId]: commandId }),\n { limit: 1, lock, observe: lock },\n );\n\n const row = read.rows[0];\n\n if (row === undefined) return { read };\n\n const grant = S.commandStorage.decode(row[d.intent]),\n result = S.disconnectedStorage.decode(row[d.decision]);\n\n const native = yield* mapping.subjectId.toNative(grant.context.subjectId);\n\n invariant(\n grant.context.moduleId === moduleId &&\n grant.context.grantId === row[d.grantId] &&\n result.grantId === grant.context.grantId &&\n mapping.subjectId.equals(native, row[d.subjectId]) &&\n !result.replayed,\n );\n\n return { read, row, grant, result };\n});\n\nexport const inspectDisconnect = Effect.fn(\"oauthConnected.inspectDisconnect\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"inspectDisconnect\">,\n) {\n const found = yield* S.useAuthority(mapping, input.authorization, \"metadata\");\n\n if (\n found === undefined ||\n input.subjectId !== found.revision.subjectId ||\n input.moduleId !== input.authorization.moduleId\n )\n return { _tag: \"Rejected\" } as const;\n const discovered = yield* command(mapping, input.moduleId, input.commandId, false);\n\n if (discovered.row !== undefined) {\n if (\n discovered.grant.context.subjectId !== input.subjectId ||\n discovered.grant.context.grantId !== input.grantId\n )\n return { _tag: \"Conflict\" } as const;\n if (\n (yield* S.useAuthority(\n mapping,\n input.authorization,\n \"metadata\",\n discovered.grant.context,\n )) === undefined\n )\n return { _tag: \"Rejected\" } as const;\n const prior = yield* command(mapping, input.moduleId, input.commandId);\n const d = mapping.command;\n\n if (\n prior.row === undefined ||\n prior.row[d.intent] !== discovered.row[d.intent] ||\n prior.row[d.decision] !== discovered.row[d.decision] ||\n prior.row[d.version] !== discovered.row[d.version]\n )\n return { _tag: \"Rejected\" } as const;\n\n return { _tag: \"Replay\", result: { ...prior.result, replayed: true } } as const;\n }\n const read = yield* A.locked(mapping, input.authorization, input.grantId, \"metadata\");\n\n if (read === undefined) return { _tag: \"Rejected\" } as const;\n const finalCommand = yield* command(mapping, input.moduleId, input.commandId);\n\n if (finalCommand.row !== undefined) return { _tag: \"Rejected\" } as const;\n\n return {\n _tag: \"Target\",\n grant: {\n context: read.grant.context,\n ...(read.grant.sealed === undefined ? {} : { sealed: read.grant.sealed }),\n },\n revision: read.found.revision,\n } as const;\n});\n\nexport const disconnect = Effect.fn(\"oauthConnected.disconnect\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"disconnect\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const token = input.grant.context,\n found = yield* S.current(mapping, token.subjectId);\n\n if (\n found === undefined ||\n input.moduleId !== token.moduleId ||\n !(yield* S.action(mapping, found, input.authorization, \"disconnect\", {\n moduleId: input.moduleId,\n flowId: input.commandId,\n commandId: input.commandId,\n revision: input.authorization.challenge.revision,\n intent: S.disconnectStorage.encode(input.grant),\n maximumAgeMillis: 300000,\n configuration: token.configuration,\n grant: token,\n }))\n )\n return { _tag: \"Rejected\" } as const;\n const client = yield* S.client(mapping, token.configuration, false);\n\n if (client === undefined) return { _tag: \"Rejected\" } as const;\n\n const tuple = yield* F.inspectTuple(mapping, token.identity),\n t = mapping.ownership.tuple;\n\n if (\n tuple.row?.[t.state] !== \"Owned\" ||\n !mapping.subjectId.equals(tuple.row[t.subjectId], found.nativeId)\n )\n return { _tag: \"Conflict\" } as const;\n const cohort = yield* S.cohort(mapping, client.id, tuple.key, false);\n\n invariant(cohort.row !== undefined);\n\n const read = yield* S.readGrant(mapping, input.moduleId, token.grantId),\n g = mapping.grant;\n\n if (\n read === undefined ||\n !C.sameContext(read.context, token) ||\n S.disconnectStorage.encode({\n context: read.context,\n ...(read.sealed === undefined ? {} : { sealed: read.sealed }),\n }) !== S.disconnectStorage.encode(input.grant)\n )\n return { _tag: \"Conflict\" } as const;\n const prior = yield* command(mapping, input.moduleId, input.commandId);\n\n // Only inspectDisconnect exposes replay. Mutation replay cannot repeat effects.\n if (prior.row !== undefined) return { _tag: \"Conflict\" } as const;\n\n const now = yield* owner.now(mapping.clock),\n wasOpen = !cohort.blocked;\n\n invariant(input.retentionUntilMillis >= now && input.retentionUntilMillis <= now + 2592000000);\n const affected = yield* C.fence(mapping, client, cohort);\n let remote: (typeof M.OAuthConnectedSummary.Type)[\"remoteRevocation\"] = \"Unsupported\";\n\n if (input.revocation !== undefined) {\n yield* C.storeJob(mapping, input.revocation, token, found.nativeId, now);\n remote = \"Pending\";\n } else if (token.configuration.profile.revocation === \"cohort\") {\n invariant(read.sealed === undefined);\n remote = \"Unknown\";\n }\n\n const result = snapshotOAuthSync(M.OAuthConnectedDisconnected, {\n _tag: \"Disconnected\",\n grantId: token.grantId,\n remoteRevocation: remote,\n affectedGrantCount: affected,\n replayed: false,\n });\n\n yield* owner.update(\n g.table,\n { [g.moduleId]: input.moduleId, [g.grantId]: token.grantId },\n {\n [g.state]: \"Disconnected\",\n [g.activeIdentityKey]: null,\n [g.sealed]: null,\n [g.revocationJobId]: input.revocation?.context.jobId ?? read.row[g.revocationJobId],\n [g.version]: owner.marker,\n },\n );\n\n const d = mapping.command,\n key = { [d.moduleId]: input.moduleId, [d.commandId]: input.commandId };\n\n const inserted = yield* owner.insert(\n d.table,\n {\n ...d.encodeInsert({\n commandId: input.commandId,\n grant: snapshotOAuthSync(M.OAuthConnectedDisconnectGrant, input.grant),\n subjectId: S.nativeCopy(found.nativeId),\n }),\n ...key,\n [d.subjectId]: found.nativeId,\n [d.grantId]: token.grantId,\n [d.intent]: S.commandStorage.encode({\n context: token,\n originalDigest: yield* digest(S.disconnectStorage.encode(input.grant)),\n ...(input.revocation === undefined\n ? {}\n : { revocationJobId: input.revocation.context.jobId }),\n }),\n [d.decision]: S.disconnectedStorage.encode(result),\n [d.retentionUntil]: mapping.clock.encodeInstant(input.retentionUntilMillis),\n [d.version]: owner.marker,\n },\n key,\n );\n\n prior.read.rows = inserted.rows;\n if (\n wasOpen &&\n input.revocation === undefined &&\n token.configuration.profile.revocation === \"unsupported\"\n )\n yield* C.clear(mapping, client, cohort, undefined, true);\n\n return result;\n});\n"],"mappings":"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"}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { invariant, oauthIdentityKey, sameIdentity } from "./oauth-state.mjs";
|
|
2
|
-
import { both } from "./transaction-owner.mjs";
|
|
3
|
-
import { CurrentOAuthTransaction, col, equal } from "./oauth-owner.mjs";
|
|
4
|
-
import { acquireTuple, readTuple } from "./oauth-registration.mjs";
|
|
5
|
-
import { action, client, clientKey, cohort, cohortKey, configuration, current, nativeCopy, orderNumber, readGrant, retainedUntil, sealedStorage, summaryStorage, tokenContextStorage } from "./oauth-connected-state.mjs";
|
|
6
|
-
import { fence, noFormerOwner, storeJob, summary } from "./oauth-connected-custody.mjs";
|
|
7
|
-
import { exact, expected, sameTarget, terminal } from "./oauth-connected-flow.mjs";
|
|
8
|
-
import { ne, sql } from "drizzle-orm";
|
|
9
|
-
import { Effect } from "effect";
|
|
10
|
-
import * as M from "@yielded/auth/OAuth";
|
|
11
|
-
import { snapshotOAuthSync } from "@yielded/auth/OAuth";
|
|
12
|
-
//#region src/drizzle/oauth-connected-settlement.ts
|
|
13
|
-
const validMetadata = (context, now) => {
|
|
14
|
-
const m = context.metadata, p = context.configuration.profile;
|
|
15
|
-
return p.provider === context.identity.provider && context.configuration.provider === context.identity.provider && context.configuration.issuer === context.identity.issuer && m.obtainedAtMillis <= now && m.useUntilMillis > m.obtainedAtMillis && m.useUntilMillis <= m.obtainedAtMillis + p.maximumAccessLifetimeMillis && (m.accessExpiresAtMillis === void 0 || m.useUntilMillis <= m.accessExpiresAtMillis) && m.scopes.every((v) => p.scopes.includes(v)) && m.resources.every((v) => p.resources.includes(v)) && new Set(m.scopes).size === m.scopes.length && new Set(m.resources).size === m.resources.length && (m.refreshUseUntilMillis === void 0 || p.retention === "access-and-refresh" && p.maximumRefreshLifetimeMillis !== void 0 && m.refreshUseUntilMillis > m.obtainedAtMillis && m.refreshUseUntilMillis <= m.obtainedAtMillis + p.maximumRefreshLifetimeMillis && (m.refreshExpiresAtMillis === void 0 || m.refreshUseUntilMillis <= m.refreshExpiresAtMillis));
|
|
16
|
-
};
|
|
17
|
-
/** The only writer that activates or replaces a confirmed connected grant. */
|
|
18
|
-
const activateGrant = Effect.fn("oauthConnected.activateGrant")(function* (mapping, grant, native, now, replacing) {
|
|
19
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
20
|
-
const token = grant.context;
|
|
21
|
-
const g = mapping.grant;
|
|
22
|
-
const identityKey = yield* oauthIdentityKey(token.identity);
|
|
23
|
-
const clientKey$1 = yield* clientKey(token.configuration);
|
|
24
|
-
const cohortKey$1 = yield* cohortKey(clientKey$1, identityKey);
|
|
25
|
-
const values = {
|
|
26
|
-
...g.encodeInsert({
|
|
27
|
-
grant: snapshotOAuthSync(M.OAuthConnectedStoredGrant, grant),
|
|
28
|
-
subjectId: nativeCopy(native)
|
|
29
|
-
}),
|
|
30
|
-
[g.moduleId]: token.moduleId,
|
|
31
|
-
[g.grantId]: token.grantId,
|
|
32
|
-
[g.subjectId]: native,
|
|
33
|
-
[g.identityKey]: identityKey,
|
|
34
|
-
[g.activeIdentityKey]: identityKey,
|
|
35
|
-
[g.clientKey]: clientKey$1,
|
|
36
|
-
[g.cohortKey]: cohortKey$1,
|
|
37
|
-
[g.profileKey]: token.configuration.profile.key,
|
|
38
|
-
[g.grantVersion]: token.grantVersion,
|
|
39
|
-
[g.tokenVersion]: token.tokenVersion,
|
|
40
|
-
[g.cohortGeneration]: token.cohortGeneration,
|
|
41
|
-
[g.state]: "Active",
|
|
42
|
-
[g.version]: owner.marker,
|
|
43
|
-
[g.context]: tokenContextStorage.encode(token),
|
|
44
|
-
[g.sealed]: sealedStorage.encode(grant.sealed),
|
|
45
|
-
[g.summary]: summaryStorage.encode(summary(token)),
|
|
46
|
-
[g.revocationJobId]: null,
|
|
47
|
-
[g.refreshWork]: "None",
|
|
48
|
-
[g.refreshClaim]: null,
|
|
49
|
-
[g.refreshClaimExpiresAt]: null,
|
|
50
|
-
[g.retentionUntil]: mapping.clock.encodeInstant(retainedUntil(mapping, Math.max(now, token.metadata.useUntilMillis, token.metadata.refreshUseUntilMillis ?? 0)))
|
|
51
|
-
};
|
|
52
|
-
if (!replacing) yield* owner.insert(g.table, values, {
|
|
53
|
-
[g.moduleId]: token.moduleId,
|
|
54
|
-
[g.grantId]: token.grantId
|
|
55
|
-
});
|
|
56
|
-
else yield* owner.update(g.table, {
|
|
57
|
-
[g.moduleId]: token.moduleId,
|
|
58
|
-
[g.grantId]: token.grantId
|
|
59
|
-
}, values);
|
|
60
|
-
});
|
|
61
|
-
const settle = Effect.fn("oauthConnected.settle")(function* (mapping, input) {
|
|
62
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
63
|
-
const c = input.claim.flow.context, out = input.outcome;
|
|
64
|
-
const found = yield* current(mapping, c.revision.subjectId);
|
|
65
|
-
const authorized = found !== void 0 && (yield* action(mapping, found, input.authorization, "settle", expected(input.claim.flow)));
|
|
66
|
-
const cl = yield* client(mapping, configuration(input.claim.flow), false);
|
|
67
|
-
if (cl === void 0) return { _tag: "Rejected" };
|
|
68
|
-
if (out._tag !== "Verified" && out._tag !== "Quarantined") {
|
|
69
|
-
if ((yield* exact(mapping, input.claim)) === void 0) return { _tag: "Rejected" };
|
|
70
|
-
const state = out._tag === "Unissued" ? "Rejected" : out._tag;
|
|
71
|
-
yield* terminal(mapping, input.claim, state, out._tag === "Cancelled" || out._tag === "Unissued" ? "Resolved" : "Unresolved");
|
|
72
|
-
return { _tag: state };
|
|
73
|
-
}
|
|
74
|
-
const grant = snapshotOAuthSync(M.OAuthConnectedStoredGrant, out.grant), token = grant.context;
|
|
75
|
-
invariant(token.moduleId === c.moduleId && token.subjectId === c.revision.subjectId && token.grantId === c.grantId && token.identity.provider === c.provider && token.identity.issuer === c.issuer && (yield* clientKey(token.configuration)) === cl.id && tokenContextStorage.encode({
|
|
76
|
-
...token,
|
|
77
|
-
configuration: configuration(input.claim.flow)
|
|
78
|
-
}) === tokenContextStorage.encode(token));
|
|
79
|
-
const native = yield* mapping.subjectId.toNative(c.revision.subjectId);
|
|
80
|
-
const tuple = yield* readTuple(mapping.ownership, token.identity), t = mapping.ownership.tuple;
|
|
81
|
-
if (tuple.row[t.state] === "Reserved" || tuple.row[t.state] === "Owned" && !mapping.subjectId.equals(tuple.row[t.subjectId], native)) {
|
|
82
|
-
if ((yield* exact(mapping, input.claim)) !== void 0) yield* terminal(mapping, input.claim, "Conflict", "Unresolved");
|
|
83
|
-
return { _tag: "Conflict" };
|
|
84
|
-
}
|
|
85
|
-
const co = yield* cohort(mapping, cl.id, tuple.key, true);
|
|
86
|
-
const original = yield* readGrant(mapping, c.moduleId, c.grantId);
|
|
87
|
-
const g = mapping.grant;
|
|
88
|
-
const other = yield* owner.read(g.table, both(equal(g.table, {
|
|
89
|
-
[g.moduleId]: c.moduleId,
|
|
90
|
-
[g.subjectId]: native,
|
|
91
|
-
[g.profileKey]: c.profile.key,
|
|
92
|
-
[g.activeIdentityKey]: tuple.key
|
|
93
|
-
}), ne(col(g.table, g.grantId), c.grantId)), { limit: 1 });
|
|
94
|
-
const claimed = yield* exact(mapping, input.claim);
|
|
95
|
-
if (claimed === void 0) return { _tag: "Rejected" };
|
|
96
|
-
invariant(token.exchangeOrder === input.claim.order && validMetadata(token, claimed.now) && token.metadata.obtainedAtMillis >= input.claim.claimedAtMillis);
|
|
97
|
-
const reconnect = c.reconnect;
|
|
98
|
-
const targetOkay = reconnect === void 0 ? original === void 0 : original !== void 0 && sameTarget(reconnect, original.context) && sameIdentity(reconnect.identity, token.identity) && original.row[g.refreshWork] !== "Unresolved";
|
|
99
|
-
const previousSafe = yield* noFormerOwner(mapping, tuple.key, cl.id, native);
|
|
100
|
-
if (!(out._tag === "Verified" && authorized && claimed.active && c.profile.issuance === "active" && token.metadata.useUntilMillis > claimed.now && !co.blocked && co.generation === token.cohortGeneration && orderNumber(input.claim.order) > co.cutoff && targetOkay && other.rows.length === 0 && previousSafe)) {
|
|
101
|
-
if (!previousSafe) {
|
|
102
|
-
yield* terminal(mapping, input.claim, "Conflict", "Unresolved");
|
|
103
|
-
return { _tag: "Conflict" };
|
|
104
|
-
}
|
|
105
|
-
if (tuple.row[t.state] === "Unowned") yield* acquireTuple(mapping.ownership, token.identity, tuple.key, nativeCopy(native));
|
|
106
|
-
yield* fence(mapping, cl, co);
|
|
107
|
-
if (out.cleanup !== void 0) {
|
|
108
|
-
yield* storeJob(mapping, out.cleanup, token, native, claimed.now);
|
|
109
|
-
yield* terminal(mapping, input.claim, "Quarantined", "Resolved", { cohort: co.id });
|
|
110
|
-
} else yield* terminal(mapping, input.claim, "Quarantined", "Unresolved", {
|
|
111
|
-
cohort: co.id,
|
|
112
|
-
sealed: grant
|
|
113
|
-
});
|
|
114
|
-
return { _tag: targetOkay && other.rows.length === 0 ? "Rejected" : "Conflict" };
|
|
115
|
-
}
|
|
116
|
-
if (tuple.row[t.state] === "Unowned") yield* acquireTuple(mapping.ownership, token.identity, tuple.key, nativeCopy(native));
|
|
117
|
-
yield* activateGrant(mapping, grant, native, claimed.now, original !== void 0);
|
|
118
|
-
yield* terminal(mapping, input.claim, "Connected", "Resolved", { cohort: co.id });
|
|
119
|
-
owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${claimed.now} and ${mapping.clock.engineNowMillis} < ${Math.min(input.claim.claimExpiresAtMillis, token.metadata.useUntilMillis)}`);
|
|
120
|
-
return {
|
|
121
|
-
_tag: "Connected",
|
|
122
|
-
grant
|
|
123
|
-
};
|
|
124
|
-
});
|
|
125
|
-
//#endregion
|
|
126
|
-
export { activateGrant, settle, validMetadata };
|
|
127
|
-
|
|
128
|
-
//# sourceMappingURL=oauth-connected-settlement.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-settlement.mjs","names":["clientKey","S.clientKey","cohortKey","S.cohortKey","S.nativeCopy","C.summary","S.retainedUntil","S.current","S.action","F.expected","S.client","S.configuration","F.exact","F.terminal","F.readTuple","S.cohort","S.readGrant","F.sameTarget","C.noFormerOwner","S.orderNumber","F.acquireTuple","C.fence","C.storeJob"],"sources":["../../src/drizzle/oauth-connected-settlement.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport { snapshotOAuthSync } from \"@yielded/auth/OAuth\";\nimport { ne, sql } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as C from \"./oauth-connected-custody\";\nimport * as F from \"./oauth-connected-flow\";\nimport * as S from \"./oauth-connected-state\";\nimport { both, col, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { invariant, sameIdentity, oauthIdentityKey } from \"./oauth-state\";\n\nexport const validMetadata = (context: M.OAuthConnectedTokenContext, now: number) => {\n const m = context.metadata,\n p = context.configuration.profile;\n\n return (\n p.provider === context.identity.provider &&\n context.configuration.provider === context.identity.provider &&\n context.configuration.issuer === context.identity.issuer &&\n m.obtainedAtMillis <= now &&\n m.useUntilMillis > m.obtainedAtMillis &&\n m.useUntilMillis <= m.obtainedAtMillis + p.maximumAccessLifetimeMillis &&\n (m.accessExpiresAtMillis === undefined || m.useUntilMillis <= m.accessExpiresAtMillis) &&\n m.scopes.every((v) => p.scopes.includes(v)) &&\n m.resources.every((v) => p.resources.includes(v)) &&\n new Set(m.scopes).size === m.scopes.length &&\n new Set(m.resources).size === m.resources.length &&\n (m.refreshUseUntilMillis === undefined ||\n (p.retention === \"access-and-refresh\" &&\n p.maximumRefreshLifetimeMillis !== undefined &&\n m.refreshUseUntilMillis > m.obtainedAtMillis &&\n m.refreshUseUntilMillis <= m.obtainedAtMillis + p.maximumRefreshLifetimeMillis &&\n (m.refreshExpiresAtMillis === undefined ||\n m.refreshUseUntilMillis <= m.refreshExpiresAtMillis)))\n );\n};\n\n/** The only writer that activates or replaces a confirmed connected grant. */\nexport const activateGrant = Effect.fn(\"oauthConnected.activateGrant\")(function* (\n mapping: S.Mapping,\n grant: M.OAuthConnectedStoredGrant,\n native: unknown,\n now: number,\n replacing: boolean,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const token = grant.context;\n const g = mapping.grant;\n const identityKey = yield* oauthIdentityKey(token.identity);\n const clientKey = yield* S.clientKey(token.configuration);\n const cohortKey = yield* S.cohortKey(clientKey, identityKey);\n\n const values = {\n ...g.encodeInsert({\n grant: snapshotOAuthSync(M.OAuthConnectedStoredGrant, grant),\n subjectId: S.nativeCopy(native),\n }),\n [g.moduleId]: token.moduleId,\n [g.grantId]: token.grantId,\n [g.subjectId]: native,\n [g.identityKey]: identityKey,\n [g.activeIdentityKey]: identityKey,\n [g.clientKey]: clientKey,\n [g.cohortKey]: cohortKey,\n [g.profileKey]: token.configuration.profile.key,\n [g.grantVersion]: token.grantVersion,\n [g.tokenVersion]: token.tokenVersion,\n [g.cohortGeneration]: token.cohortGeneration,\n [g.state]: \"Active\",\n [g.version]: owner.marker,\n [g.context]: S.tokenContextStorage.encode(token),\n [g.sealed]: S.sealedStorage.encode(grant.sealed),\n [g.summary]: S.summaryStorage.encode(C.summary(token)),\n [g.revocationJobId]: null,\n [g.refreshWork]: \"None\",\n [g.refreshClaim]: null,\n [g.refreshClaimExpiresAt]: null,\n [g.retentionUntil]: mapping.clock.encodeInstant(\n S.retainedUntil(\n mapping,\n Math.max(now, token.metadata.useUntilMillis, token.metadata.refreshUseUntilMillis ?? 0),\n ),\n ),\n };\n\n if (!replacing) {\n yield* owner.insert(g.table, values, {\n [g.moduleId]: token.moduleId,\n [g.grantId]: token.grantId,\n });\n } else\n yield* owner.update(\n g.table,\n { [g.moduleId]: token.moduleId, [g.grantId]: token.grantId },\n values,\n );\n});\n\nexport const settle = Effect.fn(\"oauthConnected.settle\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"settle\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const c = input.claim.flow.context,\n out = input.outcome;\n\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n const authorized =\n found !== undefined &&\n (yield* S.action(mapping, found, input.authorization, \"settle\", F.expected(input.claim.flow)));\n\n const cl = yield* S.client(mapping, S.configuration(input.claim.flow), false);\n\n if (cl === undefined) return { _tag: \"Rejected\" } as const;\n if (out._tag !== \"Verified\" && out._tag !== \"Quarantined\") {\n const claimed = yield* F.exact(mapping, input.claim);\n\n if (claimed === undefined) return { _tag: \"Rejected\" } as const;\n const state = out._tag === \"Unissued\" ? \"Rejected\" : out._tag;\n\n yield* F.terminal(\n mapping,\n input.claim,\n state,\n out._tag === \"Cancelled\" || out._tag === \"Unissued\" ? \"Resolved\" : \"Unresolved\",\n );\n\n return { _tag: state } as\n | { readonly _tag: \"Cancelled\" }\n | { readonly _tag: \"Rejected\" }\n | { readonly _tag: \"Conflict\" }\n | { readonly _tag: \"Ambiguous\" };\n }\n\n const grant = snapshotOAuthSync(M.OAuthConnectedStoredGrant, out.grant),\n token = grant.context;\n\n invariant(\n token.moduleId === c.moduleId &&\n token.subjectId === c.revision.subjectId &&\n token.grantId === c.grantId &&\n token.identity.provider === c.provider &&\n token.identity.issuer === c.issuer &&\n (yield* S.clientKey(token.configuration)) === cl.id &&\n S.tokenContextStorage.encode({\n ...token,\n configuration: S.configuration(input.claim.flow),\n }) === S.tokenContextStorage.encode(token),\n );\n const native = yield* mapping.subjectId.toNative(c.revision.subjectId);\n\n const tuple = yield* F.readTuple(mapping.ownership, token.identity),\n t = mapping.ownership.tuple;\n\n if (\n tuple.row[t.state] === \"Reserved\" ||\n (tuple.row[t.state] === \"Owned\" && !mapping.subjectId.equals(tuple.row[t.subjectId], native))\n ) {\n const claimed = yield* F.exact(mapping, input.claim);\n\n if (claimed !== undefined) yield* F.terminal(mapping, input.claim, \"Conflict\", \"Unresolved\");\n\n return { _tag: \"Conflict\" } as const;\n }\n const co = yield* S.cohort(mapping, cl.id, tuple.key, true);\n const original = yield* S.readGrant(mapping, c.moduleId, c.grantId);\n const g = mapping.grant;\n\n const other = yield* owner.read(\n g.table,\n both(\n equal(g.table, {\n [g.moduleId]: c.moduleId,\n [g.subjectId]: native,\n [g.profileKey]: c.profile.key,\n [g.activeIdentityKey]: tuple.key,\n }),\n ne(col(g.table, g.grantId), c.grantId),\n ),\n { limit: 1 },\n );\n\n const claimed = yield* F.exact(mapping, input.claim);\n\n if (claimed === undefined) return { _tag: \"Rejected\" } as const;\n invariant(\n token.exchangeOrder === input.claim.order &&\n validMetadata(token, claimed.now) &&\n token.metadata.obtainedAtMillis >= input.claim.claimedAtMillis,\n );\n const reconnect = c.reconnect;\n\n const targetOkay =\n reconnect === undefined\n ? original === undefined\n : original !== undefined &&\n F.sameTarget(reconnect, original.context) &&\n sameIdentity(reconnect.identity, token.identity) &&\n original.row[g.refreshWork] !== \"Unresolved\";\n\n const previousSafe = yield* C.noFormerOwner(mapping, tuple.key, cl.id, native);\n\n const active =\n out._tag === \"Verified\" &&\n authorized &&\n claimed.active &&\n c.profile.issuance === \"active\" &&\n token.metadata.useUntilMillis > claimed.now &&\n !co.blocked &&\n co.generation === token.cohortGeneration &&\n S.orderNumber(input.claim.order) > co.cutoff &&\n targetOkay &&\n other.rows.length === 0 &&\n previousSafe;\n\n if (!active) {\n // Foreign historical custody never authorizes a new remote operation.\n if (!previousSafe) {\n yield* F.terminal(mapping, input.claim, \"Conflict\", \"Unresolved\");\n\n return { _tag: \"Conflict\" } as const;\n }\n if (tuple.row[t.state] === \"Unowned\")\n yield* F.acquireTuple(mapping.ownership, token.identity, tuple.key, S.nativeCopy(native));\n yield* C.fence(mapping, cl, co);\n if (out.cleanup !== undefined) {\n yield* C.storeJob(mapping, out.cleanup, token, native, claimed.now);\n yield* F.terminal(mapping, input.claim, \"Quarantined\", \"Resolved\", { cohort: co.id });\n } else\n yield* F.terminal(mapping, input.claim, \"Quarantined\", \"Unresolved\", {\n cohort: co.id,\n sealed: grant,\n });\n\n return { _tag: targetOkay && other.rows.length === 0 ? \"Rejected\" : \"Conflict\" } as\n | { readonly _tag: \"Rejected\" }\n | { readonly _tag: \"Conflict\" };\n }\n if (tuple.row[t.state] === \"Unowned\")\n yield* F.acquireTuple(mapping.ownership, token.identity, tuple.key, S.nativeCopy(native));\n\n yield* activateGrant(mapping, grant, native, claimed.now, original !== undefined);\n yield* F.terminal(mapping, input.claim, \"Connected\", \"Resolved\", { cohort: co.id });\n owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${claimed.now} and ${mapping.clock.engineNowMillis} < ${Math.min(input.claim.claimExpiresAtMillis, token.metadata.useUntilMillis)}`,\n );\n\n return { _tag: \"Connected\", grant } as const;\n});\n"],"mappings":"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"}
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import { digest } from "./crypto.mjs";
|
|
2
|
-
import { invariant, oauthIdentityKey, sameIdentity, sameRevision, storage, unavailable } from "./oauth-state.mjs";
|
|
3
|
-
import { both } from "./transaction-owner.mjs";
|
|
4
|
-
import { CurrentOAuthTransaction, equal } from "./oauth-owner.mjs";
|
|
5
|
-
import { exactClaim } from "./oauth-flow.mjs";
|
|
6
|
-
import { readTuple } from "./oauth-registration.mjs";
|
|
7
|
-
import { client, clientKey, cohort, current, nativeOrder, nextOrder, orderNumber, policy, readGrant, touchScope } from "./oauth-connected-state.mjs";
|
|
8
|
-
import { fence, noFormerOwner, storeJob } from "./oauth-connected-custody.mjs";
|
|
9
|
-
import { inspectTuple, sameTarget } from "./oauth-connected-flow.mjs";
|
|
10
|
-
import { activateGrant, validMetadata } from "./oauth-connected-settlement.mjs";
|
|
11
|
-
import { sql } from "drizzle-orm";
|
|
12
|
-
import { Effect, Schema } from "effect";
|
|
13
|
-
import * as M from "@yielded/auth/OAuth";
|
|
14
|
-
import { snapshotOAuthSync } from "@yielded/auth/OAuth";
|
|
15
|
-
//#region src/drizzle/oauth-connected-sign-in.ts
|
|
16
|
-
const reservationStorage = storage(M.OAuthSignInAccessClaim);
|
|
17
|
-
const configurationStorage = storage(M.OAuthConnectedConfiguration);
|
|
18
|
-
/** Reservation rows share the connected-work ledger, but have no browser
|
|
19
|
-
* snapshot or subject. They can never enter the authenticated connect flow. */
|
|
20
|
-
const claimSignIn = Effect.fn("oauthConnected.claimSignIn")(function* (mapping, input) {
|
|
21
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
22
|
-
const signIn = mapping.signIn;
|
|
23
|
-
const encode = mapping.flow.encodeSignIn;
|
|
24
|
-
if (signIn === void 0 || encode === void 0) return yield* unavailable();
|
|
25
|
-
const { claim, configuration } = input;
|
|
26
|
-
const c = claim.flow.context;
|
|
27
|
-
invariant(c.access !== void 0 && configurationStorage.encode(configuration) === configurationStorage.encode({
|
|
28
|
-
...c,
|
|
29
|
-
profile: c.access
|
|
30
|
-
}));
|
|
31
|
-
if (configuration.profile.revocation === "cohort") invariant(mapping.revocation.mode === "cohort");
|
|
32
|
-
const client$1 = yield* client(mapping, configuration, true);
|
|
33
|
-
invariant(client$1 !== void 0);
|
|
34
|
-
if ((yield* exactClaim({
|
|
35
|
-
...mapping,
|
|
36
|
-
flow: signIn.flow
|
|
37
|
-
}, claim, "sign-in")) === void 0) return yield* unavailable();
|
|
38
|
-
const f = mapping.flow;
|
|
39
|
-
const key = {
|
|
40
|
-
[f.moduleId]: c.moduleId,
|
|
41
|
-
[f.flowId]: c.flowId
|
|
42
|
-
};
|
|
43
|
-
const prior = yield* owner.read(f.table, equal(f.table, key), { limit: 1 });
|
|
44
|
-
const command = yield* owner.read(f.table, equal(f.table, {
|
|
45
|
-
[f.moduleId]: c.moduleId,
|
|
46
|
-
[f.commandId]: c.commandId
|
|
47
|
-
}), { limit: 1 });
|
|
48
|
-
if (prior.rows.length || command.rows.length) return yield* unavailable();
|
|
49
|
-
yield* touchScope(mapping, client$1.scope);
|
|
50
|
-
const order = yield* nextOrder(mapping, client$1);
|
|
51
|
-
const reservation = snapshotOAuthSync(M.OAuthSignInAccessClaim, {
|
|
52
|
-
claim,
|
|
53
|
-
configuration,
|
|
54
|
-
order: String(order)
|
|
55
|
-
});
|
|
56
|
-
const inserted = yield* owner.insert(f.table, {
|
|
57
|
-
...encode(reservation),
|
|
58
|
-
...key,
|
|
59
|
-
[f.commandId]: c.commandId,
|
|
60
|
-
[f.subjectId]: null,
|
|
61
|
-
[f.clientKey]: client$1.id,
|
|
62
|
-
[f.cohortKey]: null,
|
|
63
|
-
[f.state]: "Claimed",
|
|
64
|
-
[f.version]: owner.marker,
|
|
65
|
-
[f.stateDigest]: c.stateDigest,
|
|
66
|
-
[f.snapshot]: null,
|
|
67
|
-
[f.claimId]: claim.claimId,
|
|
68
|
-
[f.claimDigest]: yield* digest(reservationStorage.encode(reservation)),
|
|
69
|
-
[f.claimOrder]: mapping.order.encode(order),
|
|
70
|
-
[f.claimedAt]: mapping.clock.encodeInstant(claim.claimedAtMillis),
|
|
71
|
-
[f.claimExpiresAt]: mapping.clock.encodeInstant(claim.claimExpiresAtMillis),
|
|
72
|
-
[f.expiresAt]: mapping.clock.encodeInstant(c.expiresAtMillis),
|
|
73
|
-
[f.retentionUntil]: mapping.clock.encodeInstant(claim.flow.retentionUntilMillis),
|
|
74
|
-
[f.work]: "Unresolved",
|
|
75
|
-
[f.custody]: null
|
|
76
|
-
}, key);
|
|
77
|
-
prior.rows = inserted.rows;
|
|
78
|
-
command.rows = inserted.rows;
|
|
79
|
-
return reservation;
|
|
80
|
-
});
|
|
81
|
-
const exact = Effect.fn("oauthConnected.exactSignIn")(function* (mapping, reservation) {
|
|
82
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
83
|
-
const f = mapping.flow;
|
|
84
|
-
const c = reservation.claim.flow.context;
|
|
85
|
-
const key = {
|
|
86
|
-
[f.moduleId]: c.moduleId,
|
|
87
|
-
[f.flowId]: c.flowId
|
|
88
|
-
};
|
|
89
|
-
const row = (yield* owner.read(f.table, equal(f.table, key), { limit: 1 })).rows[0];
|
|
90
|
-
if (row === void 0 || row[f.work] !== "Unresolved" || row[f.claimId] !== reservation.claim.claimId || row[f.claimDigest] !== (yield* digest(reservationStorage.encode(reservation)))) return void 0;
|
|
91
|
-
invariant(row[f.subjectId] === null && row[f.commandId] === c.commandId && row[f.clientKey] === (yield* clientKey(reservation.configuration)) && nativeOrder(mapping, row[f.claimOrder]) === orderNumber(reservation.order));
|
|
92
|
-
const now = yield* owner.now(mapping.clock);
|
|
93
|
-
invariant(now >= reservation.claim.claimedAtMillis);
|
|
94
|
-
return {
|
|
95
|
-
key,
|
|
96
|
-
row,
|
|
97
|
-
now,
|
|
98
|
-
active: row[f.state] === "Claimed" && now < reservation.claim.claimExpiresAtMillis
|
|
99
|
-
};
|
|
100
|
-
});
|
|
101
|
-
const credential = Effect.fn("oauthConnected.signInCredential")(function* (mapping, reservation, input) {
|
|
102
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
103
|
-
const signIn = mapping.signIn;
|
|
104
|
-
if (signIn === void 0) return void 0;
|
|
105
|
-
const context = reservation.claim.flow.context;
|
|
106
|
-
if (input.moduleId !== context.moduleId || input.identity.provider !== context.provider || input.identity.issuer !== context.issuer) return void 0;
|
|
107
|
-
const found = yield* current(mapping, input.revision.subjectId);
|
|
108
|
-
if (found === void 0 || !sameRevision(found.revision, input.revision)) return void 0;
|
|
109
|
-
const c = signIn.credential;
|
|
110
|
-
const loginWhere = both(equal(c.table, {
|
|
111
|
-
[c.moduleId]: context.moduleId,
|
|
112
|
-
[c.credentialId]: input.credentialId,
|
|
113
|
-
[c.subjectId]: found.nativeId,
|
|
114
|
-
[c.identityKey]: yield* oauthIdentityKey(input.identity),
|
|
115
|
-
[c.credentialRevision]: input.credentialRevision
|
|
116
|
-
}), c.activeCondition);
|
|
117
|
-
const login = yield* owner.read(c.table, loginWhere, { limit: 1 });
|
|
118
|
-
if (login.rows.length !== 1 || !c.isActiveStatus(login.rows[0][c.status])) return void 0;
|
|
119
|
-
const f = signIn.flow;
|
|
120
|
-
const verifiedWhere = equal(f.table, {
|
|
121
|
-
[f.moduleId]: context.moduleId,
|
|
122
|
-
[f.flowId]: context.flowId,
|
|
123
|
-
[f.state]: "Verified",
|
|
124
|
-
[f.claimId]: reservation.claim.claimId,
|
|
125
|
-
[f.stateDigest]: context.stateDigest,
|
|
126
|
-
[f.claimedAt]: mapping.clock.encodeInstant(reservation.claim.claimedAtMillis),
|
|
127
|
-
[f.claimExpiresAt]: mapping.clock.encodeInstant(reservation.claim.claimExpiresAtMillis)
|
|
128
|
-
});
|
|
129
|
-
if ((yield* owner.read(f.table, verifiedWhere, { limit: 1 })).rows.length !== 1) return void 0;
|
|
130
|
-
owner.postconditions.push(sql`exists(select 1 from ${c.table} where ${loginWhere})`, sql`exists(select 1 from ${f.table} where ${verifiedWhere})`);
|
|
131
|
-
if (!(yield* policy(mapping, {
|
|
132
|
-
kind: "sign-in",
|
|
133
|
-
subjectId: found.nativeId,
|
|
134
|
-
revision: found.revision,
|
|
135
|
-
credential: snapshotOAuthSync(M.OAuthCredentialSnapshot, input),
|
|
136
|
-
configuration: reservation.configuration
|
|
137
|
-
}))) return void 0;
|
|
138
|
-
return found;
|
|
139
|
-
});
|
|
140
|
-
const slot = Effect.fn("oauthConnected.signInSlot")(function* (mapping, moduleId, native, identityKey, profileKey) {
|
|
141
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
142
|
-
const g = mapping.grant;
|
|
143
|
-
const row = (yield* owner.read(g.table, equal(g.table, {
|
|
144
|
-
[g.moduleId]: moduleId,
|
|
145
|
-
[g.subjectId]: native,
|
|
146
|
-
[g.profileKey]: profileKey,
|
|
147
|
-
[g.activeIdentityKey]: identityKey
|
|
148
|
-
}), {
|
|
149
|
-
limit: 1,
|
|
150
|
-
admissionOnly: true
|
|
151
|
-
})).rows[0];
|
|
152
|
-
if (row === void 0) return void 0;
|
|
153
|
-
return yield* readGrant(mapping, moduleId, yield* Schema.decodeUnknownEffect(M.OAuthGrantId)(row[g.grantId]).pipe(Effect.mapError(unavailable)));
|
|
154
|
-
});
|
|
155
|
-
/** Orders belong to one client registration. Moving a profile to another client
|
|
156
|
-
* requires a newer profile generation; retired clients cannot replace it later. */
|
|
157
|
-
const canReplace = Effect.fnUntraced(function* (reservation, previous) {
|
|
158
|
-
const generation = reservation.configuration.profile.generation;
|
|
159
|
-
const oldGeneration = previous.configuration.profile.generation;
|
|
160
|
-
return (yield* clientKey(reservation.configuration)) === (yield* clientKey(previous.configuration)) ? generation >= oldGeneration && orderNumber(reservation.order) > orderNumber(previous.exchangeOrder) : generation > oldGeneration;
|
|
161
|
-
});
|
|
162
|
-
const inspectSignIn = Effect.fn("oauthConnected.inspectSignIn")(function* (mapping, input) {
|
|
163
|
-
const found = yield* credential(mapping, input.reservation, input.credential);
|
|
164
|
-
if (found === void 0) return { _tag: "Rejected" };
|
|
165
|
-
const r = input.reservation;
|
|
166
|
-
const cl = yield* client(mapping, r.configuration, false);
|
|
167
|
-
if (cl === void 0) return { _tag: "Rejected" };
|
|
168
|
-
const tuple = yield* inspectTuple(mapping, input.credential.identity);
|
|
169
|
-
const t = mapping.ownership.tuple;
|
|
170
|
-
if (tuple.row?.[t.state] !== "Owned" || !mapping.subjectId.equals(tuple.row[t.subjectId], found.nativeId)) return { _tag: "Rejected" };
|
|
171
|
-
const co = yield* cohort(mapping, cl.id, tuple.key, false);
|
|
172
|
-
const previous = yield* slot(mapping, r.claim.flow.context.moduleId, found.nativeId, tuple.key, r.configuration.profile.key);
|
|
173
|
-
const held = yield* exact(mapping, r);
|
|
174
|
-
if (held === void 0) return { _tag: "Rejected" };
|
|
175
|
-
const quarantine = !held.active || co.blocked || orderNumber(r.order) <= co.cutoff || previous?.row[mapping.grant.refreshWork] === "Unresolved" || previous !== void 0 && !(yield* canReplace(r, previous.context));
|
|
176
|
-
return snapshotOAuthSync(M.OAuthSignInAccessInspection, {
|
|
177
|
-
_tag: quarantine ? "Quarantine" : "Target",
|
|
178
|
-
grantId: previous?.context.grantId ?? input.grantId,
|
|
179
|
-
cohortGeneration: co.generation,
|
|
180
|
-
...previous === void 0 ? {} : { previous: snapshotOAuthSync(M.OAuthConnectedTarget, previous.context) }
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
const settleSignIn = Effect.fn("oauthConnected.settleSignIn")(function* (mapping, input) {
|
|
184
|
-
const owner = yield* CurrentOAuthTransaction;
|
|
185
|
-
const r = input.reservation;
|
|
186
|
-
const out = input.outcome;
|
|
187
|
-
const found = out._tag === "Verified" ? yield* credential(mapping, r, out.credential) : void 0;
|
|
188
|
-
const cl = yield* client(mapping, r.configuration, false);
|
|
189
|
-
if (cl === void 0) return { _tag: "Rejected" };
|
|
190
|
-
const f = mapping.flow;
|
|
191
|
-
if (out._tag !== "Verified") {
|
|
192
|
-
const held = yield* exact(mapping, r);
|
|
193
|
-
if (held === void 0) return { _tag: "Rejected" };
|
|
194
|
-
const state = out._tag === "Unissued" ? "Rejected" : out._tag;
|
|
195
|
-
yield* owner.update(f.table, held.key, {
|
|
196
|
-
[f.state]: state,
|
|
197
|
-
[f.work]: out._tag === "Cancelled" || out._tag === "Unissued" ? "Resolved" : "Unresolved",
|
|
198
|
-
[f.version]: owner.marker
|
|
199
|
-
});
|
|
200
|
-
return { _tag: state };
|
|
201
|
-
}
|
|
202
|
-
const token = out.grant.context;
|
|
203
|
-
invariant(token.moduleId === r.claim.flow.context.moduleId && token.subjectId === out.credential.revision.subjectId && sameIdentity(token.identity, out.credential.identity) && configurationStorage.encode(token.configuration) === configurationStorage.encode(r.configuration));
|
|
204
|
-
const native = yield* mapping.subjectId.toNative(token.subjectId);
|
|
205
|
-
const tuple = yield* readTuple(mapping.ownership, token.identity);
|
|
206
|
-
const t = mapping.ownership.tuple;
|
|
207
|
-
const owned = tuple.row[t.state] === "Owned" && mapping.subjectId.equals(tuple.row[t.subjectId], native);
|
|
208
|
-
const co = yield* cohort(mapping, cl.id, tuple.key, true);
|
|
209
|
-
const previous = yield* readGrant(mapping, token.moduleId, token.grantId);
|
|
210
|
-
const activeSlot = yield* slot(mapping, token.moduleId, native, tuple.key, token.configuration.profile.key);
|
|
211
|
-
const held = yield* exact(mapping, r);
|
|
212
|
-
if (held === void 0) return { _tag: "Rejected" };
|
|
213
|
-
invariant(token.exchangeOrder === r.order && validMetadata(token, held.now) && token.metadata.obtainedAtMillis >= r.claim.claimedAtMillis);
|
|
214
|
-
const target = out.previous === void 0 ? previous === void 0 : previous !== void 0 && sameTarget(out.previous, previous.context) && sameIdentity(previous.context.identity, token.identity) && previous.row[mapping.grant.refreshWork] !== "Unresolved" && (yield* canReplace(r, previous.context));
|
|
215
|
-
const previousSafe = yield* noFormerOwner(mapping, tuple.key, cl.id, native);
|
|
216
|
-
if (!owned || !previousSafe) {
|
|
217
|
-
yield* owner.update(f.table, held.key, {
|
|
218
|
-
[f.state]: "Conflict",
|
|
219
|
-
[f.version]: owner.marker
|
|
220
|
-
});
|
|
221
|
-
return { _tag: "Conflict" };
|
|
222
|
-
}
|
|
223
|
-
if (out.quarantine || found === void 0 || !held.active || !target || activeSlot !== void 0 && activeSlot.context.grantId !== token.grantId || co.blocked || orderNumber(r.order) <= co.cutoff || co.generation !== token.cohortGeneration || token.metadata.useUntilMillis <= held.now || token.configuration.profile.issuance !== "active") {
|
|
224
|
-
if (token.configuration.profile.revocation === "unsupported") yield* owner.update(f.table, held.key, {
|
|
225
|
-
[f.state]: "Rejected",
|
|
226
|
-
[f.work]: "Resolved",
|
|
227
|
-
[f.subjectId]: native,
|
|
228
|
-
[f.cohortKey]: co.id,
|
|
229
|
-
[f.custody]: null,
|
|
230
|
-
[f.version]: owner.marker
|
|
231
|
-
});
|
|
232
|
-
else {
|
|
233
|
-
yield* fence(mapping, cl, co);
|
|
234
|
-
if (out.cleanup === void 0) return yield* unavailable();
|
|
235
|
-
yield* storeJob(mapping, out.cleanup, token, native, held.now);
|
|
236
|
-
yield* owner.update(f.table, held.key, {
|
|
237
|
-
[f.state]: "Quarantined",
|
|
238
|
-
[f.work]: "Resolved",
|
|
239
|
-
[f.subjectId]: native,
|
|
240
|
-
[f.cohortKey]: co.id,
|
|
241
|
-
[f.custody]: null,
|
|
242
|
-
[f.version]: owner.marker
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
return { _tag: "Rejected" };
|
|
246
|
-
}
|
|
247
|
-
yield* activateGrant(mapping, out.grant, native, held.now, previous !== void 0);
|
|
248
|
-
yield* owner.update(f.table, held.key, {
|
|
249
|
-
[f.state]: "Connected",
|
|
250
|
-
[f.work]: "Resolved",
|
|
251
|
-
[f.subjectId]: native,
|
|
252
|
-
[f.cohortKey]: co.id,
|
|
253
|
-
[f.custody]: null,
|
|
254
|
-
[f.version]: owner.marker
|
|
255
|
-
});
|
|
256
|
-
owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${held.now} and ${mapping.clock.engineNowMillis} < ${Math.min(r.claim.claimExpiresAtMillis, token.metadata.useUntilMillis)}`);
|
|
257
|
-
return {
|
|
258
|
-
_tag: "Connected",
|
|
259
|
-
grant: out.grant
|
|
260
|
-
};
|
|
261
|
-
});
|
|
262
|
-
//#endregion
|
|
263
|
-
export { claimSignIn, inspectSignIn, settleSignIn };
|
|
264
|
-
|
|
265
|
-
//# sourceMappingURL=oauth-connected-sign-in.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-sign-in.mjs","names":["client","S.client","S.touchScope","S.nextOrder","S.clientKey","S.nativeOrder","S.orderNumber","S.current","S.policy","S.readGrant","F.inspectTuple","S.cohort","F.readTuple","F.sameTarget","C.noFormerOwner","C.fence","C.storeJob"],"sources":["../../src/drizzle/oauth-connected-sign-in.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport { snapshotOAuthSync } from \"@yielded/auth/OAuth\";\nimport { sql } from \"drizzle-orm\";\nimport { Effect, Schema } from \"effect\";\n\nimport * as C from \"./oauth-connected-custody\";\nimport * as F from \"./oauth-connected-flow\";\nimport { activateGrant, validMetadata } from \"./oauth-connected-settlement\";\nimport * as S from \"./oauth-connected-state\";\nimport { exactClaim } from \"./oauth-flow\";\nimport { both, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport {\n digest,\n invariant,\n oauthIdentityKey,\n sameIdentity,\n sameRevision,\n storage,\n unavailable,\n} from \"./oauth-state\";\n\nconst reservationStorage = storage(M.OAuthSignInAccessClaim);\nconst configurationStorage = storage(M.OAuthConnectedConfiguration);\n\n/** Reservation rows share the connected-work ledger, but have no browser\n * snapshot or subject. They can never enter the authenticated connect flow. */\nexport const claimSignIn = Effect.fn(\"oauthConnected.claimSignIn\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"claimSignIn\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const signIn = mapping.signIn;\n const encode = mapping.flow.encodeSignIn;\n\n if (signIn === undefined || encode === undefined) return yield* unavailable();\n const { claim, configuration } = input;\n const c = claim.flow.context;\n\n invariant(\n c.access !== undefined &&\n configurationStorage.encode(configuration) ===\n configurationStorage.encode({ ...c, profile: c.access }),\n );\n if (configuration.profile.revocation === \"cohort\")\n invariant(mapping.revocation.mode === \"cohort\");\n const client = yield* S.client(mapping, configuration, true);\n\n invariant(client !== undefined);\n const exact = yield* exactClaim({ ...mapping, flow: signIn.flow }, claim, \"sign-in\");\n\n if (exact === undefined) return yield* unavailable();\n const f = mapping.flow;\n const key = { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId };\n const prior = yield* owner.read(f.table, equal(f.table, key), { limit: 1 });\n\n const command = yield* owner.read(\n f.table,\n equal(f.table, { [f.moduleId]: c.moduleId, [f.commandId]: c.commandId }),\n { limit: 1 },\n );\n\n if (prior.rows.length || command.rows.length) return yield* unavailable();\n yield* S.touchScope(mapping, client.scope);\n const order = yield* S.nextOrder(mapping, client);\n\n const reservation = snapshotOAuthSync(M.OAuthSignInAccessClaim, {\n claim,\n configuration,\n order: String(order),\n });\n\n const inserted = yield* owner.insert(\n f.table,\n {\n ...encode(reservation),\n ...key,\n [f.commandId]: c.commandId,\n [f.subjectId]: null,\n [f.clientKey]: client.id,\n [f.cohortKey]: null,\n [f.state]: \"Claimed\",\n [f.version]: owner.marker,\n [f.stateDigest]: c.stateDigest,\n [f.snapshot]: null,\n [f.claimId]: claim.claimId,\n [f.claimDigest]: yield* digest(reservationStorage.encode(reservation)),\n [f.claimOrder]: mapping.order.encode(order),\n [f.claimedAt]: mapping.clock.encodeInstant(claim.claimedAtMillis),\n [f.claimExpiresAt]: mapping.clock.encodeInstant(claim.claimExpiresAtMillis),\n [f.expiresAt]: mapping.clock.encodeInstant(c.expiresAtMillis),\n [f.retentionUntil]: mapping.clock.encodeInstant(claim.flow.retentionUntilMillis),\n [f.work]: \"Unresolved\",\n [f.custody]: null,\n },\n key,\n );\n\n prior.rows = inserted.rows;\n command.rows = inserted.rows;\n\n return reservation;\n});\n\nconst exact = Effect.fn(\"oauthConnected.exactSignIn\")(function* (\n mapping: S.Mapping,\n reservation: M.OAuthSignInAccessClaim,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const f = mapping.flow;\n const c = reservation.claim.flow.context;\n const key = { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId };\n const read = yield* owner.read(f.table, equal(f.table, key), { limit: 1 });\n const row = read.rows[0];\n\n if (\n row === undefined ||\n row[f.work] !== \"Unresolved\" ||\n row[f.claimId] !== reservation.claim.claimId ||\n row[f.claimDigest] !== (yield* digest(reservationStorage.encode(reservation)))\n )\n return undefined;\n invariant(\n row[f.subjectId] === null &&\n row[f.commandId] === c.commandId &&\n row[f.clientKey] === (yield* S.clientKey(reservation.configuration)) &&\n S.nativeOrder(mapping, row[f.claimOrder]) === S.orderNumber(reservation.order),\n );\n const now = yield* owner.now(mapping.clock);\n\n invariant(now >= reservation.claim.claimedAtMillis);\n\n return {\n key,\n row,\n now,\n active: row[f.state] === \"Claimed\" && now < reservation.claim.claimExpiresAtMillis,\n };\n});\n\nconst credential = Effect.fn(\"oauthConnected.signInCredential\")(function* (\n mapping: S.Mapping,\n reservation: M.OAuthSignInAccessClaim,\n input: M.OAuthCredentialSnapshot,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const signIn = mapping.signIn;\n\n if (signIn === undefined) return undefined;\n const context = reservation.claim.flow.context;\n\n if (\n input.moduleId !== context.moduleId ||\n input.identity.provider !== context.provider ||\n input.identity.issuer !== context.issuer\n )\n return undefined;\n const found = yield* S.current(mapping, input.revision.subjectId);\n\n if (found === undefined || !sameRevision(found.revision, input.revision)) return undefined;\n const c = signIn.credential;\n\n const loginWhere = both(\n equal(c.table, {\n [c.moduleId]: context.moduleId,\n [c.credentialId]: input.credentialId,\n [c.subjectId]: found.nativeId,\n [c.identityKey]: yield* oauthIdentityKey(input.identity),\n [c.credentialRevision]: input.credentialRevision,\n }),\n c.activeCondition,\n );\n\n const login = yield* owner.read(c.table, loginWhere, { limit: 1 });\n\n if (login.rows.length !== 1 || !c.isActiveStatus(login.rows[0]![c.status])) return undefined;\n const f = signIn.flow;\n\n const verifiedWhere = equal(f.table, {\n [f.moduleId]: context.moduleId,\n [f.flowId]: context.flowId,\n [f.state]: \"Verified\",\n [f.claimId]: reservation.claim.claimId,\n [f.stateDigest]: context.stateDigest,\n [f.claimedAt]: mapping.clock.encodeInstant(reservation.claim.claimedAtMillis),\n [f.claimExpiresAt]: mapping.clock.encodeInstant(reservation.claim.claimExpiresAtMillis),\n });\n\n const verified = yield* owner.read(f.table, verifiedWhere, { limit: 1 });\n\n if (verified.rows.length !== 1) return undefined;\n owner.postconditions.push(\n sql`exists(select 1 from ${c.table} where ${loginWhere})`,\n sql`exists(select 1 from ${f.table} where ${verifiedWhere})`,\n );\n if (\n !(yield* S.policy(mapping, {\n kind: \"sign-in\",\n subjectId: found.nativeId,\n revision: found.revision,\n credential: snapshotOAuthSync(M.OAuthCredentialSnapshot, input),\n configuration: reservation.configuration,\n }))\n )\n return undefined;\n\n return found;\n});\n\nconst slot = Effect.fn(\"oauthConnected.signInSlot\")(function* (\n mapping: S.Mapping,\n moduleId: string,\n native: unknown,\n identityKey: string,\n profileKey: string,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const g = mapping.grant;\n\n const rows = yield* owner.read(\n g.table,\n equal(g.table, {\n [g.moduleId]: moduleId,\n [g.subjectId]: native,\n [g.profileKey]: profileKey,\n [g.activeIdentityKey]: identityKey,\n }),\n { limit: 1, admissionOnly: true },\n );\n\n const row = rows.rows[0];\n\n if (row === undefined) return undefined;\n\n return yield* S.readGrant(\n mapping,\n moduleId,\n yield* Schema.decodeUnknownEffect(M.OAuthGrantId)(row[g.grantId]).pipe(\n Effect.mapError(unavailable),\n ),\n );\n});\n\n/** Orders belong to one client registration. Moving a profile to another client\n * requires a newer profile generation; retired clients cannot replace it later. */\nconst canReplace = Effect.fnUntraced(function* (\n reservation: M.OAuthSignInAccessClaim,\n previous: M.OAuthConnectedTokenContext,\n) {\n const generation = reservation.configuration.profile.generation;\n const oldGeneration = previous.configuration.profile.generation;\n\n return (yield* S.clientKey(reservation.configuration)) ===\n (yield* S.clientKey(previous.configuration))\n ? generation >= oldGeneration &&\n S.orderNumber(reservation.order) > S.orderNumber(previous.exchangeOrder)\n : generation > oldGeneration;\n});\n\nexport const inspectSignIn = Effect.fn(\"oauthConnected.inspectSignIn\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"inspectSignIn\">,\n) {\n const found = yield* credential(mapping, input.reservation, input.credential);\n\n if (found === undefined) return { _tag: \"Rejected\" } as const;\n const r = input.reservation;\n const cl = yield* S.client(mapping, r.configuration, false);\n\n if (cl === undefined) return { _tag: \"Rejected\" } as const;\n const tuple = yield* F.inspectTuple(mapping, input.credential.identity);\n const t = mapping.ownership.tuple;\n\n if (\n tuple.row?.[t.state] !== \"Owned\" ||\n !mapping.subjectId.equals(tuple.row[t.subjectId], found.nativeId)\n )\n return { _tag: \"Rejected\" } as const;\n const co = yield* S.cohort(mapping, cl.id, tuple.key, false);\n\n const previous = yield* slot(\n mapping,\n r.claim.flow.context.moduleId,\n found.nativeId,\n tuple.key,\n r.configuration.profile.key,\n );\n\n const held = yield* exact(mapping, r);\n\n if (held === undefined) return { _tag: \"Rejected\" } as const;\n\n const quarantine =\n !held.active ||\n co.blocked ||\n S.orderNumber(r.order) <= co.cutoff ||\n previous?.row[mapping.grant.refreshWork] === \"Unresolved\" ||\n (previous !== undefined && !(yield* canReplace(r, previous.context)));\n\n return snapshotOAuthSync(M.OAuthSignInAccessInspection, {\n _tag: quarantine ? \"Quarantine\" : \"Target\",\n grantId: previous?.context.grantId ?? input.grantId,\n cohortGeneration: co.generation,\n ...(previous === undefined\n ? {}\n : { previous: snapshotOAuthSync(M.OAuthConnectedTarget, previous.context) }),\n });\n});\n\nexport const settleSignIn = Effect.fn(\"oauthConnected.settleSignIn\")(function* (\n mapping: S.Mapping,\n input: F.Input<\"settleSignIn\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const r = input.reservation;\n const out = input.outcome;\n const found = out._tag === \"Verified\" ? yield* credential(mapping, r, out.credential) : undefined;\n const cl = yield* S.client(mapping, r.configuration, false);\n\n if (cl === undefined) return { _tag: \"Rejected\" } as const;\n const f = mapping.flow;\n\n if (out._tag !== \"Verified\") {\n const held = yield* exact(mapping, r);\n\n if (held === undefined) return { _tag: \"Rejected\" } as const;\n // Unissued means the provider definitely returned no token. Resolve that\n // reservation. A Rejected outcome can follow a real exchange, so it stays open.\n const state = out._tag === \"Unissued\" ? \"Rejected\" : out._tag;\n\n yield* owner.update(f.table, held.key, {\n [f.state]: state,\n [f.work]: out._tag === \"Cancelled\" || out._tag === \"Unissued\" ? \"Resolved\" : \"Unresolved\",\n [f.version]: owner.marker,\n });\n\n return { _tag: state };\n }\n const token = out.grant.context;\n\n invariant(\n token.moduleId === r.claim.flow.context.moduleId &&\n token.subjectId === out.credential.revision.subjectId &&\n sameIdentity(token.identity, out.credential.identity) &&\n configurationStorage.encode(token.configuration) ===\n configurationStorage.encode(r.configuration),\n );\n const native = yield* mapping.subjectId.toNative(token.subjectId);\n const tuple = yield* F.readTuple(mapping.ownership, token.identity);\n const t = mapping.ownership.tuple;\n\n const owned =\n tuple.row[t.state] === \"Owned\" && mapping.subjectId.equals(tuple.row[t.subjectId], native);\n\n const co = yield* S.cohort(mapping, cl.id, tuple.key, true);\n const previous = yield* S.readGrant(mapping, token.moduleId, token.grantId);\n\n const activeSlot = yield* slot(\n mapping,\n token.moduleId,\n native,\n tuple.key,\n token.configuration.profile.key,\n );\n\n const held = yield* exact(mapping, r);\n\n if (held === undefined) return { _tag: \"Rejected\" } as const;\n invariant(\n token.exchangeOrder === r.order &&\n validMetadata(token, held.now) &&\n token.metadata.obtainedAtMillis >= r.claim.claimedAtMillis,\n );\n\n const target =\n out.previous === undefined\n ? previous === undefined\n : previous !== undefined &&\n F.sameTarget(out.previous, previous.context) &&\n sameIdentity(previous.context.identity, token.identity) &&\n previous.row[mapping.grant.refreshWork] !== \"Unresolved\" &&\n (yield* canReplace(r, previous.context));\n\n const previousSafe = yield* C.noFormerOwner(mapping, tuple.key, cl.id, native);\n\n if (!owned || !previousSafe) {\n yield* owner.update(f.table, held.key, { [f.state]: \"Conflict\", [f.version]: owner.marker });\n\n return { _tag: \"Conflict\" } as const;\n }\n if (\n out.quarantine ||\n found === undefined ||\n !held.active ||\n !target ||\n (activeSlot !== undefined && activeSlot.context.grantId !== token.grantId) ||\n co.blocked ||\n S.orderNumber(r.order) <= co.cutoff ||\n co.generation !== token.cohortGeneration ||\n token.metadata.useUntilMillis <= held.now ||\n token.configuration.profile.issuance !== \"active\"\n ) {\n if (token.configuration.profile.revocation === \"unsupported\") {\n // No remote cleanup can run for this profile. Discard the losing material;\n // it must neither replace nor revoke the currently installed grant.\n yield* owner.update(f.table, held.key, {\n [f.state]: \"Rejected\",\n [f.work]: \"Resolved\",\n [f.subjectId]: native,\n [f.cohortKey]: co.id,\n [f.custody]: null,\n [f.version]: owner.marker,\n });\n } else {\n yield* C.fence(mapping, cl, co);\n if (out.cleanup === undefined) return yield* unavailable();\n yield* C.storeJob(mapping, out.cleanup, token, native, held.now);\n yield* owner.update(f.table, held.key, {\n [f.state]: \"Quarantined\",\n [f.work]: \"Resolved\",\n [f.subjectId]: native,\n [f.cohortKey]: co.id,\n [f.custody]: null,\n [f.version]: owner.marker,\n });\n }\n\n return { _tag: \"Rejected\" } as const;\n }\n yield* activateGrant(mapping, out.grant, native, held.now, previous !== undefined);\n yield* owner.update(f.table, held.key, {\n [f.state]: \"Connected\",\n [f.work]: \"Resolved\",\n [f.subjectId]: native,\n [f.cohortKey]: co.id,\n [f.custody]: null,\n [f.version]: owner.marker,\n });\n owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${held.now} and ${mapping.clock.engineNowMillis} < ${Math.min(r.claim.claimExpiresAtMillis, token.metadata.useUntilMillis)}`,\n );\n\n return { _tag: \"Connected\", grant: out.grant } as const;\n});\n"],"mappings":"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"}
|