@yielded/auth-persistence-drizzle 0.1.0-beta.17 → 0.1.0-beta.19
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 +8 -1
- package/dist/D1.d.mts +120 -120
- package/dist/Libsql.d.mts +154 -154
- package/dist/Mysql2.d.mts +166 -166
- package/dist/Pglite.d.mts +166 -166
- package/dist/Postgres.d.mts +152 -152
- package/dist/SqliteBun.d.mts +168 -168
- package/dist/SqliteDo.d.mts +237 -259
- package/dist/SqliteDo.mjs +30 -45
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +154 -154
- package/dist/SqliteWasm.d.mts +163 -163
- package/dist/drizzle/crypto.mjs +11 -0
- package/dist/drizzle/crypto.mjs.map +1 -0
- package/dist/drizzle/d1-identity.mjs +2 -2
- package/dist/drizzle/d1-identity.mjs.map +1 -1
- package/dist/drizzle/d1-oauth.d.mts +16 -16
- package/dist/drizzle/d1-oauth.mjs.map +1 -1
- package/dist/drizzle/d1-passkey.d.mts +6 -6
- package/dist/drizzle/d1-passkey.mjs.map +1 -1
- package/dist/drizzle/d1-password-prepared.mjs +3 -3
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +1 -1
- package/dist/drizzle/d1-passwords.mjs +1 -1
- package/dist/drizzle/d1-passwords.mjs.map +1 -1
- package/dist/drizzle/d1-phone.d.mts +3 -3
- package/dist/drizzle/d1-phone.mjs.map +1 -1
- package/dist/drizzle/d1-proofs.d.mts +1 -1
- package/dist/drizzle/d1-sessions.d.mts +1 -1
- package/dist/drizzle/d1-sessions.mjs +4 -3
- package/dist/drizzle/d1-sessions.mjs.map +1 -1
- package/dist/drizzle/d1-totp.d.mts +3 -3
- package/dist/drizzle/d1-totp.mjs.map +1 -1
- package/dist/drizzle/mysql-identity.mjs +2 -2
- package/dist/drizzle/mysql-identity.mjs.map +1 -1
- package/dist/drizzle/oauth-accounts.mjs +9 -8
- package/dist/drizzle/oauth-accounts.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-collection.mjs +1 -1
- package/dist/drizzle/oauth-connected-collection.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-custody.mjs +5 -4
- package/dist/drizzle/oauth-connected-custody.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-flow.mjs +8 -7
- package/dist/drizzle/oauth-connected-flow.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-management.mjs +3 -2
- package/dist/drizzle/oauth-connected-management.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-reference.mjs +8 -4
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-settlement.mjs +4 -4
- package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-sign-in.mjs +11 -10
- package/dist/drizzle/oauth-connected-sign-in.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-state.d.mts +265 -265
- package/dist/drizzle/oauth-connected-state.mjs +23 -20
- package/dist/drizzle/oauth-connected-state.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-target.d.mts +105 -105
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
- package/dist/drizzle/oauth-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-flow.mjs +1 -1
- package/dist/drizzle/oauth-flow.mjs.map +1 -1
- package/dist/drizzle/oauth-model.d.mts +4 -4
- package/dist/drizzle/oauth-model.mjs.map +1 -1
- package/dist/drizzle/oauth-registration.mjs +2 -2
- package/dist/drizzle/oauth-registration.mjs.map +1 -1
- package/dist/drizzle/oauth-state.mjs +11 -12
- package/dist/drizzle/oauth-state.mjs.map +1 -1
- package/dist/drizzle/oauth-target.d.mts +4 -4
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/passkey-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-target.d.mts +1 -1
- package/dist/drizzle/password-prepared-sql.mjs +1 -1
- package/dist/drizzle/password-prepared-sql.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +1 -1
- package/dist/drizzle/pg-identity.mjs +2 -2
- package/dist/drizzle/pg-identity.mjs.map +1 -1
- package/dist/drizzle/phone-model.d.mts +2 -2
- package/dist/drizzle/phone-model.mjs +3 -3
- package/dist/drizzle/phone-model.mjs.map +1 -1
- package/dist/drizzle/phone-target.d.mts +1 -1
- package/dist/drizzle/phone-target.mjs +2 -2
- package/dist/drizzle/phone-target.mjs.map +1 -1
- package/dist/drizzle/sqlite-do-database.d.mts +29 -0
- package/dist/drizzle/sqlite-do-database.mjs +45 -0
- package/dist/drizzle/sqlite-do-database.mjs.map +1 -0
- package/dist/drizzle/sqlite-emails.mjs.map +1 -1
- package/dist/drizzle/sqlite-identity.mjs +2 -2
- package/dist/drizzle/sqlite-identity.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/sqlite-proofs.mjs.map +1 -1
- package/dist/drizzle/sqlite-sessions.mjs.map +1 -1
- package/dist/drizzle/storage-validation.mjs +17 -9
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-state.mjs +8 -8
- package/dist/drizzle/totp-state.mjs.map +1 -1
- package/dist/drizzle/totp-target.d.mts +1 -1
- package/dist/drizzle/totp-target.mjs +2 -2
- package/dist/drizzle/totp-target.mjs.map +1 -1
- package/package.json +1 -1
- package/src/SqliteDo.ts +63 -70
- package/src/drizzle/crypto.ts +14 -0
- package/src/drizzle/d1-identity.ts +2 -2
- package/src/drizzle/d1-oauth.ts +14 -5
- package/src/drizzle/d1-passkey.ts +5 -1
- package/src/drizzle/d1-password-prepared.ts +11 -5
- package/src/drizzle/d1-passwords.ts +1 -1
- package/src/drizzle/d1-phone.ts +2 -1
- package/src/drizzle/d1-sessions.ts +8 -2
- package/src/drizzle/d1-totp.ts +6 -2
- package/src/drizzle/mysql-identity.ts +2 -2
- package/src/drizzle/oauth-accounts.ts +14 -13
- package/src/drizzle/oauth-connected-collection.ts +1 -1
- package/src/drizzle/oauth-connected-custody.ts +8 -6
- package/src/drizzle/oauth-connected-drivers.ts +9 -3
- package/src/drizzle/oauth-connected-flow.ts +6 -6
- package/src/drizzle/oauth-connected-management.ts +1 -1
- package/src/drizzle/oauth-connected-reference.ts +14 -9
- package/src/drizzle/oauth-connected-settlement.ts +4 -4
- package/src/drizzle/oauth-connected-sign-in.ts +11 -10
- package/src/drizzle/oauth-connected-state.ts +40 -25
- package/src/drizzle/oauth-connected-target.ts +9 -5
- package/src/drizzle/oauth-drivers.ts +13 -5
- package/src/drizzle/oauth-flow.ts +1 -1
- package/src/drizzle/oauth-model.ts +4 -4
- package/src/drizzle/oauth-registration.ts +2 -2
- package/src/drizzle/oauth-state.ts +17 -15
- package/src/drizzle/oauth-target.ts +11 -3
- package/src/drizzle/passkey-drivers.ts +7 -3
- package/src/drizzle/passkey-write-drivers.ts +11 -2
- package/src/drizzle/password-prepared-sql.ts +1 -1
- package/src/drizzle/pg-identity.ts +2 -2
- package/src/drizzle/phone-model.ts +3 -3
- package/src/drizzle/phone-target.ts +11 -4
- package/src/drizzle/sqlite-do-database.ts +87 -0
- package/src/drizzle/sqlite-emails.ts +1 -1
- package/src/drizzle/sqlite-identity.ts +2 -2
- package/src/drizzle/sqlite-passwords.ts +1 -1
- package/src/drizzle/sqlite-proofs.ts +2 -2
- package/src/drizzle/sqlite-sessions.ts +2 -2
- package/src/drizzle/storage-validation.ts +15 -6
- package/src/drizzle/totp-state.ts +8 -8
- package/src/drizzle/totp-target.ts +11 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-custody.mjs","names":["S.rowCount","S.countCondition","S.nextOrder","S.clientKey","S.cohortKey","S.nativeCopy","S.retainedUntil","S.jobTable","S.unknownWork","S.cohortWork"],"sources":["../../src/drizzle/oauth-connected-custody.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport { snapshotOAuthSync } from \"@yielded/auth/OAuth\";\nimport { eq, isNotNull, ne, sql, type SQL } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as S from \"./oauth-connected-state\";\nimport { both, col, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { invariant, oauthIdentityKey } from \"./oauth-state\";\n\ntype Client = NonNullable<Effect.Success<ReturnType<typeof S.client>>>;\ntype Cohort = Effect.Success<ReturnType<typeof S.cohort>>;\n\nexport const sameContext = (a: M.OAuthConnectedTokenContext, b: M.OAuthConnectedTokenContext) =>\n S.tokenContextStorage.encode(a) === S.tokenContextStorage.encode(b);\n\nexport const sameGrant = (a: M.OAuthConnectedStoredGrant, b: M.OAuthConnectedStoredGrant) =>\n S.grantStorage.encode(a) === S.grantStorage.encode(b);\n\nexport const summary = (context: M.OAuthConnectedTokenContext) =>\n snapshotOAuthSync(M.OAuthConnectedSummary, {\n grantId: context.grantId,\n provider: context.identity.provider,\n issuer: context.identity.issuer,\n profileKey: context.configuration.profile.key,\n status: \"Active\",\n scopes: context.metadata.scopes,\n ...(context.metadata.accessExpiresAtMillis === undefined\n ? {}\n : { accessExpiresAtMillis: context.metadata.accessExpiresAtMillis }),\n useUntilMillis: context.metadata.useUntilMillis,\n ...(context.metadata.profile === undefined ? {} : { profile: context.metadata.profile }),\n remoteRevocation:\n context.configuration.profile.revocation === \"cohort\" ? \"Pending\" : \"Unsupported\",\n });\n\n/** A generation fences every sibling, including those beyond a bounded metadata page. */\nexport const fence = Effect.fn(\"oauthConnected.fence\")(function* (\n mapping: S.Authority,\n client: Client,\n cohort: Cohort,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n invariant(cohort.row !== undefined);\n\n const g = mapping.grant,\n h = mapping.cohort;\n\n const active = both(\n eq(col(g.table, g.cohortKey), cohort.id),\n isNotNull(col(g.table, g.activeIdentityKey)),\n );\n\n const affected = yield* S.rowCount(g.table, active);\n\n invariant(yield* owner.check(S.countCondition(g.table, active, affected)));\n const cutoff = yield* S.nextOrder(mapping, client);\n const generation = M.OAuthConnectedTarget.fields.cohortGeneration.make(owner.marker);\n\n yield* owner.update(\n h.table,\n { [h.cohortKey]: cohort.id },\n {\n [h.generation]: generation,\n [h.cutoff]: mapping.order.encode(cutoff),\n [h.state]: \"Blocked\",\n [h.version]: owner.marker,\n },\n );\n yield* owner.write(\n owner.database\n .update(g.table)\n .set({\n [g.activeIdentityKey]: null,\n [g.state]: \"ReauthorizationRequired\",\n [g.version]: owner.marker,\n })\n .where(active),\n );\n for (const observation of owner.observations)\n if (observation.table === g.table)\n observation.rows = observation.rows.map((row) =>\n row[g.cohortKey] === cohort.id && row[g.activeIdentityKey] !== null\n ? {\n ...row,\n [g.activeIdentityKey]: null,\n [g.state]: \"ReauthorizationRequired\",\n [g.version]: owner.marker,\n }\n : row,\n );\n owner.postconditions.push(sql`not exists(select 1 from ${g.table} where ${active})`);\n cohort.generation = generation;\n cohort.cutoff = cutoff;\n cohort.blocked = true;\n\n return affected;\n});\n\nexport const storeJob = Effect.fn(\"oauthConnected.storeJob\")(function* (\n mapping: S.Mapping,\n job: M.OAuthConnectedRevocationJob,\n token: M.OAuthConnectedTokenContext,\n native: unknown,\n now: number,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n invariant(\n mapping.revocation.mode === \"cohort\" &&\n token.configuration.profile.revocation === \"cohort\" &&\n sameContext(job.context.token, token),\n );\n\n const j = mapping.revocation.job,\n identity = oauthIdentityKey(token.identity),\n client = S.clientKey(token.configuration),\n cohort = S.cohortKey(client, identity);\n\n const h = mapping.cohort;\n\n owner.postconditions.push(\n sql`exists(select 1 from ${h.table} where ${both(equal(h.table, { [h.cohortKey]: cohort, [h.clientKey]: client, [h.identityKey]: identity, [h.state]: \"Blocked\" }))})`,\n );\n const key = { [j.jobId]: job.context.jobId };\n const prior = yield* owner.read(j.table, equal(j.table, key), { limit: 1 });\n\n if (prior.rows.length) {\n const row = prior.rows[0]!;\n\n invariant(\n row[j.snapshot] === S.jobStorage.encode(job) &&\n row[j.moduleId] === token.moduleId &&\n mapping.subjectId.equals(row[j.subjectId], native) &&\n row[j.identityKey] === identity &&\n row[j.clientKey] === client &&\n row[j.cohortKey] === cohort &&\n row[j.grantId] === token.grantId &&\n [\"Pending\", \"Claimed\", \"Confirmed\", \"Unknown\"].includes(row[j.state]),\n );\n invariant(\n row[j.state] === \"Pending\"\n ? row[j.claimId] === null && row[j.claimedAt] === null && row[j.claimExpiresAt] === null\n : typeof row[j.claimId] === \"string\" &&\n mapping.clock.decodeInstant(row[j.claimExpiresAt]) >\n mapping.clock.decodeInstant(row[j.claimedAt]),\n );\n\n return;\n }\n\n const inserted = yield* owner.insert(\n j.table,\n {\n ...j.encodeInsert({\n job: snapshotOAuthSync(M.OAuthConnectedRevocationJob, job),\n subjectId: S.nativeCopy(native),\n }),\n ...key,\n [j.moduleId]: token.moduleId,\n [j.subjectId]: native,\n [j.identityKey]: identity,\n [j.clientKey]: client,\n [j.cohortKey]: cohort,\n [j.grantId]: token.grantId,\n [j.snapshot]: S.jobStorage.encode(job),\n [j.state]: \"Pending\",\n [j.claimId]: null,\n [j.claimedAt]: null,\n [j.claimExpiresAt]: null,\n [j.retentionUntil]: mapping.clock.encodeInstant(S.retainedUntil(mapping, now)),\n [j.version]: owner.marker,\n },\n key,\n );\n\n prior.rows = inserted.rows;\n});\n\nconst noJobs = (mapping: S.Authority, id: string | SQL, except?: string) => {\n const j = S.jobTable(mapping);\n\n return j === undefined\n ? sql`1 = 1`\n : sql`not exists(select 1 from ${j.table} where ${both(eq(col(j.table, j.cohortKey), id), ne(col(j.table, j.state), \"Confirmed\"), except === undefined ? undefined : ne(col(j.table, j.jobId), except))})`;\n};\n\nexport const clearableCondition = (\n mapping: S.Authority,\n cohortId: string | SQL,\n clientId: string | SQL,\n) => {\n const f = mapping.flow;\n\n return both(\n sql`not exists(select 1 from ${f.table} where ${S.unknownWork(mapping, clientId)})`,\n S.cohortWork(mapping, cohortId),\n noJobs(mapping, cohortId),\n );\n};\n\n/** Clearing owns a NEW cutoff. Claims made while the remote revoke was pending\n * cannot enter the next generation even if they finish after that revoke. */\nexport const clear = Effect.fn(\"oauthConnected.clear\")(function* (\n mapping: S.Authority,\n client: Client,\n cohort: Cohort,\n confirmedJob?: string,\n provenOpenWithoutNewJob = false,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n if (\n !cohort.blocked ||\n cohort.row === undefined ||\n (S.jobTable(mapping) === undefined && !provenOpenWithoutNewJob)\n )\n return false;\n const f = mapping.flow;\n const noUnknown = sql`not exists(select 1 from ${f.table} where ${S.unknownWork(mapping, client.id)})`;\n const work = S.cohortWork(mapping, cohort.id);\n\n if (!(yield* owner.check(both(noUnknown, work, noJobs(mapping, cohort.id, confirmedJob)))))\n return false;\n\n const cutoff = yield* S.nextOrder(mapping, client),\n h = mapping.cohort;\n\n const generation = M.OAuthConnectedTarget.fields.cohortGeneration.make(owner.marker + \":open\");\n\n yield* owner.update(\n h.table,\n { [h.cohortKey]: cohort.id },\n {\n [h.generation]: generation,\n [h.cutoff]: mapping.order.encode(cutoff),\n [h.state]: \"Open\",\n [h.version]: owner.marker,\n },\n );\n owner.postconditions.push(noUnknown, work, noJobs(mapping, cohort.id));\n cohort.generation = generation;\n cohort.cutoff = cutoff;\n cohort.blocked = false;\n\n return true;\n});\n\n/** Former local owners remain visible. A foreign historical dependency cannot be\n * ignored simply because the global tuple was changed outside this authority. */\nexport const noFormerOwner = (\n mapping: S.Authority,\n identity: string,\n client: string,\n native: unknown,\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) => {\n const g = mapping.grant,\n f = mapping.flow,\n j = S.jobTable(mapping);\n\n const condition = both(\n sql`not exists(select 1 from ${g.table} where ${both(eq(col(g.table, g.identityKey), identity), sql`not (${owner.exact(g.table, { [g.subjectId]: native })})`)})`,\n sql`not exists(select 1 from ${f.table} where ${both(eq(col(f.table, f.cohortKey), S.cohortKey(client, identity)), eq(col(f.table, f.work), \"Unresolved\"), sql`not (${owner.exact(f.table, { [f.subjectId]: native })})`)})`,\n ...(j === undefined\n ? []\n : [\n sql`not exists(select 1 from ${j.table} where ${both(eq(col(j.table, j.identityKey), identity), sql`not (${owner.exact(j.table, { [j.subjectId]: native })})`)})`,\n ]),\n );\n\n return Effect.map(owner.check(condition), (accepted) => {\n if (accepted) owner.postconditions.push(condition);\n\n return accepted;\n });\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-connected-custody.mjs","names":["S.rowCount","S.countCondition","S.nextOrder","S.clientKey","S.cohortKey","S.nativeCopy","S.retainedUntil","S.jobTable","S.unknownWork","S.cohortWork"],"sources":["../../src/drizzle/oauth-connected-custody.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport { snapshotOAuthSync } from \"@yielded/auth/OAuth\";\nimport { eq, isNotNull, ne, sql, type SQL } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as S from \"./oauth-connected-state\";\nimport { both, col, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { invariant, oauthIdentityKey } from \"./oauth-state\";\n\ntype Client = NonNullable<Effect.Success<ReturnType<typeof S.client>>>;\ntype Cohort = Effect.Success<ReturnType<typeof S.cohort>>;\n\nexport const sameContext = (a: M.OAuthConnectedTokenContext, b: M.OAuthConnectedTokenContext) =>\n S.tokenContextStorage.encode(a) === S.tokenContextStorage.encode(b);\n\nexport const sameGrant = (a: M.OAuthConnectedStoredGrant, b: M.OAuthConnectedStoredGrant) =>\n S.grantStorage.encode(a) === S.grantStorage.encode(b);\n\nexport const summary = (context: M.OAuthConnectedTokenContext) =>\n snapshotOAuthSync(M.OAuthConnectedSummary, {\n grantId: context.grantId,\n provider: context.identity.provider,\n issuer: context.identity.issuer,\n profileKey: context.configuration.profile.key,\n status: \"Active\",\n scopes: context.metadata.scopes,\n ...(context.metadata.accessExpiresAtMillis === undefined\n ? {}\n : { accessExpiresAtMillis: context.metadata.accessExpiresAtMillis }),\n useUntilMillis: context.metadata.useUntilMillis,\n ...(context.metadata.profile === undefined ? {} : { profile: context.metadata.profile }),\n remoteRevocation:\n context.configuration.profile.revocation === \"cohort\" ? \"Pending\" : \"Unsupported\",\n });\n\n/** A generation fences every sibling, including those beyond a bounded metadata page. */\nexport const fence = Effect.fn(\"oauthConnected.fence\")(function* (\n mapping: S.Authority,\n client: Client,\n cohort: Cohort,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n invariant(cohort.row !== undefined);\n\n const g = mapping.grant,\n h = mapping.cohort;\n\n const active = both(\n eq(col(g.table, g.cohortKey), cohort.id),\n isNotNull(col(g.table, g.activeIdentityKey)),\n );\n\n const affected = yield* S.rowCount(g.table, active);\n\n invariant(yield* owner.check(S.countCondition(g.table, active, affected)));\n const cutoff = yield* S.nextOrder(mapping, client);\n const generation = M.OAuthConnectedTarget.fields.cohortGeneration.make(owner.marker);\n\n yield* owner.update(\n h.table,\n { [h.cohortKey]: cohort.id },\n {\n [h.generation]: generation,\n [h.cutoff]: mapping.order.encode(cutoff),\n [h.state]: \"Blocked\",\n [h.version]: owner.marker,\n },\n );\n yield* owner.write(\n owner.database\n .update(g.table)\n .set({\n [g.activeIdentityKey]: null,\n [g.state]: \"ReauthorizationRequired\",\n [g.version]: owner.marker,\n })\n .where(active),\n );\n for (const observation of owner.observations)\n if (observation.table === g.table)\n observation.rows = observation.rows.map((row) =>\n row[g.cohortKey] === cohort.id && row[g.activeIdentityKey] !== null\n ? {\n ...row,\n [g.activeIdentityKey]: null,\n [g.state]: \"ReauthorizationRequired\",\n [g.version]: owner.marker,\n }\n : row,\n );\n owner.postconditions.push(sql`not exists(select 1 from ${g.table} where ${active})`);\n cohort.generation = generation;\n cohort.cutoff = cutoff;\n cohort.blocked = true;\n\n return affected;\n});\n\nexport const storeJob = Effect.fn(\"oauthConnected.storeJob\")(function* (\n mapping: S.Mapping,\n job: M.OAuthConnectedRevocationJob,\n token: M.OAuthConnectedTokenContext,\n native: unknown,\n now: number,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n invariant(\n mapping.revocation.mode === \"cohort\" &&\n token.configuration.profile.revocation === \"cohort\" &&\n sameContext(job.context.token, token),\n );\n\n const j = mapping.revocation.job,\n identity = yield* oauthIdentityKey(token.identity),\n client = yield* S.clientKey(token.configuration),\n cohort = yield* S.cohortKey(client, identity);\n\n const h = mapping.cohort;\n\n owner.postconditions.push(\n sql`exists(select 1 from ${h.table} where ${both(equal(h.table, { [h.cohortKey]: cohort, [h.clientKey]: client, [h.identityKey]: identity, [h.state]: \"Blocked\" }))})`,\n );\n const key = { [j.jobId]: job.context.jobId };\n const prior = yield* owner.read(j.table, equal(j.table, key), { limit: 1 });\n\n if (prior.rows.length) {\n const row = prior.rows[0]!;\n\n invariant(\n row[j.snapshot] === S.jobStorage.encode(job) &&\n row[j.moduleId] === token.moduleId &&\n mapping.subjectId.equals(row[j.subjectId], native) &&\n row[j.identityKey] === identity &&\n row[j.clientKey] === client &&\n row[j.cohortKey] === cohort &&\n row[j.grantId] === token.grantId &&\n [\"Pending\", \"Claimed\", \"Confirmed\", \"Unknown\"].includes(row[j.state]),\n );\n invariant(\n row[j.state] === \"Pending\"\n ? row[j.claimId] === null && row[j.claimedAt] === null && row[j.claimExpiresAt] === null\n : typeof row[j.claimId] === \"string\" &&\n mapping.clock.decodeInstant(row[j.claimExpiresAt]) >\n mapping.clock.decodeInstant(row[j.claimedAt]),\n );\n\n return;\n }\n\n const inserted = yield* owner.insert(\n j.table,\n {\n ...j.encodeInsert({\n job: snapshotOAuthSync(M.OAuthConnectedRevocationJob, job),\n subjectId: S.nativeCopy(native),\n }),\n ...key,\n [j.moduleId]: token.moduleId,\n [j.subjectId]: native,\n [j.identityKey]: identity,\n [j.clientKey]: client,\n [j.cohortKey]: cohort,\n [j.grantId]: token.grantId,\n [j.snapshot]: S.jobStorage.encode(job),\n [j.state]: \"Pending\",\n [j.claimId]: null,\n [j.claimedAt]: null,\n [j.claimExpiresAt]: null,\n [j.retentionUntil]: mapping.clock.encodeInstant(S.retainedUntil(mapping, now)),\n [j.version]: owner.marker,\n },\n key,\n );\n\n prior.rows = inserted.rows;\n});\n\nconst noJobs = (mapping: S.Authority, id: string | SQL, except?: string) => {\n const j = S.jobTable(mapping);\n\n return j === undefined\n ? sql`1 = 1`\n : sql`not exists(select 1 from ${j.table} where ${both(eq(col(j.table, j.cohortKey), id), ne(col(j.table, j.state), \"Confirmed\"), except === undefined ? undefined : ne(col(j.table, j.jobId), except))})`;\n};\n\nexport const clearableCondition = (\n mapping: S.Authority,\n cohortId: string | SQL,\n clientId: string | SQL,\n) => {\n const f = mapping.flow;\n\n return both(\n sql`not exists(select 1 from ${f.table} where ${S.unknownWork(mapping, clientId)})`,\n S.cohortWork(mapping, cohortId),\n noJobs(mapping, cohortId),\n );\n};\n\n/** Clearing owns a NEW cutoff. Claims made while the remote revoke was pending\n * cannot enter the next generation even if they finish after that revoke. */\nexport const clear = Effect.fn(\"oauthConnected.clear\")(function* (\n mapping: S.Authority,\n client: Client,\n cohort: Cohort,\n confirmedJob?: string,\n provenOpenWithoutNewJob = false,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n if (\n !cohort.blocked ||\n cohort.row === undefined ||\n (S.jobTable(mapping) === undefined && !provenOpenWithoutNewJob)\n )\n return false;\n const f = mapping.flow;\n const noUnknown = sql`not exists(select 1 from ${f.table} where ${S.unknownWork(mapping, client.id)})`;\n const work = S.cohortWork(mapping, cohort.id);\n\n if (!(yield* owner.check(both(noUnknown, work, noJobs(mapping, cohort.id, confirmedJob)))))\n return false;\n\n const cutoff = yield* S.nextOrder(mapping, client),\n h = mapping.cohort;\n\n const generation = M.OAuthConnectedTarget.fields.cohortGeneration.make(owner.marker + \":open\");\n\n yield* owner.update(\n h.table,\n { [h.cohortKey]: cohort.id },\n {\n [h.generation]: generation,\n [h.cutoff]: mapping.order.encode(cutoff),\n [h.state]: \"Open\",\n [h.version]: owner.marker,\n },\n );\n owner.postconditions.push(noUnknown, work, noJobs(mapping, cohort.id));\n cohort.generation = generation;\n cohort.cutoff = cutoff;\n cohort.blocked = false;\n\n return true;\n});\n\n/** Former local owners remain visible. A foreign historical dependency cannot be\n * ignored simply because the global tuple was changed outside this authority. */\nexport const noFormerOwner = (\n mapping: S.Authority,\n identity: string,\n client: string,\n native: unknown,\n) =>\n Effect.gen(function* () {\n const owner = yield* CurrentOAuthTransaction;\n\n const g = mapping.grant,\n f = mapping.flow,\n j = S.jobTable(mapping);\n\n const condition = both(\n sql`not exists(select 1 from ${g.table} where ${both(eq(col(g.table, g.identityKey), identity), sql`not (${owner.exact(g.table, { [g.subjectId]: native })})`)})`,\n sql`not exists(select 1 from ${f.table} where ${both(eq(col(f.table, f.cohortKey), yield* S.cohortKey(client, identity)), eq(col(f.table, f.work), \"Unresolved\"), sql`not (${owner.exact(f.table, { [f.subjectId]: native })})`)})`,\n ...(j === undefined\n ? []\n : [\n sql`not exists(select 1 from ${j.table} where ${both(eq(col(j.table, j.identityKey), identity), sql`not (${owner.exact(j.table, { [j.subjectId]: native })})`)})`,\n ]),\n );\n\n return yield* Effect.map(owner.check(condition), (accepted) => {\n if (accepted) owner.postconditions.push(condition);\n\n return accepted;\n });\n });\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-drivers.mjs","names":[],"sources":["../../src/drizzle/oauth-connected-drivers.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n OAuthConnectedPersistence,\n OAuthConnectedRevocations,\n OAuthUnavailable,\n} from \"@yielded/auth/OAuth\";\nimport type { Table } from \"drizzle-orm\";\nimport { Effect, Context } from \"effect\";\n\nimport { makeD1Owner } from \"./d1-planning\";\nimport { D1BatchStatements } from \"./D1BatchStatements\";\nimport { nativeDatabase } from \"./native-database\";\nimport type {\n OAuthConnectedMapping,\n OAuthConnectedRevocationMapping,\n} from \"./oauth-connected-model\";\nimport {\n coordinateTargetOAuthConnected,\n coordinateTargetOAuthConnectedRevocations,\n makeTargetOAuthConnectedServices,\n makeTargetOAuthConnectedRevocationServices,\n} from \"./oauth-connected-target\";\nimport { type OAuthCoordinatorError, type OAuthTargetConfiguration } from \"./oauth-target\";\nimport type { SuppliedService } from \"./SuppliedService\";\n// oxlint-disable-next-line no-explicit-any -- inspect the actual installed native transaction callback without erasing it.\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\nconst unavailable = () => OAuthUnavailable.make({});\n\nexport const makeOAuthConnectedTarget = <\n DatabaseId,\n Database,\n Family extends Table,\n Extra = {},\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, Database>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthConnectedPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedPersistence>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthConnectedPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedPersistence | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthConnectedPersistence> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnected<TransactionOf<D>, A, E, Exclude<R, OAuthConnectedPersistence>>(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<D>,\n services: { readonly oauthConnectedPersistence: OAuthConnectedPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthConnectedPersistence,\n services.oauthConnectedPersistence,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthConnectedRevocations> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedRevocations>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthConnectedRevocations | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedRevocations | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthConnectedRevocations> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnectedRevocations<\n TransactionOf<D>,\n A,\n E,\n Exclude<R, OAuthConnectedRevocations>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<D>,\n services: { readonly oauthConnectedRevocations: OAuthConnectedRevocations[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthConnectedRevocations,\n services.oauthConnectedRevocations,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n makeOAuthConnectedServices: <\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family = never,\n >(\n mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra,\n ) =>\n makeTargetOAuthConnectedServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthConnectedRevocationServices: <\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n >(\n mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra,\n ) =>\n makeTargetOAuthConnectedRevocationServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateOAuthConnected,\n coordinateOAuthConnectedRevocations,\n };\n};\n\nexport const makeD1OAuthConnectedTarget = <DatabaseId, Database, Family extends Table, Extra>(\n databaseService: Context.Service<DatabaseId, Database>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthConnected<\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | Exclude<R, OAuthConnectedPersistence | D1BatchStatements>\n | LifecycleHooks\n | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnected<\n Database,\n A,\n E | OAuthUnavailable,\n Exclude<R, OAuthConnectedPersistence | D1BatchStatements>\n >(database, options.mapping, configuration, (_tx, services, append) =>\n Effect.gen(function* () {\n const original = services.oauthConnectedPersistence;\n\n const nativeCollector = D1BatchStatements.of({\n append: (statement) => Effect.sync(() => append(statement)),\n });\n\n const owner = yield* makeD1Owner(unavailable()).pipe(\n Effect.provideService(D1BatchStatements, nativeCollector),\n );\n\n const service: OAuthConnectedPersistence[\"Service\"] = {\n claimSignIn: (input, prepare) => owner.run(original.claimSignIn(input, prepare)),\n inspectSignIn: (input) => owner.run(original.inspectSignIn(input)),\n settleSignIn: (input, prepare) => owner.run(original.settleSignIn(input, prepare)),\n capture: (input) => owner.run(original.capture(input)),\n issue: (input, prepare) => owner.run(original.issue(input, prepare)),\n prepare: (input, prepare) => owner.run(original.prepare(input, prepare)),\n inspectPrepared: (input) => owner.run(original.inspectPrepared(input)),\n preflight: (input) => owner.run(original.preflight(input)),\n claim: (input, prepare) => owner.run(original.claim(input, prepare)),\n inspectGrant: (input) => owner.run(original.inspectGrant(input)),\n settle: (input, prepare) => owner.run(original.settle(input, prepare)),\n list: (input) => owner.run(original.list(input)),\n inspectDisconnect: (input) => owner.run(original.inspectDisconnect(input)),\n disconnect: (input, prepare) => owner.run(original.disconnect(input, prepare)),\n inspectAccess: (input) => owner.run(original.inspectAccess(input)),\n claimRefresh: (input, prepare) => owner.run(original.claimRefresh(input, prepare)),\n settleRefresh: (input, prepare) => owner.run(original.settleRefresh(input, prepare)),\n admitUse: (input, prepare) => owner.run(original.admitUse(input, prepare)),\n cleanup: (input, prepare) => owner.run(original.cleanup(input, prepare)),\n };\n\n const provided = Context.make(OAuthConnectedPersistence, service).pipe(\n Context.add(D1BatchStatements, owner.collector),\n );\n\n return yield* owner.close(Effect.provideContext(body, provided));\n }),\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthConnectedRevocations<\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: { readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | Exclude<R, OAuthConnectedRevocations | D1BatchStatements>\n | LifecycleHooks\n | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnectedRevocations<\n Database,\n A,\n E | OAuthUnavailable,\n Exclude<R, OAuthConnectedRevocations | D1BatchStatements>\n >(database, options.mapping, configuration, (_tx, services, append) =>\n Effect.gen(function* () {\n const original = services.oauthConnectedRevocations;\n\n const nativeCollector = D1BatchStatements.of({\n append: (statement) => Effect.sync(() => append(statement)),\n });\n\n const owner = yield* makeD1Owner(unavailable()).pipe(\n Effect.provideService(D1BatchStatements, nativeCollector),\n );\n\n const service: OAuthConnectedRevocations[\"Service\"] = {\n claim: (input, prepare) => owner.run(original.claim(input, prepare)),\n settle: (input, prepare) => owner.run(original.settle(input, prepare)),\n };\n\n const provided = Context.make(OAuthConnectedRevocations, service).pipe(\n Context.add(D1BatchStatements, owner.collector),\n );\n\n return yield* owner.close(Effect.provideContext(body, provided));\n }),\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n ...makeOAuthConnectedTarget<DatabaseId, Database, Family, Extra>(\n databaseService,\n configuration,\n ),\n coordinateOAuthConnected,\n coordinateOAuthConnectedRevocations,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-connected-drivers.mjs","names":[],"sources":["../../src/drizzle/oauth-connected-drivers.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n OAuthConnectedPersistence,\n OAuthConnectedRevocations,\n OAuthUnavailable,\n} from \"@yielded/auth/OAuth\";\nimport type { Table } from \"drizzle-orm\";\nimport { type Crypto, Effect, Context } from \"effect\";\n\nimport { makeD1Owner } from \"./d1-planning\";\nimport { D1BatchStatements } from \"./D1BatchStatements\";\nimport { nativeDatabase } from \"./native-database\";\nimport type {\n OAuthConnectedMapping,\n OAuthConnectedRevocationMapping,\n} from \"./oauth-connected-model\";\nimport {\n coordinateTargetOAuthConnected,\n coordinateTargetOAuthConnectedRevocations,\n makeTargetOAuthConnectedServices,\n makeTargetOAuthConnectedRevocationServices,\n} from \"./oauth-connected-target\";\nimport { type OAuthCoordinatorError, type OAuthTargetConfiguration } from \"./oauth-target\";\nimport type { SuppliedService } from \"./SuppliedService\";\n// oxlint-disable-next-line no-explicit-any -- inspect the actual installed native transaction callback without erasing it.\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\nconst unavailable = () => OAuthUnavailable.make({});\n\nexport const makeOAuthConnectedTarget = <\n DatabaseId,\n Database,\n Family extends Table,\n Extra = {},\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, Database>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthConnectedPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedPersistence>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthConnectedPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedPersistence | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnected<\n D extends Database,\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthConnectedPersistence> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnected<TransactionOf<D>, A, E, Exclude<R, OAuthConnectedPersistence>>(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<D>,\n services: { readonly oauthConnectedPersistence: OAuthConnectedPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthConnectedPersistence,\n services.oauthConnectedPersistence,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthConnectedRevocations> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedRevocations>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthConnectedRevocations | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthConnectedRevocations | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthConnectedRevocations<\n D extends Database,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthConnectedRevocations> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnectedRevocations<\n TransactionOf<D>,\n A,\n E,\n Exclude<R, OAuthConnectedRevocations>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<D>,\n services: { readonly oauthConnectedRevocations: OAuthConnectedRevocations[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthConnectedRevocations,\n services.oauthConnectedRevocations,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n makeOAuthConnectedServices: <\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family = never,\n >(\n mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra,\n ) =>\n makeTargetOAuthConnectedServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthConnectedRevocationServices: <\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n >(\n mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra,\n ) =>\n makeTargetOAuthConnectedRevocationServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateOAuthConnected,\n coordinateOAuthConnectedRevocations,\n };\n};\n\nexport const makeD1OAuthConnectedTarget = <DatabaseId, Database, Family extends Table, Extra>(\n databaseService: Context.Service<DatabaseId, Database>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthConnected<\n S extends Family,\n AC extends Family,\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n UA extends Family,\n DC extends Family,\n N,\n J extends Family,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, UA, DC, N, J> & Extra;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | Exclude<R, OAuthConnectedPersistence | D1BatchStatements>\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnected<\n Database,\n A,\n E | OAuthUnavailable,\n Exclude<R, OAuthConnectedPersistence | D1BatchStatements>\n >(database, options.mapping, configuration, (_tx, services, append) =>\n Effect.gen(function* () {\n const original = services.oauthConnectedPersistence;\n\n const nativeCollector = D1BatchStatements.of({\n append: (statement) => Effect.sync(() => append(statement)),\n });\n\n const owner = yield* makeD1Owner(unavailable()).pipe(\n Effect.provideService(D1BatchStatements, nativeCollector),\n );\n\n const service: OAuthConnectedPersistence[\"Service\"] = {\n claimSignIn: (input, prepare) => owner.run(original.claimSignIn(input, prepare)),\n inspectSignIn: (input) => owner.run(original.inspectSignIn(input)),\n settleSignIn: (input, prepare) => owner.run(original.settleSignIn(input, prepare)),\n capture: (input) => owner.run(original.capture(input)),\n issue: (input, prepare) => owner.run(original.issue(input, prepare)),\n prepare: (input, prepare) => owner.run(original.prepare(input, prepare)),\n inspectPrepared: (input) => owner.run(original.inspectPrepared(input)),\n preflight: (input) => owner.run(original.preflight(input)),\n claim: (input, prepare) => owner.run(original.claim(input, prepare)),\n inspectGrant: (input) => owner.run(original.inspectGrant(input)),\n settle: (input, prepare) => owner.run(original.settle(input, prepare)),\n list: (input) => owner.run(original.list(input)),\n inspectDisconnect: (input) => owner.run(original.inspectDisconnect(input)),\n disconnect: (input, prepare) => owner.run(original.disconnect(input, prepare)),\n inspectAccess: (input) => owner.run(original.inspectAccess(input)),\n claimRefresh: (input, prepare) => owner.run(original.claimRefresh(input, prepare)),\n settleRefresh: (input, prepare) => owner.run(original.settleRefresh(input, prepare)),\n admitUse: (input, prepare) => owner.run(original.admitUse(input, prepare)),\n cleanup: (input, prepare) => owner.run(original.cleanup(input, prepare)),\n };\n\n const provided = Context.make(OAuthConnectedPersistence, service).pipe(\n Context.add(D1BatchStatements, owner.collector),\n );\n\n return yield* owner.close(Effect.provideContext(body, provided));\n }),\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthConnectedRevocations<\n T extends Family,\n O extends Family,\n F extends Family,\n G extends Family,\n C extends Family,\n H extends Family,\n J extends Family,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: { readonly mapping: OAuthConnectedRevocationMapping<T, O, F, G, C, H, J, N> & Extra },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | Exclude<R, OAuthConnectedRevocations | D1BatchStatements>\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthConnectedRevocations<\n Database,\n A,\n E | OAuthUnavailable,\n Exclude<R, OAuthConnectedRevocations | D1BatchStatements>\n >(database, options.mapping, configuration, (_tx, services, append) =>\n Effect.gen(function* () {\n const original = services.oauthConnectedRevocations;\n\n const nativeCollector = D1BatchStatements.of({\n append: (statement) => Effect.sync(() => append(statement)),\n });\n\n const owner = yield* makeD1Owner(unavailable()).pipe(\n Effect.provideService(D1BatchStatements, nativeCollector),\n );\n\n const service: OAuthConnectedRevocations[\"Service\"] = {\n claim: (input, prepare) => owner.run(original.claim(input, prepare)),\n settle: (input, prepare) => owner.run(original.settle(input, prepare)),\n };\n\n const provided = Context.make(OAuthConnectedRevocations, service).pipe(\n Context.add(D1BatchStatements, owner.collector),\n );\n\n return yield* owner.close(Effect.provideContext(body, provided));\n }),\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n ...makeOAuthConnectedTarget<DatabaseId, Database, Family, Extra>(\n databaseService,\n configuration,\n ),\n coordinateOAuthConnected,\n coordinateOAuthConnectedRevocations,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { digest
|
|
1
|
+
import { digest } from "./crypto.mjs";
|
|
2
|
+
import { invariant, oauthIdentityKey, sameIdentity, sameRevision } from "./oauth-state.mjs";
|
|
2
3
|
import { both } from "./transaction-owner.mjs";
|
|
3
4
|
import { CurrentOAuthTransaction, copiedRow, equal } from "./oauth-owner.mjs";
|
|
4
5
|
import "./oauth-registration.mjs";
|
|
@@ -22,7 +23,7 @@ const pending = Effect.fn("oauthConnected.pending")(function* (mapping, access,
|
|
|
22
23
|
if (row === void 0 || row[f.snapshot] === null) return void 0;
|
|
23
24
|
const flow = flowStorage.decode(row[f.snapshot]), c = flow.context;
|
|
24
25
|
const native = yield* mapping.subjectId.toNative(c.revision.subjectId);
|
|
25
|
-
invariant(row[f.moduleId] === c.moduleId && row[f.flowId] === c.flowId && row[f.commandId] === c.commandId && mapping.subjectId.equals(native, row[f.subjectId]) && row[f.clientKey] === clientKey(configuration(flow)) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis);
|
|
26
|
+
invariant(row[f.moduleId] === c.moduleId && row[f.flowId] === c.flowId && row[f.commandId] === c.commandId && mapping.subjectId.equals(native, row[f.subjectId]) && row[f.clientKey] === (yield* clientKey(configuration(flow))) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis);
|
|
26
27
|
return c.moduleId === access.moduleId && c.generation === access.generation && c.flowId === access.flowId && c.revision.subjectId === access.subjectId && c.provider === access.provider && c.callbackId === access.callbackId && c.stateDigest === access.stateDigest && c.requestBindingVerifier === access.requestBindingVerifier && c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis && (c.responseIssuerMode === "required" ? access.responseIssuer === c.issuer : access.responseIssuer === void 0) ? {
|
|
27
28
|
row,
|
|
28
29
|
flow,
|
|
@@ -143,7 +144,7 @@ const inspectPrepared = Effect.fn("oauthConnected.inspectPrepared")(function* (m
|
|
|
143
144
|
if (row === void 0 || row[f.state] !== "Prepared" || row[f.snapshot] === null) return void 0;
|
|
144
145
|
const flow = flowStorage.decode(row[f.snapshot]);
|
|
145
146
|
const c = flow.context;
|
|
146
|
-
invariant(row[f.moduleId] === c.moduleId && row[f.flowId] === c.flowId && row[f.commandId] === c.commandId && mapping.subjectId.equals(found.nativeId, row[f.subjectId]) && row[f.clientKey] === clientKey(configuration(flow)) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis);
|
|
147
|
+
invariant(row[f.moduleId] === c.moduleId && row[f.flowId] === c.flowId && row[f.commandId] === c.commandId && mapping.subjectId.equals(found.nativeId, row[f.subjectId]) && row[f.clientKey] === (yield* clientKey(configuration(flow))) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis);
|
|
147
148
|
const now = yield* owner.now(mapping.clock);
|
|
148
149
|
return c.moduleId === access.moduleId && c.generation === access.generation && c.flowId === access.flowId && c.commandId === access.commandId && c.revision.subjectId === access.subjectId && sameRevision(found.revision, c.revision) && c.requestBindingVerifier === access.requestBindingVerifier && c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis && live(flow, now) ? flow : void 0;
|
|
149
150
|
});
|
|
@@ -197,7 +198,7 @@ const claim = Effect.fn("oauthConnected.claim")(function* (mapping, input) {
|
|
|
197
198
|
}, {
|
|
198
199
|
[f.state]: "Claimed",
|
|
199
200
|
[f.claimId]: claimed.claimId,
|
|
200
|
-
[f.claimDigest]: digest(claimStorage.encode(claimed)),
|
|
201
|
+
[f.claimDigest]: yield* digest(claimStorage.encode(claimed)),
|
|
201
202
|
[f.claimOrder]: mapping.order.encode(order),
|
|
202
203
|
[f.claimedAt]: mapping.clock.encodeInstant(now),
|
|
203
204
|
[f.claimExpiresAt]: mapping.clock.encodeInstant(expires),
|
|
@@ -217,9 +218,9 @@ const exact = Effect.fn("oauthConnected.exactClaim")(function* (mapping, claim)
|
|
|
217
218
|
[f.moduleId]: c.moduleId,
|
|
218
219
|
[f.flowId]: c.flowId
|
|
219
220
|
}), { limit: 1 })).rows[0];
|
|
220
|
-
if (row === void 0 || row[f.work] !== "Unresolved" || row[f.claimId] !== claim.claimId || row[f.claimDigest] !== digest(claimStorage.encode(claim))) return void 0;
|
|
221
|
+
if (row === void 0 || row[f.work] !== "Unresolved" || row[f.claimId] !== claim.claimId || row[f.claimDigest] !== (yield* digest(claimStorage.encode(claim)))) return void 0;
|
|
221
222
|
const native = yield* mapping.subjectId.toNative(c.revision.subjectId);
|
|
222
|
-
invariant(row[f.commandId] === c.commandId && mapping.subjectId.equals(native, row[f.subjectId]) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === claim.flow.retentionUntilMillis && row[f.clientKey] === clientKey(configuration(claim.flow)) && nativeOrder(mapping, row[f.claimOrder]) === orderNumber(claim.order) && mapping.clock.decodeInstant(row[f.claimedAt]) === claim.claimedAtMillis && mapping.clock.decodeInstant(row[f.claimExpiresAt]) === claim.claimExpiresAtMillis);
|
|
223
|
+
invariant(row[f.commandId] === c.commandId && mapping.subjectId.equals(native, row[f.subjectId]) && row[f.stateDigest] === c.stateDigest && mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis && mapping.clock.decodeInstant(row[f.retentionUntil]) === claim.flow.retentionUntilMillis && row[f.clientKey] === (yield* clientKey(configuration(claim.flow))) && nativeOrder(mapping, row[f.claimOrder]) === orderNumber(claim.order) && mapping.clock.decodeInstant(row[f.claimedAt]) === claim.claimedAtMillis && mapping.clock.decodeInstant(row[f.claimExpiresAt]) === claim.claimExpiresAtMillis);
|
|
223
224
|
const now = yield* owner.now(mapping.clock);
|
|
224
225
|
invariant(now >= claim.claimedAtMillis);
|
|
225
226
|
return {
|
|
@@ -246,7 +247,7 @@ const terminal = Effect.fn("oauthConnected.terminal")(function* (mapping, claim,
|
|
|
246
247
|
});
|
|
247
248
|
const inspectTuple = Effect.fn("oauthConnected.inspectTuple")(function* (mapping, identity) {
|
|
248
249
|
const owner = yield* CurrentOAuthTransaction;
|
|
249
|
-
const t = mapping.ownership.tuple, key = oauthIdentityKey(identity);
|
|
250
|
+
const t = mapping.ownership.tuple, key = yield* oauthIdentityKey(identity);
|
|
250
251
|
const row = (yield* owner.read(t.table, equal(t.table, { [t.identityKey]: key }), { limit: 1 })).rows[0];
|
|
251
252
|
if (row !== void 0) invariant(row[t.provider] === identity.provider && row[t.issuer] === identity.issuer && row[t.externalSubject] === identity.subject && [
|
|
252
253
|
"Owned",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-flow.mjs","names":["S.clientKey","S.configuration","S.current","S.useAuthority","S.action","client","S.client","S.readGrant","S.nativeCopy","S.touchScope","S.nextOrder","S.nativeOrder","S.orderNumber","S.cohort"],"sources":["../../src/drizzle/oauth-connected-flow.ts"],"sourcesContent":["import {\n OAuthAccountRevision,\n snapshotOAuthSync,\n type OAuthConnectedPersistence,\n} from \"@yielded/auth/OAuth\";\nimport * as M from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- private mapped rows; public adapters retain native IDs and closed Effects. */\nimport { sql } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as S from \"./oauth-connected-state\";\nimport { both, copiedRow, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { acquireTuple, readTuple } from \"./oauth-registration\";\nimport { digest, invariant, oauthIdentityKey, sameIdentity, sameRevision } from \"./oauth-state\";\n\nexport type Input<K extends keyof OAuthConnectedPersistence[\"Service\"]> = Parameters<\n OAuthConnectedPersistence[\"Service\"][K]\n>[0];\n\nexport const pending = Effect.fn(\"oauthConnected.pending\")(function* (\n mapping: S.Authority,\n access: M.OAuthConnectedAccess,\n lock = true,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const f = mapping.flow;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, { [f.moduleId]: access.moduleId, [f.flowId]: access.flowId }),\n { limit: 1, lock, observe: lock },\n );\n\n const row = read.rows[0];\n\n if (row === undefined || row[f.snapshot] === null) return undefined;\n\n const flow = S.flowStorage.decode(row[f.snapshot]),\n c = flow.context;\n\n const native = yield* mapping.subjectId.toNative(c.revision.subjectId);\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(native, row[f.subjectId]) &&\n row[f.clientKey] === S.clientKey(S.configuration(flow)) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n\n const matches =\n c.moduleId === access.moduleId &&\n c.generation === access.generation &&\n c.flowId === access.flowId &&\n c.revision.subjectId === access.subjectId &&\n c.provider === access.provider &&\n c.callbackId === access.callbackId &&\n c.stateDigest === access.stateDigest &&\n c.requestBindingVerifier === access.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis &&\n (c.responseIssuerMode === \"required\"\n ? access.responseIssuer === c.issuer\n : access.responseIssuer === undefined);\n\n return matches ? { row, flow, native } : undefined;\n});\n\nexport const live = (flow: M.OAuthConnectedPendingFlow, now: number) =>\n flow.context.issuedAtMillis <= now &&\n now < flow.context.expiresAtMillis &&\n flow.context.expiresAtMillis <= flow.context.requestBindingExpiresAtMillis &&\n flow.retentionUntilMillis >= flow.context.expiresAtMillis + flow.context.claimLifetimeMillis;\n\nexport const expected = (flow: M.OAuthConnectedPendingFlow) => ({\n moduleId: flow.context.moduleId,\n flowId: flow.context.flowId,\n commandId: flow.context.commandId,\n revision: flow.context.revision,\n intent: S.contextStorage.encode(flow.context),\n maximumAgeMillis: flow.context.maximumEvidenceAgeMillis,\n configuration: S.configuration(flow),\n});\n\nconst retain = Effect.fn(\"oauthConnected.retain\")(function* (\n mapping: S.Mapping,\n input:\n | ({ readonly _tag: \"Prepare\" } & Input<\"prepare\">)\n | ({ readonly _tag: \"Issue\" } & Input<\"issue\">),\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const flow = snapshotOAuthSync(M.OAuthConnectedPendingFlow, input.flow),\n c = flow.context;\n\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (found === undefined) return { _tag: \"Rejected\" } as const;\n if (input._tag === \"Prepare\") {\n if (\n input.authorization.moduleId !== c.moduleId ||\n !sameRevision(input.authorization.revision, c.revision) ||\n !sameRevision(found.revision, c.revision) ||\n (yield* S.useAuthority(mapping, input.authorization, \"metadata\")) === undefined\n )\n return { _tag: \"Rejected\" } as const;\n } else if (!(yield* S.action(mapping, found, input.authorization, \"issue\", expected(flow))))\n return { _tag: \"Rejected\" } as const;\n if (c.profile.revocation === \"cohort\") invariant(mapping.revocation.mode === \"cohort\");\n const client = yield* S.client(mapping, S.configuration(flow), true);\n\n invariant(client !== undefined);\n\n const now = yield* owner.now(mapping.clock),\n f = mapping.flow;\n\n if (!live(flow, now)) return { _tag: \"Rejected\" } as const;\n if (c.reconnect !== undefined) {\n const original = yield* S.readGrant(mapping, c.moduleId, c.reconnect.grantId, false);\n\n if (\n original === undefined ||\n original.context.subjectId !== c.revision.subjectId ||\n !sameTarget(c.reconnect, original.context)\n )\n return { _tag: \"Rejected\" } as const;\n owner.postconditions.push(\n sql`exists(select 1 from ${mapping.grant.table} where ${owner.exact(mapping.grant.table, original.row)})`,\n );\n }\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 owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${c.issuedAtMillis} and ${mapping.clock.engineNowMillis} < ${c.expiresAtMillis}`,\n );\n if (input._tag === \"Issue\") {\n const row = prior.rows[0];\n\n if (\n row === undefined ||\n command.rows[0] === undefined ||\n row[f.state] !== \"Prepared\" ||\n row[f.snapshot] !== S.flowStorage.encode(flow) ||\n command.rows[0][f.flowId] !== c.flowId\n )\n return { _tag: \"Rejected\" } as const;\n yield* owner.update(\n f.table,\n { ...key, [f.state]: \"Prepared\", [f.version]: row[f.version] },\n { [f.state]: \"Pending\", [f.version]: owner.marker },\n );\n owner.postconditions.push(\n sql`exists(select 1 from ${f.table} where ${equal(f.table, { ...key, [f.state]: \"Pending\", [f.version]: owner.marker })})`,\n );\n\n return { _tag: \"Issued\", flow } as const;\n }\n if (prior.rows.length || command.rows.length) return { _tag: \"Rejected\" } as const;\n\n const values = {\n ...f.encodeInsert({\n flow: snapshotOAuthSync(M.OAuthConnectedPendingFlow, flow),\n subjectId: S.nativeCopy(found.nativeId),\n }),\n ...key,\n [f.commandId]: c.commandId,\n [f.subjectId]: found.nativeId,\n [f.clientKey]: client.id,\n [f.cohortKey]: null,\n [f.state]: \"Prepared\",\n [f.version]: owner.marker,\n [f.stateDigest]: c.stateDigest,\n [f.snapshot]: S.flowStorage.encode(flow),\n [f.claimId]: null,\n [f.claimDigest]: null,\n [f.claimOrder]: null,\n [f.claimedAt]: null,\n [f.claimExpiresAt]: null,\n [f.expiresAt]: mapping.clock.encodeInstant(c.expiresAtMillis),\n [f.retentionUntil]: mapping.clock.encodeInstant(flow.retentionUntilMillis),\n [f.work]: \"None\",\n [f.custody]: null,\n };\n\n const inserted = yield* owner.insert(f.table, values, key, true);\n\n prior.rows = inserted.rows;\n command.rows = inserted.rows;\n if (inserted.rows[0]?.[f.version] !== owner.marker) return { _tag: \"Rejected\" } as const;\n\n return { _tag: \"Issued\", flow } as const;\n});\n\nexport const prepare = (mapping: S.Mapping, input: Input<\"prepare\">) =>\n retain(mapping, { _tag: \"Prepare\", ...input });\n\nexport const issue = (mapping: S.Mapping, input: Input<\"issue\">) =>\n retain(mapping, { _tag: \"Issue\", ...input });\n\nexport const inspectPrepared = Effect.fn(\"oauthConnected.inspectPrepared\")(function* (\n mapping: S.Mapping,\n access: M.OAuthConnectedPreparedAccess,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const found = yield* S.current(mapping, access.subjectId);\n\n if (found === undefined) return undefined;\n const f = mapping.flow;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: access.moduleId,\n [f.flowId]: access.flowId,\n [f.subjectId]: found.nativeId,\n }),\n { limit: 1 },\n );\n\n const row = read.rows[0];\n\n if (row === undefined || row[f.state] !== \"Prepared\" || row[f.snapshot] === null)\n return undefined;\n const flow = S.flowStorage.decode(row[f.snapshot]);\n const c = flow.context;\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(found.nativeId, row[f.subjectId]) &&\n row[f.clientKey] === S.clientKey(S.configuration(flow)) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n const now = yield* owner.now(mapping.clock);\n\n return c.moduleId === access.moduleId &&\n c.generation === access.generation &&\n c.flowId === access.flowId &&\n c.commandId === access.commandId &&\n c.revision.subjectId === access.subjectId &&\n sameRevision(found.revision, c.revision) &&\n c.requestBindingVerifier === access.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis &&\n live(flow, now)\n ? flow\n : undefined;\n});\n\nexport const sameTarget = (target: M.OAuthConnectedTarget, context: M.OAuthConnectedTokenContext) =>\n target.grantId === context.grantId &&\n target.grantVersion === context.grantVersion &&\n target.tokenVersion === context.tokenVersion &&\n target.cohortGeneration === context.cohortGeneration &&\n sameIdentity(target.identity, context.identity) &&\n S.tokenContextStorage.encode({ ...context, configuration: target.configuration }) ===\n S.tokenContextStorage.encode(context);\n\nexport const capture = Effect.fn(\"oauthConnected.capture\")(function* (\n mapping: S.Mapping,\n input: Input<\"capture\">,\n) {\n const found = yield* S.current(mapping, input.subjectId);\n\n if (found === undefined) return undefined;\n if (input.grantId === undefined)\n return { revision: snapshotOAuthSync(OAuthAccountRevision, found.revision) };\n const grant = yield* S.readGrant(mapping, input.moduleId, input.grantId, false);\n\n if (grant === undefined || grant.context.subjectId !== input.subjectId) return undefined;\n\n return {\n revision: snapshotOAuthSync(OAuthAccountRevision, found.revision),\n target: snapshotOAuthSync(M.OAuthConnectedTarget, grant.context),\n };\n});\n\nexport const preflight = Effect.fn(\"oauthConnected.preflight\")(function* (\n mapping: S.Mapping,\n input: Input<\"preflight\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const read = yield* pending(mapping, input);\n const now = yield* owner.now(mapping.clock);\n\n if (read === undefined || read.row[mapping.flow.state] !== \"Pending\" || !live(read.flow, now))\n return undefined;\n\n return read.flow;\n});\n\nexport const claim = Effect.fn(\"oauthConnected.claim\")(function* (\n mapping: S.Mapping,\n input: Input<\"claim\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const flow = snapshotOAuthSync(M.OAuthConnectedPendingFlow, input.flow),\n c = flow.context;\n\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (\n found === undefined ||\n !(yield* S.action(mapping, found, input.authorization, \"claim\", expected(flow)))\n )\n return { _tag: \"Rejected\" } as const;\n const client = yield* S.client(mapping, S.configuration(flow), false);\n\n if (client === undefined) return { _tag: \"Rejected\" } as const;\n\n const read = yield* pending(mapping, input.access),\n now = yield* owner.now(mapping.clock),\n f = mapping.flow;\n\n if (\n read === undefined ||\n read.row[f.state] !== \"Pending\" ||\n S.flowStorage.encode(read.flow) !== S.flowStorage.encode(flow) ||\n !live(flow, now)\n )\n return { _tag: \"Rejected\" } as const;\n const expires = now + c.claimLifetimeMillis;\n\n invariant(Number.isSafeInteger(expires) && expires <= flow.retentionUntilMillis);\n yield* S.touchScope(mapping, client.scope);\n const order = yield* S.nextOrder(mapping, client);\n\n const claimed = snapshotOAuthSync(M.OAuthConnectedClaim, {\n flow,\n claimId: input.claimId,\n claimedAtMillis: now,\n claimExpiresAtMillis: expires,\n order: String(order),\n });\n\n yield* owner.update(\n f.table,\n {\n [f.moduleId]: c.moduleId,\n [f.flowId]: c.flowId,\n [f.state]: \"Pending\",\n [f.version]: read.row[f.version],\n },\n {\n [f.state]: \"Claimed\",\n [f.claimId]: claimed.claimId,\n [f.claimDigest]: digest(S.claimStorage.encode(claimed)),\n [f.claimOrder]: mapping.order.encode(order),\n [f.claimedAt]: mapping.clock.encodeInstant(now),\n [f.claimExpiresAt]: mapping.clock.encodeInstant(expires),\n [f.work]: \"Unresolved\",\n [f.version]: owner.marker,\n },\n );\n owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${now} and ${mapping.clock.engineNowMillis} < ${Math.min(c.expiresAtMillis, expires)}`,\n );\n\n return { _tag: \"Claimed\", claim: claimed } as const;\n});\n\nexport const exact = Effect.fn(\"oauthConnected.exactClaim\")(function* (\n mapping: S.Authority,\n claim: M.OAuthConnectedClaim,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const f = mapping.flow,\n c = claim.flow.context;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId }),\n { limit: 1 },\n );\n\n const row = read.rows[0];\n\n if (\n row === undefined ||\n row[f.work] !== \"Unresolved\" ||\n row[f.claimId] !== claim.claimId ||\n row[f.claimDigest] !== digest(S.claimStorage.encode(claim))\n )\n return undefined;\n const native = yield* mapping.subjectId.toNative(c.revision.subjectId);\n\n invariant(\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(native, row[f.subjectId]) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === claim.flow.retentionUntilMillis &&\n row[f.clientKey] === S.clientKey(S.configuration(claim.flow)) &&\n S.nativeOrder(mapping, row[f.claimOrder]) === S.orderNumber(claim.order) &&\n mapping.clock.decodeInstant(row[f.claimedAt]) === claim.claimedAtMillis &&\n mapping.clock.decodeInstant(row[f.claimExpiresAt]) === claim.claimExpiresAtMillis,\n );\n const now = yield* owner.now(mapping.clock);\n\n invariant(now >= claim.claimedAtMillis);\n\n return { row, now, active: row[f.state] === \"Claimed\" && now < claim.claimExpiresAtMillis };\n});\n\nexport const terminal = Effect.fn(\"oauthConnected.terminal\")(function* (\n mapping: S.Authority,\n claim: M.OAuthConnectedClaim,\n state: string,\n work: \"Resolved\" | \"Unresolved\",\n custody?: { cohort: string; sealed?: M.OAuthConnectedStoredGrant },\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const f = mapping.flow,\n c = claim.flow.context;\n\n yield* owner.update(\n f.table,\n { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId, [f.claimId]: claim.claimId },\n {\n [f.state]: state,\n [f.snapshot]: null,\n [f.work]: work,\n [f.cohortKey]: custody?.cohort ?? null,\n [f.custody]: custody?.sealed === undefined ? null : S.grantStorage.encode(custody.sealed),\n [f.version]: owner.marker,\n },\n );\n});\n\nexport const inspectTuple = Effect.fn(\"oauthConnected.inspectTuple\")(function* (\n mapping: S.Authority,\n identity: M.OAuthConnectedTokenContext[\"identity\"],\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const t = mapping.ownership.tuple,\n key = oauthIdentityKey(identity);\n\n const read = yield* owner.read(t.table, equal(t.table, { [t.identityKey]: key }), { limit: 1 });\n const row = read.rows[0];\n\n if (row !== undefined) {\n invariant(\n row[t.provider] === identity.provider &&\n row[t.issuer] === identity.issuer &&\n row[t.externalSubject] === identity.subject &&\n [\"Owned\", \"Unowned\", \"Reserved\"].includes(row[t.state]),\n );\n }\n if (mapping.ownership.mode === \"separate\") {\n const o = mapping.ownership.external;\n\n const external = yield* owner.read(o.table, equal(o.table, { [o.identityKey]: key }), {\n limit: 1,\n });\n\n if (row?.[t.state] === \"Owned\") {\n const e = external.rows[0];\n\n invariant(\n e !== undefined &&\n e[o.provider] === identity.provider &&\n e[o.issuer] === identity.issuer &&\n e[o.externalSubject] === identity.subject &&\n mapping.subjectId.equals(o.decodeSubjectId(copiedRow(e)), row[t.subjectId]),\n );\n const condition = sql`exists(select 1 from ${o.table} where ${both(equal(o.table, { [o.identityKey]: key }), o.ownedCondition)})`;\n\n invariant(yield* owner.check(condition));\n owner.postconditions.push(condition);\n } else invariant(external.rows.length === 0);\n }\n\n return { key, row };\n});\n\nexport const inspectGrant = Effect.fn(\"oauthConnected.inspectGrant\")(function* (\n mapping: S.Mapping,\n input: Input<\"inspectGrant\">,\n) {\n const c = input.claim.flow.context;\n\n if (input.identity.provider !== c.provider || input.identity.issuer !== c.issuer)\n return { _tag: \"Rejected\" } as const;\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (found === undefined || !sameRevision(found.revision, c.revision))\n return { _tag: \"Rejected\" } as const;\n const cl = yield* S.client(mapping, S.configuration(input.claim.flow), false);\n\n if (cl === undefined) return { _tag: \"Rejected\" } as const;\n\n const tuple = yield* inspectTuple(mapping, input.identity),\n t = mapping.ownership.tuple;\n\n if (\n tuple.row?.[t.state] === \"Reserved\" ||\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 co = yield* S.cohort(mapping, cl.id, tuple.key, false);\n const claimed = yield* exact(mapping, input.claim);\n\n if (claimed === undefined) return { _tag: \"Rejected\" } as const;\n if (c.reconnect !== undefined && !sameIdentity(c.reconnect.identity, input.identity))\n return { _tag: \"Conflict\" } as const;\n\n return co.blocked || S.orderNumber(input.claim.order) <= co.cutoff || !claimed.active\n ? ({ _tag: \"Quarantine\", cohortGeneration: co.generation } as const)\n : ({ _tag: \"Target\", cohortGeneration: co.generation } as const);\n});\n\n/** Global tuple acquisition is shared with registration/accounts. */\nexport { acquireTuple, readTuple };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-connected-flow.mjs","names":["S.clientKey","S.configuration","S.current","S.useAuthority","S.action","client","S.client","S.readGrant","S.nativeCopy","S.touchScope","S.nextOrder","S.nativeOrder","S.orderNumber","S.cohort"],"sources":["../../src/drizzle/oauth-connected-flow.ts"],"sourcesContent":["import {\n OAuthAccountRevision,\n snapshotOAuthSync,\n type OAuthConnectedPersistence,\n} from \"@yielded/auth/OAuth\";\nimport * as M from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- private mapped rows; public adapters retain native IDs and closed Effects. */\nimport { sql } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport * as S from \"./oauth-connected-state\";\nimport { both, copiedRow, equal, CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { acquireTuple, readTuple } from \"./oauth-registration\";\nimport { digest, invariant, oauthIdentityKey, sameIdentity, sameRevision } from \"./oauth-state\";\n\nexport type Input<K extends keyof OAuthConnectedPersistence[\"Service\"]> = Parameters<\n OAuthConnectedPersistence[\"Service\"][K]\n>[0];\n\nexport const pending = Effect.fn(\"oauthConnected.pending\")(function* (\n mapping: S.Authority,\n access: M.OAuthConnectedAccess,\n lock = true,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const f = mapping.flow;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, { [f.moduleId]: access.moduleId, [f.flowId]: access.flowId }),\n { limit: 1, lock, observe: lock },\n );\n\n const row = read.rows[0];\n\n if (row === undefined || row[f.snapshot] === null) return undefined;\n\n const flow = S.flowStorage.decode(row[f.snapshot]),\n c = flow.context;\n\n const native = yield* mapping.subjectId.toNative(c.revision.subjectId);\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(native, row[f.subjectId]) &&\n row[f.clientKey] === (yield* S.clientKey(S.configuration(flow))) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n\n const matches =\n c.moduleId === access.moduleId &&\n c.generation === access.generation &&\n c.flowId === access.flowId &&\n c.revision.subjectId === access.subjectId &&\n c.provider === access.provider &&\n c.callbackId === access.callbackId &&\n c.stateDigest === access.stateDigest &&\n c.requestBindingVerifier === access.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis &&\n (c.responseIssuerMode === \"required\"\n ? access.responseIssuer === c.issuer\n : access.responseIssuer === undefined);\n\n return matches ? { row, flow, native } : undefined;\n});\n\nexport const live = (flow: M.OAuthConnectedPendingFlow, now: number) =>\n flow.context.issuedAtMillis <= now &&\n now < flow.context.expiresAtMillis &&\n flow.context.expiresAtMillis <= flow.context.requestBindingExpiresAtMillis &&\n flow.retentionUntilMillis >= flow.context.expiresAtMillis + flow.context.claimLifetimeMillis;\n\nexport const expected = (flow: M.OAuthConnectedPendingFlow) => ({\n moduleId: flow.context.moduleId,\n flowId: flow.context.flowId,\n commandId: flow.context.commandId,\n revision: flow.context.revision,\n intent: S.contextStorage.encode(flow.context),\n maximumAgeMillis: flow.context.maximumEvidenceAgeMillis,\n configuration: S.configuration(flow),\n});\n\nconst retain = Effect.fn(\"oauthConnected.retain\")(function* (\n mapping: S.Mapping,\n input:\n | ({ readonly _tag: \"Prepare\" } & Input<\"prepare\">)\n | ({ readonly _tag: \"Issue\" } & Input<\"issue\">),\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const flow = snapshotOAuthSync(M.OAuthConnectedPendingFlow, input.flow),\n c = flow.context;\n\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (found === undefined) return { _tag: \"Rejected\" } as const;\n if (input._tag === \"Prepare\") {\n if (\n input.authorization.moduleId !== c.moduleId ||\n !sameRevision(input.authorization.revision, c.revision) ||\n !sameRevision(found.revision, c.revision) ||\n (yield* S.useAuthority(mapping, input.authorization, \"metadata\")) === undefined\n )\n return { _tag: \"Rejected\" } as const;\n } else if (!(yield* S.action(mapping, found, input.authorization, \"issue\", expected(flow))))\n return { _tag: \"Rejected\" } as const;\n if (c.profile.revocation === \"cohort\") invariant(mapping.revocation.mode === \"cohort\");\n const client = yield* S.client(mapping, S.configuration(flow), true);\n\n invariant(client !== undefined);\n\n const now = yield* owner.now(mapping.clock),\n f = mapping.flow;\n\n if (!live(flow, now)) return { _tag: \"Rejected\" } as const;\n if (c.reconnect !== undefined) {\n const original = yield* S.readGrant(mapping, c.moduleId, c.reconnect.grantId, false);\n\n if (\n original === undefined ||\n original.context.subjectId !== c.revision.subjectId ||\n !sameTarget(c.reconnect, original.context)\n )\n return { _tag: \"Rejected\" } as const;\n owner.postconditions.push(\n sql`exists(select 1 from ${mapping.grant.table} where ${owner.exact(mapping.grant.table, original.row)})`,\n );\n }\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 owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${c.issuedAtMillis} and ${mapping.clock.engineNowMillis} < ${c.expiresAtMillis}`,\n );\n if (input._tag === \"Issue\") {\n const row = prior.rows[0];\n\n if (\n row === undefined ||\n command.rows[0] === undefined ||\n row[f.state] !== \"Prepared\" ||\n row[f.snapshot] !== S.flowStorage.encode(flow) ||\n command.rows[0][f.flowId] !== c.flowId\n )\n return { _tag: \"Rejected\" } as const;\n yield* owner.update(\n f.table,\n { ...key, [f.state]: \"Prepared\", [f.version]: row[f.version] },\n { [f.state]: \"Pending\", [f.version]: owner.marker },\n );\n owner.postconditions.push(\n sql`exists(select 1 from ${f.table} where ${equal(f.table, { ...key, [f.state]: \"Pending\", [f.version]: owner.marker })})`,\n );\n\n return { _tag: \"Issued\", flow } as const;\n }\n if (prior.rows.length || command.rows.length) return { _tag: \"Rejected\" } as const;\n\n const values = {\n ...f.encodeInsert({\n flow: snapshotOAuthSync(M.OAuthConnectedPendingFlow, flow),\n subjectId: S.nativeCopy(found.nativeId),\n }),\n ...key,\n [f.commandId]: c.commandId,\n [f.subjectId]: found.nativeId,\n [f.clientKey]: client.id,\n [f.cohortKey]: null,\n [f.state]: \"Prepared\",\n [f.version]: owner.marker,\n [f.stateDigest]: c.stateDigest,\n [f.snapshot]: S.flowStorage.encode(flow),\n [f.claimId]: null,\n [f.claimDigest]: null,\n [f.claimOrder]: null,\n [f.claimedAt]: null,\n [f.claimExpiresAt]: null,\n [f.expiresAt]: mapping.clock.encodeInstant(c.expiresAtMillis),\n [f.retentionUntil]: mapping.clock.encodeInstant(flow.retentionUntilMillis),\n [f.work]: \"None\",\n [f.custody]: null,\n };\n\n const inserted = yield* owner.insert(f.table, values, key, true);\n\n prior.rows = inserted.rows;\n command.rows = inserted.rows;\n if (inserted.rows[0]?.[f.version] !== owner.marker) return { _tag: \"Rejected\" } as const;\n\n return { _tag: \"Issued\", flow } as const;\n});\n\nexport const prepare = (mapping: S.Mapping, input: Input<\"prepare\">) =>\n retain(mapping, { _tag: \"Prepare\", ...input });\n\nexport const issue = (mapping: S.Mapping, input: Input<\"issue\">) =>\n retain(mapping, { _tag: \"Issue\", ...input });\n\nexport const inspectPrepared = Effect.fn(\"oauthConnected.inspectPrepared\")(function* (\n mapping: S.Mapping,\n access: M.OAuthConnectedPreparedAccess,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const found = yield* S.current(mapping, access.subjectId);\n\n if (found === undefined) return undefined;\n const f = mapping.flow;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: access.moduleId,\n [f.flowId]: access.flowId,\n [f.subjectId]: found.nativeId,\n }),\n { limit: 1 },\n );\n\n const row = read.rows[0];\n\n if (row === undefined || row[f.state] !== \"Prepared\" || row[f.snapshot] === null)\n return undefined;\n const flow = S.flowStorage.decode(row[f.snapshot]);\n const c = flow.context;\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(found.nativeId, row[f.subjectId]) &&\n row[f.clientKey] === (yield* S.clientKey(S.configuration(flow))) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n const now = yield* owner.now(mapping.clock);\n\n return c.moduleId === access.moduleId &&\n c.generation === access.generation &&\n c.flowId === access.flowId &&\n c.commandId === access.commandId &&\n c.revision.subjectId === access.subjectId &&\n sameRevision(found.revision, c.revision) &&\n c.requestBindingVerifier === access.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis &&\n live(flow, now)\n ? flow\n : undefined;\n});\n\nexport const sameTarget = (target: M.OAuthConnectedTarget, context: M.OAuthConnectedTokenContext) =>\n target.grantId === context.grantId &&\n target.grantVersion === context.grantVersion &&\n target.tokenVersion === context.tokenVersion &&\n target.cohortGeneration === context.cohortGeneration &&\n sameIdentity(target.identity, context.identity) &&\n S.tokenContextStorage.encode({ ...context, configuration: target.configuration }) ===\n S.tokenContextStorage.encode(context);\n\nexport const capture = Effect.fn(\"oauthConnected.capture\")(function* (\n mapping: S.Mapping,\n input: Input<\"capture\">,\n) {\n const found = yield* S.current(mapping, input.subjectId);\n\n if (found === undefined) return undefined;\n if (input.grantId === undefined)\n return { revision: snapshotOAuthSync(OAuthAccountRevision, found.revision) };\n const grant = yield* S.readGrant(mapping, input.moduleId, input.grantId, false);\n\n if (grant === undefined || grant.context.subjectId !== input.subjectId) return undefined;\n\n return {\n revision: snapshotOAuthSync(OAuthAccountRevision, found.revision),\n target: snapshotOAuthSync(M.OAuthConnectedTarget, grant.context),\n };\n});\n\nexport const preflight = Effect.fn(\"oauthConnected.preflight\")(function* (\n mapping: S.Mapping,\n input: Input<\"preflight\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n const read = yield* pending(mapping, input);\n const now = yield* owner.now(mapping.clock);\n\n if (read === undefined || read.row[mapping.flow.state] !== \"Pending\" || !live(read.flow, now))\n return undefined;\n\n return read.flow;\n});\n\nexport const claim = Effect.fn(\"oauthConnected.claim\")(function* (\n mapping: S.Mapping,\n input: Input<\"claim\">,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const flow = snapshotOAuthSync(M.OAuthConnectedPendingFlow, input.flow),\n c = flow.context;\n\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (\n found === undefined ||\n !(yield* S.action(mapping, found, input.authorization, \"claim\", expected(flow)))\n )\n return { _tag: \"Rejected\" } as const;\n const client = yield* S.client(mapping, S.configuration(flow), false);\n\n if (client === undefined) return { _tag: \"Rejected\" } as const;\n\n const read = yield* pending(mapping, input.access),\n now = yield* owner.now(mapping.clock),\n f = mapping.flow;\n\n if (\n read === undefined ||\n read.row[f.state] !== \"Pending\" ||\n S.flowStorage.encode(read.flow) !== S.flowStorage.encode(flow) ||\n !live(flow, now)\n )\n return { _tag: \"Rejected\" } as const;\n const expires = now + c.claimLifetimeMillis;\n\n invariant(Number.isSafeInteger(expires) && expires <= flow.retentionUntilMillis);\n yield* S.touchScope(mapping, client.scope);\n const order = yield* S.nextOrder(mapping, client);\n\n const claimed = snapshotOAuthSync(M.OAuthConnectedClaim, {\n flow,\n claimId: input.claimId,\n claimedAtMillis: now,\n claimExpiresAtMillis: expires,\n order: String(order),\n });\n\n yield* owner.update(\n f.table,\n {\n [f.moduleId]: c.moduleId,\n [f.flowId]: c.flowId,\n [f.state]: \"Pending\",\n [f.version]: read.row[f.version],\n },\n {\n [f.state]: \"Claimed\",\n [f.claimId]: claimed.claimId,\n [f.claimDigest]: yield* digest(S.claimStorage.encode(claimed)),\n [f.claimOrder]: mapping.order.encode(order),\n [f.claimedAt]: mapping.clock.encodeInstant(now),\n [f.claimExpiresAt]: mapping.clock.encodeInstant(expires),\n [f.work]: \"Unresolved\",\n [f.version]: owner.marker,\n },\n );\n owner.postconditions.push(\n sql`${mapping.clock.engineNowMillis} >= ${now} and ${mapping.clock.engineNowMillis} < ${Math.min(c.expiresAtMillis, expires)}`,\n );\n\n return { _tag: \"Claimed\", claim: claimed } as const;\n});\n\nexport const exact = Effect.fn(\"oauthConnected.exactClaim\")(function* (\n mapping: S.Authority,\n claim: M.OAuthConnectedClaim,\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const f = mapping.flow,\n c = claim.flow.context;\n\n const read = yield* owner.read(\n f.table,\n equal(f.table, { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId }),\n { limit: 1 },\n );\n\n const row = read.rows[0];\n\n if (\n row === undefined ||\n row[f.work] !== \"Unresolved\" ||\n row[f.claimId] !== claim.claimId ||\n row[f.claimDigest] !== (yield* digest(S.claimStorage.encode(claim)))\n )\n return undefined;\n const native = yield* mapping.subjectId.toNative(c.revision.subjectId);\n\n invariant(\n row[f.commandId] === c.commandId &&\n mapping.subjectId.equals(native, row[f.subjectId]) &&\n row[f.stateDigest] === c.stateDigest &&\n mapping.clock.decodeInstant(row[f.expiresAt]) === c.expiresAtMillis &&\n mapping.clock.decodeInstant(row[f.retentionUntil]) === claim.flow.retentionUntilMillis &&\n row[f.clientKey] === (yield* S.clientKey(S.configuration(claim.flow))) &&\n S.nativeOrder(mapping, row[f.claimOrder]) === S.orderNumber(claim.order) &&\n mapping.clock.decodeInstant(row[f.claimedAt]) === claim.claimedAtMillis &&\n mapping.clock.decodeInstant(row[f.claimExpiresAt]) === claim.claimExpiresAtMillis,\n );\n const now = yield* owner.now(mapping.clock);\n\n invariant(now >= claim.claimedAtMillis);\n\n return { row, now, active: row[f.state] === \"Claimed\" && now < claim.claimExpiresAtMillis };\n});\n\nexport const terminal = Effect.fn(\"oauthConnected.terminal\")(function* (\n mapping: S.Authority,\n claim: M.OAuthConnectedClaim,\n state: string,\n work: \"Resolved\" | \"Unresolved\",\n custody?: { cohort: string; sealed?: M.OAuthConnectedStoredGrant },\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const f = mapping.flow,\n c = claim.flow.context;\n\n yield* owner.update(\n f.table,\n { [f.moduleId]: c.moduleId, [f.flowId]: c.flowId, [f.claimId]: claim.claimId },\n {\n [f.state]: state,\n [f.snapshot]: null,\n [f.work]: work,\n [f.cohortKey]: custody?.cohort ?? null,\n [f.custody]: custody?.sealed === undefined ? null : S.grantStorage.encode(custody.sealed),\n [f.version]: owner.marker,\n },\n );\n});\n\nexport const inspectTuple = Effect.fn(\"oauthConnected.inspectTuple\")(function* (\n mapping: S.Authority,\n identity: M.OAuthConnectedTokenContext[\"identity\"],\n) {\n const owner = yield* CurrentOAuthTransaction;\n\n const t = mapping.ownership.tuple,\n key = yield* oauthIdentityKey(identity);\n\n const read = yield* owner.read(t.table, equal(t.table, { [t.identityKey]: key }), { limit: 1 });\n const row = read.rows[0];\n\n if (row !== undefined) {\n invariant(\n row[t.provider] === identity.provider &&\n row[t.issuer] === identity.issuer &&\n row[t.externalSubject] === identity.subject &&\n [\"Owned\", \"Unowned\", \"Reserved\"].includes(row[t.state]),\n );\n }\n if (mapping.ownership.mode === \"separate\") {\n const o = mapping.ownership.external;\n\n const external = yield* owner.read(o.table, equal(o.table, { [o.identityKey]: key }), {\n limit: 1,\n });\n\n if (row?.[t.state] === \"Owned\") {\n const e = external.rows[0];\n\n invariant(\n e !== undefined &&\n e[o.provider] === identity.provider &&\n e[o.issuer] === identity.issuer &&\n e[o.externalSubject] === identity.subject &&\n mapping.subjectId.equals(o.decodeSubjectId(copiedRow(e)), row[t.subjectId]),\n );\n const condition = sql`exists(select 1 from ${o.table} where ${both(equal(o.table, { [o.identityKey]: key }), o.ownedCondition)})`;\n\n invariant(yield* owner.check(condition));\n owner.postconditions.push(condition);\n } else invariant(external.rows.length === 0);\n }\n\n return { key, row };\n});\n\nexport const inspectGrant = Effect.fn(\"oauthConnected.inspectGrant\")(function* (\n mapping: S.Mapping,\n input: Input<\"inspectGrant\">,\n) {\n const c = input.claim.flow.context;\n\n if (input.identity.provider !== c.provider || input.identity.issuer !== c.issuer)\n return { _tag: \"Rejected\" } as const;\n const found = yield* S.current(mapping, c.revision.subjectId);\n\n if (found === undefined || !sameRevision(found.revision, c.revision))\n return { _tag: \"Rejected\" } as const;\n const cl = yield* S.client(mapping, S.configuration(input.claim.flow), false);\n\n if (cl === undefined) return { _tag: \"Rejected\" } as const;\n\n const tuple = yield* inspectTuple(mapping, input.identity),\n t = mapping.ownership.tuple;\n\n if (\n tuple.row?.[t.state] === \"Reserved\" ||\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 co = yield* S.cohort(mapping, cl.id, tuple.key, false);\n const claimed = yield* exact(mapping, input.claim);\n\n if (claimed === undefined) return { _tag: \"Rejected\" } as const;\n if (c.reconnect !== undefined && !sameIdentity(c.reconnect.identity, input.identity))\n return { _tag: \"Conflict\" } as const;\n\n return co.blocked || S.orderNumber(input.claim.order) <= co.cutoff || !claimed.active\n ? ({ _tag: \"Quarantine\", cohortGeneration: co.generation } as const)\n : ({ _tag: \"Target\", cohortGeneration: co.generation } as const);\n});\n\n/** Global tuple acquisition is shared with registration/accounts. */\nexport { acquireTuple, readTuple };\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { digest
|
|
1
|
+
import { digest } from "./crypto.mjs";
|
|
2
|
+
import { invariant } from "./oauth-state.mjs";
|
|
2
3
|
import { both } from "./transaction-owner.mjs";
|
|
3
4
|
import { CurrentOAuthTransaction, col, equal } from "./oauth-owner.mjs";
|
|
4
5
|
import { action, client, cohort, commandStorage, current, disconnectStorage, disconnectedStorage, jobTable, nativeCopy, readGrant, summaryStorage, useAuthority } from "./oauth-connected-state.mjs";
|
|
@@ -211,7 +212,7 @@ const disconnect = Effect.fn("oauthConnected.disconnect")(function* (mapping, in
|
|
|
211
212
|
[d.grantId]: token.grantId,
|
|
212
213
|
[d.intent]: commandStorage.encode({
|
|
213
214
|
context: token,
|
|
214
|
-
originalDigest: digest(disconnectStorage.encode(input.grant)),
|
|
215
|
+
originalDigest: yield* digest(disconnectStorage.encode(input.grant)),
|
|
215
216
|
...input.revocation === void 0 ? {} : { revocationJobId: input.revocation.context.jobId }
|
|
216
217
|
}),
|
|
217
218
|
[d.decision]: disconnectedStorage.encode(result),
|
|
@@ -1 +1 @@
|
|
|
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: 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
|
+
{"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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"}
|
|
@@ -4,6 +4,7 @@ import { both } from "./transaction-owner.mjs";
|
|
|
4
4
|
import { col, equal } from "./oauth-owner.mjs";
|
|
5
5
|
import { scopeKey } from "./oauth-connected-state.mjs";
|
|
6
6
|
import { eq, is, sql } from "drizzle-orm";
|
|
7
|
+
import { Effect } from "effect";
|
|
7
8
|
import { MySqlTable } from "drizzle-orm/mysql-core/table";
|
|
8
9
|
import { PgTable } from "drizzle-orm/pg-core/table";
|
|
9
10
|
//#region src/drizzle/oauth-connected-reference.ts
|
|
@@ -19,10 +20,13 @@ const oauthConnectedOwnershipReferences = (original) => {
|
|
|
19
20
|
connectedReferenceGuards: [oauthReferenceGuardTable({
|
|
20
21
|
table: c.table,
|
|
21
22
|
orderBy: c.clientKey,
|
|
22
|
-
condition: (input) =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
condition: (input) => Effect.gen(function* () {
|
|
24
|
+
const key = yield* scopeKey(input.identity.provider, input.identity.issuer);
|
|
25
|
+
return both(equal(c.table, {
|
|
26
|
+
[c.clientKey]: key,
|
|
27
|
+
[c.counter]: mapping.order.encode(0)
|
|
28
|
+
}), exactText(c.table, c.provider, input.identity.provider), exactText(c.table, c.issuer, input.identity.issuer), exactText(c.table, c.clientRegistrationId, ""));
|
|
29
|
+
})
|
|
26
30
|
})],
|
|
27
31
|
connectedReference: (input) => connectedReferenceCondition(mapping, input.identityKey)
|
|
28
32
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-connected-reference.mjs","names":[],"sources":["../../src/drizzle/oauth-connected-reference.ts"],"sourcesContent":["import { eq, is, sql, type SQL, type Table } from \"drizzle-orm\";\nimport { MySqlTable } from \"drizzle-orm/mysql-core/table\";\nimport { PgTable } from \"drizzle-orm/pg-core/table\";\n\nimport type { OAuthConnectedMapping } from \"./oauth-connected-model\";\nimport { scopeKey, type Mapping } from \"./oauth-connected-state\";\nimport { oauthReferenceGuardTable, type OAuthReferenceGuardDescriptor } from \"./oauth-model\";\nimport { both, col, equal } from \"./oauth-owner\";\nimport { captureOAuthMapping } from \"./oauth-state\";\n\nconst exactText = (table: Table, key: string, value: string) => {\n const column = col(table, key),\n bound = sql.param(value, column);\n\n return is(table, MySqlTable)\n ? sql`binary ${column} = binary ${bound}`\n : is(table, PgTable)\n ? sql`convert_to(cast(${column} as text),'UTF8') = convert_to(cast(${bound} as text),'UTF8')`\n : sql`cast(${column} as blob) = cast(${bound} as blob)`;\n};\n\n/** Compose Accounts.Unlink with this connected authority. The stable scope lock\n * serializes unknown claims across every client registration for an issuer. */\nexport const oauthConnectedOwnershipReferences = <\n S extends Table,\n AC extends Table,\n T extends Table,\n O extends Table,\n F extends Table,\n G extends Table,\n C extends Table,\n H extends Table,\n A extends Table,\n D extends Table,\n N,\n J extends Table,\n>(\n original: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, A, D, N, J>,\n): {\n readonly connectedReferenceGuards: ReadonlyArray<OAuthReferenceGuardDescriptor<N>>;\n readonly connectedReference: (input: {\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL;\n} => {\n const mapping = captureOAuthMapping(original),\n c = mapping.client;\n\n return Object.freeze({\n connectedReferenceGuards: [\n oauthReferenceGuardTable<C, N>({\n table: c.table,\n orderBy: c.clientKey,\n condition: (input) =>\n
|
|
1
|
+
{"version":3,"file":"oauth-connected-reference.mjs","names":[],"sources":["../../src/drizzle/oauth-connected-reference.ts"],"sourcesContent":["import { eq, is, sql, type SQL, type Table } from \"drizzle-orm\";\nimport { MySqlTable } from \"drizzle-orm/mysql-core/table\";\nimport { PgTable } from \"drizzle-orm/pg-core/table\";\nimport { Effect } from \"effect\";\n\nimport type { OAuthConnectedMapping } from \"./oauth-connected-model\";\nimport { scopeKey, type Mapping } from \"./oauth-connected-state\";\nimport { oauthReferenceGuardTable, type OAuthReferenceGuardDescriptor } from \"./oauth-model\";\nimport { both, col, equal } from \"./oauth-owner\";\nimport { captureOAuthMapping } from \"./oauth-state\";\n\nconst exactText = (table: Table, key: string, value: string) => {\n const column = col(table, key),\n bound = sql.param(value, column);\n\n return is(table, MySqlTable)\n ? sql`binary ${column} = binary ${bound}`\n : is(table, PgTable)\n ? sql`convert_to(cast(${column} as text),'UTF8') = convert_to(cast(${bound} as text),'UTF8')`\n : sql`cast(${column} as blob) = cast(${bound} as blob)`;\n};\n\n/** Compose Accounts.Unlink with this connected authority. The stable scope lock\n * serializes unknown claims across every client registration for an issuer. */\nexport const oauthConnectedOwnershipReferences = <\n S extends Table,\n AC extends Table,\n T extends Table,\n O extends Table,\n F extends Table,\n G extends Table,\n C extends Table,\n H extends Table,\n A extends Table,\n D extends Table,\n N,\n J extends Table,\n>(\n original: OAuthConnectedMapping<S, AC, T, O, F, G, C, H, A, D, N, J>,\n): {\n readonly connectedReferenceGuards: ReadonlyArray<OAuthReferenceGuardDescriptor<N>>;\n readonly connectedReference: (input: {\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL;\n} => {\n const mapping = captureOAuthMapping(original),\n c = mapping.client;\n\n return Object.freeze({\n connectedReferenceGuards: [\n oauthReferenceGuardTable<C, N>({\n table: c.table,\n orderBy: c.clientKey,\n condition: (input) =>\n Effect.gen(function* () {\n const key = yield* scopeKey(input.identity.provider, input.identity.issuer);\n\n return both(\n equal(c.table, {\n [c.clientKey]: key,\n [c.counter]: mapping.order.encode(0),\n }),\n exactText(c.table, c.provider, input.identity.provider),\n exactText(c.table, c.issuer, input.identity.issuer),\n exactText(c.table, c.clientRegistrationId, \"\"),\n );\n }),\n }),\n ],\n connectedReference: (input) => connectedReferenceCondition(mapping, input.identityKey),\n });\n};\n\nexport const connectedReferenceCondition = (\n mapping: Mapping,\n identityKey: string | SQL,\n knownIdentity?: { readonly provider: string | SQL; readonly issuer: string | SQL },\n) => {\n const c = mapping.client,\n t = mapping.ownership.tuple,\n f = mapping.flow,\n g = mapping.grant,\n h = mapping.cohort,\n a = mapping.admission,\n j = mapping.revocation.mode === \"cohort\" ? mapping.revocation.job : undefined;\n\n const tuple = equal(t.table, { [t.identityKey]: identityKey });\n const knownFlow = sql`exists(select 1 from ${h.table} where ${col(h.table, h.cohortKey)} = ${col(f.table, f.cohortKey)} and ${col(h.table, h.identityKey)} = ${identityKey})`;\n\n const unknownFlow =\n knownIdentity === undefined\n ? sql`${col(f.table, f.cohortKey)} is null and exists(select 1 from ${c.table} where ${col(c.table, c.clientKey)} = ${col(f.table, f.clientKey)} and exists(select 1 from ${t.table} where ${tuple} and ${col(c.table, c.provider)} = ${col(t.table, t.provider)} and ${col(c.table, c.issuer)} = ${col(t.table, t.issuer)}))`\n : sql`${col(f.table, f.cohortKey)} is null and exists(select 1 from ${c.table} where ${col(c.table, c.clientKey)} = ${col(f.table, f.clientKey)} and ${col(c.table, c.provider)} = ${knownIdentity.provider} and ${col(c.table, c.issuer)} = ${knownIdentity.issuer})`;\n\n const related = [f, g, h, ...(j === undefined ? [] : [j])];\n\n return sql`(${sql.join(\n [\n sql`exists(select 1 from ${g.table} where ${eq(col(g.table, g.identityKey), identityKey)})`,\n sql`exists(select 1 from ${a.table} where ${eq(col(a.table, a.identityKey), identityKey)})`,\n sql`exists(select 1 from ${h.table} where ${both(eq(col(h.table, h.identityKey), identityKey), eq(col(h.table, h.state), \"Blocked\"))})`,\n sql`exists(select 1 from ${f.table} where ${col(f.table, f.work)} = 'Unresolved' and (${knownFlow} or (${unknownFlow})))`,\n ...(j === undefined\n ? []\n : [\n sql`exists(select 1 from ${j.table} where ${eq(col(j.table, j.identityKey), identityKey)})`,\n ]),\n // A missing real client cannot turn erased unknown work into absence.\n ...related.map(\n (v) =>\n sql`exists(select 1 from ${v.table} where not exists(select 1 from ${c.table} where ${col(c.table, c.clientKey)} = ${col(v.table, v.clientKey)}))`,\n ),\n ],\n sql` or `,\n )})`;\n};\n"],"mappings":"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"}
|
|
@@ -19,9 +19,9 @@ const activateGrant = Effect.fn("oauthConnected.activateGrant")(function* (mappi
|
|
|
19
19
|
const owner = yield* CurrentOAuthTransaction;
|
|
20
20
|
const token = grant.context;
|
|
21
21
|
const g = mapping.grant;
|
|
22
|
-
const identityKey = oauthIdentityKey(token.identity);
|
|
23
|
-
const clientKey$1 = clientKey(token.configuration);
|
|
24
|
-
const cohortKey$1 = cohortKey(clientKey$1, identityKey);
|
|
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
25
|
const values = {
|
|
26
26
|
...g.encodeInsert({
|
|
27
27
|
grant: snapshotOAuthSync(M.OAuthConnectedStoredGrant, grant),
|
|
@@ -72,7 +72,7 @@ const settle = Effect.fn("oauthConnected.settle")(function* (mapping, input) {
|
|
|
72
72
|
return { _tag: state };
|
|
73
73
|
}
|
|
74
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 && clientKey(token.configuration) === cl.id && tokenContextStorage.encode({
|
|
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
76
|
...token,
|
|
77
77
|
configuration: configuration(input.claim.flow)
|
|
78
78
|
}) === tokenContextStorage.encode(token));
|