@yielded/auth-persistence 0.1.0-beta.30 → 0.1.0-beta.32
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 -7
- package/dist/Adapter.d.mts +1 -1
- package/dist/Adapter.mjs +8 -8
- package/dist/OAuthPersistence.mjs +10 -5
- package/dist/OAuthPersistence.mjs.map +1 -1
- package/dist/internal/configuration.d.mts +49 -13
- package/dist/internal/configuration.mjs.map +1 -1
- package/dist/internal/email-native.mjs +10 -2
- package/dist/internal/email-native.mjs.map +1 -1
- package/dist/internal/email-policy.mjs +3 -2
- package/dist/internal/email-policy.mjs.map +1 -1
- package/dist/internal/models/oauth-model.d.mts +4 -2
- package/dist/internal/models/oauth-model.mjs.map +1 -1
- package/dist/internal/models/password-model.d.mts +2 -1
- package/dist/internal/models/password-model.mjs.map +1 -1
- package/dist/internal/oauth/native-accounts.d.mts +1 -1
- package/dist/internal/oauth/native-accounts.mjs +6 -6
- package/dist/internal/oauth/native-accounts.mjs.map +1 -1
- package/dist/internal/oauth/native-connected.d.mts +1 -1
- package/dist/internal/oauth/native-connected.mjs +1 -1
- package/dist/internal/oauth/native-registration.mjs +19 -8
- package/dist/internal/oauth/native-registration.mjs.map +1 -1
- package/dist/internal/oauth/native-sign-in.d.mts +1 -1
- package/dist/internal/oauth/native-sign-in.mjs +1 -1
- package/dist/internal/oauth/native-state.mjs +21 -11
- package/dist/internal/oauth/native-state.mjs.map +1 -1
- package/dist/internal/oauth/state.d.mts +1 -1
- package/dist/internal/oauth/state.mjs +1 -1
- package/dist/internal/oauth-managed.mjs +182 -0
- package/dist/internal/oauth-managed.mjs.map +1 -0
- package/dist/internal/passkey-managed.mjs +5 -3
- package/dist/internal/passkey-managed.mjs.map +1 -1
- package/dist/internal/passkey-native-registration.mjs +1 -1
- package/dist/internal/passkey-native-state.mjs +33 -23
- package/dist/internal/passkey-native-state.mjs.map +1 -1
- package/dist/internal/passkey-native-write.mjs +3 -3
- package/dist/internal/passkey-native-write.mjs.map +1 -1
- package/dist/internal/passkey-native.d.mts +15 -7
- package/dist/internal/passkey-native.mjs +2 -1
- package/dist/internal/passkey-native.mjs.map +1 -1
- package/dist/internal/passkey-policy.mjs +9 -7
- package/dist/internal/passkey-policy.mjs.map +1 -1
- package/dist/internal/password-native.mjs +22 -5
- package/dist/internal/password-native.mjs.map +1 -1
- package/dist/internal/password-policy.mjs +7 -6
- package/dist/internal/password-policy.mjs.map +1 -1
- package/dist/internal/password-registration-native.d.mts +1 -1
- package/dist/internal/persistence.d.mts +3 -0
- package/dist/internal/persistence.mjs +99 -42
- package/dist/internal/persistence.mjs.map +1 -1
- package/dist/internal/phone-native.mjs +1 -1
- package/dist/internal/phone-native.mjs.map +1 -1
- package/dist/internal/registration.mjs +17 -8
- package/dist/internal/registration.mjs.map +1 -1
- package/dist/internal/session-native-authority.mjs +8 -6
- package/dist/internal/session-native-authority.mjs.map +1 -1
- package/dist/internal/session-native-login.d.mts +2 -2
- package/dist/internal/session-native-login.mjs +4 -2
- package/dist/internal/session-native-login.mjs.map +1 -1
- package/dist/internal/session-native-pending-read.mjs +26 -20
- package/dist/internal/session-native-pending-read.mjs.map +1 -1
- package/dist/internal/session-native-record.mjs +6 -4
- package/dist/internal/session-native-record.mjs.map +1 -1
- package/dist/internal/session-native-state.mjs +24 -8
- package/dist/internal/session-native-state.mjs.map +1 -1
- package/dist/internal/session-native-stateful.d.mts +2 -2
- package/dist/internal/session-native-stateful.mjs +67 -38
- package/dist/internal/session-native-stateful.mjs.map +1 -1
- package/dist/internal/session-native-step-up.d.mts +2 -2
- package/dist/internal/session-native-step-up.mjs +17 -19
- package/dist/internal/session-native-step-up.mjs.map +1 -1
- package/dist/internal/session-native-validity.mjs +3 -1
- package/dist/internal/session-native-validity.mjs.map +1 -1
- package/dist/internal/sql-authority.mjs +5 -1
- package/dist/internal/sql-authority.mjs.map +1 -1
- package/dist/internal/sql-storage-validation.mjs +2 -1
- package/dist/internal/sql-storage-validation.mjs.map +1 -1
- package/dist/internal/sql-table.d.mts +1 -0
- package/dist/internal/sql-table.mjs.map +1 -1
- package/dist/internal/sqlite-policy-guard.mjs +23 -0
- package/dist/internal/sqlite-policy-guard.mjs.map +1 -0
- package/dist/internal/step-up-state.mjs +19 -6
- package/dist/internal/step-up-state.mjs.map +1 -1
- package/dist/internal/storage-mapping.d.mts +9 -5
- package/dist/internal/storage-mapping.mjs +17 -5
- package/dist/internal/storage-mapping.mjs.map +1 -1
- package/dist/internal/storage-tables.d.mts +237 -0
- package/dist/internal/storage-tables.mjs +68 -0
- package/dist/internal/storage-tables.mjs.map +1 -1
- package/dist/internal/storage-validation.d.mts +3 -1
- package/dist/internal/storage-validation.mjs +70 -17
- package/dist/internal/storage-validation.mjs.map +1 -1
- package/dist/internal/totp-native.mjs +1 -1
- package/package.json +1 -1
- package/src/OAuthPersistence.ts +7 -2
- package/src/internal/configuration.ts +72 -15
- package/src/internal/email-native.ts +16 -6
- package/src/internal/email-policy.ts +12 -3
- package/src/internal/models/oauth-model.ts +7 -1
- package/src/internal/models/password-model.ts +2 -1
- package/src/internal/oauth/native-accounts.ts +3 -3
- package/src/internal/oauth/native-registration.ts +17 -6
- package/src/internal/oauth/native-state.ts +38 -18
- package/src/internal/oauth-managed.ts +277 -0
- package/src/internal/passkey-managed.ts +8 -2
- package/src/internal/passkey-native-state.ts +59 -52
- package/src/internal/passkey-native-write.ts +2 -2
- package/src/internal/passkey-native.ts +4 -2
- package/src/internal/passkey-policy.ts +13 -9
- package/src/internal/password-native.ts +45 -11
- package/src/internal/password-policy.ts +16 -8
- package/src/internal/persistence.ts +360 -204
- package/src/internal/phone-native.ts +1 -1
- package/src/internal/registration.ts +53 -40
- package/src/internal/session-native-authority.ts +26 -8
- package/src/internal/session-native-login.ts +9 -4
- package/src/internal/session-native-pending-read.ts +46 -33
- package/src/internal/session-native-record.ts +6 -4
- package/src/internal/session-native-state.ts +32 -10
- package/src/internal/session-native-stateful.ts +147 -52
- package/src/internal/session-native-step-up.ts +31 -24
- package/src/internal/session-native-validity.ts +3 -1
- package/src/internal/sql-authority.ts +5 -1
- package/src/internal/sql-storage-validation.ts +53 -46
- package/src/internal/sql-table.ts +1 -0
- package/src/internal/sqlite-policy-guard.ts +34 -0
- package/src/internal/step-up-state.ts +43 -6
- package/src/internal/storage-mapping.ts +40 -4
- package/src/internal/storage-tables.ts +76 -0
- package/src/internal/storage-validation.ts +127 -27
|
@@ -4,7 +4,9 @@ import { requireStandalone } from "./standalone.mjs";
|
|
|
4
4
|
import { SqlBatchCommit } from "./sql-commit.mjs";
|
|
5
5
|
import { makeNativeProofServices } from "./proof-native.mjs";
|
|
6
6
|
import { makeNativeEmailAddressServices } from "./email-native.mjs";
|
|
7
|
+
import { validateStorageBatch, withStorageValidation } from "./storage-validation.mjs";
|
|
7
8
|
import { storageTables, tableDefinition } from "./storage-tables.mjs";
|
|
9
|
+
import { makeManagedOAuth } from "./oauth-managed.mjs";
|
|
8
10
|
import { makeManagedPasskeys } from "./passkey-managed.mjs";
|
|
9
11
|
import { makeNativePasswordServices } from "./password-native.mjs";
|
|
10
12
|
import { makeComposedPhoneTargets } from "./phone-composed.mjs";
|
|
@@ -15,14 +17,14 @@ import { makeNativePendingAuthenticationServices } from "./session-native-login.
|
|
|
15
17
|
import { makeNativeStatefulSessionServices } from "./session-native-stateful.mjs";
|
|
16
18
|
import { makeNativeSessionStepUpServices } from "./session-native-step-up.mjs";
|
|
17
19
|
import { makeMappings } from "./storage-mapping.mjs";
|
|
18
|
-
import { validateStorageBatch, withStorageValidation } from "./storage-validation.mjs";
|
|
19
20
|
import { Context, Effect, Layer, Schema } from "effect";
|
|
20
21
|
import { SqlClient } from "effect/sql";
|
|
21
22
|
import { EmailAddressPersistence, EmailUnavailable } from "@yielded/auth/Email";
|
|
22
23
|
import { hasCommitScope } from "@yielded/auth/Hooks";
|
|
24
|
+
import { OAuthConnectedPersistence, OAuthConnectedRevocations, OAuthSignInPersistence, OAuthUnavailable } from "@yielded/auth/OAuth";
|
|
23
25
|
import { PasskeyCredentials, PasskeyManagementPersistence, PasskeyPersistence, PasskeyUnavailable } from "@yielded/auth/Passkey";
|
|
24
26
|
import { PasswordPersistence, PasswordUnavailable } from "@yielded/auth/Password";
|
|
25
|
-
import { hooksLayer } from "@yielded/auth/Persistence";
|
|
27
|
+
import { hooksLayer, reportAuthDiagnostic } from "@yielded/auth/Persistence";
|
|
26
28
|
import { PhoneOtpUnavailable, PhoneSignInTargets } from "@yielded/auth/PhoneOtp";
|
|
27
29
|
import { ProofPersistence, ProofUnavailable } from "@yielded/auth/Proofs";
|
|
28
30
|
import { AuthenticationAuthority, SessionUnavailable } from "@yielded/auth/Sessions";
|
|
@@ -45,27 +47,37 @@ const timestampKeys = /* @__PURE__ */ new Set([
|
|
|
45
47
|
"admittedAt",
|
|
46
48
|
"deadline",
|
|
47
49
|
"occurredAt",
|
|
48
|
-
"dedupUntil"
|
|
50
|
+
"dedupUntil",
|
|
51
|
+
"binderExpiresAt",
|
|
52
|
+
"refreshClaimedAt",
|
|
53
|
+
"refreshClaimExpiresAt",
|
|
54
|
+
"claimedAt",
|
|
55
|
+
"claimExpiresAt"
|
|
49
56
|
]);
|
|
50
57
|
const createPersistence = (backend) => {
|
|
51
58
|
const make = (auth) => {
|
|
52
|
-
const features = Object.values(auth.strategies).
|
|
53
|
-
const phone = features.some((feature) => feature
|
|
54
|
-
const password = features.some((feature) => feature
|
|
55
|
-
const passkeys = features.filter((feature) => feature
|
|
56
|
-
const
|
|
57
|
-
const
|
|
59
|
+
const features = Object.values(auth.strategies).flatMap((strategy) => strategy.persistence === void 0 ? [] : [strategy.persistence]);
|
|
60
|
+
const phone = features.some((feature) => feature.kind === "phone");
|
|
61
|
+
const password = features.some((feature) => feature.kind === "password");
|
|
62
|
+
const passkeys = features.filter((feature) => feature.kind === "passkey");
|
|
63
|
+
const oauth = features.filter((feature) => feature?.kind === "oauth");
|
|
64
|
+
const oauthSignIn = oauth.some((feature) => feature.signIn);
|
|
65
|
+
const oauthConnected = oauth.some((feature) => feature.connected !== void 0);
|
|
66
|
+
const stateful = auth.sessionMode === "stateful";
|
|
67
|
+
const stateless = auth.sessionMode === "stateless" && features.length > 0 && features.every((feature) => feature?.kind === "oauth");
|
|
68
|
+
const management = features.some((feature) => feature.kind === "password" && feature.management);
|
|
69
|
+
const email = features.some((feature) => feature.kind === "email" && feature.addresses);
|
|
58
70
|
const proofs = phone || management || email;
|
|
59
|
-
const roles = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"sessions",
|
|
63
|
-
"pending"
|
|
64
|
-
];
|
|
71
|
+
const roles = ["identifiers", "credentials"];
|
|
72
|
+
if (stateful) roles.push("sessions");
|
|
73
|
+
roles.push("pending");
|
|
65
74
|
if (password) roles.push("passwords");
|
|
66
75
|
if (email) roles.push("emailCredentials");
|
|
67
76
|
if (passkeys.length > 0) roles.push("passkeyCredentials", "passkeyFlows");
|
|
68
77
|
if (proofs) roles.push("proofs");
|
|
78
|
+
if (oauth.length > 0) roles.push("oauthIdentities", "oauthCredentials");
|
|
79
|
+
if (oauthSignIn) roles.push("oauthSignInFlows");
|
|
80
|
+
if (oauthConnected) roles.push("oauthConnectedFlows", "oauthConnectedGrants", "oauthConnectedRevocations");
|
|
69
81
|
const ConfigKey = Context.Service()(`@yielded/auth-persistence/${auth.namespace}/Config`);
|
|
70
82
|
const Config = Object.assign(ConfigKey, { layer: (value) => Layer.succeed(ConfigKey, value) });
|
|
71
83
|
const ProvisioningKey = Context.Service()(`@yielded/auth-persistence/${auth.namespace}/Provisioning`);
|
|
@@ -122,18 +134,15 @@ const createPersistence = (backend) => {
|
|
|
122
134
|
decodeInstantSync
|
|
123
135
|
});
|
|
124
136
|
};
|
|
125
|
-
const services = Layer.effectContext(Effect.gen(function* () {
|
|
137
|
+
const services = Layer.effectContext(Effect.flatMap(backend.acquire, (database) => Effect.gen(function* () {
|
|
126
138
|
const storage = yield* ConfigKey;
|
|
127
|
-
const
|
|
128
|
-
const database = yield* backend.acquire;
|
|
129
|
-
const dialect = client.onDialectOrElse({
|
|
139
|
+
const dialect = (yield* SqlClient.SqlClient).onDialectOrElse({
|
|
130
140
|
pg: () => "pg",
|
|
131
141
|
sqlite: () => "sqlite",
|
|
132
142
|
orElse: () => void 0
|
|
133
143
|
});
|
|
134
144
|
if (dialect === void 0) return yield* configError("Use an explicit adapter for this SQL dialect");
|
|
135
|
-
if (
|
|
136
|
-
if (features.some((feature) => feature === void 0 || "lifecycle" in feature && feature.lifecycle || feature.kind === "email" && !feature.addresses)) return yield* configError("Use explicit services for strategies without composed persistence support");
|
|
145
|
+
if (features.some((feature) => "lifecycle" in feature && feature.lifecycle || feature.kind === "email" && !feature.addresses)) return yield* configError("Use explicit services for strategies without composed persistence support");
|
|
137
146
|
if (storage.namespace !== auth.namespace) return yield* configError("Persistence configuration belongs to a different Auth definition");
|
|
138
147
|
const validations = [];
|
|
139
148
|
for (const role of roles) {
|
|
@@ -152,16 +161,21 @@ const createPersistence = (backend) => {
|
|
|
152
161
|
required: [[storage.subjects.id]]
|
|
153
162
|
});
|
|
154
163
|
yield* validateStorageBatch(dialect, validations);
|
|
155
|
-
const mappings = yield* makeMappings(storage);
|
|
156
164
|
const nativeTables = backend.nativeTables(database);
|
|
157
|
-
const
|
|
165
|
+
const mappings = yield* makeMappings(storage, nativeTables);
|
|
166
|
+
const sessionMapping = stateful ? mappings.sessions(auth.claims, auth.sessions.moduleId) : void 0;
|
|
158
167
|
const pendingMapping = mappings.pending(auth.claims, auth.sessions.moduleId);
|
|
159
|
-
const
|
|
160
|
-
|
|
168
|
+
const { authenticationAuthority } = yield* makeNativeAuthenticationAuthorityServices(nativeTables, sessionMapping ?? {
|
|
169
|
+
...pendingMapping,
|
|
170
|
+
pending: {
|
|
171
|
+
pending: pendingMapping.pending,
|
|
172
|
+
login: pendingMapping.login
|
|
173
|
+
}
|
|
174
|
+
});
|
|
161
175
|
const { pendingAuthentication } = yield* makeNativePendingAuthenticationServices(nativeTables, pendingMapping);
|
|
162
176
|
const { sessionStepUpPersistence } = yield* makeNativeSessionStepUpServices(nativeTables, {
|
|
163
177
|
...pendingMapping,
|
|
164
|
-
source: {
|
|
178
|
+
source: sessionMapping === void 0 ? { kind: "StatelessSigned" } : {
|
|
165
179
|
kind: "Stateful",
|
|
166
180
|
session: sessionMapping.session,
|
|
167
181
|
sessionId: sessionMapping.sessionId,
|
|
@@ -169,7 +183,11 @@ const createPersistence = (backend) => {
|
|
|
169
183
|
}
|
|
170
184
|
});
|
|
171
185
|
const { sessionCleanup } = yield* makeNativeSessionCleanupServices(nativeTables, pendingMapping);
|
|
172
|
-
let context = Context.make(AuthenticationAuthority, authenticationAuthority).pipe(Context.add(auth.sessions.
|
|
186
|
+
let context = Context.make(AuthenticationAuthority, authenticationAuthority).pipe(Context.add(auth.sessions.PendingAuthentication, pendingAuthentication), Context.add(auth.sessions.SessionStepUpPersistence, sessionStepUpPersistence), Context.add(auth.sessions.SessionCleanup, sessionCleanup));
|
|
187
|
+
if (sessionMapping !== void 0) {
|
|
188
|
+
const sessionServices = yield* makeNativeStatefulSessionServices(nativeTables, sessionMapping);
|
|
189
|
+
context = context.pipe(Context.add(auth.sessions.StatefulSessionPersistence, sessionServices.statefulSessionPersistence), Context.add(auth.sessions.SessionRepository, sessionServices.sessionRepository));
|
|
190
|
+
}
|
|
173
191
|
const proofMapping = proofs ? mappings.proofs() : void 0;
|
|
174
192
|
if (proofMapping !== void 0) {
|
|
175
193
|
const services = yield* makeNativeProofServices(backend.nativeTables(database), proofMapping);
|
|
@@ -188,23 +206,28 @@ const createPersistence = (backend) => {
|
|
|
188
206
|
context = Context.add(context, key, registration);
|
|
189
207
|
}
|
|
190
208
|
if (email) context = Context.add(context, EmailAddressPersistence, (yield* makeNativeEmailAddressServices(backend.nativeTables(database), mappings.emails(), proofMapping)).emailAddressPersistence);
|
|
191
|
-
if (phone) context = Context.add(context, PhoneSignInTargets, yield* makeComposedPhoneTargets(backend.nativeTables(database), storage, mappings.proofs(), features.flatMap((feature) => feature
|
|
209
|
+
if (phone) context = Context.add(context, PhoneSignInTargets, yield* makeComposedPhoneTargets(backend.nativeTables(database), storage, mappings.proofs(), features.flatMap((feature) => feature.kind === "phone" ? [feature.moduleId] : [])));
|
|
192
210
|
if (passkeys.length > 0) {
|
|
193
211
|
const services = makeManagedPasskeys({
|
|
194
212
|
storage,
|
|
195
213
|
namespace: auth.namespace,
|
|
196
214
|
dialect,
|
|
197
215
|
features: passkeys,
|
|
198
|
-
passwordModules: features.flatMap((feature) => feature
|
|
216
|
+
passwordModules: features.flatMap((feature) => feature.kind === "password" ? [feature.moduleId] : [])
|
|
199
217
|
}, backend.nativeTables(database));
|
|
200
218
|
context = Context.merge(context, yield* services);
|
|
201
219
|
}
|
|
220
|
+
if (oauth.length > 0) context = Context.merge(context, yield* makeManagedOAuth(storage, nativeTables, oauth));
|
|
202
221
|
return context;
|
|
203
|
-
}).pipe(Effect.provideService(SqlBatchCommit,
|
|
222
|
+
}).pipe(Effect.provideService(SqlBatchCommit, backend.batch?.(database)))).pipe(withStorageValidation)).pipe(Layer.provide(hooksLayer));
|
|
204
223
|
return {
|
|
205
224
|
Config,
|
|
206
225
|
Provisioning: ProvisioningKey,
|
|
207
226
|
layer: Layer.effectContext(Effect.gen(function* () {
|
|
227
|
+
if (!stateful && !stateless) {
|
|
228
|
+
if (auth.sessionMode === "stateless") return yield* configError("Composed stateless sessions support only OAuth strategies; use explicit persistence for other strategies");
|
|
229
|
+
return yield* configError("Composed persistence supports stateful or OAuth-only stateless sessions; state-assisted validity and other session modes require explicit persistence");
|
|
230
|
+
}
|
|
208
231
|
const scope = yield* Effect.scope;
|
|
209
232
|
const captured = yield* Effect.context();
|
|
210
233
|
const client = Context.get(captured, SqlClient.SqlClient);
|
|
@@ -214,16 +237,13 @@ const createPersistence = (backend) => {
|
|
|
214
237
|
if (yield* hasCommitScope) return yield* Effect.fail(unavailable());
|
|
215
238
|
yield* requireStandalone(unavailable, client.transactionService);
|
|
216
239
|
}
|
|
217
|
-
const acquired = yield* initialize.pipe(Effect.mapError(unavailable));
|
|
240
|
+
const acquired = yield* initialize.pipe(Effect.tapError((error) => reportAuthDiagnostic("persistence-initialization", Schema.is(PersistenceConfigurationError)(error) ? "configuration" : Schema.is(PersistenceMappingError)(error) ? "mapping" : "unavailable")), Effect.mapError(unavailable));
|
|
218
241
|
const value = Context.getOrUndefined(acquired, key);
|
|
219
242
|
return value === void 0 ? yield* Effect.fail(unavailable()) : value;
|
|
220
243
|
});
|
|
221
244
|
const sessionUnavailable = () => SessionUnavailable.make({});
|
|
222
245
|
const authority = service(AuthenticationAuthority, sessionUnavailable, false);
|
|
223
246
|
const authorityMutation = service(AuthenticationAuthority, sessionUnavailable);
|
|
224
|
-
const sessions = service(auth.sessions.StatefulSessionPersistence, sessionUnavailable, false);
|
|
225
|
-
const sessionMutations = service(auth.sessions.StatefulSessionPersistence, sessionUnavailable);
|
|
226
|
-
const repository = service(auth.sessions.SessionRepository, sessionUnavailable, false);
|
|
227
247
|
const pendingRead = service(auth.sessions.PendingAuthentication, sessionUnavailable, false);
|
|
228
248
|
const pendingMutation = service(auth.sessions.PendingAuthentication, sessionUnavailable);
|
|
229
249
|
const stepUpRead = service(auth.sessions.SessionStepUpPersistence, sessionUnavailable, false);
|
|
@@ -233,14 +253,7 @@ const createPersistence = (backend) => {
|
|
|
233
253
|
capture: (subjectId, credentialIds) => Effect.flatMap(authority, (s) => s.capture(subjectId, credentialIds)),
|
|
234
254
|
requirements: (evidence) => Effect.flatMap(authority, (s) => s.requirements(evidence)),
|
|
235
255
|
approve: (input, prepare) => Effect.flatMap(authorityMutation, (s) => s.approve(input, prepare))
|
|
236
|
-
}).pipe(Context.add(auth.sessions.
|
|
237
|
-
establish: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.establish(input, prepare)),
|
|
238
|
-
verify: (input) => Effect.flatMap(sessions, (s) => s.verify(input)),
|
|
239
|
-
rotate: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.rotate(input, prepare)),
|
|
240
|
-
revokeDigest: (digest, prepare) => Effect.flatMap(sessionMutations, (s) => s.revokeDigest(digest, prepare)),
|
|
241
|
-
revoke: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.revoke(input, prepare)),
|
|
242
|
-
revokeAll: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.revokeAll(input, prepare))
|
|
243
|
-
}), Context.add(auth.sessions.SessionRepository, { list: (input) => Effect.flatMap(repository, (s) => s.list(input)) }), Context.add(auth.sessions.PendingAuthentication, {
|
|
256
|
+
}).pipe(Context.add(auth.sessions.PendingAuthentication, {
|
|
244
257
|
create: (input, now, prepare) => Effect.flatMap(pendingMutation, (s) => s.create(input, now, prepare)),
|
|
245
258
|
read: (input) => Effect.flatMap(pendingRead, (s) => s.read(input)),
|
|
246
259
|
reject: (input, prepare) => Effect.flatMap(pendingMutation, (s) => s.reject(input, prepare))
|
|
@@ -250,6 +263,19 @@ const createPersistence = (backend) => {
|
|
|
250
263
|
reject: (input, prepare) => Effect.flatMap(stepUpMutation, (s) => s.reject(input, prepare)),
|
|
251
264
|
complete: (plan, prepare) => Effect.flatMap(stepUpMutation, (s) => s.complete(plan, prepare))
|
|
252
265
|
}), Context.add(auth.sessions.SessionCleanup, { cleanup: (input) => Effect.flatMap(cleanup, (s) => s.cleanup(input)) }));
|
|
266
|
+
if (stateful) {
|
|
267
|
+
const sessions = service(auth.sessions.StatefulSessionPersistence, sessionUnavailable, false);
|
|
268
|
+
const sessionMutations = service(auth.sessions.StatefulSessionPersistence, sessionUnavailable);
|
|
269
|
+
const repository = service(auth.sessions.SessionRepository, sessionUnavailable, false);
|
|
270
|
+
context = context.pipe(Context.add(auth.sessions.StatefulSessionPersistence, {
|
|
271
|
+
establish: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.establish(input, prepare)),
|
|
272
|
+
verify: (input) => Effect.flatMap(sessions, (s) => s.verify(input)),
|
|
273
|
+
rotate: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.rotate(input, prepare)),
|
|
274
|
+
revokeDigest: (digest, prepare) => Effect.flatMap(sessionMutations, (s) => s.revokeDigest(digest, prepare)),
|
|
275
|
+
revoke: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.revoke(input, prepare)),
|
|
276
|
+
revokeAll: (input, prepare) => Effect.flatMap(sessionMutations, (s) => s.revokeAll(input, prepare))
|
|
277
|
+
}), Context.add(auth.sessions.SessionRepository, { list: (input) => Effect.flatMap(repository, (s) => s.list(input)) }));
|
|
278
|
+
}
|
|
253
279
|
if (proofs) {
|
|
254
280
|
const persistence = service(ProofPersistence, () => ProofUnavailable.make({}));
|
|
255
281
|
context = Context.add(context, ProofPersistence, {
|
|
@@ -315,6 +341,37 @@ const createPersistence = (backend) => {
|
|
|
315
341
|
}));
|
|
316
342
|
}
|
|
317
343
|
}
|
|
344
|
+
const oauthUnavailable = () => OAuthUnavailable.make({});
|
|
345
|
+
function oauthService(key, moduleId, capability) {
|
|
346
|
+
return oauth.some((feature) => feature.moduleId === moduleId && (capability === "signIn" ? feature.signIn : feature.connected !== void 0)) ? service(key, oauthUnavailable) : Effect.fail(oauthUnavailable());
|
|
347
|
+
}
|
|
348
|
+
if (oauthSignIn) {
|
|
349
|
+
const persistence = (moduleId) => oauthService(OAuthSignInPersistence, moduleId, "signIn");
|
|
350
|
+
context = Context.add(context, OAuthSignInPersistence, {
|
|
351
|
+
issue: (input, prepare) => Effect.flatMap(persistence(input.context.moduleId), (s) => s.issue(input, prepare)),
|
|
352
|
+
consume: (input, prepare) => Effect.flatMap(persistence(input.moduleId), (s) => s.consume(input, prepare)),
|
|
353
|
+
resolve: (input) => Effect.flatMap(persistence(input.moduleId), (s) => s.resolve(input)),
|
|
354
|
+
cleanup: (input, prepare) => Effect.flatMap(persistence(input.moduleId), (s) => s.cleanup(input, prepare))
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
if (oauthConnected) {
|
|
358
|
+
const persistence = (moduleId) => oauthService(OAuthConnectedPersistence, moduleId, "connected");
|
|
359
|
+
const revocations = (moduleId) => oauthService(OAuthConnectedRevocations, moduleId, "connected");
|
|
360
|
+
context = context.pipe(Context.add(OAuthConnectedPersistence, {
|
|
361
|
+
read: (input) => Effect.flatMap(persistence(input.moduleId), (s) => s.read(input)),
|
|
362
|
+
issue: (input, prepare) => Effect.flatMap(persistence(input.context.moduleId), (s) => s.issue(input, prepare)),
|
|
363
|
+
consume: (input, prepare) => Effect.flatMap(persistence(input.moduleId), (s) => s.consume(input, prepare)),
|
|
364
|
+
settle: (input, prepare) => Effect.flatMap(persistence(input.grant.context.moduleId), (s) => s.settle(input, prepare)),
|
|
365
|
+
list: (input) => Effect.flatMap(persistence(input.authorization.moduleId), (s) => s.list(input)),
|
|
366
|
+
disconnect: (input, prepare) => Effect.flatMap(persistence(input.key.moduleId), (s) => s.disconnect(input, prepare)),
|
|
367
|
+
claimRefresh: (input, prepare) => Effect.flatMap(persistence(input.grant.context.moduleId), (s) => s.claimRefresh(input, prepare)),
|
|
368
|
+
settleRefresh: (input, prepare) => Effect.flatMap(persistence(input.claim.grant.context.moduleId), (s) => s.settleRefresh(input, prepare)),
|
|
369
|
+
cleanup: (input, prepare) => Effect.flatMap(persistence(input.moduleId), (s) => s.cleanup(input, prepare))
|
|
370
|
+
}), Context.add(OAuthConnectedRevocations, {
|
|
371
|
+
claim: (input, prepare) => Effect.flatMap(revocations(input.moduleId), (s) => s.claim(input, prepare)),
|
|
372
|
+
settle: (input, prepare) => Effect.flatMap(revocations(input.claim.job.grant.context.moduleId), (s) => s.settle(input, prepare))
|
|
373
|
+
}));
|
|
374
|
+
}
|
|
318
375
|
return context;
|
|
319
376
|
})),
|
|
320
377
|
managed: (options) => layout(options, true),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.mjs","names":[],"sources":["../../src/internal/persistence.ts"],"sourcesContent":["import { EmailAddressPersistence, EmailUnavailable } from \"@yielded/auth/Email\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { hasCommitScope } from \"@yielded/auth/Hooks\";\nimport {\n PasskeyCredentials,\n PasskeyManagementPersistence,\n PasskeyPersistence,\n PasskeyUnavailable,\n} from \"@yielded/auth/Passkey\";\nimport { PasswordPersistence, PasswordUnavailable } from \"@yielded/auth/Password\";\nimport { hooksLayer } from \"@yielded/auth/Persistence\";\nimport { PhoneSignInTargets, PhoneOtpUnavailable } from \"@yielded/auth/PhoneOtp\";\nimport { ProofPersistence, ProofUnavailable } from \"@yielded/auth/Proofs\";\nimport { AuthenticationAuthority, SessionUnavailable } from \"@yielded/auth/Sessions\";\nimport { Context, type Crypto, Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql\";\n\nimport {\n PersistenceConfigurationError,\n type ClaimsCodec,\n type ConfigId,\n type Definition,\n type PersistenceApi,\n type Ports,\n type Roles,\n type Provisioning,\n type ProvisioningRequirement,\n type StorageLayout,\n type SubjectMapping,\n type SubjectOptions,\n type PasskeyFeature,\n type PasskeyRequirement,\n} from \"./configuration\";\nimport { makeNativeEmailAddressServices } from \"./email-native\";\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport type { NativeSqlTables } from \"./native-sql-table\";\nimport { makeManagedPasskeys } from \"./passkey-managed\";\nimport { makeNativePasswordServices } from \"./password-native\";\nimport { makeComposedPhoneTargets } from \"./phone-composed\";\nimport { makeNativeProofServices } from \"./proof-native\";\nimport { makeRegistrationAuthority } from \"./registration\";\nimport type { PasswordRegistrationAuthority } from \"./registration-contract\";\nimport { makeNativeAuthenticationAuthorityServices } from \"./session-native-authority\";\nimport { makeNativeSessionCleanupServices } from \"./session-native-cleanup\";\nimport { makeNativePendingAuthenticationServices } from \"./session-native-login\";\nimport { makeNativeStatefulSessionServices } from \"./session-native-stateful\";\nimport { makeNativeSessionStepUpServices } from \"./session-native-step-up\";\nimport { SqlBatchCommit } from \"./sql-commit\";\nimport { requireStandalone } from \"./standalone\";\nimport { makeMappings } from \"./storage-mapping\";\nimport {\n tableDefinition,\n storageTables,\n type StorageRole,\n type StorageTable,\n} from \"./storage-tables\";\nimport {\n validateStorageBatch,\n withStorageValidation,\n type StorageValidation,\n} from \"./storage-validation\";\n\nexport interface Backend<T extends object, R, Database extends object = object> {\n readonly makeTable: (definition: StorageTable) => T;\n readonly describe: (table: T) => StorageTable;\n readonly acquire: Effect.Effect<Database, PersistenceConfigurationError, R | SqlClient.SqlClient>;\n readonly nativeTables: (database: Database) => NativeSqlTables;\n}\n\nconst configError = (reason: string) => PersistenceConfigurationError.make({ reason });\n\nconst mappingError = (cause: unknown) =>\n PersistenceMappingError.make({ operation: \"mapping\", cause });\n\nconst timestampKeys = new Set([\n \"verifiedAt\",\n \"createdAt\",\n \"lastIssueAt\",\n \"issuedAt\",\n \"expiresAt\",\n \"absoluteExpiresAt\",\n \"retentionUntil\",\n \"claimDeadline\",\n \"retryAt\",\n \"admittedAt\",\n \"deadline\",\n \"occurredAt\",\n \"dedupUntil\",\n]);\n\nexport const createPersistence = <T extends object, R, Database extends object = object>(\n backend: Backend<T, R, Database>,\n): PersistenceApi<T, R> => {\n const make = <C extends ClaimsCodec, const Id extends string, const A extends Definition<C, Id>>(\n auth: A & Definition<C, Id>,\n ) => {\n const features = Object.values(auth.strategies).map((strategy) => strategy.persistence);\n const phone = features.some((feature) => feature?.kind === \"phone\");\n const password = features.some((feature) => feature?.kind === \"password\");\n\n const passkeys = features.filter(\n (feature): feature is PasskeyFeature => feature?.kind === \"passkey\",\n );\n\n const management = features.some(\n (feature) => feature?.kind === \"password\" && feature.management,\n );\n\n const email = features.some((feature) => feature?.kind === \"email\" && feature.addresses);\n const proofs = phone || management || email;\n\n const roles: StorageRole[] = [\"identifiers\", \"credentials\", \"sessions\", \"pending\"];\n\n if (password) roles.push(\"passwords\");\n if (email) roles.push(\"emailCredentials\");\n if (passkeys.length > 0) roles.push(\"passkeyCredentials\", \"passkeyFlows\");\n if (proofs) roles.push(\"proofs\");\n\n const ConfigKey = Context.Service<\n ConfigId<A[\"namespace\"]>,\n StorageLayout<T, Roles<C, Id, A>>\n >()(`@yielded/auth-persistence/${auth.namespace}/Config`);\n\n const Config = Object.assign(ConfigKey, {\n layer: (value: StorageLayout<T, Roles<C, Id, A>>) => Layer.succeed(ConfigKey, value),\n });\n\n const ProvisioningKey = Context.Service<ProvisioningRequirement<A>, Provisioning<A>>()(\n `@yielded/auth-persistence/${auth.namespace}/Provisioning`,\n );\n\n const layout = <N, Instant>(\n options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<StorageRole, T>>;\n readonly prefix?: string;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n },\n managed: boolean,\n ): StorageLayout<T, Roles<C, Id, A>> => {\n const subject = options.subjects;\n\n if (passkeys.length > 0 && options.timestamps !== undefined)\n throw configError(\n \"Composed passkey storage uses integer milliseconds; use an explicit passkey adapter for a custom timestamp representation\",\n );\n const description = backend.describe(subject.table);\n const idColumn = description.columns[subject.id];\n\n for (const key of [subject.id, subject.status, subject.securityRevision]) {\n if (description.columns[key] === undefined)\n throw configError(`Missing subject column ${key}`);\n }\n if (subject.activeValue === undefined)\n throw configError(\"An explicit active subject value is required\");\n\n if (idColumn === undefined || idColumn.type === \"boolean\")\n throw configError(\"Subject ID must map a text or integer column\");\n\n const prefix = options.prefix;\n\n if (managed && (prefix === undefined || !/^[A-Za-z_][A-Za-z0-9_]{0,100}$/.test(prefix)))\n throw configError(\"Managed persistence requires an explicit SQL table prefix\");\n\n const schema: Partial<Record<StorageRole, T>> = { ...options.tables };\n\n for (const role of roles) {\n if (schema[role] === undefined && managed) {\n const definition = tableDefinition(role, `${prefix}_${role}`, idColumn.type);\n\n const adjusted =\n options.timestamps === undefined\n ? definition\n : {\n ...definition,\n columns: Object.fromEntries(\n Object.entries(definition.columns).map(([key, column]) => [\n key,\n timestampKeys.has(key)\n ? { ...column, type: options.timestamps?.type ?? column.type }\n : column,\n ]),\n ),\n };\n\n schema[role] = backend.makeTable(adjusted);\n }\n }\n for (const role of roles) {\n if (schema[role] === undefined) throw configError(`Missing ${role} table`);\n }\n const instantCodec = options.timestamps?.codec;\n\n const decodeInstant =\n instantCodec === undefined\n ? Schema.decodeUnknownEffect(Schema.Int)\n : Schema.decodeUnknownEffect(instantCodec);\n\n const decodeInstantSync =\n instantCodec === undefined\n ? Schema.decodeUnknownSync(Schema.Int)\n : Schema.decodeUnknownSync(instantCodec);\n\n const subjects: SubjectMapping = {\n table: subject.table,\n id: subject.id,\n status: subject.status,\n securityRevision: subject.securityRevision,\n activeValue: subject.activeValue,\n requirements: subject.requirements,\n actionRequirements: subject.actionRequirements ?? subject.requirements,\n toSubject: (id) =>\n Schema.decodeUnknownEffect(subject.idCodec)(id).pipe(Effect.mapError(mappingError)),\n toNative: (id) =>\n Schema.encodeEffect(subject.idCodec)(id).pipe(Effect.mapError(mappingError)),\n toSubjectSync: Schema.decodeUnknownSync(subject.idCodec),\n toNativeSync: Schema.encodeSync(subject.idCodec),\n };\n\n return Object.freeze({\n namespace: auth.namespace,\n schema: Object.freeze(schema) as Readonly<Record<Roles<C, Id, A>, T>>,\n tables: schema,\n subjects,\n encodeInstant:\n instantCodec === undefined ? (millis: number) => millis : Schema.encodeSync(instantCodec),\n decodeInstant: (value: unknown) => decodeInstant(value).pipe(Effect.mapError(mappingError)),\n decodeInstantSync,\n });\n };\n\n const services = Layer.effectContext(\n Effect.gen(function* () {\n const storage = yield* ConfigKey;\n const client = yield* SqlClient.SqlClient;\n const database = yield* backend.acquire;\n\n const dialect = client.onDialectOrElse({\n pg: () => \"pg\" as const,\n sqlite: () => \"sqlite\" as const,\n orElse: () => undefined,\n });\n\n if (dialect === undefined)\n return yield* configError(\"Use an explicit adapter for this SQL dialect\");\n if (auth.sessionMode !== \"stateful\")\n return yield* configError(\"The composed layer currently requires stateful sessions\");\n if (\n features.some(\n (feature) =>\n feature === undefined ||\n (\"lifecycle\" in feature && feature.lifecycle) ||\n (feature.kind === \"email\" && !feature.addresses),\n )\n )\n return yield* configError(\n \"Use explicit services for strategies without composed persistence support\",\n );\n if (storage.namespace !== auth.namespace)\n return yield* configError(\n \"Persistence configuration belongs to a different Auth definition\",\n );\n const validations: StorageValidation[] = [];\n\n for (const role of roles) {\n const table = (storage.schema as Partial<Record<StorageRole, T>>)[role];\n\n if (table === undefined) return yield* configError(`Missing ${role} table`);\n const description = backend.describe(table);\n const columns = description.columns;\n\n for (const name of Object.keys(storageTables[role].columns)) {\n if (columns[name] === undefined)\n return yield* configError(`Missing ${role}.${name} column`);\n }\n validations.push({ table: description, required: storageTables[role].unique });\n }\n validations.push({\n table: backend.describe(storage.subjects.table as T),\n required: [[storage.subjects.id]],\n });\n yield* validateStorageBatch(dialect, validations);\n const mappings = yield* makeMappings(storage);\n\n const nativeTables = backend.nativeTables(database);\n const sessionMapping = mappings.sessions(auth.claims, auth.sessions.moduleId);\n const pendingMapping = mappings.pending(auth.claims, auth.sessions.moduleId);\n\n const sessionServices = yield* makeNativeStatefulSessionServices(\n nativeTables,\n sessionMapping,\n );\n\n const { authenticationAuthority } = yield* makeNativeAuthenticationAuthorityServices(\n nativeTables,\n sessionMapping,\n );\n\n const { pendingAuthentication } = yield* makeNativePendingAuthenticationServices(\n nativeTables,\n pendingMapping,\n );\n\n const { sessionStepUpPersistence } = yield* makeNativeSessionStepUpServices(nativeTables, {\n ...pendingMapping,\n source: {\n kind: \"Stateful\",\n session: sessionMapping.session,\n sessionId: sessionMapping.sessionId,\n constraints: { sessionDigest: \"unique(session.digest)\" },\n },\n });\n\n const { sessionCleanup } = yield* makeNativeSessionCleanupServices(\n nativeTables,\n pendingMapping,\n );\n\n let context: Context.Context<never> = Context.make(\n AuthenticationAuthority,\n authenticationAuthority,\n ).pipe(\n Context.add(\n auth.sessions.StatefulSessionPersistence,\n sessionServices.statefulSessionPersistence,\n ),\n Context.add(auth.sessions.SessionRepository, sessionServices.sessionRepository),\n Context.add(auth.sessions.PendingAuthentication, pendingAuthentication),\n Context.add(auth.sessions.SessionStepUpPersistence, sessionStepUpPersistence),\n Context.add(auth.sessions.SessionCleanup, sessionCleanup),\n );\n\n const proofMapping = proofs ? mappings.proofs() : undefined;\n\n if (proofMapping !== undefined) {\n const services = yield* makeNativeProofServices(\n backend.nativeTables(database),\n proofMapping,\n );\n\n context = Context.add(context, ProofPersistence, services.proofPersistence);\n }\n\n if (password) {\n const mapping = mappings.passwords();\n\n const services = yield* makeNativePasswordServices(\n backend.nativeTables(database),\n mapping,\n proofMapping,\n );\n\n context = Context.add(context, PasswordPersistence, services.passwordPersistence);\n }\n for (const [name, strategy] of Object.entries(auth.strategies)) {\n if (strategy.persistence?.kind !== \"password\" || !strategy.persistence.management)\n continue;\n const key = strategy.RegistrationAuthority;\n\n if (key === undefined)\n return yield* configError(`Missing subject provisioning for ${name}`);\n\n const registration = yield* makeRegistrationAuthority(\n backend.nativeTables(database),\n mappings.passwords(),\n ProvisioningKey,\n name,\n );\n\n context = Context.add(context, key, registration);\n }\n if (email)\n context = Context.add(\n context,\n EmailAddressPersistence,\n (yield* makeNativeEmailAddressServices(\n backend.nativeTables(database),\n mappings.emails(),\n proofMapping,\n )).emailAddressPersistence,\n );\n\n if (phone)\n context = Context.add(\n context,\n PhoneSignInTargets,\n yield* makeComposedPhoneTargets(\n backend.nativeTables(database),\n storage,\n mappings.proofs(),\n features.flatMap((feature) => (feature?.kind === \"phone\" ? [feature.moduleId] : [])),\n ),\n );\n\n if (passkeys.length > 0) {\n // Auth capability metadata determines whether PasskeyConfig is required.\n const services = makeManagedPasskeys(\n {\n storage,\n namespace: auth.namespace,\n dialect,\n features: passkeys,\n passwordModules: features.flatMap((feature) =>\n feature?.kind === \"password\" ? [feature.moduleId] : [],\n ),\n },\n backend.nativeTables(database),\n ) as Effect.Effect<\n Context.Context<never>,\n PersistenceConfigurationError,\n PasskeyRequirement<A> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient\n >;\n\n context = Context.merge(context, yield* services);\n }\n\n // The checked capability metadata above determines exactly these service keys.\n return context as Context.Context<Ports<C, Id, A>>;\n }).pipe(\n Effect.provideService(SqlBatchCommit, undefined),\n withStorageValidation,\n Effect.mapError((error) =>\n Schema.is(PersistenceConfigurationError)(error)\n ? error\n : configError(\"Cannot acquire SQL persistence\"),\n ),\n ),\n ).pipe(Layer.provide(hooksLayer));\n\n const layer = Layer.effectContext(\n Effect.gen(function* () {\n const scope = yield* Effect.scope;\n const captured = yield* Effect.context<Layer.Services<typeof services>>();\n const client = Context.get(captured, SqlClient.SqlClient);\n\n // Construction uses the layer's exact environment and lifetime, never the\n // first operation's SQL transaction, service overrides, or request scope.\n // Cache the full exit: concurrent callers share failures/interruption too,\n // and cannot retry partially completed setup within this acquired layer.\n const initialize = yield* Effect.cached(\n Layer.buildWithScope(services, scope).pipe(Effect.setContext(captured)),\n );\n\n const service = Effect.fnUntraced(function* <I, S, Failure>(\n key: Context.Key<I, S>,\n unavailable: () => Failure,\n standalone = true,\n ): Effect.fn.Return<S, Failure> {\n // Reject unsupported ownership before setup can perform any writes.\n // Session/authority reads retain their existing ambient-read semantics.\n if (standalone) {\n if (yield* hasCommitScope) return yield* Effect.fail(unavailable());\n yield* requireStandalone(unavailable, client.transactionService);\n }\n const acquired = yield* initialize.pipe(Effect.mapError(unavailable));\n const value = Context.getOrUndefined(acquired, key);\n\n return value === undefined ? yield* Effect.fail(unavailable()) : value;\n });\n\n const sessionUnavailable = () => SessionUnavailable.make({});\n const authority = service(AuthenticationAuthority, sessionUnavailable, false);\n const authorityMutation = service(AuthenticationAuthority, sessionUnavailable);\n\n const sessions = service(\n auth.sessions.StatefulSessionPersistence,\n sessionUnavailable,\n false,\n );\n\n const sessionMutations = service(\n auth.sessions.StatefulSessionPersistence,\n sessionUnavailable,\n );\n\n const repository = service(auth.sessions.SessionRepository, sessionUnavailable, false);\n const pendingRead = service(auth.sessions.PendingAuthentication, sessionUnavailable, false);\n const pendingMutation = service(auth.sessions.PendingAuthentication, sessionUnavailable);\n\n const stepUpRead = service(\n auth.sessions.SessionStepUpPersistence,\n sessionUnavailable,\n false,\n );\n\n const stepUpMutation = service(auth.sessions.SessionStepUpPersistence, sessionUnavailable);\n const cleanup = service(auth.sessions.SessionCleanup, sessionUnavailable);\n\n let context: Context.Context<never> = Context.make(AuthenticationAuthority, {\n capture: (subjectId, credentialIds) =>\n Effect.flatMap(authority, (s) => s.capture(subjectId, credentialIds)),\n requirements: (evidence) => Effect.flatMap(authority, (s) => s.requirements(evidence)),\n approve: (input, prepare) =>\n Effect.flatMap(authorityMutation, (s) => s.approve(input, prepare)),\n }).pipe(\n Context.add(auth.sessions.StatefulSessionPersistence, {\n establish: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.establish(input, prepare)),\n verify: (input) => Effect.flatMap(sessions, (s) => s.verify(input)),\n rotate: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.rotate(input, prepare)),\n revokeDigest: (digest, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revokeDigest(digest, prepare)),\n revoke: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revoke(input, prepare)),\n revokeAll: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revokeAll(input, prepare)),\n }),\n Context.add(auth.sessions.SessionRepository, {\n list: (input) => Effect.flatMap(repository, (s) => s.list(input)),\n }),\n Context.add(auth.sessions.PendingAuthentication, {\n create: (input, now, prepare) =>\n Effect.flatMap(pendingMutation, (s) => s.create(input, now, prepare)),\n read: (input) => Effect.flatMap(pendingRead, (s) => s.read(input)),\n reject: (input, prepare) =>\n Effect.flatMap(pendingMutation, (s) => s.reject(input, prepare)),\n }),\n Context.add(auth.sessions.SessionStepUpPersistence, {\n create: (input, now, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.create(input, now, prepare)),\n read: (input) => Effect.flatMap(stepUpRead, (s) => s.read(input)),\n reject: (input, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.reject(input, prepare)),\n complete: (plan, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.complete(plan, prepare)),\n }),\n Context.add(auth.sessions.SessionCleanup, {\n cleanup: (input) => Effect.flatMap(cleanup, (s) => s.cleanup(input)),\n }),\n );\n\n if (proofs) {\n const persistence = service(ProofPersistence, () => ProofUnavailable.make({}));\n\n context = Context.add(context, ProofPersistence, {\n issue: (input, prepare) => Effect.flatMap(persistence, (s) => s.issue(input, prepare)),\n redeem: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.redeem(input, prepare)),\n cancel: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cancel(input, prepare)),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cleanup(input, prepare)),\n });\n }\n if (password) {\n const persistence = service(PasswordPersistence, () => PasswordUnavailable.make({}));\n\n context = Context.add(context, PasswordPersistence, {\n findCredential: (input) => Effect.flatMap(persistence, (s) => s.findCredential(input)),\n rehashIfCurrent: (input) =>\n Effect.flatMap(persistence, (s) => s.rehashIfCurrent(input)),\n readForSubject: (input) => Effect.flatMap(persistence, (s) => s.readForSubject(input)),\n recoveryTarget: (input) => Effect.flatMap(persistence, (s) => s.recoveryTarget(input)),\n addIfAbsent: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.addIfAbsent(input, prepare)),\n replaceIfCurrent: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.replaceIfCurrent(input, prepare)),\n resetWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.resetWithProof(input, prepare)),\n });\n }\n for (const [name, strategy] of Object.entries(auth.strategies)) {\n if (strategy.persistence?.kind !== \"password\" || !strategy.persistence.management)\n continue;\n const key = strategy.RegistrationAuthority;\n\n if (key === undefined)\n return yield* configError(`Missing subject provisioning for ${name}`);\n\n // The heterogeneous strategy table erases the registration input type;\n // its decoded value is forwarded unchanged to the same authority key.\n const registration = service(\n key as Context.Key<unknown, PasswordRegistrationAuthority<unknown>>,\n () => PasswordUnavailable.make({}),\n );\n\n context = Context.add(context, key, {\n register: (input, prepare) =>\n Effect.flatMap(registration, (s) => s.register(input, prepare)),\n } satisfies PasswordRegistrationAuthority<unknown>);\n }\n if (email) {\n const persistence = service(EmailAddressPersistence, () => EmailUnavailable.make({}));\n\n context = Context.add(context, EmailAddressPersistence, {\n target: (input) => Effect.flatMap(persistence, (s) => s.target(input)),\n verifyWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.verifyWithProof(input, prepare)),\n changeWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.changeWithProof(input, prepare)),\n });\n }\n if (phone) {\n const unavailable = () => PhoneOtpUnavailable.make({});\n const targets = service(PhoneSignInTargets, unavailable);\n\n context = context.pipe(\n Context.add(PhoneSignInTargets, {\n lookup: (input) => Effect.flatMap(targets, (s) => s.lookup(input)),\n }),\n );\n }\n if (passkeys.length > 0) {\n const unavailable = () => PasskeyUnavailable.make({});\n const credentials = service(PasskeyCredentials, unavailable);\n const persistence = service(PasskeyPersistence, unavailable);\n\n context = context.pipe(\n Context.add(PasskeyCredentials, {\n lookup: (input) => Effect.flatMap(credentials, (s) => s.lookup(input)),\n listForSubject: (input) =>\n Effect.flatMap(credentials, (s) => s.listForSubject(input)),\n }),\n Context.add(PasskeyPersistence, {\n issue: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.issue(input, prepare)),\n context: (input) => Effect.flatMap(persistence, (s) => s.context(input)),\n consume: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.consume(input, prepare)),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cleanup(input, prepare)),\n }),\n );\n if (passkeys.some((feature) => feature.management)) {\n const manager = service(PasskeyManagementPersistence, unavailable);\n\n context = context.pipe(\n Context.add(PasskeyManagementPersistence, {\n list: (input) => Effect.flatMap(manager, (s) => s.list(input)),\n completeEnrollment: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.completeEnrollment(input, prepare)),\n inspectRemove: (input) => Effect.flatMap(manager, (s) => s.inspectRemove(input)),\n remove: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.remove(input, prepare)),\n rename: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.rename(input, prepare)),\n }),\n );\n }\n }\n\n // Match the same capability-selected service keys as the acquired graph.\n return context as Context.Context<Ports<C, Id, A>>;\n }),\n );\n\n return {\n Config,\n Provisioning: ProvisioningKey,\n layer,\n managed: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<Roles<C, Id, A>, T>>;\n readonly prefix?: string;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n }) => layout(options, true),\n map: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables: Partial<Record<StorageRole, T>>;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n }) => layout(options, false),\n };\n };\n\n return { make };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"persistence.mjs","names":[],"sources":["../../src/internal/persistence.ts"],"sourcesContent":["import { EmailAddressPersistence, EmailUnavailable } from \"@yielded/auth/Email\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { hasCommitScope } from \"@yielded/auth/Hooks\";\nimport {\n OAuthConnectedPersistence,\n OAuthConnectedRevocations,\n OAuthSignInPersistence,\n OAuthUnavailable,\n} from \"@yielded/auth/OAuth\";\nimport {\n PasskeyCredentials,\n PasskeyManagementPersistence,\n PasskeyPersistence,\n PasskeyUnavailable,\n} from \"@yielded/auth/Passkey\";\nimport { PasswordPersistence, PasswordUnavailable } from \"@yielded/auth/Password\";\nimport { hooksLayer, reportAuthDiagnostic } from \"@yielded/auth/Persistence\";\nimport { PhoneSignInTargets, PhoneOtpUnavailable } from \"@yielded/auth/PhoneOtp\";\nimport { ProofPersistence, ProofUnavailable } from \"@yielded/auth/Proofs\";\nimport { AuthenticationAuthority, SessionUnavailable } from \"@yielded/auth/Sessions\";\nimport { Context, type Crypto, Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql\";\n\nimport {\n PersistenceConfigurationError,\n type ClaimsCodec,\n type ConfigId,\n type Definition,\n type PersistenceApi,\n type Ports,\n type Roles,\n type Provisioning,\n type ProvisioningRequirement,\n type StorageLayout,\n type SubjectMapping,\n type SubjectOptions,\n type PasskeyFeature,\n type PasskeyRequirement,\n type OAuthFeature,\n} from \"./configuration\";\nimport { makeNativeEmailAddressServices } from \"./email-native\";\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport type { NativeSqlTables } from \"./native-sql-table\";\nimport { makeManagedOAuth } from \"./oauth-managed\";\nimport { makeManagedPasskeys } from \"./passkey-managed\";\nimport { makeNativePasswordServices } from \"./password-native\";\nimport { makeComposedPhoneTargets } from \"./phone-composed\";\nimport { makeNativeProofServices } from \"./proof-native\";\nimport { makeRegistrationAuthority } from \"./registration\";\nimport type { PasswordRegistrationAuthority } from \"./registration-contract\";\nimport { makeNativeAuthenticationAuthorityServices } from \"./session-native-authority\";\nimport { makeNativeSessionCleanupServices } from \"./session-native-cleanup\";\nimport { makeNativePendingAuthenticationServices } from \"./session-native-login\";\nimport { makeNativeStatefulSessionServices } from \"./session-native-stateful\";\nimport { makeNativeSessionStepUpServices } from \"./session-native-step-up\";\nimport { SqlBatchCommit } from \"./sql-commit\";\nimport { requireStandalone } from \"./standalone\";\nimport { makeMappings } from \"./storage-mapping\";\nimport {\n tableDefinition,\n storageTables,\n type StorageRole,\n type StorageTable,\n} from \"./storage-tables\";\nimport {\n validateStorageBatch,\n withStorageValidation,\n type StorageValidation,\n} from \"./storage-validation\";\n\nexport interface Backend<T extends object, R, Database extends object = object> {\n readonly makeTable: (definition: StorageTable) => T;\n readonly describe: (table: T) => StorageTable;\n readonly acquire: Effect.Effect<Database, PersistenceConfigurationError, R | SqlClient.SqlClient>;\n readonly nativeTables: (database: Database) => NativeSqlTables;\n /** Fixed atomic batches replace interactive transactions on backends such as D1. */\n readonly batch?: (database: Database) => NonNullable<SqlBatchCommit[\"Service\"]>;\n}\n\nconst configError = (reason: string) => PersistenceConfigurationError.make({ reason });\n\nconst mappingError = (cause: unknown) =>\n PersistenceMappingError.make({ operation: \"mapping\", cause });\n\nconst timestampKeys = new Set([\n \"verifiedAt\",\n \"createdAt\",\n \"lastIssueAt\",\n \"issuedAt\",\n \"expiresAt\",\n \"absoluteExpiresAt\",\n \"retentionUntil\",\n \"claimDeadline\",\n \"retryAt\",\n \"admittedAt\",\n \"deadline\",\n \"occurredAt\",\n \"dedupUntil\",\n \"binderExpiresAt\",\n \"refreshClaimedAt\",\n \"refreshClaimExpiresAt\",\n \"claimedAt\",\n \"claimExpiresAt\",\n]);\n\nexport const createPersistence = <T extends object, R, Database extends object = object>(\n backend: Backend<T, R, Database>,\n): PersistenceApi<T, R> => {\n const make = <C extends ClaimsCodec, const Id extends string, const A extends Definition<C, Id>>(\n auth: A & Definition<C, Id>,\n ) => {\n const features = Object.values(auth.strategies).flatMap((strategy) =>\n strategy.persistence === undefined ? [] : [strategy.persistence],\n );\n\n const phone = features.some((feature) => feature.kind === \"phone\");\n const password = features.some((feature) => feature.kind === \"password\");\n\n const passkeys = features.filter(\n (feature): feature is PasskeyFeature => feature.kind === \"passkey\",\n );\n\n const oauth = features.filter((feature): feature is OAuthFeature => feature?.kind === \"oauth\");\n const oauthSignIn = oauth.some((feature) => feature.signIn);\n const oauthConnected = oauth.some((feature) => feature.connected !== undefined);\n const stateful = auth.sessionMode === \"stateful\";\n\n const stateless =\n auth.sessionMode === \"stateless\" &&\n features.length > 0 &&\n features.every((feature) => feature?.kind === \"oauth\");\n\n const management = features.some(\n (feature) => feature.kind === \"password\" && feature.management,\n );\n\n const email = features.some((feature) => feature.kind === \"email\" && feature.addresses);\n const proofs = phone || management || email;\n\n const roles: StorageRole[] = [\"identifiers\", \"credentials\"];\n\n if (stateful) roles.push(\"sessions\");\n roles.push(\"pending\");\n if (password) roles.push(\"passwords\");\n if (email) roles.push(\"emailCredentials\");\n if (passkeys.length > 0) roles.push(\"passkeyCredentials\", \"passkeyFlows\");\n if (proofs) roles.push(\"proofs\");\n if (oauth.length > 0) roles.push(\"oauthIdentities\", \"oauthCredentials\");\n if (oauthSignIn) roles.push(\"oauthSignInFlows\");\n if (oauthConnected)\n roles.push(\"oauthConnectedFlows\", \"oauthConnectedGrants\", \"oauthConnectedRevocations\");\n\n const ConfigKey = Context.Service<\n ConfigId<A[\"namespace\"]>,\n StorageLayout<T, Roles<C, Id, A>>\n >()(`@yielded/auth-persistence/${auth.namespace}/Config`);\n\n const Config = Object.assign(ConfigKey, {\n layer: (value: StorageLayout<T, Roles<C, Id, A>>) => Layer.succeed(ConfigKey, value),\n });\n\n const ProvisioningKey = Context.Service<ProvisioningRequirement<A>, Provisioning<A>>()(\n `@yielded/auth-persistence/${auth.namespace}/Provisioning`,\n );\n\n const layout = <N, Instant>(\n options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<StorageRole, T>>;\n readonly prefix?: string;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n },\n managed: boolean,\n ): StorageLayout<T, Roles<C, Id, A>> => {\n const subject = options.subjects;\n\n if (passkeys.length > 0 && options.timestamps !== undefined)\n throw configError(\n \"Composed passkey storage uses integer milliseconds; use an explicit passkey adapter for a custom timestamp representation\",\n );\n const description = backend.describe(subject.table);\n const idColumn = description.columns[subject.id];\n\n for (const key of [subject.id, subject.status, subject.securityRevision]) {\n if (description.columns[key] === undefined)\n throw configError(`Missing subject column ${key}`);\n }\n if (subject.activeValue === undefined)\n throw configError(\"An explicit active subject value is required\");\n\n if (idColumn === undefined || idColumn.type === \"boolean\")\n throw configError(\"Subject ID must map a text or integer column\");\n\n const prefix = options.prefix;\n\n if (managed && (prefix === undefined || !/^[A-Za-z_][A-Za-z0-9_]{0,100}$/.test(prefix)))\n throw configError(\"Managed persistence requires an explicit SQL table prefix\");\n\n const schema: Partial<Record<StorageRole, T>> = { ...options.tables };\n\n for (const role of roles) {\n if (schema[role] === undefined && managed) {\n const definition = tableDefinition(role, `${prefix}_${role}`, idColumn.type);\n\n const adjusted =\n options.timestamps === undefined\n ? definition\n : {\n ...definition,\n columns: Object.fromEntries(\n Object.entries(definition.columns).map(([key, column]) => [\n key,\n timestampKeys.has(key)\n ? { ...column, type: options.timestamps?.type ?? column.type }\n : column,\n ]),\n ),\n };\n\n schema[role] = backend.makeTable(adjusted);\n }\n }\n for (const role of roles) {\n if (schema[role] === undefined) throw configError(`Missing ${role} table`);\n }\n const instantCodec = options.timestamps?.codec;\n\n const decodeInstant =\n instantCodec === undefined\n ? Schema.decodeUnknownEffect(Schema.Int)\n : Schema.decodeUnknownEffect(instantCodec);\n\n const decodeInstantSync =\n instantCodec === undefined\n ? Schema.decodeUnknownSync(Schema.Int)\n : Schema.decodeUnknownSync(instantCodec);\n\n const subjects: SubjectMapping = {\n table: subject.table,\n id: subject.id,\n status: subject.status,\n securityRevision: subject.securityRevision,\n activeValue: subject.activeValue,\n requirements: subject.requirements,\n actionRequirements: subject.actionRequirements ?? subject.requirements,\n toSubject: (id) =>\n Schema.decodeUnknownEffect(subject.idCodec)(id).pipe(Effect.mapError(mappingError)),\n toNative: (id) =>\n Schema.encodeEffect(subject.idCodec)(id).pipe(Effect.mapError(mappingError)),\n toSubjectSync: Schema.decodeUnknownSync(subject.idCodec),\n toNativeSync: Schema.encodeSync(subject.idCodec),\n };\n\n return Object.freeze({\n namespace: auth.namespace,\n schema: Object.freeze(schema) as Readonly<Record<Roles<C, Id, A>, T>>,\n tables: schema,\n subjects,\n encodeInstant:\n instantCodec === undefined ? (millis: number) => millis : Schema.encodeSync(instantCodec),\n decodeInstant: (value: unknown) => decodeInstant(value).pipe(Effect.mapError(mappingError)),\n decodeInstantSync,\n });\n };\n\n const services = Layer.effectContext(\n Effect.flatMap(backend.acquire, (database) =>\n Effect.gen(function* () {\n const storage = yield* ConfigKey;\n const client = yield* SqlClient.SqlClient;\n\n const dialect = client.onDialectOrElse({\n pg: () => \"pg\" as const,\n sqlite: () => \"sqlite\" as const,\n orElse: () => undefined,\n });\n\n if (dialect === undefined)\n return yield* configError(\"Use an explicit adapter for this SQL dialect\");\n if (\n features.some(\n (feature) =>\n (\"lifecycle\" in feature && feature.lifecycle) ||\n (feature.kind === \"email\" && !feature.addresses),\n )\n )\n return yield* configError(\n \"Use explicit services for strategies without composed persistence support\",\n );\n if (storage.namespace !== auth.namespace)\n return yield* configError(\n \"Persistence configuration belongs to a different Auth definition\",\n );\n const validations: StorageValidation[] = [];\n\n for (const role of roles) {\n const table = (storage.schema as Partial<Record<StorageRole, T>>)[role];\n\n if (table === undefined) return yield* configError(`Missing ${role} table`);\n const description = backend.describe(table);\n const columns = description.columns;\n\n for (const name of Object.keys(storageTables[role].columns)) {\n if (columns[name] === undefined)\n return yield* configError(`Missing ${role}.${name} column`);\n }\n validations.push({ table: description, required: storageTables[role].unique });\n }\n validations.push({\n table: backend.describe(storage.subjects.table as T),\n required: [[storage.subjects.id]],\n });\n yield* validateStorageBatch(dialect, validations);\n const nativeTables = backend.nativeTables(database);\n const mappings = yield* makeMappings(storage, nativeTables);\n\n const sessionMapping = stateful\n ? mappings.sessions(auth.claims, auth.sessions.moduleId)\n : undefined;\n\n const pendingMapping = mappings.pending(auth.claims, auth.sessions.moduleId);\n\n const { authenticationAuthority } = yield* makeNativeAuthenticationAuthorityServices(\n nativeTables,\n sessionMapping ?? {\n ...pendingMapping,\n pending: { pending: pendingMapping.pending, login: pendingMapping.login },\n },\n );\n\n const { pendingAuthentication } = yield* makeNativePendingAuthenticationServices(\n nativeTables,\n pendingMapping,\n );\n\n const { sessionStepUpPersistence } = yield* makeNativeSessionStepUpServices(\n nativeTables,\n {\n ...pendingMapping,\n source:\n sessionMapping === undefined\n ? { kind: \"StatelessSigned\" }\n : {\n kind: \"Stateful\",\n session: sessionMapping.session,\n sessionId: sessionMapping.sessionId,\n constraints: { sessionDigest: \"unique(session.digest)\" },\n },\n },\n );\n\n const { sessionCleanup } = yield* makeNativeSessionCleanupServices(\n nativeTables,\n pendingMapping,\n );\n\n let context: Context.Context<never> = Context.make(\n AuthenticationAuthority,\n authenticationAuthority,\n ).pipe(\n Context.add(auth.sessions.PendingAuthentication, pendingAuthentication),\n Context.add(auth.sessions.SessionStepUpPersistence, sessionStepUpPersistence),\n Context.add(auth.sessions.SessionCleanup, sessionCleanup),\n );\n\n if (sessionMapping !== undefined) {\n const sessionServices = yield* makeNativeStatefulSessionServices(\n nativeTables,\n sessionMapping,\n );\n\n context = context.pipe(\n Context.add(\n auth.sessions.StatefulSessionPersistence,\n sessionServices.statefulSessionPersistence,\n ),\n Context.add(auth.sessions.SessionRepository, sessionServices.sessionRepository),\n );\n }\n\n const proofMapping = proofs ? mappings.proofs() : undefined;\n\n if (proofMapping !== undefined) {\n const services = yield* makeNativeProofServices(\n backend.nativeTables(database),\n proofMapping,\n );\n\n context = Context.add(context, ProofPersistence, services.proofPersistence);\n }\n\n if (password) {\n const mapping = mappings.passwords();\n\n const services = yield* makeNativePasswordServices(\n backend.nativeTables(database),\n mapping,\n proofMapping,\n );\n\n context = Context.add(context, PasswordPersistence, services.passwordPersistence);\n }\n for (const [name, strategy] of Object.entries(auth.strategies)) {\n if (strategy.persistence?.kind !== \"password\" || !strategy.persistence.management)\n continue;\n const key = strategy.RegistrationAuthority;\n\n if (key === undefined)\n return yield* configError(`Missing subject provisioning for ${name}`);\n\n const registration = yield* makeRegistrationAuthority(\n backend.nativeTables(database),\n mappings.passwords(),\n ProvisioningKey,\n name,\n );\n\n context = Context.add(context, key, registration);\n }\n if (email)\n context = Context.add(\n context,\n EmailAddressPersistence,\n (yield* makeNativeEmailAddressServices(\n backend.nativeTables(database),\n mappings.emails(),\n proofMapping,\n )).emailAddressPersistence,\n );\n\n if (phone)\n context = Context.add(\n context,\n PhoneSignInTargets,\n yield* makeComposedPhoneTargets(\n backend.nativeTables(database),\n storage,\n mappings.proofs(),\n features.flatMap((feature) => (feature.kind === \"phone\" ? [feature.moduleId] : [])),\n ),\n );\n\n if (passkeys.length > 0) {\n // Auth capability metadata determines whether PasskeyConfig is required.\n const services = makeManagedPasskeys(\n {\n storage,\n namespace: auth.namespace,\n dialect,\n features: passkeys,\n passwordModules: features.flatMap((feature) =>\n feature.kind === \"password\" ? [feature.moduleId] : [],\n ),\n },\n backend.nativeTables(database),\n ) as Effect.Effect<\n Context.Context<never>,\n PersistenceConfigurationError,\n | PasskeyRequirement<A>\n | Crypto.Crypto\n | LifecycleHooks\n | SqlClient.SqlClient\n | SqlBatchCommit\n >;\n\n context = Context.merge(context, yield* services);\n }\n\n if (oauth.length > 0)\n context = Context.merge(context, yield* makeManagedOAuth(storage, nativeTables, oauth));\n\n // The checked capability metadata above determines exactly these service keys.\n return context as Context.Context<Ports<C, Id, A>>;\n }).pipe(Effect.provideService(SqlBatchCommit, backend.batch?.(database))),\n ).pipe(withStorageValidation),\n ).pipe(Layer.provide(hooksLayer));\n\n const layer = Layer.effectContext(\n Effect.gen(function* () {\n if (!stateful && !stateless) {\n if (auth.sessionMode === \"stateless\")\n return yield* configError(\n \"Composed stateless sessions support only OAuth strategies; use explicit persistence for other strategies\",\n );\n\n return yield* configError(\n \"Composed persistence supports stateful or OAuth-only stateless sessions; state-assisted validity and other session modes require explicit persistence\",\n );\n }\n const scope = yield* Effect.scope;\n const captured = yield* Effect.context<Layer.Services<typeof services>>();\n const client = Context.get(captured, SqlClient.SqlClient);\n\n // Construction uses the layer's exact environment and lifetime, never the\n // first operation's SQL transaction, service overrides, or request scope.\n // Cache the full exit: concurrent callers share failures/interruption too,\n // and cannot retry partially completed setup within this acquired layer.\n const initialize = yield* Effect.cached(\n Layer.buildWithScope(services, scope).pipe(Effect.setContext(captured)),\n );\n\n const service = Effect.fnUntraced(function* <I, S, Failure>(\n key: Context.Key<I, S>,\n unavailable: () => Failure,\n standalone = true,\n ): Effect.fn.Return<S, Failure> {\n // Reject unsupported ownership before setup can perform any writes.\n // Session/authority reads retain their existing ambient-read semantics.\n if (standalone) {\n if (yield* hasCommitScope) return yield* Effect.fail(unavailable());\n yield* requireStandalone(unavailable, client.transactionService);\n }\n\n // Observe the cached failure in this invocation, not the captured setup context.\n const acquired = yield* initialize.pipe(\n Effect.tapError((error) =>\n reportAuthDiagnostic(\n \"persistence-initialization\",\n Schema.is(PersistenceConfigurationError)(error)\n ? \"configuration\"\n : Schema.is(PersistenceMappingError)(error)\n ? \"mapping\"\n : \"unavailable\",\n ),\n ),\n Effect.mapError(unavailable),\n );\n\n const value = Context.getOrUndefined(acquired, key);\n\n return value === undefined ? yield* Effect.fail(unavailable()) : value;\n });\n\n const sessionUnavailable = () => SessionUnavailable.make({});\n const authority = service(AuthenticationAuthority, sessionUnavailable, false);\n const authorityMutation = service(AuthenticationAuthority, sessionUnavailable);\n\n const pendingRead = service(auth.sessions.PendingAuthentication, sessionUnavailable, false);\n const pendingMutation = service(auth.sessions.PendingAuthentication, sessionUnavailable);\n\n const stepUpRead = service(\n auth.sessions.SessionStepUpPersistence,\n sessionUnavailable,\n false,\n );\n\n const stepUpMutation = service(auth.sessions.SessionStepUpPersistence, sessionUnavailable);\n const cleanup = service(auth.sessions.SessionCleanup, sessionUnavailable);\n\n let context: Context.Context<never> = Context.make(AuthenticationAuthority, {\n capture: (subjectId, credentialIds) =>\n Effect.flatMap(authority, (s) => s.capture(subjectId, credentialIds)),\n requirements: (evidence) => Effect.flatMap(authority, (s) => s.requirements(evidence)),\n approve: (input, prepare) =>\n Effect.flatMap(authorityMutation, (s) => s.approve(input, prepare)),\n }).pipe(\n Context.add(auth.sessions.PendingAuthentication, {\n create: (input, now, prepare) =>\n Effect.flatMap(pendingMutation, (s) => s.create(input, now, prepare)),\n read: (input) => Effect.flatMap(pendingRead, (s) => s.read(input)),\n reject: (input, prepare) =>\n Effect.flatMap(pendingMutation, (s) => s.reject(input, prepare)),\n }),\n Context.add(auth.sessions.SessionStepUpPersistence, {\n create: (input, now, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.create(input, now, prepare)),\n read: (input) => Effect.flatMap(stepUpRead, (s) => s.read(input)),\n reject: (input, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.reject(input, prepare)),\n complete: (plan, prepare) =>\n Effect.flatMap(stepUpMutation, (s) => s.complete(plan, prepare)),\n }),\n Context.add(auth.sessions.SessionCleanup, {\n cleanup: (input) => Effect.flatMap(cleanup, (s) => s.cleanup(input)),\n }),\n );\n\n if (stateful) {\n const sessions = service(\n auth.sessions.StatefulSessionPersistence,\n sessionUnavailable,\n false,\n );\n\n const sessionMutations = service(\n auth.sessions.StatefulSessionPersistence,\n sessionUnavailable,\n );\n\n const repository = service(auth.sessions.SessionRepository, sessionUnavailable, false);\n\n context = context.pipe(\n Context.add(auth.sessions.StatefulSessionPersistence, {\n establish: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.establish(input, prepare)),\n verify: (input) => Effect.flatMap(sessions, (s) => s.verify(input)),\n rotate: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.rotate(input, prepare)),\n revokeDigest: (digest, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revokeDigest(digest, prepare)),\n revoke: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revoke(input, prepare)),\n revokeAll: (input, prepare) =>\n Effect.flatMap(sessionMutations, (s) => s.revokeAll(input, prepare)),\n }),\n Context.add(auth.sessions.SessionRepository, {\n list: (input) => Effect.flatMap(repository, (s) => s.list(input)),\n }),\n );\n }\n\n if (proofs) {\n const persistence = service(ProofPersistence, () => ProofUnavailable.make({}));\n\n context = Context.add(context, ProofPersistence, {\n issue: (input, prepare) => Effect.flatMap(persistence, (s) => s.issue(input, prepare)),\n redeem: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.redeem(input, prepare)),\n cancel: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cancel(input, prepare)),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cleanup(input, prepare)),\n });\n }\n if (password) {\n const persistence = service(PasswordPersistence, () => PasswordUnavailable.make({}));\n\n context = Context.add(context, PasswordPersistence, {\n findCredential: (input) => Effect.flatMap(persistence, (s) => s.findCredential(input)),\n rehashIfCurrent: (input) =>\n Effect.flatMap(persistence, (s) => s.rehashIfCurrent(input)),\n readForSubject: (input) => Effect.flatMap(persistence, (s) => s.readForSubject(input)),\n recoveryTarget: (input) => Effect.flatMap(persistence, (s) => s.recoveryTarget(input)),\n addIfAbsent: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.addIfAbsent(input, prepare)),\n replaceIfCurrent: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.replaceIfCurrent(input, prepare)),\n resetWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.resetWithProof(input, prepare)),\n });\n }\n for (const [name, strategy] of Object.entries(auth.strategies)) {\n if (strategy.persistence?.kind !== \"password\" || !strategy.persistence.management)\n continue;\n const key = strategy.RegistrationAuthority;\n\n if (key === undefined)\n return yield* configError(`Missing subject provisioning for ${name}`);\n\n // The heterogeneous strategy table erases the registration input type;\n // its decoded value is forwarded unchanged to the same authority key.\n const registration = service(\n key as Context.Key<unknown, PasswordRegistrationAuthority<unknown>>,\n () => PasswordUnavailable.make({}),\n );\n\n context = Context.add(context, key, {\n register: (input, prepare) =>\n Effect.flatMap(registration, (s) => s.register(input, prepare)),\n } satisfies PasswordRegistrationAuthority<unknown>);\n }\n if (email) {\n const persistence = service(EmailAddressPersistence, () => EmailUnavailable.make({}));\n\n context = Context.add(context, EmailAddressPersistence, {\n target: (input) => Effect.flatMap(persistence, (s) => s.target(input)),\n verifyWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.verifyWithProof(input, prepare)),\n changeWithProof: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.changeWithProof(input, prepare)),\n });\n }\n if (phone) {\n const unavailable = () => PhoneOtpUnavailable.make({});\n const targets = service(PhoneSignInTargets, unavailable);\n\n context = context.pipe(\n Context.add(PhoneSignInTargets, {\n lookup: (input) => Effect.flatMap(targets, (s) => s.lookup(input)),\n }),\n );\n }\n if (passkeys.length > 0) {\n const unavailable = () => PasskeyUnavailable.make({});\n const credentials = service(PasskeyCredentials, unavailable);\n const persistence = service(PasskeyPersistence, unavailable);\n\n context = context.pipe(\n Context.add(PasskeyCredentials, {\n lookup: (input) => Effect.flatMap(credentials, (s) => s.lookup(input)),\n listForSubject: (input) =>\n Effect.flatMap(credentials, (s) => s.listForSubject(input)),\n }),\n Context.add(PasskeyPersistence, {\n issue: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.issue(input, prepare)),\n context: (input) => Effect.flatMap(persistence, (s) => s.context(input)),\n consume: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.consume(input, prepare)),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence, (s) => s.cleanup(input, prepare)),\n }),\n );\n if (passkeys.some((feature) => feature.management)) {\n const manager = service(PasskeyManagementPersistence, unavailable);\n\n context = context.pipe(\n Context.add(PasskeyManagementPersistence, {\n list: (input) => Effect.flatMap(manager, (s) => s.list(input)),\n completeEnrollment: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.completeEnrollment(input, prepare)),\n inspectRemove: (input) => Effect.flatMap(manager, (s) => s.inspectRemove(input)),\n remove: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.remove(input, prepare)),\n rename: (input, prepare) =>\n Effect.flatMap(manager, (s) => s.rename(input, prepare)),\n }),\n );\n }\n }\n\n const oauthUnavailable = () => OAuthUnavailable.make({});\n\n function oauthService<I, S>(\n key: Context.Key<I, S>,\n moduleId: string,\n capability: \"signIn\" | \"connected\",\n ): Effect.Effect<S, OAuthUnavailable> {\n const enabled = oauth.some(\n (feature) =>\n feature.moduleId === moduleId &&\n (capability === \"signIn\" ? feature.signIn : feature.connected !== undefined),\n );\n\n return enabled ? service(key, oauthUnavailable) : Effect.fail(oauthUnavailable());\n }\n\n if (oauthSignIn) {\n const persistence = (moduleId: string) =>\n oauthService(OAuthSignInPersistence, moduleId, \"signIn\");\n\n context = Context.add(context, OAuthSignInPersistence, {\n issue: (input, prepare) =>\n Effect.flatMap(persistence(input.context.moduleId), (s) => s.issue(input, prepare)),\n consume: (input, prepare) =>\n Effect.flatMap(persistence(input.moduleId), (s) => s.consume(input, prepare)),\n resolve: (input) =>\n Effect.flatMap(persistence(input.moduleId), (s) => s.resolve(input)),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence(input.moduleId), (s) => s.cleanup(input, prepare)),\n });\n }\n if (oauthConnected) {\n const persistence = (moduleId: string) =>\n oauthService(OAuthConnectedPersistence, moduleId, \"connected\");\n\n const revocations = (moduleId: string) =>\n oauthService(OAuthConnectedRevocations, moduleId, \"connected\");\n\n context = context.pipe(\n Context.add(OAuthConnectedPersistence, {\n read: (input) => Effect.flatMap(persistence(input.moduleId), (s) => s.read(input)),\n issue: (input, prepare) =>\n Effect.flatMap(persistence(input.context.moduleId), (s) => s.issue(input, prepare)),\n consume: (input, prepare) =>\n Effect.flatMap(persistence(input.moduleId), (s) => s.consume(input, prepare)),\n settle: (input, prepare) =>\n Effect.flatMap(persistence(input.grant.context.moduleId), (s) =>\n s.settle(input, prepare),\n ),\n list: (input) =>\n Effect.flatMap(persistence(input.authorization.moduleId), (s) => s.list(input)),\n disconnect: (input, prepare) =>\n Effect.flatMap(persistence(input.key.moduleId), (s) =>\n s.disconnect(input, prepare),\n ),\n claimRefresh: (input, prepare) =>\n Effect.flatMap(persistence(input.grant.context.moduleId), (s) =>\n s.claimRefresh(input, prepare),\n ),\n settleRefresh: (input, prepare) =>\n Effect.flatMap(persistence(input.claim.grant.context.moduleId), (s) =>\n s.settleRefresh(input, prepare),\n ),\n cleanup: (input, prepare) =>\n Effect.flatMap(persistence(input.moduleId), (s) => s.cleanup(input, prepare)),\n }),\n Context.add(OAuthConnectedRevocations, {\n claim: (input, prepare) =>\n Effect.flatMap(revocations(input.moduleId), (s) => s.claim(input, prepare)),\n settle: (input, prepare) =>\n Effect.flatMap(revocations(input.claim.job.grant.context.moduleId), (s) =>\n s.settle(input, prepare),\n ),\n }),\n );\n }\n\n // Match the same capability-selected service keys as the acquired graph.\n return context as Context.Context<Ports<C, Id, A>>;\n }),\n );\n\n return {\n Config,\n Provisioning: ProvisioningKey,\n layer,\n managed: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<Roles<C, Id, A>, T>>;\n readonly prefix?: string;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n }) => layout(options, true),\n map: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables: Partial<Record<StorageRole, T>>;\n readonly timestamps?: {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n };\n }) => layout(options, false),\n };\n };\n\n return { make };\n};\n"],"mappings":"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"}
|
|
@@ -187,7 +187,7 @@ const makeNativePhoneServices = Effect.fnUntraced(function* (tables, mapping) {
|
|
|
187
187
|
];
|
|
188
188
|
for (const originalRequirement of requirements) {
|
|
189
189
|
const requirement = yield* Schema.decodeEffect(AuthenticationRequirement)(originalRequirement);
|
|
190
|
-
if (!passwordEvidenceSatisfiedAt(evidence, requirement, captured.now)) return yield* rejected();
|
|
190
|
+
if (!(yield* passwordEvidenceSatisfiedAt(evidence, requirement, captured.now))) return yield* rejected();
|
|
191
191
|
}
|
|
192
192
|
if (evidence.proofs.length === 0) return yield* rejected();
|
|
193
193
|
for (const proof of evidence.proofs) {
|