@yielded/auth-persistence 0.1.0-beta.23 → 0.1.0-beta.25
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/email-kernel.d.mts +1 -1
- package/dist/internal/email-kernel.mjs +1 -1
- package/dist/internal/email-kernel.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 +6 -48
- 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/write-state.mjs +9 -1
- package/dist/internal/passkey/write-state.mjs.map +1 -1
- package/dist/internal/passkey-kernel.d.mts +9 -9
- 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 +5 -43
- 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/email-kernel.ts +2 -1
- 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 +2 -57
- package/src/internal/native-sql-table.ts +14 -0
- package/src/internal/oauth/accounts.ts +839 -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/passkey/write-state.ts +18 -4
- package/src/internal/password-credentials.ts +245 -0
- package/src/internal/password-kernel.ts +7 -99
- 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,427 @@
|
|
|
1
|
+
/** Direct Effect SQL persistence for upstream OAuth accounts. PostgreSQL and SQLite
|
|
2
|
+
* require interactive transactions; provider exchanges occur outside coordinators. */
|
|
3
|
+
import type { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
4
|
+
import {
|
|
5
|
+
OAuthAccountsPersistence,
|
|
6
|
+
OAuthSignInPersistence,
|
|
7
|
+
OAuthRegistrationIntents,
|
|
8
|
+
OAuthConnectedPersistence,
|
|
9
|
+
OAuthConnectedRevocations,
|
|
10
|
+
OAuthUnavailable,
|
|
11
|
+
} from "@yielded/auth/OAuth";
|
|
12
|
+
import type { AuthenticationAuthority } from "@yielded/auth/Sessions";
|
|
13
|
+
import { SessionUnavailable } from "@yielded/auth/Sessions";
|
|
14
|
+
import { type Context, type Crypto, Effect, Predicate, Schema } from "effect";
|
|
15
|
+
import { SqlClient } from "effect/sql";
|
|
16
|
+
|
|
17
|
+
import { PersistenceConfigurationError } from "./internal/configuration";
|
|
18
|
+
import type { AuthenticationAuthorityMapping as AuthorityMapping } from "./internal/models/session-model";
|
|
19
|
+
import { makeNativeSqlTables } from "./internal/native-sql-table";
|
|
20
|
+
import { makeOAuthKernel } from "./internal/oauth-kernel";
|
|
21
|
+
import type { OAuthCoordinatorError, OAuthTargetConfiguration } from "./internal/oauth/target";
|
|
22
|
+
import {
|
|
23
|
+
CurrentSessionSql,
|
|
24
|
+
makeSessionKernel,
|
|
25
|
+
type SessionSqlDatabase,
|
|
26
|
+
} from "./internal/session-kernel";
|
|
27
|
+
import type {
|
|
28
|
+
OAuthConnectedMapping,
|
|
29
|
+
OAuthConnectedRevocationMapping,
|
|
30
|
+
} from "./internal/sql-oauth-connected-model";
|
|
31
|
+
import type {
|
|
32
|
+
SqlTableModel,
|
|
33
|
+
OAuthAccountsMapping,
|
|
34
|
+
OAuthSignInMapping,
|
|
35
|
+
OAuthRegistrationIntentMapping,
|
|
36
|
+
OAuthRegistrationMapping,
|
|
37
|
+
OAuthRegistrationAuthority,
|
|
38
|
+
OAuthReferenceGuardDescriptor,
|
|
39
|
+
} from "./internal/sql-oauth-model";
|
|
40
|
+
import { makeSqlDatabase, sqlQueryOperations, sql } from "./internal/sql-query";
|
|
41
|
+
import { validateSqlStorage } from "./internal/sql-storage-validation";
|
|
42
|
+
import { Table, Fragment } from "./internal/sql-table";
|
|
43
|
+
import { requireStandalone } from "./internal/standalone";
|
|
44
|
+
import type { StorageTable } from "./internal/storage-tables";
|
|
45
|
+
import { NativeDatabase } from "./internal/transaction-kernel";
|
|
46
|
+
import type { TransactionNativeDatabase } from "./internal/transaction-kernel";
|
|
47
|
+
export * from "./internal/sql-oauth-model";
|
|
48
|
+
export * from "./internal/sql-oauth-connected-model";
|
|
49
|
+
export { sql };
|
|
50
|
+
export { and, eq } from "./internal/sql-query";
|
|
51
|
+
|
|
52
|
+
/** Physical identifiers and representations only; applications own migrations. */
|
|
53
|
+
export const table = (definition: StorageTable) =>
|
|
54
|
+
new Table(definition.name, definition.columns, definition.unique, definition.schema);
|
|
55
|
+
|
|
56
|
+
/** Integer-millisecond engine clock, sampled after locks on either supported dialect. */
|
|
57
|
+
export const clock = {
|
|
58
|
+
encodeInstant: Schema.encodeSync(Schema.Int),
|
|
59
|
+
decodeInstant: Schema.decodeUnknownSync(Schema.Int),
|
|
60
|
+
engineNowMillis: new Fragment((compiler) =>
|
|
61
|
+
compiler.dialect === "pg"
|
|
62
|
+
? "cast(extract(epoch from clock_timestamp()) * 1000 as bigint)"
|
|
63
|
+
: "cast(round((julianday('now') - 2440587.5) * 86400000) as integer)",
|
|
64
|
+
),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const operations = { ...sqlQueryOperations, validateStorage: validateSqlStorage };
|
|
68
|
+
|
|
69
|
+
const kernels = {
|
|
70
|
+
pg: makeOAuthKernel(operations, () => "pg"),
|
|
71
|
+
sqlite: makeOAuthKernel(operations, () => "sqlite"),
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const acquire = Effect.gen(function* () {
|
|
75
|
+
const client = yield* SqlClient.SqlClient;
|
|
76
|
+
|
|
77
|
+
const dialect = client.onDialectOrElse({
|
|
78
|
+
pg: () => "pg" as const,
|
|
79
|
+
sqlite: () => "sqlite" as const,
|
|
80
|
+
orElse: () => undefined,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// D1 exposes the SQLite compiler but its public driver brand identifies a
|
|
84
|
+
// batch-only client. Keep the default package free of a D1 runtime dependency.
|
|
85
|
+
if (dialect === undefined || Predicate.hasProperty(client, "~@effect/sql-d1/D1Client"))
|
|
86
|
+
return yield* PersistenceConfigurationError.make({
|
|
87
|
+
reason: "OAuth persistence requires PostgreSQL or SQLite with interactive transactions",
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const database = yield* makeSqlDatabase(dialect);
|
|
91
|
+
|
|
92
|
+
const configuration: OAuthTargetConfiguration = {
|
|
93
|
+
mode: "interactive",
|
|
94
|
+
dialect,
|
|
95
|
+
locking: dialect === "pg",
|
|
96
|
+
standaloneGuard: (service) => requireStandalone(() => OAuthUnavailable.make({}), service),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Erase only the query-builder handle; batch methods are never selected by this adapter.
|
|
100
|
+
return {
|
|
101
|
+
database: database as unknown as TransactionNativeDatabase,
|
|
102
|
+
configuration,
|
|
103
|
+
kernel: kernels[dialect],
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const using = <A, E, R>(body: (input: Effect.Success<typeof acquire>) => Effect.Effect<A, E, R>) =>
|
|
108
|
+
Effect.flatMap(acquire, (input) =>
|
|
109
|
+
body(input).pipe(Effect.provideService(NativeDatabase, input.database)),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
export const makeOAuthSignInServices = <N>(
|
|
113
|
+
mapping: OAuthSignInMapping<Table, Table, Table, Table, Table, N>,
|
|
114
|
+
): Effect.Effect<
|
|
115
|
+
{ readonly oauthSignInPersistence: OAuthSignInPersistence["Service"] },
|
|
116
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
117
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
118
|
+
> =>
|
|
119
|
+
using(({ kernel, configuration }) =>
|
|
120
|
+
kernel.target.makeTargetOAuthSignInServices(mapping, configuration),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
/** Run auth and application SQL in one adapter-owned transaction and commit journal. */
|
|
124
|
+
export const coordinateOAuthSignIn = <N, A, E, R>(
|
|
125
|
+
options: { readonly mapping: OAuthSignInMapping<Table, Table, Table, Table, Table, N> },
|
|
126
|
+
body: Effect.Effect<A, E, R>,
|
|
127
|
+
): Effect.Effect<
|
|
128
|
+
A,
|
|
129
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
130
|
+
Exclude<R, OAuthSignInPersistence> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
131
|
+
> =>
|
|
132
|
+
using(({ kernel, configuration, database }) =>
|
|
133
|
+
kernel.target.coordinateTargetOAuthSignIn(
|
|
134
|
+
database,
|
|
135
|
+
options.mapping,
|
|
136
|
+
configuration,
|
|
137
|
+
(_transaction, services) =>
|
|
138
|
+
Effect.provideService(body, OAuthSignInPersistence, services.oauthSignInPersistence),
|
|
139
|
+
),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
export const makeOAuthRegistrationIntentServices = <N>(
|
|
143
|
+
mapping: OAuthRegistrationIntentMapping<Table, Table, Table, Table, Table, Table, Table, N>,
|
|
144
|
+
): Effect.Effect<
|
|
145
|
+
{ readonly oauthRegistrationIntents: OAuthRegistrationIntents["Service"] },
|
|
146
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
147
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
148
|
+
> =>
|
|
149
|
+
using(({ kernel, configuration }) =>
|
|
150
|
+
kernel.target.makeTargetOAuthRegistrationIntentServices(mapping, configuration),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
/** Run auth and application SQL in one adapter-owned transaction and commit journal. */
|
|
154
|
+
export const coordinateOAuthRegistrationIntents = <N, A, E, R>(
|
|
155
|
+
options: {
|
|
156
|
+
readonly mapping: OAuthRegistrationIntentMapping<
|
|
157
|
+
Table,
|
|
158
|
+
Table,
|
|
159
|
+
Table,
|
|
160
|
+
Table,
|
|
161
|
+
Table,
|
|
162
|
+
Table,
|
|
163
|
+
Table,
|
|
164
|
+
N
|
|
165
|
+
>;
|
|
166
|
+
},
|
|
167
|
+
body: Effect.Effect<A, E, R>,
|
|
168
|
+
): Effect.Effect<
|
|
169
|
+
A,
|
|
170
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
171
|
+
Exclude<R, OAuthRegistrationIntents> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
172
|
+
> =>
|
|
173
|
+
using(({ kernel, configuration, database }) =>
|
|
174
|
+
kernel.target.coordinateTargetOAuthRegistrationIntents(
|
|
175
|
+
database,
|
|
176
|
+
options.mapping,
|
|
177
|
+
configuration,
|
|
178
|
+
(_transaction, services) =>
|
|
179
|
+
Effect.provideService(body, OAuthRegistrationIntents, services.oauthRegistrationIntents),
|
|
180
|
+
),
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
export const makeOAuthAccountsServices = <N>(
|
|
184
|
+
mapping: OAuthAccountsMapping<Table, Table, Table, Table, Table, Table, Table, N>,
|
|
185
|
+
): Effect.Effect<
|
|
186
|
+
{ readonly oauthAccountsPersistence: OAuthAccountsPersistence["Service"] },
|
|
187
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
188
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
189
|
+
> =>
|
|
190
|
+
using(({ kernel, configuration }) =>
|
|
191
|
+
kernel.target.makeTargetOAuthAccountsServices(mapping, configuration),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
/** Run auth and application SQL in one adapter-owned transaction and commit journal. */
|
|
195
|
+
export const coordinateOAuthAccounts = <N, A, E, R>(
|
|
196
|
+
options: {
|
|
197
|
+
readonly mapping: OAuthAccountsMapping<Table, Table, Table, Table, Table, Table, Table, N>;
|
|
198
|
+
},
|
|
199
|
+
body: Effect.Effect<A, E, R>,
|
|
200
|
+
): Effect.Effect<
|
|
201
|
+
A,
|
|
202
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
203
|
+
Exclude<R, OAuthAccountsPersistence> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
204
|
+
> =>
|
|
205
|
+
using(({ kernel, configuration, database }) =>
|
|
206
|
+
kernel.target.coordinateTargetOAuthAccounts(
|
|
207
|
+
database,
|
|
208
|
+
options.mapping,
|
|
209
|
+
configuration,
|
|
210
|
+
(_transaction, services) =>
|
|
211
|
+
Effect.provideService(body, OAuthAccountsPersistence, services.oauthAccountsPersistence),
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
export const makeOAuthConnectedServices = <N>(
|
|
216
|
+
mapping: OAuthConnectedMapping<
|
|
217
|
+
Table,
|
|
218
|
+
Table,
|
|
219
|
+
Table,
|
|
220
|
+
Table,
|
|
221
|
+
Table,
|
|
222
|
+
Table,
|
|
223
|
+
Table,
|
|
224
|
+
Table,
|
|
225
|
+
Table,
|
|
226
|
+
Table,
|
|
227
|
+
N,
|
|
228
|
+
Table
|
|
229
|
+
>,
|
|
230
|
+
): Effect.Effect<
|
|
231
|
+
{ readonly oauthConnectedPersistence: OAuthConnectedPersistence["Service"] },
|
|
232
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
233
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
234
|
+
> =>
|
|
235
|
+
using(({ kernel, configuration }) =>
|
|
236
|
+
kernel.connectedTarget.makeTargetOAuthConnectedServices(mapping, configuration),
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
/** Run auth and application SQL in one adapter-owned transaction and commit journal. */
|
|
240
|
+
export const coordinateOAuthConnected = <N, A, E, R>(
|
|
241
|
+
options: {
|
|
242
|
+
readonly mapping: OAuthConnectedMapping<
|
|
243
|
+
Table,
|
|
244
|
+
Table,
|
|
245
|
+
Table,
|
|
246
|
+
Table,
|
|
247
|
+
Table,
|
|
248
|
+
Table,
|
|
249
|
+
Table,
|
|
250
|
+
Table,
|
|
251
|
+
Table,
|
|
252
|
+
Table,
|
|
253
|
+
N,
|
|
254
|
+
Table
|
|
255
|
+
>;
|
|
256
|
+
},
|
|
257
|
+
body: Effect.Effect<A, E, R>,
|
|
258
|
+
): Effect.Effect<
|
|
259
|
+
A,
|
|
260
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
261
|
+
Exclude<R, OAuthConnectedPersistence> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
262
|
+
> =>
|
|
263
|
+
using(({ kernel, configuration, database }) =>
|
|
264
|
+
kernel.connectedTarget.coordinateTargetOAuthConnected(
|
|
265
|
+
database,
|
|
266
|
+
options.mapping,
|
|
267
|
+
configuration,
|
|
268
|
+
(_transaction, services) =>
|
|
269
|
+
Effect.provideService(body, OAuthConnectedPersistence, services.oauthConnectedPersistence),
|
|
270
|
+
),
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
export const makeOAuthConnectedRevocationServices = <N>(
|
|
274
|
+
mapping: OAuthConnectedRevocationMapping<Table, Table, Table, Table, Table, Table, Table, N>,
|
|
275
|
+
): Effect.Effect<
|
|
276
|
+
{ readonly oauthConnectedRevocations: OAuthConnectedRevocations["Service"] },
|
|
277
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
278
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
279
|
+
> =>
|
|
280
|
+
using(({ kernel, configuration }) =>
|
|
281
|
+
kernel.connectedTarget.makeTargetOAuthConnectedRevocationServices(mapping, configuration),
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
/** Run auth and application SQL in one adapter-owned transaction and commit journal. */
|
|
285
|
+
export const coordinateOAuthConnectedRevocations = <N, A, E, R>(
|
|
286
|
+
options: {
|
|
287
|
+
readonly mapping: OAuthConnectedRevocationMapping<
|
|
288
|
+
Table,
|
|
289
|
+
Table,
|
|
290
|
+
Table,
|
|
291
|
+
Table,
|
|
292
|
+
Table,
|
|
293
|
+
Table,
|
|
294
|
+
Table,
|
|
295
|
+
N
|
|
296
|
+
>;
|
|
297
|
+
},
|
|
298
|
+
body: Effect.Effect<A, E, R>,
|
|
299
|
+
): Effect.Effect<
|
|
300
|
+
A,
|
|
301
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
302
|
+
Exclude<R, OAuthConnectedRevocations> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
303
|
+
> =>
|
|
304
|
+
using(({ kernel, configuration, database }) =>
|
|
305
|
+
kernel.connectedTarget.coordinateTargetOAuthConnectedRevocations(
|
|
306
|
+
database,
|
|
307
|
+
options.mapping,
|
|
308
|
+
configuration,
|
|
309
|
+
(_transaction, services) =>
|
|
310
|
+
Effect.provideService(body, OAuthConnectedRevocations, services.oauthConnectedRevocations),
|
|
311
|
+
),
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
export const makeOAuthRegistrationServices = <Registration, N>(
|
|
315
|
+
mapping: OAuthRegistrationMapping<
|
|
316
|
+
Registration,
|
|
317
|
+
Table,
|
|
318
|
+
Table,
|
|
319
|
+
Table,
|
|
320
|
+
Table,
|
|
321
|
+
Table,
|
|
322
|
+
Table,
|
|
323
|
+
Table,
|
|
324
|
+
N
|
|
325
|
+
>,
|
|
326
|
+
): Effect.Effect<
|
|
327
|
+
{ readonly registrationAuthority: OAuthRegistrationAuthority<Registration> },
|
|
328
|
+
OAuthUnavailable | PersistenceConfigurationError,
|
|
329
|
+
Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
330
|
+
> =>
|
|
331
|
+
using(({ kernel, configuration }) =>
|
|
332
|
+
kernel.target.makeTargetOAuthRegistrationServices<Registration>(mapping, configuration),
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
export const coordinateOAuthRegistration = <Id, Registration, N, A, E, R>(
|
|
336
|
+
options: {
|
|
337
|
+
readonly mapping: OAuthRegistrationMapping<
|
|
338
|
+
NoInfer<Registration>,
|
|
339
|
+
Table,
|
|
340
|
+
Table,
|
|
341
|
+
Table,
|
|
342
|
+
Table,
|
|
343
|
+
Table,
|
|
344
|
+
Table,
|
|
345
|
+
Table,
|
|
346
|
+
N
|
|
347
|
+
>;
|
|
348
|
+
readonly target: Context.Key<Id, OAuthRegistrationAuthority<Registration>>;
|
|
349
|
+
},
|
|
350
|
+
body: Effect.Effect<A, E, R>,
|
|
351
|
+
): Effect.Effect<
|
|
352
|
+
A,
|
|
353
|
+
OAuthCoordinatorError<E> | PersistenceConfigurationError,
|
|
354
|
+
Exclude<R, Id> | Crypto.Crypto | LifecycleHooks | SqlClient.SqlClient
|
|
355
|
+
> =>
|
|
356
|
+
using(({ kernel, configuration, database }) =>
|
|
357
|
+
kernel.target.coordinateTargetOAuthRegistration<Registration, unknown, A, E, Exclude<R, Id>>(
|
|
358
|
+
database,
|
|
359
|
+
options.mapping,
|
|
360
|
+
configuration,
|
|
361
|
+
(_transaction, services) =>
|
|
362
|
+
Effect.provideService(body, options.target, services.registrationAuthority),
|
|
363
|
+
),
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
/** Include these guards when login ownership may also hold retained grants. */
|
|
367
|
+
export const oauthConnectedOwnershipReferences = <N>(
|
|
368
|
+
mapping: OAuthConnectedMapping<
|
|
369
|
+
Table,
|
|
370
|
+
Table,
|
|
371
|
+
Table,
|
|
372
|
+
Table,
|
|
373
|
+
Table,
|
|
374
|
+
Table,
|
|
375
|
+
Table,
|
|
376
|
+
Table,
|
|
377
|
+
Table,
|
|
378
|
+
Table,
|
|
379
|
+
N,
|
|
380
|
+
Table
|
|
381
|
+
>,
|
|
382
|
+
dialect: "pg" | "sqlite",
|
|
383
|
+
) =>
|
|
384
|
+
// The selected compiler supplies Fragment handles; domain values retain their codecs.
|
|
385
|
+
kernels[dialect].connectedReference.oauthConnectedOwnershipReferences(mapping) as {
|
|
386
|
+
readonly connectedReferenceGuards: ReadonlyArray<OAuthReferenceGuardDescriptor<N>>;
|
|
387
|
+
readonly connectedReference: (input: {
|
|
388
|
+
readonly identityKey: string;
|
|
389
|
+
readonly subjectId: N;
|
|
390
|
+
}) => Fragment;
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
export const {
|
|
394
|
+
oauthAccountsPersistenceLayer,
|
|
395
|
+
oauthSignInPersistenceLayer,
|
|
396
|
+
oauthRegistrationIntentsLayer,
|
|
397
|
+
oauthRegistrationAuthorityLayer,
|
|
398
|
+
} = kernels.sqlite.target;
|
|
399
|
+
|
|
400
|
+
export const { oauthConnectedPersistenceLayer, oauthConnectedRevocationsLayer } =
|
|
401
|
+
kernels.sqlite.connectedTarget;
|
|
402
|
+
|
|
403
|
+
/** Shared session issuance must validate the same subject and credential authority
|
|
404
|
+
* as OAuth. Supply this service when it is not already provided by session storage. */
|
|
405
|
+
export const makeAuthenticationAuthorityServices = <Claims, N>(
|
|
406
|
+
mapping: AuthorityMapping<Claims, SqlTableModel, SqlTableModel, SqlTableModel, SqlTableModel, N>,
|
|
407
|
+
): Effect.Effect<
|
|
408
|
+
{ readonly authenticationAuthority: AuthenticationAuthority["Service"] },
|
|
409
|
+
SessionUnavailable | PersistenceConfigurationError,
|
|
410
|
+
LifecycleHooks | SqlClient.SqlClient
|
|
411
|
+
> =>
|
|
412
|
+
using(({ database, configuration }) =>
|
|
413
|
+
makeSessionKernel(operations, (client) => makeNativeSqlTables(client))
|
|
414
|
+
.makeSqlAuthenticationAuthority(mapping, {
|
|
415
|
+
mode: "interactive",
|
|
416
|
+
locking: configuration.locking,
|
|
417
|
+
standaloneGuard: requireStandalone(
|
|
418
|
+
() => SessionUnavailable.make({}),
|
|
419
|
+
database.$client.transactionService,
|
|
420
|
+
),
|
|
421
|
+
})
|
|
422
|
+
.pipe(
|
|
423
|
+
// Both kernels capture the same raw SQL query-builder handle and client.
|
|
424
|
+
Effect.provideService(CurrentSessionSql, database as unknown as SessionSqlDatabase),
|
|
425
|
+
Effect.map((authenticationAuthority) => ({ authenticationAuthority })),
|
|
426
|
+
),
|
|
427
|
+
);
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { AuthPersistence } from "./internal/sql-persistence";
|
|
2
2
|
export { OAuthServerPersistence } from "./internal/oauth-server";
|
|
3
|
+
export { OAuthProxyPersistence } from "./internal/oauth-proxy";
|
|
3
4
|
export { BrowserLoginPersistence } from "./internal/browser-login";
|
|
4
5
|
export { PersistenceConfigurationError } from "./internal/configuration";
|
|
5
6
|
export { PersistenceMappingError } from "./internal/mapping-error";
|
|
6
7
|
export { StorageColumn, StorageTable } from "./internal/storage-tables";
|
|
8
|
+
|
|
9
|
+
export * as OAuthPersistence from "./OAuthPersistence.ts";
|
|
@@ -149,9 +149,7 @@ export type Roles<C extends ClaimsCodec, Id extends string, A extends Definition
|
|
|
149
149
|
| "credentials"
|
|
150
150
|
| "sessions"
|
|
151
151
|
| "sessionFlows"
|
|
152
|
-
| (Enabled<A, "password"> extends never
|
|
153
|
-
? never
|
|
154
|
-
: "passwords" | "passwordAttempts" | "passwordCommands")
|
|
152
|
+
| (Enabled<A, "password"> extends never ? never : "passwords" | "passwordCommands")
|
|
155
153
|
| (ManagedPassword<A> extends never ? never : "passwordRegistrations")
|
|
156
154
|
| (Enabled<A, "phone"> extends never ? never : "phoneState")
|
|
157
155
|
| (Enabled<A, "email"> extends never ? never : "emailCredentials" | "emailCommands")
|
|
@@ -809,7 +809,8 @@ export const makeEmailKernel = <
|
|
|
809
809
|
(action === "verify-address" && input.captured.source !== undefined) ||
|
|
810
810
|
(action === "change-address" && input.captured.source === undefined) ||
|
|
811
811
|
confirmsExisting !== (input.invalidation === undefined) ||
|
|
812
|
-
(input.invalidation?.existingSessions === "immediate"
|
|
812
|
+
((input.invalidation?.existingSessions === "immediate" ||
|
|
813
|
+
input.invalidation?.existingSessions === "cache-expiry") &&
|
|
813
814
|
mapping.sessionInvalidation !== "same-authority-immediate")
|
|
814
815
|
)
|
|
815
816
|
return undefined;
|