@yielded/auth-persistence 0.1.0-beta.23 → 0.1.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/Adapter.d.mts +12 -6
- package/dist/Adapter.mjs +8 -3
- package/dist/OAuthPersistence.d.mts +87 -0
- package/dist/OAuthPersistence.mjs +125 -0
- package/dist/OAuthPersistence.mjs.map +1 -0
- package/dist/_virtual/_rolldown/runtime.mjs +13 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -1
- package/dist/internal/configuration.d.mts +1 -1
- package/dist/internal/configuration.mjs.map +1 -1
- package/dist/internal/models/oauth-connected-model.d.mts +294 -0
- package/dist/internal/models/oauth-connected-model.mjs +22 -0
- package/dist/internal/models/oauth-connected-model.mjs.map +1 -0
- package/dist/internal/models/oauth-model.d.mts +467 -0
- package/dist/internal/models/oauth-model.mjs +49 -0
- package/dist/internal/models/oauth-model.mjs.map +1 -0
- package/dist/internal/models/password-model.d.mts +4 -47
- package/dist/internal/models/password-model.mjs +0 -1
- package/dist/internal/models/password-model.mjs.map +1 -1
- package/dist/internal/native-sql-table.d.mts +4 -0
- package/dist/internal/native-sql-table.mjs +7 -0
- package/dist/internal/native-sql-table.mjs.map +1 -1
- package/dist/internal/oauth/accounts.d.mts +8 -0
- package/dist/internal/oauth/accounts.mjs +379 -0
- package/dist/internal/oauth/accounts.mjs.map +1 -0
- package/dist/internal/oauth/connected-access.d.mts +9 -0
- package/dist/internal/oauth/connected-access.mjs +229 -0
- package/dist/internal/oauth/connected-access.mjs.map +1 -0
- package/dist/internal/oauth/connected-collection.d.mts +7 -0
- package/dist/internal/oauth/connected-collection.mjs +214 -0
- package/dist/internal/oauth/connected-collection.mjs.map +1 -0
- package/dist/internal/oauth/connected-custody.d.mts +6 -0
- package/dist/internal/oauth/connected-custody.mjs +165 -0
- package/dist/internal/oauth/connected-custody.mjs.map +1 -0
- package/dist/internal/oauth/connected-flow.d.mts +7 -0
- package/dist/internal/oauth/connected-flow.mjs +324 -0
- package/dist/internal/oauth/connected-flow.mjs.map +1 -0
- package/dist/internal/oauth/connected-input.mjs +122 -0
- package/dist/internal/oauth/connected-input.mjs.map +1 -0
- package/dist/internal/oauth/connected-keys.d.mts +2 -0
- package/dist/internal/oauth/connected-keys.mjs +22 -0
- package/dist/internal/oauth/connected-keys.mjs.map +1 -0
- package/dist/internal/oauth/connected-maintenance.d.mts +9 -0
- package/dist/internal/oauth/connected-maintenance.mjs +226 -0
- package/dist/internal/oauth/connected-maintenance.mjs.map +1 -0
- package/dist/internal/oauth/connected-management.d.mts +9 -0
- package/dist/internal/oauth/connected-management.mjs +243 -0
- package/dist/internal/oauth/connected-management.mjs.map +1 -0
- package/dist/internal/oauth/connected-reference.mjs +63 -0
- package/dist/internal/oauth/connected-reference.mjs.map +1 -0
- package/dist/internal/oauth/connected-settlement.d.mts +8 -0
- package/dist/internal/oauth/connected-settlement.mjs +141 -0
- package/dist/internal/oauth/connected-settlement.mjs.map +1 -0
- package/dist/internal/oauth/connected-sign-in.d.mts +10 -0
- package/dist/internal/oauth/connected-sign-in.mjs +281 -0
- package/dist/internal/oauth/connected-sign-in.mjs.map +1 -0
- package/dist/internal/oauth/connected-state.d.mts +14 -0
- package/dist/internal/oauth/connected-state.mjs +469 -0
- package/dist/internal/oauth/connected-state.mjs.map +1 -0
- package/dist/internal/oauth/connected-target.d.mts +21 -0
- package/dist/internal/oauth/connected-target.mjs +117 -0
- package/dist/internal/oauth/connected-target.mjs.map +1 -0
- package/dist/internal/oauth/flow.d.mts +5 -0
- package/dist/internal/oauth/flow.mjs +279 -0
- package/dist/internal/oauth/flow.mjs.map +1 -0
- package/dist/internal/oauth/input.mjs +127 -0
- package/dist/internal/oauth/input.mjs.map +1 -0
- package/dist/internal/oauth/owner.d.mts +10 -0
- package/dist/internal/oauth/owner.mjs +10 -0
- package/dist/internal/oauth/owner.mjs.map +1 -0
- package/dist/internal/oauth/query-compiler.d.mts +7 -0
- package/dist/internal/oauth/query-compiler.mjs +9 -0
- package/dist/internal/oauth/query-compiler.mjs.map +1 -0
- package/dist/internal/oauth/registration.d.mts +7 -0
- package/dist/internal/oauth/registration.mjs +393 -0
- package/dist/internal/oauth/registration.mjs.map +1 -0
- package/dist/internal/oauth/state.mjs +107 -0
- package/dist/internal/oauth/state.mjs.map +1 -0
- package/dist/internal/oauth/target.d.mts +31 -0
- package/dist/internal/oauth/target.mjs +273 -0
- package/dist/internal/oauth/target.mjs.map +1 -0
- package/dist/internal/oauth-kernel.d.mts +1423 -0
- package/dist/internal/oauth-kernel.mjs +187 -0
- package/dist/internal/oauth-kernel.mjs.map +1 -0
- package/dist/internal/oauth-proxy.d.mts +31 -0
- package/dist/internal/oauth-proxy.mjs +129 -0
- package/dist/internal/oauth-proxy.mjs.map +1 -0
- package/dist/internal/passkey-kernel.d.mts +5 -5
- package/dist/internal/{password-attempts.d.mts → password-credentials.d.mts} +3 -4
- package/dist/internal/password-credentials.mjs +121 -0
- package/dist/internal/password-credentials.mjs.map +1 -0
- package/dist/internal/password-kernel.d.mts +8 -24
- package/dist/internal/password-kernel.mjs +4 -42
- package/dist/internal/password-kernel.mjs.map +1 -1
- package/dist/internal/persistence.d.mts +1 -1
- package/dist/internal/persistence.mjs +2 -2
- package/dist/internal/persistence.mjs.map +1 -1
- package/dist/internal/query-operations.d.mts +2 -0
- package/dist/internal/session-kernel.d.mts +2 -2
- package/dist/internal/session-kernel.mjs +74 -18
- package/dist/internal/session-kernel.mjs.map +1 -1
- package/dist/internal/sql-oauth-connected-model.d.mts +29 -0
- package/dist/internal/sql-oauth-connected-model.mjs +7 -0
- package/dist/internal/sql-oauth-connected-model.mjs.map +1 -0
- package/dist/internal/sql-oauth-model.d.mts +60 -0
- package/dist/internal/sql-oauth-model.mjs +10 -0
- package/dist/internal/sql-oauth-model.mjs.map +1 -0
- package/dist/internal/sql-query.d.mts +12 -0
- package/dist/internal/sql-query.mjs +15 -18
- package/dist/internal/sql-query.mjs.map +1 -1
- package/dist/internal/sql-storage-validation.mjs +54 -0
- package/dist/internal/sql-storage-validation.mjs.map +1 -0
- package/dist/internal/storage-mapping.mjs +1 -37
- package/dist/internal/storage-mapping.mjs.map +1 -1
- package/dist/internal/storage-plans.d.mts +7 -0
- package/dist/internal/storage-plans.mjs +189 -0
- package/dist/internal/storage-plans.mjs.map +1 -0
- package/dist/internal/storage-tables.d.mts +0 -56
- package/dist/internal/storage-tables.mjs +0 -17
- package/dist/internal/storage-tables.mjs.map +1 -1
- package/dist/internal/storage-validation.d.mts +6 -1
- package/dist/internal/storage-validation.mjs +42 -1
- package/dist/internal/storage-validation.mjs.map +1 -1
- package/dist/internal/transaction-kernel.mjs +3 -2
- package/dist/internal/transaction-kernel.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Adapter.ts +89 -5
- package/src/OAuthPersistence.ts +427 -0
- package/src/index.ts +3 -0
- package/src/internal/configuration.ts +1 -3
- package/src/internal/models/oauth-connected-model.ts +396 -0
- package/src/internal/models/oauth-model.ts +708 -0
- package/src/internal/models/password-model.ts +0 -56
- package/src/internal/native-sql-table.ts +14 -0
- package/src/internal/oauth/accounts.ts +838 -0
- package/src/internal/oauth/connected-access.ts +388 -0
- package/src/internal/oauth/connected-collection.ts +345 -0
- package/src/internal/oauth/connected-custody.ts +308 -0
- package/src/internal/oauth/connected-flow.ts +562 -0
- package/src/internal/oauth/connected-input.ts +147 -0
- package/src/internal/oauth/connected-keys.ts +31 -0
- package/src/internal/oauth/connected-maintenance.ts +379 -0
- package/src/internal/oauth/connected-management.ts +391 -0
- package/src/internal/oauth/connected-reference.ts +135 -0
- package/src/internal/oauth/connected-settlement.ts +278 -0
- package/src/internal/oauth/connected-sign-in.ts +472 -0
- package/src/internal/oauth/connected-state.ts +924 -0
- package/src/internal/oauth/connected-target.ts +307 -0
- package/src/internal/oauth/flow.ts +505 -0
- package/src/internal/oauth/input.ts +201 -0
- package/src/internal/oauth/owner.ts +22 -0
- package/src/internal/oauth/query-compiler.ts +15 -0
- package/src/internal/oauth/registration.ts +676 -0
- package/src/internal/oauth/state.ts +218 -0
- package/src/internal/oauth/target.ts +803 -0
- package/src/internal/oauth-kernel.ts +294 -0
- package/src/internal/oauth-proxy.ts +176 -0
- package/src/internal/password-credentials.ts +245 -0
- package/src/internal/password-kernel.ts +5 -98
- package/src/internal/persistence.ts +1 -1
- package/src/internal/query-operations.ts +2 -0
- package/src/internal/session-kernel.ts +143 -55
- package/src/internal/sql-oauth-connected-model.ts +145 -0
- package/src/internal/sql-oauth-model.ts +263 -0
- package/src/internal/sql-query.ts +16 -13
- package/src/internal/sql-storage-validation.ts +64 -0
- package/src/internal/storage-mapping.ts +0 -37
- package/src/internal/storage-plans.ts +218 -0
- package/src/internal/storage-tables.ts +0 -20
- package/src/internal/storage-validation.ts +58 -0
- package/src/internal/transaction-kernel.ts +6 -2
- package/dist/internal/password-attempts.mjs +0 -197
- package/dist/internal/password-attempts.mjs.map +0 -1
- package/src/internal/password-attempts.ts +0 -466
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { digest, randomId } from "../crypto.mjs";
|
|
2
|
+
import { Crypto, DateTime, Effect, Schema } from "effect";
|
|
3
|
+
import { Base64Url } from "effect/encoding";
|
|
4
|
+
import { OAuthExternalIdentity, OAuthUnavailable, snapshotOAuthSync } from "@yielded/auth/OAuth";
|
|
5
|
+
//#region src/internal/oauth/state.ts
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
8
|
+
const unavailable = () => OAuthUnavailable.make({});
|
|
9
|
+
const invariant = (value) => {
|
|
10
|
+
if (!value) throw unavailable();
|
|
11
|
+
};
|
|
12
|
+
const nonce = randomId;
|
|
13
|
+
/** Capture configuration/callback references while preserving adapter table, SQL
|
|
14
|
+
* and Effect objects. Never freeze or mutate the consumer's original graph. */
|
|
15
|
+
const captureOAuthMapping = (input) => {
|
|
16
|
+
const seen = /* @__PURE__ */ new Map();
|
|
17
|
+
const copy = (value) => {
|
|
18
|
+
if (value === null || typeof value !== "object" || Effect.isEffect(value)) return value;
|
|
19
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) return value;
|
|
20
|
+
const prior = seen.get(value);
|
|
21
|
+
if (prior !== void 0) return prior;
|
|
22
|
+
if (Array.isArray(value)) {
|
|
23
|
+
const result = [];
|
|
24
|
+
seen.set(value, result);
|
|
25
|
+
result.push(...value.map(copy));
|
|
26
|
+
return Object.freeze(result);
|
|
27
|
+
}
|
|
28
|
+
const result = {};
|
|
29
|
+
seen.set(value, result);
|
|
30
|
+
for (const [key, child] of Object.entries(value)) result[key] = copy(child);
|
|
31
|
+
return Object.freeze(result);
|
|
32
|
+
};
|
|
33
|
+
return copy(input);
|
|
34
|
+
};
|
|
35
|
+
/** Versioned length-delimited UTF-8 tuple; the module is deliberately excluded.
|
|
36
|
+
* Reject ill-formed UTF-16 rather than letting UTF-8 replacement alias identities. */
|
|
37
|
+
const oauthIdentityKey = Effect.fnUntraced(function* (input) {
|
|
38
|
+
const identity = snapshotOAuthSync(OAuthExternalIdentity, input);
|
|
39
|
+
const bytes = [
|
|
40
|
+
"effect-auth/oauth-identity-key/v1",
|
|
41
|
+
identity.provider,
|
|
42
|
+
identity.issuer,
|
|
43
|
+
identity.subject
|
|
44
|
+
].map((field) => {
|
|
45
|
+
const value = encoder.encode(field);
|
|
46
|
+
invariant(decoder.decode(value) === field);
|
|
47
|
+
return value;
|
|
48
|
+
});
|
|
49
|
+
const packed = new Uint8Array(bytes.reduce((size, value) => size + 4 + value.length, 0));
|
|
50
|
+
const view = new DataView(packed.buffer);
|
|
51
|
+
let offset = 0;
|
|
52
|
+
for (const value of bytes) {
|
|
53
|
+
view.setUint32(offset, value.length, false);
|
|
54
|
+
packed.set(value, offset + 4);
|
|
55
|
+
offset += 4 + value.length;
|
|
56
|
+
}
|
|
57
|
+
const crypto = yield* Crypto.Crypto;
|
|
58
|
+
return "v1:" + Base64Url.encode(yield* crypto.digest("SHA-256", packed));
|
|
59
|
+
});
|
|
60
|
+
const sameIdentity = (left, right) => left.provider === right.provider && left.issuer === right.issuer && left.subject === right.subject;
|
|
61
|
+
/** Private Type storage: opaque wrappers and DateTimes are freshly reconstructed. */
|
|
62
|
+
const storage = (schema) => {
|
|
63
|
+
const codec = Schema.fromJsonString(Schema.toCodecJson(Schema.toType(schema)));
|
|
64
|
+
const encode = Schema.encodeSync(codec);
|
|
65
|
+
const decode = Schema.decodeSync(codec);
|
|
66
|
+
return {
|
|
67
|
+
encode: (value) => encode(snapshotOAuthSync(schema, value)),
|
|
68
|
+
decode: (value) => snapshotOAuthSync(schema, decode(value))
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const sameRevision = (left, right) => {
|
|
72
|
+
if (left.subjectId !== right.subjectId || left.securityRevision !== right.securityRevision || left.credentials.length !== right.credentials.length) return false;
|
|
73
|
+
const revisions = new Map(left.credentials.map((item) => [item.credentialId, item.revision]));
|
|
74
|
+
return revisions.size === left.credentials.length && new Set(right.credentials.map((item) => item.credentialId)).size === right.credentials.length && right.credentials.every((item) => revisions.get(item.credentialId) === item.revision);
|
|
75
|
+
};
|
|
76
|
+
const satisfies = (proofs, requirement) => {
|
|
77
|
+
const factors = new Set(proofs.flatMap((proof) => [...proof.factors]));
|
|
78
|
+
const count = new Set(proofs.map((proof) => proof.credentialId)).size;
|
|
79
|
+
return requirement.alternatives.some((alternative) => alternative.factors.every((factor) => factors.has(factor)) && count >= alternative.minimumCredentials && proofs.some((proof) => (!alternative.userVerified || proof.userVerified) && (!alternative.phishingResistant || proof.phishingResistant)));
|
|
80
|
+
};
|
|
81
|
+
const validAction = Effect.fnUntraced(function* (authorization, expected, currentRequirement, now, maximumAgeMillis) {
|
|
82
|
+
const challenge = authorization.challenge;
|
|
83
|
+
const evidence = authorization.evidence;
|
|
84
|
+
const intentDigest = yield* digest(expected.intent);
|
|
85
|
+
const binding = yield* digest(JSON.stringify([
|
|
86
|
+
"effect-auth/oauth-action/v1",
|
|
87
|
+
expected.moduleId,
|
|
88
|
+
expected.action,
|
|
89
|
+
expected.flowId,
|
|
90
|
+
expected.commandId,
|
|
91
|
+
intentDigest
|
|
92
|
+
]));
|
|
93
|
+
if (challenge.moduleId !== expected.moduleId || challenge.action !== expected.action || challenge.flowId !== expected.flowId || challenge.commandId !== expected.commandId || challenge.intentDigest !== intentDigest || challenge.bindingDigest !== binding || evidence.flowId !== expected.flowId || evidence.bindingDigest !== binding || !sameRevision(challenge.revision, expected.revision) || !sameRevision(evidence.revision, expected.revision)) return false;
|
|
94
|
+
const revisions = new Map(expected.revision.credentials.map((item) => [item.credentialId, item.revision]));
|
|
95
|
+
if (evidence.proofs.some((proof) => !revisions.has(proof.credentialId) || DateTime.toEpochMillis(proof.verifiedAt) > now)) return false;
|
|
96
|
+
return [authorization.requirement, currentRequirement].every((requirement) => {
|
|
97
|
+
const fresh = evidence.proofs.filter((proof) => {
|
|
98
|
+
const age = now - DateTime.toEpochMillis(proof.verifiedAt);
|
|
99
|
+
return age >= 0 && age < Math.min(maximumAgeMillis, requirement.maximumAgeMillis);
|
|
100
|
+
});
|
|
101
|
+
return satisfies(fresh, requirement);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//#endregion
|
|
105
|
+
export { captureOAuthMapping, digest, invariant, nonce, oauthIdentityKey, sameIdentity, sameRevision, satisfies, storage, unavailable, validAction };
|
|
106
|
+
|
|
107
|
+
//# sourceMappingURL=state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.mjs","names":[],"sources":["../../../src/internal/oauth/state.ts"],"sourcesContent":["import {\n type OAuthActionAuthorization,\n type OAuthAccountRevision,\n OAuthUnavailable,\n OAuthExternalIdentity,\n snapshotOAuthSync,\n} from \"@yielded/auth/OAuth\";\nimport type { AuthenticationRequirement } from \"@yielded/auth/Sessions\";\nimport { Crypto, DateTime, Effect, Schema } from \"effect\";\nimport { Base64Url } from \"effect/encoding\";\n\nimport { digest, randomId } from \"../crypto\";\nexport { digest } from \"../crypto\";\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder(\"utf-8\", { fatal: true });\n\nexport const unavailable = () => OAuthUnavailable.make({});\n\nexport const invariant: (value: unknown) => asserts value = (value) => {\n if (!value) throw unavailable();\n};\n\nexport const nonce = randomId;\n\n/** Capture configuration/callback references while preserving adapter table, SQL\n * and Effect objects. Never freeze or mutate the consumer's original graph. */\nexport const captureOAuthMapping = <A>(input: A): A => {\n const seen = new Map<object, unknown>();\n\n const copy = (value: unknown): unknown => {\n if (value === null || typeof value !== \"object\" || Effect.isEffect(value)) return value;\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) return value;\n const prior = seen.get(value);\n\n if (prior !== undefined) return prior;\n if (Array.isArray(value)) {\n const result: unknown[] = [];\n\n seen.set(value, result);\n result.push(...value.map(copy));\n\n return Object.freeze(result);\n }\n const result: Record<string, unknown> = {};\n\n seen.set(value, result);\n for (const [key, child] of Object.entries(value)) result[key] = copy(child);\n\n return Object.freeze(result);\n };\n\n return copy(input) as A;\n};\n\n/** Versioned length-delimited UTF-8 tuple; the module is deliberately excluded.\n * Reject ill-formed UTF-16 rather than letting UTF-8 replacement alias identities. */\nexport const oauthIdentityKey = Effect.fnUntraced(function* (\n input: typeof OAuthExternalIdentity.Type,\n) {\n const identity = snapshotOAuthSync(OAuthExternalIdentity, input);\n\n const fields = [\n \"effect-auth/oauth-identity-key/v1\",\n identity.provider,\n identity.issuer,\n identity.subject,\n ];\n\n const bytes = fields.map((field) => {\n const value = encoder.encode(field);\n\n invariant(decoder.decode(value) === field);\n\n return value;\n });\n\n const packed = new Uint8Array(bytes.reduce((size, value) => size + 4 + value.length, 0));\n const view = new DataView(packed.buffer);\n let offset = 0;\n\n for (const value of bytes) {\n view.setUint32(offset, value.length, false);\n packed.set(value, offset + 4);\n offset += 4 + value.length;\n }\n\n const crypto = yield* Crypto.Crypto;\n\n return \"v1:\" + Base64Url.encode(yield* crypto.digest(\"SHA-256\", packed));\n});\n\nexport const sameIdentity = (\n left: typeof OAuthExternalIdentity.Type,\n right: typeof OAuthExternalIdentity.Type,\n) =>\n left.provider === right.provider &&\n left.issuer === right.issuer &&\n left.subject === right.subject;\n\n/** Private Type storage: opaque wrappers and DateTimes are freshly reconstructed. */\nexport const storage = <S extends Schema.Codec<unknown, unknown, never, never>>(schema: S) => {\n const codec = Schema.fromJsonString(Schema.toCodecJson(Schema.toType(schema)));\n const encode = Schema.encodeSync(codec);\n const decode = Schema.decodeSync(codec);\n\n return {\n encode: (value: S[\"Type\"]) => encode(snapshotOAuthSync(schema, value)),\n decode: (value: string) => snapshotOAuthSync(schema, decode(value)),\n };\n};\n\nexport const sameRevision = (left: OAuthAccountRevision, right: OAuthAccountRevision) => {\n if (\n left.subjectId !== right.subjectId ||\n left.securityRevision !== right.securityRevision ||\n left.credentials.length !== right.credentials.length\n )\n return false;\n const revisions = new Map(left.credentials.map((item) => [item.credentialId, item.revision]));\n\n return (\n revisions.size === left.credentials.length &&\n new Set(right.credentials.map((item) => item.credentialId)).size === right.credentials.length &&\n right.credentials.every((item) => revisions.get(item.credentialId) === item.revision)\n );\n};\n\nexport const satisfies = (\n proofs: ReadonlyArray<{\n readonly credentialId: string;\n readonly factors: ReadonlyArray<string>;\n readonly userVerified: boolean;\n readonly phishingResistant: boolean;\n }>,\n requirement: AuthenticationRequirement,\n) => {\n const factors = new Set(proofs.flatMap((proof) => [...proof.factors]));\n const count = new Set(proofs.map((proof) => proof.credentialId)).size;\n\n return requirement.alternatives.some(\n (alternative) =>\n alternative.factors.every((factor) => factors.has(factor)) &&\n count >= alternative.minimumCredentials &&\n proofs.some(\n (proof) =>\n (!alternative.userVerified || proof.userVerified) &&\n (!alternative.phishingResistant || proof.phishingResistant),\n ),\n );\n};\n\nexport const validAction = Effect.fnUntraced(function* (\n authorization: OAuthActionAuthorization,\n expected: {\n readonly moduleId: string;\n readonly action: OAuthActionAuthorization[\"challenge\"][\"action\"];\n readonly flowId: string;\n readonly commandId: string;\n readonly revision: OAuthAccountRevision;\n readonly intent: string;\n },\n currentRequirement: AuthenticationRequirement,\n now: number,\n maximumAgeMillis: number,\n) {\n const challenge = authorization.challenge;\n const evidence = authorization.evidence;\n const intentDigest = yield* digest(expected.intent);\n\n const binding = yield* digest(\n // oxlint-disable-next-line no-restricted-properties -- Fixed private action fingerprint format shared with the core verifier.\n JSON.stringify([\n \"effect-auth/oauth-action/v1\",\n expected.moduleId,\n expected.action,\n expected.flowId,\n expected.commandId,\n intentDigest,\n ]),\n );\n\n if (\n challenge.moduleId !== expected.moduleId ||\n challenge.action !== expected.action ||\n challenge.flowId !== expected.flowId ||\n challenge.commandId !== expected.commandId ||\n challenge.intentDigest !== intentDigest ||\n challenge.bindingDigest !== binding ||\n evidence.flowId !== expected.flowId ||\n evidence.bindingDigest !== binding ||\n !sameRevision(challenge.revision, expected.revision) ||\n !sameRevision(evidence.revision, expected.revision)\n )\n return false;\n\n const revisions = new Map(\n expected.revision.credentials.map((item) => [item.credentialId, item.revision]),\n );\n\n if (\n evidence.proofs.some(\n (proof) =>\n !revisions.has(proof.credentialId) || DateTime.toEpochMillis(proof.verifiedAt) > now,\n )\n )\n return false;\n\n return [authorization.requirement, currentRequirement].every((requirement) => {\n const fresh = evidence.proofs.filter((proof) => {\n const age = now - DateTime.toEpochMillis(proof.verifiedAt);\n\n return age >= 0 && age < Math.min(maximumAgeMillis, requirement.maximumAgeMillis);\n });\n\n return satisfies(fresh, requirement);\n });\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import "../transaction-kernel.mjs";
|
|
2
|
+
import "../models/common.mjs";
|
|
3
|
+
import { TransactionCoordinatorError, TransactionExecution, TransactionTargetConfiguration } from "../transaction-execution-kernel.mjs";
|
|
4
|
+
import { OAuthRegistrationAuthority } from "../models/oauth-model.mjs";
|
|
5
|
+
import { CurrentOAuthTransaction } from "./owner.mjs";
|
|
6
|
+
import "./query-compiler.mjs";
|
|
7
|
+
import "./flow.mjs";
|
|
8
|
+
import "./registration.mjs";
|
|
9
|
+
import "./accounts.mjs";
|
|
10
|
+
import { Context, Crypto, Effect, Layer } from "effect";
|
|
11
|
+
import { Statement } from "effect/sql/Statement";
|
|
12
|
+
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
13
|
+
import { OAuthAccountRevision, OAuthAccountsPersistence, OAuthClaim, OAuthClaimDecision, OAuthCleanupInput, OAuthCredentialSnapshot, OAuthIssueDecision, OAuthLinkClaimDecision, OAuthLinkDecision, OAuthLinkIssueDecision, OAuthLinkPendingFlow, OAuthPendingFlow, OAuthRegistrationIntent, OAuthRegistrationIntents, OAuthSettlementDecision, OAuthSignInPersistence, OAuthUnavailable, OAuthUnlinkDecision, OAuthUnlinkInspection, OAuthVerifiedExternalIdentity, PrepareOAuthCommit } from "@yielded/auth/OAuth";
|
|
14
|
+
//#region src/internal/oauth/target.d.ts
|
|
15
|
+
export type OAuthTargetConfiguration = TransactionTargetConfiguration<OAuthUnavailable>;
|
|
16
|
+
export type OAuthCoordinatorError<E> = TransactionCoordinatorError<E, OAuthUnavailable>;
|
|
17
|
+
export type OAuthExecution = TransactionExecution<OAuthUnavailable, CurrentOAuthTransaction, never>;
|
|
18
|
+
export declare const oauthAccountsPersistenceLayer: <E, R>(services: Effect.Effect<{
|
|
19
|
+
readonly oauthAccountsPersistence: OAuthAccountsPersistence["Service"];
|
|
20
|
+
}, E, R>) => Layer.Layer<OAuthAccountsPersistence, E, Exclude<R, import("effect/Scope").Scope>>;
|
|
21
|
+
export declare const oauthSignInPersistenceLayer: <E, R>(services: Effect.Effect<{
|
|
22
|
+
readonly oauthSignInPersistence: OAuthSignInPersistence["Service"];
|
|
23
|
+
}, E, R>) => Layer.Layer<OAuthSignInPersistence, E, Exclude<R, import("effect/Scope").Scope>>;
|
|
24
|
+
export declare const oauthRegistrationIntentsLayer: <E, R>(services: Effect.Effect<{
|
|
25
|
+
readonly oauthRegistrationIntents: OAuthRegistrationIntents["Service"];
|
|
26
|
+
}, E, R>) => Layer.Layer<OAuthRegistrationIntents, E, Exclude<R, import("effect/Scope").Scope>>;
|
|
27
|
+
export declare const oauthRegistrationAuthorityLayer: <Id, Registration, E, R>(tag: Context.Key<Id, OAuthRegistrationAuthority<Registration>>, services: Effect.Effect<{
|
|
28
|
+
readonly registrationAuthority: OAuthRegistrationAuthority<Registration>;
|
|
29
|
+
}, E, R>) => Layer.Layer<Id, E, Exclude<R, import("effect/Scope").Scope>>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//# sourceMappingURL=target.d.mts.map
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { CurrentOAuthTransaction, OAuthTransactionExecution } from "./owner.mjs";
|
|
2
|
+
import { OAuthQueryCompiler } from "./query-compiler.mjs";
|
|
3
|
+
import { captureOAuthMapping, invariant, nonce, unavailable } from "./state.mjs";
|
|
4
|
+
import { OAuthFlow } from "./flow.mjs";
|
|
5
|
+
import { OAuthRegistration } from "./registration.mjs";
|
|
6
|
+
import { OAuthAccounts } from "./accounts.mjs";
|
|
7
|
+
import { accountsInputs, capturedOAuthService, registrationInputs, registrationIntentInputs, signInInputs } from "./input.mjs";
|
|
8
|
+
import { Context, Effect, Layer } from "effect";
|
|
9
|
+
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
10
|
+
import { OAuthAccountRevision, OAuthAccountsPersistence, OAuthClaim, OAuthClaimDecision, OAuthCleanupInput, OAuthCredentialSnapshot, OAuthIssueDecision, OAuthLinkClaimDecision, OAuthLinkDecision, OAuthLinkIssueDecision, OAuthLinkPendingFlow, OAuthPendingFlow, OAuthRegistrationFingerprint, OAuthRegistrationIntent, OAuthRegistrationIntents, OAuthSettlementDecision, OAuthSignInPersistence, OAuthUnlinkDecision, OAuthUnlinkInspection, OAuthVerifiedExternalIdentity, snapshotOAuthSync } from "@yielded/auth/OAuth";
|
|
11
|
+
//#region src/internal/oauth/target.ts
|
|
12
|
+
const make = Effect.gen(function* () {
|
|
13
|
+
const operations = yield* OAuthQueryCompiler;
|
|
14
|
+
const accounts = yield* OAuthAccounts;
|
|
15
|
+
const flow = yield* OAuthFlow;
|
|
16
|
+
const registration = yield* OAuthRegistration;
|
|
17
|
+
const execution = yield* OAuthTransactionExecution;
|
|
18
|
+
const { eq, sql } = operations;
|
|
19
|
+
const { accountCurrent, claimLink, inspectUnlink, issueLink, preflightLink, settleLink, unlink } = accounts;
|
|
20
|
+
const { claimFlow, cleanupFlows, discoverOwned, exactClaim, issueFlow, matchesAccess, readFlow, resolveOwned, terminalFlow } = flow;
|
|
21
|
+
const { both, col, equal } = operations;
|
|
22
|
+
const { inspectIntent, register, registrationData, registrationResources, settleRegistrationIntent } = registration;
|
|
23
|
+
const { coordinateTransactionOwner, makeTransactionExecution } = execution;
|
|
24
|
+
const makeOAuthExecution = Effect.fnUntraced(function* (configuration, mapping) {
|
|
25
|
+
const hooks = yield* LifecycleHooks;
|
|
26
|
+
yield* (operations.validateStorage?.(mapping) ?? Effect.void).pipe(Effect.mapError(unavailable));
|
|
27
|
+
const execution = yield* makeTransactionExecution(CurrentOAuthTransaction, configuration, unavailable, nonce);
|
|
28
|
+
return {
|
|
29
|
+
...execution,
|
|
30
|
+
run: (operation, mutation) => execution.run(operation, mutation).pipe(Effect.provideService(LifecycleHooks, hooks))
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
const prepareValue = (value, prepare) => Effect.flatMap(CurrentOAuthTransaction, (owner) => Effect.sync(() => {
|
|
34
|
+
owner.guards.push(owner.journal.prepare(void 0));
|
|
35
|
+
return prepare(value, owner.journal);
|
|
36
|
+
}));
|
|
37
|
+
const makeOAuthSignIn = (mapping, execute) => capturedOAuthService({
|
|
38
|
+
issue: (original, prepare) => execute.run(Effect.gen(function* () {
|
|
39
|
+
const input = snapshotOAuthSync(OAuthPendingFlow, original);
|
|
40
|
+
const value = yield* issueFlow(mapping, input, "sign-in");
|
|
41
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthIssueDecision, value), prepare);
|
|
42
|
+
})),
|
|
43
|
+
claim: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
44
|
+
const read = yield* readFlow(mapping, input, "sign-in");
|
|
45
|
+
const claim = read.row !== void 0 && read.flow !== void 0 && matchesAccess(read.flow, input) ? yield* claimFlow(mapping, {
|
|
46
|
+
row: read.row,
|
|
47
|
+
flow: read.flow
|
|
48
|
+
}, input.claimId) : void 0;
|
|
49
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthClaimDecision, claim === void 0 ? { _tag: "Rejected" } : {
|
|
50
|
+
_tag: "Claimed",
|
|
51
|
+
claim
|
|
52
|
+
}), prepare);
|
|
53
|
+
})),
|
|
54
|
+
settle: (original, prepare) => execute.run(Effect.gen(function* () {
|
|
55
|
+
const claim = snapshotOAuthSync(OAuthClaim, original.claim);
|
|
56
|
+
const outcome = original.outcome;
|
|
57
|
+
const identity = outcome._tag === "Verified" ? snapshotOAuthSync(OAuthVerifiedExternalIdentity, outcome.identity).identity : void 0;
|
|
58
|
+
if (identity !== void 0) invariant(identity.provider === claim.flow.context.provider && identity.issuer === claim.flow.context.issuer);
|
|
59
|
+
const found = identity === void 0 ? void 0 : yield* discoverOwned(mapping, identity);
|
|
60
|
+
const exact = yield* exactClaim(mapping, claim, "sign-in");
|
|
61
|
+
let value = { _tag: "Rejected" };
|
|
62
|
+
if (exact !== void 0) {
|
|
63
|
+
const credential = identity === void 0 ? void 0 : resolveOwned(mapping, claim.flow.context.moduleId, identity, found);
|
|
64
|
+
value = outcome._tag !== "Verified" ? { _tag: outcome._tag } : credential === void 0 ? { _tag: "Rejected" } : {
|
|
65
|
+
_tag: "Verified",
|
|
66
|
+
credential
|
|
67
|
+
};
|
|
68
|
+
yield* terminalFlow(mapping, claim.flow, value._tag);
|
|
69
|
+
}
|
|
70
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthSettlementDecision, value), prepare);
|
|
71
|
+
})),
|
|
72
|
+
cleanup: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
73
|
+
const value = yield* cleanupFlows(mapping, input, "sign-in");
|
|
74
|
+
return yield* prepareValue(value, prepare);
|
|
75
|
+
}))
|
|
76
|
+
}, signInInputs, execute.active, execute.poison);
|
|
77
|
+
const makeOAuthRegistrationIntents = (mapping, execute) => capturedOAuthService({ settle: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
78
|
+
const value = yield* settleRegistrationIntent(mapping, {
|
|
79
|
+
claim: snapshotOAuthSync(OAuthClaim, input.claim),
|
|
80
|
+
identity: snapshotOAuthSync(OAuthVerifiedExternalIdentity, input.identity),
|
|
81
|
+
...input.intent === void 0 ? {} : { intent: snapshotOAuthSync(OAuthRegistrationIntent, input.intent) }
|
|
82
|
+
});
|
|
83
|
+
return yield* prepareValue(value, prepare);
|
|
84
|
+
})) }, registrationIntentInputs, execute.active, execute.poison);
|
|
85
|
+
const makeOAuthRegistration = (mapping, execute, allocated) => capturedOAuthService({
|
|
86
|
+
read: (input) => execute.run(Effect.map(inspectIntent(mapping, input), (result) => result?.inspection), false),
|
|
87
|
+
inspect: (input) => Effect.gen(function* () {
|
|
88
|
+
yield* execute.admit;
|
|
89
|
+
const intent = snapshotOAuthSync(OAuthRegistrationIntent, input.intent);
|
|
90
|
+
const stored = mapping.application.encode(input.registration);
|
|
91
|
+
invariant(typeof stored === "string" && new TextEncoder().encode(stored).length <= 1048576);
|
|
92
|
+
const detached = {
|
|
93
|
+
intent,
|
|
94
|
+
registration: mapping.application.decode(stored)
|
|
95
|
+
};
|
|
96
|
+
const checked = execute.bound ? (invariant(mapping.inspectSync !== void 0), mapping.inspectSync(detached)) : yield* mapping.inspect(detached);
|
|
97
|
+
invariant(typeof checked.eligible === "boolean");
|
|
98
|
+
return {
|
|
99
|
+
fingerprint: snapshotOAuthSync(OAuthRegistrationFingerprint, checked.fingerprint),
|
|
100
|
+
eligible: checked.eligible
|
|
101
|
+
};
|
|
102
|
+
}).pipe((effect) => execute.bound ? execute.run(effect, false) : effect, Effect.onExit((exit) => Effect.sync(() => {
|
|
103
|
+
if (exit._tag === "Failure") execute.poison();
|
|
104
|
+
})), Effect.mapError(unavailable), Effect.catchDefect(() => Effect.fail(unavailable()))),
|
|
105
|
+
register: (input, prepare) => Effect.gen(function* () {
|
|
106
|
+
yield* execute.admit;
|
|
107
|
+
const data = yield* registrationData(mapping, input, execute.bound);
|
|
108
|
+
const resources = allocated ?? (yield* registrationResources(mapping));
|
|
109
|
+
return yield* execute.run(Effect.gen(function* () {
|
|
110
|
+
const value = yield* register(mapping, input, data, resources);
|
|
111
|
+
return yield* prepareValue(value, prepare);
|
|
112
|
+
}));
|
|
113
|
+
}).pipe(Effect.onExit((exit) => Effect.sync(() => {
|
|
114
|
+
if (exit._tag === "Failure") execute.poison();
|
|
115
|
+
})), Effect.mapError(unavailable), Effect.catchDefect(() => Effect.fail(unavailable()))),
|
|
116
|
+
cleanup: (original, prepare) => execute.run(Effect.gen(function* () {
|
|
117
|
+
const owner = yield* CurrentOAuthTransaction;
|
|
118
|
+
const input = snapshotOAuthSync(OAuthCleanupInput, original), i = mapping.intent, r = mapping.command;
|
|
119
|
+
const now = yield* owner.now(mapping.clock);
|
|
120
|
+
const candidates = yield* owner.read(i.table, both(eq(col(i.table, i.moduleId), input.moduleId), sql`${col(i.table, i.state)} <> 'ProvisioningPending' and ${col(i.table, i.retentionUntil)} < ${mapping.clock.encodeInstant(now)}`), {
|
|
121
|
+
limit: input.limit,
|
|
122
|
+
observe: false,
|
|
123
|
+
takeOnly: true
|
|
124
|
+
});
|
|
125
|
+
let removed = 0;
|
|
126
|
+
for (const candidate of candidates.rows) {
|
|
127
|
+
const row = (yield* owner.read(i.table, equal(i.table, {
|
|
128
|
+
[i.moduleId]: input.moduleId,
|
|
129
|
+
[i.reference]: candidate[i.reference]
|
|
130
|
+
}), { limit: 1 })).rows[0];
|
|
131
|
+
if (row === void 0 || row[i.state] === "ProvisioningPending") continue;
|
|
132
|
+
let horizon = mapping.clock.decodeInstant(row[i.retentionUntil]);
|
|
133
|
+
if (!Number.isSafeInteger(horizon) || horizon >= (yield* owner.now(mapping.clock))) continue;
|
|
134
|
+
if (row[i.commandId] !== null) {
|
|
135
|
+
const command = (yield* owner.read(r.table, equal(r.table, {
|
|
136
|
+
[r.moduleId]: input.moduleId,
|
|
137
|
+
[r.commandId]: row[i.commandId]
|
|
138
|
+
}), { limit: 1 })).rows[0];
|
|
139
|
+
if (command === void 0) continue;
|
|
140
|
+
horizon = Math.max(horizon, mapping.clock.decodeInstant(command[r.retentionUntil]));
|
|
141
|
+
if (!Number.isSafeInteger(horizon) || horizon >= (yield* owner.now(mapping.clock))) continue;
|
|
142
|
+
yield* owner.remove(r.table, {
|
|
143
|
+
[r.moduleId]: input.moduleId,
|
|
144
|
+
[r.commandId]: row[i.commandId]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
yield* owner.remove(i.table, {
|
|
148
|
+
[i.moduleId]: input.moduleId,
|
|
149
|
+
[i.reference]: row[i.reference]
|
|
150
|
+
});
|
|
151
|
+
owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${horizon}`);
|
|
152
|
+
removed++;
|
|
153
|
+
}
|
|
154
|
+
return yield* prepareValue({
|
|
155
|
+
removed,
|
|
156
|
+
hasMore: candidates.rows.length === input.limit
|
|
157
|
+
}, prepare);
|
|
158
|
+
}))
|
|
159
|
+
}, registrationInputs(mapping.application), execute.active, execute.poison);
|
|
160
|
+
const makeTargetOAuthSignInServices = (mapping, configuration) => {
|
|
161
|
+
const captured = captureOAuthMapping(mapping);
|
|
162
|
+
return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({ oauthSignInPersistence: makeOAuthSignIn(captured, execution) }));
|
|
163
|
+
};
|
|
164
|
+
const makeTargetOAuthRegistrationIntentServices = (mapping, configuration) => {
|
|
165
|
+
const captured = captureOAuthMapping(mapping);
|
|
166
|
+
return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({ oauthRegistrationIntents: makeOAuthRegistrationIntents(captured, execution) }));
|
|
167
|
+
};
|
|
168
|
+
const makeTargetOAuthRegistrationServices = (mapping, configuration) => {
|
|
169
|
+
const captured = captureOAuthMapping(mapping);
|
|
170
|
+
return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({ registrationAuthority: makeOAuthRegistration(captured, execution) }));
|
|
171
|
+
};
|
|
172
|
+
const coordinateOAuthOwner = (database, mapping, configuration, allocate, services, owner) => {
|
|
173
|
+
const captured = captureOAuthMapping(mapping);
|
|
174
|
+
return Effect.flatMap(LifecycleHooks, (hooks) => coordinateTransactionOwner(database, CurrentOAuthTransaction, configuration, (operations.validateStorage?.(captured) ?? Effect.void).pipe(Effect.andThen(Effect.suspend(() => allocate(captured)))), unavailable, nonce, (execution, resources) => services(captured, {
|
|
175
|
+
...execution,
|
|
176
|
+
run: (operation, mutation) => execution.run(operation, mutation).pipe(Effect.provideService(LifecycleHooks, hooks))
|
|
177
|
+
}, resources), owner).pipe(Effect.provideService(LifecycleHooks, hooks)));
|
|
178
|
+
};
|
|
179
|
+
const accountResources = (mapping) => Effect.gen(function* () {
|
|
180
|
+
return {
|
|
181
|
+
credentialId: snapshotOAuthSync(OAuthCredentialSnapshot.fields.credentialId, yield* mapping.allocateCredentialId),
|
|
182
|
+
revision: snapshotOAuthSync(OAuthCredentialSnapshot.fields.credentialRevision, yield* mapping.allocateRevision)
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
const coordinateTargetOAuthRegistration = (database, mapping, configuration, owner) => coordinateOAuthOwner(database, mapping, configuration, registrationResources, (captured, execute, resources) => ({ registrationAuthority: makeOAuthRegistration(captured, execute, resources) }), owner);
|
|
186
|
+
const coordinateTargetOAuthSignIn = (database, mapping, configuration, owner) => coordinateOAuthOwner(database, mapping, configuration, () => Effect.void, (captured, execute) => ({ oauthSignInPersistence: makeOAuthSignIn(captured, execute) }), owner);
|
|
187
|
+
const coordinateTargetOAuthRegistrationIntents = (database, mapping, configuration, owner) => coordinateOAuthOwner(database, mapping, configuration, () => Effect.void, (captured, execute) => ({ oauthRegistrationIntents: makeOAuthRegistrationIntents(captured, execute) }), owner);
|
|
188
|
+
const coordinateTargetOAuthAccounts = (database, mapping, configuration, owner) => coordinateOAuthOwner(database, mapping, configuration, accountResources, (captured, execute, resources) => ({ oauthAccountsPersistence: makeOAuthAccounts(captured, execute, resources) }), owner);
|
|
189
|
+
const makeOAuthAccounts = (mapping, execute, resources) => capturedOAuthService({
|
|
190
|
+
capture: (input) => execute.run(Effect.map(accountCurrent(mapping, input.subjectId), (current) => current === void 0 ? void 0 : snapshotOAuthSync(OAuthAccountRevision, current.revision)), false),
|
|
191
|
+
issue: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
192
|
+
const value = yield* issueLink(mapping, input);
|
|
193
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthLinkIssueDecision, value), prepare);
|
|
194
|
+
})),
|
|
195
|
+
preflight: (input) => execute.run(Effect.map(preflightLink(mapping, input), (current) => current === void 0 ? void 0 : snapshotOAuthSync(OAuthLinkPendingFlow, current.flow)), false),
|
|
196
|
+
claim: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
197
|
+
const value = yield* claimLink(mapping, input);
|
|
198
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthLinkClaimDecision, value), prepare);
|
|
199
|
+
})),
|
|
200
|
+
settle: (input, prepare) => Effect.gen(function* () {
|
|
201
|
+
yield* execute.admit;
|
|
202
|
+
const allocated = resources ?? (yield* accountResources(mapping));
|
|
203
|
+
return yield* execute.run(Effect.gen(function* () {
|
|
204
|
+
const value = yield* settleLink(mapping, input, allocated);
|
|
205
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthLinkDecision, value), prepare);
|
|
206
|
+
}));
|
|
207
|
+
}).pipe(Effect.mapError(unavailable), Effect.catchDefect(() => Effect.fail(unavailable()))),
|
|
208
|
+
inspectUnlink: (input) => execute.run(Effect.map(inspectUnlink(mapping, input), (value) => snapshotOAuthSync(OAuthUnlinkInspection, value)), false),
|
|
209
|
+
unlink: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
210
|
+
const value = yield* unlink(mapping, input);
|
|
211
|
+
return yield* prepareValue(snapshotOAuthSync(OAuthUnlinkDecision, value), prepare);
|
|
212
|
+
})),
|
|
213
|
+
cleanup: (input, prepare) => execute.run(Effect.gen(function* () {
|
|
214
|
+
const owner = yield* CurrentOAuthTransaction;
|
|
215
|
+
const value = yield* cleanupFlows(mapping, input, "link");
|
|
216
|
+
const remaining = input.limit - value.terminalized - value.removed;
|
|
217
|
+
const now = yield* owner.now(mapping.clock), r = mapping.command;
|
|
218
|
+
let removed = 0;
|
|
219
|
+
if (remaining > 0) {
|
|
220
|
+
const rows = yield* owner.read(r.table, both(eq(col(r.table, r.moduleId), input.moduleId), sql`${col(r.table, r.retentionUntil)} < ${mapping.clock.encodeInstant(now)}`), {
|
|
221
|
+
limit: remaining,
|
|
222
|
+
observe: false,
|
|
223
|
+
takeOnly: true
|
|
224
|
+
});
|
|
225
|
+
for (const row of rows.rows) {
|
|
226
|
+
const key = {
|
|
227
|
+
[r.moduleId]: input.moduleId,
|
|
228
|
+
[r.commandId]: row[r.commandId]
|
|
229
|
+
};
|
|
230
|
+
const current = (yield* owner.read(r.table, equal(r.table, key), { limit: 1 })).rows[0];
|
|
231
|
+
if (current === void 0) continue;
|
|
232
|
+
const horizon = mapping.clock.decodeInstant(current[r.retentionUntil]);
|
|
233
|
+
if (!Number.isSafeInteger(horizon) || horizon >= (yield* owner.now(mapping.clock))) continue;
|
|
234
|
+
yield* owner.remove(r.table, key);
|
|
235
|
+
owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${horizon}`);
|
|
236
|
+
removed++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return yield* prepareValue({
|
|
240
|
+
...value,
|
|
241
|
+
removed: value.removed + removed,
|
|
242
|
+
hasMore: value.hasMore || remaining === removed
|
|
243
|
+
}, prepare);
|
|
244
|
+
}))
|
|
245
|
+
}, accountsInputs, execute.active, execute.poison);
|
|
246
|
+
const makeTargetOAuthAccountsServices = (mapping, configuration) => {
|
|
247
|
+
const captured = captureOAuthMapping(mapping);
|
|
248
|
+
return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({ oauthAccountsPersistence: makeOAuthAccounts(captured, execution) }));
|
|
249
|
+
};
|
|
250
|
+
return {
|
|
251
|
+
makeOAuthExecution,
|
|
252
|
+
makeTargetOAuthSignInServices,
|
|
253
|
+
makeTargetOAuthRegistrationIntentServices,
|
|
254
|
+
makeTargetOAuthRegistrationServices,
|
|
255
|
+
coordinateOAuthOwner,
|
|
256
|
+
coordinateTargetOAuthRegistration,
|
|
257
|
+
coordinateTargetOAuthSignIn,
|
|
258
|
+
coordinateTargetOAuthRegistrationIntents,
|
|
259
|
+
coordinateTargetOAuthAccounts,
|
|
260
|
+
makeTargetOAuthAccountsServices
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
var OAuthTarget = class OAuthTarget extends Context.Service()("effect-auth/persistence/OAuthTarget") {
|
|
264
|
+
static layer = Layer.effect(OAuthTarget, make);
|
|
265
|
+
};
|
|
266
|
+
const oauthAccountsPersistenceLayer = (services) => Layer.effect(OAuthAccountsPersistence, Effect.map(services, (value) => value.oauthAccountsPersistence));
|
|
267
|
+
const oauthSignInPersistenceLayer = (services) => Layer.effect(OAuthSignInPersistence, Effect.map(services, (value) => value.oauthSignInPersistence));
|
|
268
|
+
const oauthRegistrationIntentsLayer = (services) => Layer.effect(OAuthRegistrationIntents, Effect.map(services, (value) => value.oauthRegistrationIntents));
|
|
269
|
+
const oauthRegistrationAuthorityLayer = (tag, services) => Layer.effect(tag, Effect.map(services, (value) => value.registrationAuthority));
|
|
270
|
+
//#endregion
|
|
271
|
+
export { OAuthTarget, oauthAccountsPersistenceLayer, oauthRegistrationAuthorityLayer, oauthRegistrationIntentsLayer, oauthSignInPersistenceLayer };
|
|
272
|
+
|
|
273
|
+
//# sourceMappingURL=target.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.mjs","names":[],"sources":["../../../src/internal/oauth/target.ts"],"sourcesContent":["import { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n OAuthAccountRevision,\n OAuthLinkClaimDecision,\n OAuthLinkDecision,\n OAuthLinkIssueDecision,\n OAuthLinkPendingFlow,\n OAuthUnlinkDecision,\n OAuthUnlinkInspection,\n OAuthAccountsPersistence,\n OAuthRegistrationIntents,\n OAuthSignInPersistence,\n type PrepareOAuthCommit,\n OAuthRegistrationIntent,\n OAuthRegistrationFingerprint,\n OAuthClaim,\n OAuthClaimDecision,\n OAuthCleanupInput,\n OAuthIssueDecision,\n OAuthPendingFlow,\n OAuthSettlementDecision,\n OAuthVerifiedExternalIdentity,\n OAuthCredentialSnapshot,\n snapshotOAuthSync,\n type OAuthUnavailable,\n} from \"@yielded/auth/OAuth\";\nimport type { SecurityRevision } from \"@yielded/auth/Sessions\";\nimport { type Crypto, Context, Effect, Layer } from \"effect\";\nimport type { Statement } from \"effect/sql/Statement\";\n\nimport type { PersistenceMappingError } from \"../models/common\";\nimport type { OAuthRegistrationAuthority } from \"../models/oauth-model\";\nimport type {\n TransactionTargetConfiguration,\n TransactionCoordinatorError,\n TransactionExecution,\n} from \"../transaction-execution-kernel\";\n/* oxlint-disable no-explicit-any -- compiler table shapes are erased; domain codecs and error channels remain typed. */\nimport type { NativeDatabase } from \"../transaction-kernel\";\nimport { OAuthAccounts } from \"./accounts\";\nimport { OAuthFlow } from \"./flow\";\nimport {\n accountsInputs,\n capturedOAuthService,\n registrationInputs,\n registrationIntentInputs,\n signInInputs,\n} from \"./input\";\nimport { OAuthTransactionExecution, CurrentOAuthTransaction } from \"./owner\";\nimport type { OAuthNativeDatabase } from \"./owner\";\nimport { OAuthQueryCompiler } from \"./query-compiler\";\nimport { OAuthRegistration } from \"./registration\";\nimport type { RegistrationCallbacks } from \"./registration\";\nimport { captureOAuthMapping, invariant, nonce, unavailable } from \"./state\";\n\nexport type OAuthTargetConfiguration = TransactionTargetConfiguration<OAuthUnavailable>;\n\nexport type OAuthCoordinatorError<E> = TransactionCoordinatorError<E, OAuthUnavailable>;\n\nexport type OAuthExecution = TransactionExecution<OAuthUnavailable, CurrentOAuthTransaction, never>;\n\nconst make = Effect.gen(function* () {\n const operations = yield* OAuthQueryCompiler;\n const accounts = yield* OAuthAccounts;\n const flow = yield* OAuthFlow;\n const registration = yield* OAuthRegistration;\n const execution = yield* OAuthTransactionExecution;\n\n const { eq, sql } = operations;\n\n const { accountCurrent, claimLink, inspectUnlink, issueLink, preflightLink, settleLink, unlink } =\n accounts;\n\n const {\n claimFlow,\n cleanupFlows,\n discoverOwned,\n exactClaim,\n issueFlow,\n matchesAccess,\n readFlow,\n resolveOwned,\n terminalFlow,\n } = flow;\n\n const { both, col, equal } = operations;\n\n const {\n inspectIntent,\n register,\n registrationData,\n registrationResources,\n settleRegistrationIntent,\n } = registration;\n\n const { coordinateTransactionOwner, makeTransactionExecution } = execution;\n\n const makeOAuthExecution = Effect.fnUntraced(function* (\n configuration: OAuthTargetConfiguration,\n mapping: unknown,\n ): Effect.fn.Return<\n OAuthExecution,\n OAuthUnavailable,\n LifecycleHooks | NativeDatabase | Crypto.Crypto\n > {\n const hooks = yield* LifecycleHooks;\n\n yield* (operations.validateStorage?.(mapping) ?? Effect.void).pipe(\n Effect.mapError(unavailable),\n );\n\n const execution = yield* makeTransactionExecution(\n CurrentOAuthTransaction,\n configuration,\n unavailable,\n nonce,\n );\n\n return {\n ...execution,\n run: (operation, mutation) =>\n execution.run(operation, mutation).pipe(Effect.provideService(LifecycleHooks, hooks)),\n };\n });\n\n const prepareValue = <Value, A>(value: Value, prepare: PrepareOAuthCommit<Value, A>) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.sync(() => {\n owner.guards.push(owner.journal.prepare(undefined));\n\n return prepare(value, owner.journal);\n }),\n );\n\n const makeOAuthSignIn = (\n mapping: any,\n execute: OAuthExecution,\n ): OAuthSignInPersistence[\"Service\"] =>\n capturedOAuthService<OAuthSignInPersistence[\"Service\"]>(\n {\n issue: (original, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const input = snapshotOAuthSync(OAuthPendingFlow, original);\n const value = yield* issueFlow(mapping, input, \"sign-in\");\n\n return yield* prepareValue(\n snapshotOAuthSync(OAuthIssueDecision, value as never),\n prepare,\n );\n }),\n ),\n claim: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const read = yield* readFlow(mapping, input, \"sign-in\");\n\n const claim =\n read.row !== undefined && read.flow !== undefined && matchesAccess(read.flow, input)\n ? yield* claimFlow(mapping, { row: read.row, flow: read.flow }, input.claimId)\n : undefined;\n\n return yield* prepareValue(\n snapshotOAuthSync(\n OAuthClaimDecision,\n claim === undefined\n ? { _tag: \"Rejected\" }\n : { _tag: \"Claimed\", claim: claim as typeof OAuthClaim.Type },\n ),\n prepare,\n );\n }),\n ),\n settle: (original, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const claim = snapshotOAuthSync(OAuthClaim, original.claim);\n const outcome = original.outcome;\n\n const identity =\n outcome._tag === \"Verified\"\n ? snapshotOAuthSync(OAuthVerifiedExternalIdentity, outcome.identity).identity\n : undefined;\n\n if (identity !== undefined)\n invariant(\n identity.provider === claim.flow.context.provider &&\n identity.issuer === claim.flow.context.issuer,\n );\n\n // Discover/lock the existing subject before locking its claimed flow.\n const found =\n identity === undefined ? undefined : yield* discoverOwned(mapping, identity);\n\n const exact = yield* exactClaim(mapping, claim, \"sign-in\");\n let value: typeof OAuthSettlementDecision.Type = { _tag: \"Rejected\" };\n\n if (exact !== undefined) {\n const credential =\n identity === undefined\n ? undefined\n : resolveOwned(mapping, claim.flow.context.moduleId, identity, found);\n\n value =\n outcome._tag !== \"Verified\"\n ? { _tag: outcome._tag }\n : credential === undefined\n ? { _tag: \"Rejected\" }\n : { _tag: \"Verified\", credential };\n yield* terminalFlow(mapping, claim.flow, value._tag);\n }\n\n return yield* prepareValue(\n snapshotOAuthSync(OAuthSettlementDecision, value),\n prepare,\n );\n }),\n ),\n cleanup: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const value = yield* cleanupFlows(mapping, input, \"sign-in\");\n\n return yield* prepareValue(value, prepare);\n }),\n ),\n },\n signInInputs,\n execute.active,\n execute.poison,\n );\n\n const makeOAuthRegistrationIntents = (\n mapping: any,\n execute: OAuthExecution,\n ): OAuthRegistrationIntents[\"Service\"] =>\n capturedOAuthService<OAuthRegistrationIntents[\"Service\"]>(\n {\n settle: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const value = yield* settleRegistrationIntent(mapping, {\n claim: snapshotOAuthSync(OAuthClaim, input.claim),\n identity: snapshotOAuthSync(OAuthVerifiedExternalIdentity, input.identity),\n ...(input.intent === undefined\n ? {}\n : { intent: snapshotOAuthSync(OAuthRegistrationIntent, input.intent) }),\n });\n\n return yield* prepareValue(value, prepare);\n }),\n ),\n },\n registrationIntentInputs,\n execute.active,\n execute.poison,\n );\n\n const makeOAuthRegistration = <Registration>(\n mapping: any,\n execute: OAuthExecution,\n allocated?: Awaited<ReturnType<typeof registrationResources>> extends Effect.Effect<\n infer A,\n any,\n any\n >\n ? A\n : never,\n ): OAuthRegistrationAuthority<Registration> =>\n capturedOAuthService<OAuthRegistrationAuthority<Registration>>(\n {\n read: (input) =>\n execute.run(\n Effect.map(inspectIntent(mapping, input), (result) => result?.inspection),\n false,\n ),\n inspect: (input) =>\n Effect.gen(function* () {\n yield* execute.admit;\n const intent = snapshotOAuthSync(OAuthRegistrationIntent, input.intent);\n const stored = mapping.application.encode(input.registration);\n\n invariant(\n typeof stored === \"string\" && new TextEncoder().encode(stored).length <= 1048576,\n );\n const detached = { intent, registration: mapping.application.decode(stored) };\n\n const checked = execute.bound\n ? (invariant(mapping.inspectSync !== undefined), mapping.inspectSync(detached))\n : yield* (mapping as RegistrationCallbacks<Registration>).inspect(detached);\n\n invariant(typeof checked.eligible === \"boolean\");\n\n return {\n fingerprint: snapshotOAuthSync(OAuthRegistrationFingerprint, checked.fingerprint),\n eligible: checked.eligible,\n };\n }).pipe(\n (effect) => (execute.bound ? execute.run(effect, false) : effect),\n Effect.onExit((exit) =>\n Effect.sync(() => {\n if (exit._tag === \"Failure\") execute.poison();\n }),\n ),\n Effect.mapError(unavailable),\n Effect.catchDefect(() => Effect.fail(unavailable())),\n ) as never,\n register: (input, prepare) =>\n Effect.gen(function* () {\n yield* execute.admit;\n const data = yield* registrationData(mapping, input, execute.bound);\n const resources = allocated ?? (yield* registrationResources(mapping));\n\n return yield* execute.run(\n Effect.gen(function* () {\n const value = yield* register(mapping, input, data, resources);\n\n return yield* prepareValue(value, prepare);\n }),\n );\n }).pipe(\n Effect.onExit((exit) =>\n Effect.sync(() => {\n if (exit._tag === \"Failure\") execute.poison();\n }),\n ),\n Effect.mapError(unavailable),\n Effect.catchDefect(() => Effect.fail(unavailable())),\n ) as never,\n cleanup: (original, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const owner = yield* CurrentOAuthTransaction;\n\n const input = snapshotOAuthSync(OAuthCleanupInput, original),\n i = mapping.intent,\n r = mapping.command;\n\n const now = yield* owner.now(mapping.clock);\n\n const candidates = yield* owner.read(\n i.table,\n both(\n eq(col(i.table, i.moduleId), input.moduleId),\n sql`${col(i.table, i.state)} <> 'ProvisioningPending' and ${col(i.table, i.retentionUntil)} < ${mapping.clock.encodeInstant(now)}`,\n ),\n { limit: input.limit, observe: false, takeOnly: true },\n );\n\n let removed = 0;\n\n for (const candidate of candidates.rows) {\n const selected = yield* owner.read(\n i.table,\n equal(i.table, {\n [i.moduleId]: input.moduleId,\n [i.reference]: candidate[i.reference],\n }),\n { limit: 1 },\n );\n\n const row = selected.rows[0];\n\n if (row === undefined || row[i.state] === \"ProvisioningPending\") continue;\n let horizon = mapping.clock.decodeInstant(row[i.retentionUntil]);\n\n if (!Number.isSafeInteger(horizon) || horizon >= (yield* owner.now(mapping.clock)))\n continue;\n if (row[i.commandId] !== null) {\n const commands = yield* owner.read(\n r.table,\n equal(r.table, {\n [r.moduleId]: input.moduleId,\n [r.commandId]: row[i.commandId],\n }),\n { limit: 1 },\n );\n\n const command = commands.rows[0];\n\n if (command === undefined) continue;\n horizon = Math.max(\n horizon,\n mapping.clock.decodeInstant(command[r.retentionUntil]),\n );\n if (\n !Number.isSafeInteger(horizon) ||\n horizon >= (yield* owner.now(mapping.clock))\n )\n continue;\n yield* owner.remove(r.table, {\n [r.moduleId]: input.moduleId,\n [r.commandId]: row[i.commandId],\n });\n }\n yield* owner.remove(i.table, {\n [i.moduleId]: input.moduleId,\n [i.reference]: row[i.reference],\n });\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${horizon}`);\n removed++;\n }\n\n return yield* prepareValue(\n { removed, hasMore: candidates.rows.length === input.limit },\n prepare,\n );\n }),\n ),\n },\n registrationInputs(mapping.application),\n execute.active,\n execute.poison,\n );\n\n const makeTargetOAuthSignInServices = (mapping: any, configuration: OAuthTargetConfiguration) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({\n oauthSignInPersistence: makeOAuthSignIn(captured, execution),\n }));\n };\n\n const makeTargetOAuthRegistrationIntentServices = (\n mapping: any,\n configuration: OAuthTargetConfiguration,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({\n oauthRegistrationIntents: makeOAuthRegistrationIntents(captured, execution),\n }));\n };\n\n const makeTargetOAuthRegistrationServices = <Registration>(\n mapping: any,\n configuration: OAuthTargetConfiguration,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({\n registrationAuthority: makeOAuthRegistration<Registration>(captured, execution),\n }));\n };\n\n const coordinateOAuthOwner = <Services, Transaction, A, E, R>(\n database: OAuthNativeDatabase,\n mapping: any,\n configuration: OAuthTargetConfiguration,\n allocate: (mapping: any) => Effect.Effect<any, PersistenceMappingError>,\n services: (mapping: any, execution: OAuthExecution, resources: any) => Services,\n owner: (\n transaction: Transaction,\n services: Services,\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E>,\n R | Crypto.Crypto | LifecycleHooks | NativeDatabase\n > => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.flatMap(LifecycleHooks, (hooks) =>\n coordinateTransactionOwner(\n database,\n CurrentOAuthTransaction,\n configuration,\n (operations.validateStorage?.(captured) ?? Effect.void).pipe(\n Effect.andThen(Effect.suspend(() => allocate(captured))),\n ),\n unavailable,\n nonce,\n (execution, resources) =>\n services(\n captured,\n {\n ...execution,\n run: (operation, mutation) =>\n execution\n .run(operation, mutation)\n .pipe(Effect.provideService(LifecycleHooks, hooks)),\n },\n resources,\n ),\n owner,\n ).pipe(Effect.provideService(LifecycleHooks, hooks)),\n );\n };\n\n const accountResources = (mapping: any) =>\n Effect.gen(function* () {\n return {\n credentialId: snapshotOAuthSync(\n OAuthCredentialSnapshot.fields.credentialId,\n yield* mapping.allocateCredentialId as Effect.Effect<string, PersistenceMappingError>,\n ),\n revision: snapshotOAuthSync(\n OAuthCredentialSnapshot.fields.credentialRevision,\n yield* mapping.allocateRevision as Effect.Effect<\n SecurityRevision,\n PersistenceMappingError\n >,\n ),\n };\n });\n\n const coordinateTargetOAuthRegistration = <Registration, Transaction, A, E, R>(\n database: any,\n mapping: any,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly registrationAuthority: OAuthRegistrationAuthority<Registration> },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n ) =>\n coordinateOAuthOwner(\n database,\n mapping,\n configuration,\n registrationResources,\n (captured, execute, resources) => ({\n registrationAuthority: makeOAuthRegistration<Registration>(captured, execute, resources),\n }),\n owner,\n );\n\n const coordinateTargetOAuthSignIn = <Transaction, A, E, R>(\n database: any,\n mapping: any,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthSignInPersistence: OAuthSignInPersistence[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n ) =>\n coordinateOAuthOwner(\n database,\n mapping,\n configuration,\n () => Effect.void,\n (captured, execute) => ({ oauthSignInPersistence: makeOAuthSignIn(captured, execute) }),\n owner,\n );\n\n const coordinateTargetOAuthRegistrationIntents = <Transaction, A, E, R>(\n database: any,\n mapping: any,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthRegistrationIntents: OAuthRegistrationIntents[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n ) =>\n coordinateOAuthOwner(\n database,\n mapping,\n configuration,\n () => Effect.void,\n (captured, execute) => ({\n oauthRegistrationIntents: makeOAuthRegistrationIntents(captured, execute),\n }),\n owner,\n );\n\n const coordinateTargetOAuthAccounts = <Transaction, A, E, R>(\n database: any,\n mapping: any,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthAccountsPersistence: OAuthAccountsPersistence[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n ) =>\n coordinateOAuthOwner(\n database,\n mapping,\n configuration,\n accountResources,\n (captured, execute, resources) => ({\n oauthAccountsPersistence: makeOAuthAccounts(captured, execute, resources),\n }),\n owner,\n );\n\n const makeOAuthAccounts = (\n mapping: any,\n execute: OAuthExecution,\n resources?: any,\n ): OAuthAccountsPersistence[\"Service\"] =>\n capturedOAuthService<OAuthAccountsPersistence[\"Service\"]>(\n {\n capture: (input) =>\n execute.run(\n Effect.map(accountCurrent(mapping, input.subjectId), (current) =>\n current === undefined\n ? undefined\n : snapshotOAuthSync(OAuthAccountRevision, current.revision),\n ),\n false,\n ),\n issue: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const value = yield* issueLink(mapping, input);\n\n return yield* prepareValue(\n snapshotOAuthSync(OAuthLinkIssueDecision, value as never),\n prepare,\n );\n }),\n ),\n preflight: (input) =>\n execute.run(\n Effect.map(preflightLink(mapping, input), (current) =>\n current === undefined\n ? undefined\n : snapshotOAuthSync(OAuthLinkPendingFlow, current.flow),\n ),\n false,\n ),\n claim: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const value = yield* claimLink(mapping, input);\n\n return yield* prepareValue(\n snapshotOAuthSync(OAuthLinkClaimDecision, value as never),\n prepare,\n );\n }),\n ),\n settle: (input, prepare) =>\n Effect.gen(function* () {\n yield* execute.admit;\n const allocated = resources ?? (yield* accountResources(mapping));\n\n return yield* execute.run(\n Effect.gen(function* () {\n const value = yield* settleLink(mapping, input, allocated as never);\n\n return yield* prepareValue(snapshotOAuthSync(OAuthLinkDecision, value), prepare);\n }),\n );\n }).pipe(\n Effect.mapError(unavailable),\n Effect.catchDefect(() => Effect.fail(unavailable())),\n ) as never,\n inspectUnlink: (input) =>\n execute.run(\n Effect.map(inspectUnlink(mapping, input), (value) =>\n snapshotOAuthSync(OAuthUnlinkInspection, value),\n ),\n false,\n ),\n unlink: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const value = yield* unlink(mapping, input);\n\n return yield* prepareValue(snapshotOAuthSync(OAuthUnlinkDecision, value), prepare);\n }),\n ),\n cleanup: (input, prepare) =>\n execute.run(\n Effect.gen(function* () {\n const owner = yield* CurrentOAuthTransaction;\n const value = yield* cleanupFlows(mapping, input, \"link\");\n const remaining = input.limit - value.terminalized - value.removed;\n\n const now = yield* owner.now(mapping.clock),\n r = mapping.command;\n\n let removed = 0;\n\n if (remaining > 0) {\n const rows = yield* owner.read(\n r.table,\n both(\n eq(col(r.table, r.moduleId), input.moduleId),\n sql`${col(r.table, r.retentionUntil)} < ${mapping.clock.encodeInstant(now)}`,\n ),\n { limit: remaining, observe: false, takeOnly: true },\n );\n\n for (const row of rows.rows) {\n const key = { [r.moduleId]: input.moduleId, [r.commandId]: row[r.commandId] };\n const selected = yield* owner.read(r.table, equal(r.table, key), { limit: 1 });\n const current = selected.rows[0];\n\n if (current === undefined) continue;\n const horizon = mapping.clock.decodeInstant(current[r.retentionUntil]);\n\n if (\n !Number.isSafeInteger(horizon) ||\n horizon >= (yield* owner.now(mapping.clock))\n )\n continue;\n yield* owner.remove(r.table, key);\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${horizon}`);\n removed++;\n }\n }\n\n return yield* prepareValue(\n {\n ...value,\n removed: value.removed + removed,\n hasMore: value.hasMore || remaining === removed,\n },\n prepare,\n );\n }),\n ),\n },\n accountsInputs,\n execute.active,\n execute.poison,\n );\n\n const makeTargetOAuthAccountsServices = (\n mapping: any,\n configuration: OAuthTargetConfiguration,\n ) => {\n const captured = captureOAuthMapping(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, captured), (execution) => ({\n oauthAccountsPersistence: makeOAuthAccounts(captured, execution),\n }));\n };\n\n return {\n makeOAuthExecution,\n makeTargetOAuthSignInServices,\n makeTargetOAuthRegistrationIntentServices,\n makeTargetOAuthRegistrationServices,\n coordinateOAuthOwner,\n coordinateTargetOAuthRegistration,\n coordinateTargetOAuthSignIn,\n coordinateTargetOAuthRegistrationIntents,\n coordinateTargetOAuthAccounts,\n makeTargetOAuthAccountsServices,\n };\n});\n\nexport class OAuthTarget extends Context.Service<OAuthTarget, Effect.Success<typeof make>>()(\n \"effect-auth/persistence/OAuthTarget\",\n) {\n static readonly layer = Layer.effect(OAuthTarget, make);\n}\n\nexport const oauthAccountsPersistenceLayer = <E, R>(\n services: Effect.Effect<\n { readonly oauthAccountsPersistence: OAuthAccountsPersistence[\"Service\"] },\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthAccountsPersistence,\n Effect.map(services, (value) => value.oauthAccountsPersistence),\n );\n\nexport const oauthSignInPersistenceLayer = <E, R>(\n services: Effect.Effect<\n { readonly oauthSignInPersistence: OAuthSignInPersistence[\"Service\"] },\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthSignInPersistence,\n Effect.map(services, (value) => value.oauthSignInPersistence),\n );\n\nexport const oauthRegistrationIntentsLayer = <E, R>(\n services: Effect.Effect<\n { readonly oauthRegistrationIntents: OAuthRegistrationIntents[\"Service\"] },\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthRegistrationIntents,\n Effect.map(services, (value) => value.oauthRegistrationIntents),\n );\n\nexport const oauthRegistrationAuthorityLayer = <Id, Registration, E, R>(\n tag: Context.Key<Id, OAuthRegistrationAuthority<Registration>>,\n services: Effect.Effect<\n { readonly registrationAuthority: OAuthRegistrationAuthority<Registration> },\n E,\n R\n >,\n) =>\n Layer.effect(\n tag,\n Effect.map(services, (value) => value.registrationAuthority),\n );\n"],"mappings":"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"}
|