@selvajs/platform 0.16.1-beta.2 → 0.17.0
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 +25 -28
- package/dist/access/rules.d.ts +20 -26
- package/dist/access/rules.d.ts.map +1 -1
- package/dist/access/rules.js +16 -16
- package/dist/access/rules.js.map +1 -1
- package/dist/auth/interface.d.ts +99 -116
- package/dist/auth/interface.d.ts.map +1 -1
- package/dist/auth/types.d.ts +1 -4
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/bindings/interface.d.ts +19 -32
- package/dist/bindings/interface.d.ts.map +1 -1
- package/dist/bindings/interface.js +6 -12
- package/dist/bindings/interface.js.map +1 -1
- package/dist/computeServer/interface.d.ts +34 -41
- package/dist/computeServer/interface.d.ts.map +1 -1
- package/dist/computeServer/secrets.d.ts +16 -20
- package/dist/computeServer/secrets.d.ts.map +1 -1
- package/dist/computeServer/secrets.js +11 -12
- package/dist/computeServer/secrets.js.map +1 -1
- package/dist/computeServer/types.d.ts +15 -17
- package/dist/computeServer/types.d.ts.map +1 -1
- package/dist/computeServer/types.js.map +1 -1
- package/dist/computeServer/utils.d.ts +8 -14
- package/dist/computeServer/utils.d.ts.map +1 -1
- package/dist/computeServer/utils.js +8 -16
- package/dist/computeServer/utils.js.map +1 -1
- package/dist/config.d.ts +16 -39
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +12 -19
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +6 -10
- package/dist/context.js.map +1 -1
- package/dist/data/interface.d.ts +32 -47
- package/dist/data/interface.d.ts.map +1 -1
- package/dist/data/interface.js +7 -10
- package/dist/data/interface.js.map +1 -1
- package/dist/definitions/interface.d.ts +24 -31
- package/dist/definitions/interface.d.ts.map +1 -1
- package/dist/definitions/schemas.d.ts.map +1 -1
- package/dist/definitions/schemas.js +6 -9
- package/dist/definitions/schemas.js.map +1 -1
- package/dist/definitions/types.d.ts +26 -42
- package/dist/definitions/types.d.ts.map +1 -1
- package/dist/definitions/types.js +0 -1
- package/dist/definitions/types.js.map +1 -1
- package/dist/errors/interface.d.ts +4 -8
- package/dist/errors/interface.d.ts.map +1 -1
- package/dist/errors/interface.js.map +1 -1
- package/dist/errors.d.ts +2 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -5
- package/dist/errors.js.map +1 -1
- package/dist/events/audit.d.ts +13 -26
- package/dist/events/audit.d.ts.map +1 -1
- package/dist/events/interface.d.ts +17 -33
- package/dist/events/interface.d.ts.map +1 -1
- package/dist/events/interface.js +7 -22
- package/dist/events/interface.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/invites/interface.d.ts +3 -9
- package/dist/invites/interface.d.ts.map +1 -1
- package/dist/invites/types.d.ts +4 -11
- package/dist/invites/types.d.ts.map +1 -1
- package/dist/logging/interface.d.ts +19 -33
- package/dist/logging/interface.d.ts.map +1 -1
- package/dist/logging/interface.js +9 -17
- package/dist/logging/interface.js.map +1 -1
- package/dist/metrics/interface.d.ts +16 -31
- package/dist/metrics/interface.d.ts.map +1 -1
- package/dist/metrics/interface.js +1 -5
- package/dist/metrics/interface.js.map +1 -1
- package/dist/organizations/interface.d.ts +14 -23
- package/dist/organizations/interface.d.ts.map +1 -1
- package/dist/organizations/paths.d.ts +9 -12
- package/dist/organizations/paths.d.ts.map +1 -1
- package/dist/organizations/paths.js +12 -16
- package/dist/organizations/paths.js.map +1 -1
- package/dist/organizations/schemas.d.ts +10 -19
- package/dist/organizations/schemas.d.ts.map +1 -1
- package/dist/organizations/schemas.js +10 -19
- package/dist/organizations/schemas.js.map +1 -1
- package/dist/organizations/types.d.ts +3 -4
- package/dist/organizations/types.d.ts.map +1 -1
- package/dist/pagination.d.ts +13 -21
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/permissions/interface.d.ts +12 -21
- package/dist/permissions/interface.d.ts.map +1 -1
- package/dist/permissions/types.d.ts +5 -5
- package/dist/permissions/types.js +5 -5
- package/dist/platformProjects/interface.d.ts +7 -14
- package/dist/platformProjects/interface.d.ts.map +1 -1
- package/dist/platformProjects/types.d.ts +1 -4
- package/dist/platformProjects/types.d.ts.map +1 -1
- package/dist/projects/interface.d.ts +12 -17
- package/dist/projects/interface.d.ts.map +1 -1
- package/dist/shareLinks/interface.d.ts +5 -8
- package/dist/shareLinks/interface.d.ts.map +1 -1
- package/dist/shareLinks/schemas.d.ts.map +1 -1
- package/dist/shareLinks/schemas.js +1 -5
- package/dist/shareLinks/schemas.js.map +1 -1
- package/dist/shareLinks/types.d.ts +5 -6
- package/dist/shareLinks/types.d.ts.map +1 -1
- package/dist/shareLinks/types.js.map +1 -1
- package/dist/solveCache/interface.d.ts +32 -46
- package/dist/solveCache/interface.d.ts.map +1 -1
- package/dist/solveCache/interface.js.map +1 -1
- package/dist/storage/assetClasses.d.ts +16 -24
- package/dist/storage/assetClasses.d.ts.map +1 -1
- package/dist/storage/assetClasses.js +21 -28
- package/dist/storage/assetClasses.js.map +1 -1
- package/dist/storage/cacheBust.d.ts +12 -14
- package/dist/storage/cacheBust.d.ts.map +1 -1
- package/dist/storage/cacheBust.js +12 -14
- package/dist/storage/cacheBust.js.map +1 -1
- package/dist/storage/image.d.ts +9 -13
- package/dist/storage/image.d.ts.map +1 -1
- package/dist/storage/image.js +9 -13
- package/dist/storage/image.js.map +1 -1
- package/dist/userProfile/interface.d.ts +1 -1
- package/dist/userProfile/types.d.ts +1 -5
- package/dist/userProfile/types.d.ts.map +1 -1
- package/dist/userProfile/types.js.map +1 -1
- package/package.json +4 -4
package/dist/auth/interface.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ import type { ListOptions, Page } from '../pagination.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export interface IPasswordAuth {
|
|
9
9
|
/**
|
|
10
|
-
* Verify credentials.
|
|
11
|
-
* never treat truthiness as authenticated.
|
|
10
|
+
* Verify credentials. Returns a discriminated union — callers must
|
|
11
|
+
* `switch (result.kind)`, never treat truthiness as authenticated.
|
|
12
12
|
*/
|
|
13
13
|
verifyLogin(email: string, password: string): Promise<LoginResult>;
|
|
14
14
|
/**
|
|
15
|
-
* Admin-initiated user creation.
|
|
16
|
-
*
|
|
15
|
+
* Admin-initiated user creation. Grant platform permissions separately
|
|
16
|
+
* via `IPlatformPermissionStore.set`.
|
|
17
17
|
*/
|
|
18
18
|
createUserWithPassword(email: string, password: string): Promise<AuthUser>;
|
|
19
19
|
/** Self-service registration. Return null when self-registration is disabled. */
|
|
@@ -21,47 +21,43 @@ export interface IPasswordAuth {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Optional OAuth surface. Implemented by providers that broker OAuth flows
|
|
24
|
-
* (Supabase Auth, future Eterna/Auth0/etc.)
|
|
24
|
+
* (Supabase Auth, future Eterna/Auth0/etc.); local credential-only providers
|
|
25
25
|
* leave `IAuthProvider.oauth` undefined.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
27
|
+
* Standard authorization-code flow:
|
|
28
28
|
*
|
|
29
29
|
* 1. Browser hits `/auth/{provider}/start?provider=google` → server calls
|
|
30
30
|
* `getOAuthAuthorizationUrl` and 303s to the result.
|
|
31
|
-
* 2. IdP redirects back to `/auth/{provider}/callback?code=...` →
|
|
32
|
-
*
|
|
33
|
-
* 3. When the access token expires,
|
|
34
|
-
* `hooks.server.ts` calls `refreshSession`
|
|
35
|
-
*
|
|
31
|
+
* 2. IdP redirects back to `/auth/{provider}/callback?code=...` → server
|
|
32
|
+
* calls `exchangeOAuthCode` to mint the session pair.
|
|
33
|
+
* 3. When the access token expires, session-refresh middleware in
|
|
34
|
+
* `hooks.server.ts` calls `refreshSession` to swap in a fresh pair
|
|
35
|
+
* without bouncing the user.
|
|
36
36
|
*
|
|
37
|
-
* Each method returns `null`
|
|
38
|
-
* credential failures
|
|
39
|
-
*
|
|
37
|
+
* Each method returns `null` rather than throwing on irrecoverable
|
|
38
|
+
* credential failures, so the route layer can pick the right HTTP shape
|
|
39
|
+
* (401 for refresh, login redirect for callback).
|
|
40
40
|
*/
|
|
41
41
|
export interface IOAuthAuth {
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* own configuration source (env var, dashboard, hard-coded list) and
|
|
46
|
-
* decides what's available. Empty array when none are wired.
|
|
43
|
+
* OAuth providers this adapter is configured to broker, as lowercased
|
|
44
|
+
* identifiers ("google", "github", …). Empty array when none are wired.
|
|
47
45
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* `selva`.
|
|
46
|
+
* Route/UI code calls this instead of reading provider-specific env vars
|
|
47
|
+
* directly, keeping provider config out of `selva`.
|
|
51
48
|
*/
|
|
52
49
|
listProviders(): readonly string[];
|
|
53
50
|
/**
|
|
54
|
-
* Build the IdP authorization URL the browser
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
51
|
+
* Build the IdP authorization URL to redirect the browser to. `redirectTo`
|
|
52
|
+
* must be the route that handles the `?code=...` exchange. Provider-name
|
|
53
|
+
* validation is the caller's job — an unconfigured provider may surface
|
|
54
|
+
* as an upstream error.
|
|
58
55
|
*/
|
|
59
56
|
getOAuthAuthorizationUrl(provider: 'google' | 'github' | 'azure' | 'gitlab', redirectTo: string): Promise<string>;
|
|
60
57
|
/**
|
|
61
|
-
* Exchange an authorization code for a session
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* "send the user back to /login".
|
|
58
|
+
* Exchange an authorization code for a session: the resolved identity plus
|
|
59
|
+
* an access/refresh token pair, or `null` if the code is invalid, expired,
|
|
60
|
+
* or already redeemed. Callers must treat null as "send back to /login".
|
|
65
61
|
*/
|
|
66
62
|
exchangeOAuthCode(code: string): Promise<{
|
|
67
63
|
user: AuthUser;
|
|
@@ -75,8 +71,8 @@ export interface IOAuthAuth {
|
|
|
75
71
|
* clearing the refresh cookie.
|
|
76
72
|
*
|
|
77
73
|
* @deprecated Session refresh is session lifecycle, not OAuth — a consumer
|
|
78
|
-
* that brokers no OAuth still needs it (
|
|
79
|
-
*
|
|
74
|
+
* that brokers no OAuth still needs it (refreshing a password session, or
|
|
75
|
+
* revoking on logout). Moved to `IAuthProvider.sessionRefresh`
|
|
80
76
|
* (`ISessionRefresh`). This member delegates for one release and will be
|
|
81
77
|
* removed in the next minor; migrate callers to
|
|
82
78
|
* `auth.sessionRefresh?.refreshSession(...)`.
|
|
@@ -87,16 +83,14 @@ export interface IOAuthAuth {
|
|
|
87
83
|
} | null>;
|
|
88
84
|
}
|
|
89
85
|
/**
|
|
90
|
-
* Optional session-lifecycle surface: refresh an expiring session,
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* needs to revoke on logout, and would otherwise have to reach into an OAuth
|
|
95
|
-
* capability whose stated precondition it does not meet.
|
|
86
|
+
* Optional session-lifecycle surface: refresh an expiring session, revoke one
|
|
87
|
+
* server-side. Deliberately not part of `IOAuthAuth` — refresh and revoke are
|
|
88
|
+
* properties of a *session*, regardless of how it was minted. A deployment
|
|
89
|
+
* that brokers no OAuth still needs to revoke on logout.
|
|
96
90
|
*
|
|
97
|
-
* Undefined for providers that
|
|
98
|
-
* local HMAC provider mints stateless tokens
|
|
99
|
-
*
|
|
91
|
+
* Undefined for providers that can't invalidate a session server-side (the
|
|
92
|
+
* local HMAC provider mints stateless tokens — nothing to revoke). Callers
|
|
93
|
+
* must treat absence as "cookie deletion is all we can do".
|
|
100
94
|
*/
|
|
101
95
|
export interface ISessionRefresh {
|
|
102
96
|
/**
|
|
@@ -110,30 +104,30 @@ export interface ISessionRefresh {
|
|
|
110
104
|
refreshToken: string;
|
|
111
105
|
} | null>;
|
|
112
106
|
/**
|
|
113
|
-
* Invalidate a session server-side so
|
|
107
|
+
* Invalidate a session server-side so its token stops being accepted
|
|
114
108
|
* before it would naturally expire. Called on logout.
|
|
115
109
|
*
|
|
116
|
-
* `token` is the session's access token (
|
|
117
|
-
*
|
|
118
|
-
*
|
|
110
|
+
* `token` is the session's access token (what the driving layer holds in
|
|
111
|
+
* its session cookie). Adapters that revoke by refresh token accept
|
|
112
|
+
* either — the contract is "the credential the caller has".
|
|
119
113
|
*
|
|
120
114
|
* Best-effort and idempotent: revoking an already-revoked, expired, or
|
|
121
|
-
* unknown token returns `true`,
|
|
115
|
+
* unknown token returns `true`, since the desired end state (that token
|
|
122
116
|
* grants nothing) holds either way. Returns `false` only when the provider
|
|
123
|
-
*
|
|
124
|
-
* callers
|
|
125
|
-
* throws: a failed revoke
|
|
117
|
+
* couldn't carry out the revocation and the token may still be live —
|
|
118
|
+
* callers should still clear the cookie but may log the failure. Never
|
|
119
|
+
* throws: a failed revoke must not block logout.
|
|
126
120
|
*/
|
|
127
121
|
revokeSession(token: string): Promise<boolean>;
|
|
128
122
|
}
|
|
129
123
|
/**
|
|
130
124
|
* Optional passwordless email surface — "type your email, click the link in
|
|
131
125
|
* your inbox, you're in." Implemented by providers that broker email delivery
|
|
132
|
-
*
|
|
126
|
+
* and token verification (Supabase Auth, future Eterna ID, …). Adapters that
|
|
133
127
|
* can't send mail or don't model this flow leave `IAuthProvider.emailLink`
|
|
134
128
|
* undefined.
|
|
135
129
|
*
|
|
136
|
-
*
|
|
130
|
+
* Two phases, mirroring OAuth's start/callback split:
|
|
137
131
|
*
|
|
138
132
|
* 1. User submits an email → server calls `sendMagicLink(email,
|
|
139
133
|
* callbackUrl)`. The adapter delivers a link to that callback URL with
|
|
@@ -142,20 +136,19 @@ export interface ISessionRefresh {
|
|
|
142
136
|
* 2. User clicks the link, browser hits the callback route → server calls
|
|
143
137
|
* `verifyMagicLink(rawTokenFromUrl)` to mint a session.
|
|
144
138
|
*
|
|
145
|
-
* The
|
|
146
|
-
*
|
|
139
|
+
* The route layer never inspects the token — it just forwards the raw URL
|
|
140
|
+
* string. Adapter-specific token shapes stay inside the adapter.
|
|
147
141
|
*/
|
|
148
142
|
export interface IEmailLinkAuth {
|
|
149
143
|
/**
|
|
150
|
-
* Send a magic-link email. `callbackUrl` is the absolute URL the
|
|
151
|
-
*
|
|
152
|
-
*
|
|
144
|
+
* Send a magic-link email. `callbackUrl` is the absolute URL the adapter
|
|
145
|
+
* embeds in the link — must point at the route that handles
|
|
146
|
+
* `verifyMagicLink`.
|
|
153
147
|
*
|
|
154
|
-
* Returns `{ ok:
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* still throw.
|
|
148
|
+
* Returns `{ ok: false, reason }` for adapter-classified failures (rate
|
|
149
|
+
* limit, signup disabled, invalid email) so the route can render a
|
|
150
|
+
* user-friendly message without exposing provider internals. Network or
|
|
151
|
+
* unknown errors still throw.
|
|
159
152
|
*/
|
|
160
153
|
sendMagicLink(email: string, callbackUrl: string): Promise<{
|
|
161
154
|
ok: true;
|
|
@@ -164,12 +157,12 @@ export interface IEmailLinkAuth {
|
|
|
164
157
|
reason: 'rate_limited' | 'signup_disabled' | 'invalid_email';
|
|
165
158
|
}>;
|
|
166
159
|
/**
|
|
167
|
-
* Verify the token the IdP sent the user. `rawCallbackUrl` is the full
|
|
168
|
-
*
|
|
160
|
+
* Verify the token the IdP sent the user. `rawCallbackUrl` is the full URL
|
|
161
|
+
* the user landed on (or an opaque adapter-specific token string —
|
|
169
162
|
* adapters document which); the adapter pulls whatever fields it needs.
|
|
170
163
|
*
|
|
171
|
-
* Returns `null` for invalid
|
|
172
|
-
*
|
|
164
|
+
* Returns `null` for invalid, expired, or already-redeemed tokens —
|
|
165
|
+
* callers must treat null as "send back to /login". `refreshToken` is
|
|
173
166
|
* present only for adapters that issue refresh tokens for email-link
|
|
174
167
|
* sessions (Supabase does); omit otherwise.
|
|
175
168
|
*/
|
|
@@ -182,59 +175,52 @@ export interface IEmailLinkAuth {
|
|
|
182
175
|
/**
|
|
183
176
|
* Optional forward-proxy authentication surface. Implemented by providers
|
|
184
177
|
* that derive identity from signals injected by a trusted upstream reverse
|
|
185
|
-
* proxy (HTTP headers, mTLS, etc.) — e.g. Caddy `forward_auth`,
|
|
186
|
-
*
|
|
178
|
+
* proxy (HTTP headers, mTLS, etc.) — e.g. Caddy `forward_auth`, oauth2-proxy,
|
|
179
|
+
* Authelia, Pomerium, Traefik forward-auth.
|
|
187
180
|
*
|
|
188
|
-
*
|
|
181
|
+
* TRUST BOUNDARY — READ BEFORE IMPLEMENTING
|
|
189
182
|
*
|
|
190
183
|
* The signals this surface consumes are NOT verified cryptographically by
|
|
191
|
-
* Selva. They
|
|
184
|
+
* Selva. They're trusted only because the deployment runs the app behind a
|
|
192
185
|
* proxy that:
|
|
193
186
|
*
|
|
194
187
|
* 1. Authenticates the user against an upstream IdP, AND
|
|
195
|
-
* 2.
|
|
188
|
+
* 2. Strips any client-supplied copies of the trusted headers from
|
|
196
189
|
* inbound requests before adding its own, AND
|
|
197
|
-
* 3. Is the
|
|
198
|
-
* 127.0.0.1, firewall the app port, or a private socket).
|
|
190
|
+
* 3. Is the only network path that can reach the app process (bind to
|
|
191
|
+
* 127.0.0.1, firewall the app port, or use a private socket).
|
|
199
192
|
*
|
|
200
193
|
* If any condition fails, an attacker can spoof the headers and become
|
|
201
|
-
* anyone.
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* operator.
|
|
194
|
+
* anyone. Each implementer of this interface MUST ship a README stating the
|
|
195
|
+
* exact proxy configuration required — the platform layer can't verify this;
|
|
196
|
+
* it's the provider's contract with its operator.
|
|
205
197
|
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
198
|
+
* `identifyFromHeaders` is called from `hooks.server.ts` on every authed
|
|
199
|
+
* request whose session cookie is missing or invalid. It must be cheap — a
|
|
200
|
+
* header read plus at most one indexed lookup, no network calls, no
|
|
201
|
+
* unbounded disk scans.
|
|
210
202
|
*/
|
|
211
203
|
export interface IProxyAuth {
|
|
212
204
|
/**
|
|
213
|
-
* Identify the caller from trusted upstream-proxy signals on the
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
205
|
+
* Identify the caller from trusted upstream-proxy signals on the incoming
|
|
206
|
+
* request. Returns `null` for "not identified" (header missing, UPN not
|
|
207
|
+
* allowlisted, account disabled) — must not throw for absent headers,
|
|
208
|
+
* since that's the normal anonymous case.
|
|
217
209
|
*
|
|
218
210
|
* On first identification of a previously-allowlisted user, the
|
|
219
|
-
* implementation
|
|
220
|
-
*
|
|
221
|
-
*
|
|
211
|
+
* implementation may materialize stored fields (display name, email) from
|
|
212
|
+
* the same headers. Auto-creating arbitrary users from headers is
|
|
213
|
+
* forbidden: the allowlist is the security boundary.
|
|
222
214
|
*/
|
|
223
215
|
identifyFromHeaders(headers: Headers): Promise<AuthUser | null>;
|
|
224
216
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* forward-auth misconfigurations apart from real allowlist gaps without
|
|
230
|
-
* leaking the trusted header names to end users.
|
|
217
|
+
* True iff none of the identity headers this provider trusts arrived on
|
|
218
|
+
* the request. The hook layer uses this on `/login` misses to tell
|
|
219
|
+
* "proxy never reached us" apart from "proxy is here but didn't recognise
|
|
220
|
+
* the user", without leaking the trusted header names to end users.
|
|
231
221
|
*/
|
|
232
222
|
hasNoIdentityHeaders(headers: Headers): boolean;
|
|
233
|
-
/**
|
|
234
|
-
* Diagnostic helper. Returns the identity-header names this provider is
|
|
235
|
-
* configured to read. Used purely for log output — never surfaced to end
|
|
236
|
-
* users.
|
|
237
|
-
*/
|
|
223
|
+
/** Identity-header names this provider reads. Log output only, never surfaced to end users. */
|
|
238
224
|
readonly configuredHeaderNames: readonly string[];
|
|
239
225
|
}
|
|
240
226
|
/**
|
|
@@ -242,8 +228,8 @@ export interface IProxyAuth {
|
|
|
242
228
|
* in `IUserProfileStore`, platform permissions in `IPlatformPermissionStore`,
|
|
243
229
|
* password ops in optional `passwordAuth`, OAuth in optional `oauth`.
|
|
244
230
|
*
|
|
245
|
-
* Methods here
|
|
246
|
-
* identity used to
|
|
231
|
+
* Methods here don't take a `RequestContext` — the provider produces the
|
|
232
|
+
* identity used to build the context, not the other way around.
|
|
247
233
|
*/
|
|
248
234
|
export interface IAuthProvider {
|
|
249
235
|
/** Display name shown in admin UI (e.g. "Local", "Microsoft Entra ID"). */
|
|
@@ -265,38 +251,35 @@ export interface IAuthProvider {
|
|
|
265
251
|
readonly emailLink?: IEmailLinkAuth;
|
|
266
252
|
/**
|
|
267
253
|
* Present for providers that derive identity from a trusted upstream
|
|
268
|
-
* proxy (forward-auth headers, mTLS, etc.). Undefined for credential
|
|
269
|
-
*
|
|
254
|
+
* proxy (forward-auth headers, mTLS, etc.). Undefined for credential or
|
|
255
|
+
* OIDC-broker providers. See `IProxyAuth` for the trust contract.
|
|
270
256
|
*
|
|
271
|
-
* When set, the platform treats sign-out as the proxy/IdP's job and
|
|
272
|
-
*
|
|
257
|
+
* When set, the platform treats sign-out as the proxy/IdP's job and skips
|
|
258
|
+
* the logout button — Selva has no session to destroy.
|
|
273
259
|
*/
|
|
274
260
|
readonly proxyAuth?: IProxyAuth;
|
|
275
|
-
/**
|
|
276
|
-
* Verify a token (session cookie, JWT, ID token, etc.). Returns the user
|
|
277
|
-
* or null when invalid/expired.
|
|
278
|
-
*/
|
|
261
|
+
/** Verify a token (session cookie, JWT, ID token, etc.); null if invalid or expired. */
|
|
279
262
|
verifyToken(token: string): Promise<AuthUser | null>;
|
|
280
263
|
getUser(id: string): Promise<AuthUser | null>;
|
|
281
264
|
/** Returns null if the provider does not support user management. */
|
|
282
265
|
listUsers(opts?: ListOptions): Promise<Page<AuthUser> | null>;
|
|
283
266
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
267
|
+
* Allowlist a user without a password (OAuth providers). Callers grant
|
|
268
|
+
* permissions via `IPlatformPermissionStore.set`.
|
|
286
269
|
*/
|
|
287
270
|
createUser?(email: string): Promise<AuthUser>;
|
|
288
271
|
/**
|
|
289
|
-
* Delete a user identity.
|
|
290
|
-
* enforced here — callers MUST consult
|
|
272
|
+
* Delete a user identity. Callers must consult
|
|
291
273
|
* `IPlatformPermissionStore.countInstanceAdminsExcluding(id)` first and
|
|
292
|
-
* surface `'last_admin'` themselves
|
|
274
|
+
* surface `'last_admin'` themselves — the sole-`instance_admin` invariant
|
|
275
|
+
* isn't enforced here.
|
|
293
276
|
*/
|
|
294
277
|
deleteUser(id: string): Promise<UserManagementResult>;
|
|
295
278
|
/**
|
|
296
|
-
* Disable a user
|
|
279
|
+
* Disable a user, preserving identity (preferred over deletion). Same
|
|
297
280
|
* invariant rules as `deleteUser`.
|
|
298
281
|
*
|
|
299
|
-
* Existing sessions
|
|
282
|
+
* Existing sessions aren't guaranteed to stop working the instant this
|
|
300
283
|
* returns — adapters that verify tokens locally may keep accepting an
|
|
301
284
|
* already-issued access token until their next revalidation (the Supabase
|
|
302
285
|
* adapter bounds this by `revalidateMs`, default 60s). Callers needing
|
|
@@ -304,8 +287,8 @@ export interface IAuthProvider {
|
|
|
304
287
|
*/
|
|
305
288
|
disableUser(id: string): Promise<UserManagementResult>;
|
|
306
289
|
/**
|
|
307
|
-
* Stamp `lastLoginAt`. Best-effort — failure
|
|
308
|
-
*
|
|
290
|
+
* Stamp `lastLoginAt`. Best-effort — failure must not block auth. Adapters
|
|
291
|
+
* may debounce (e.g. skip if the existing timestamp is under 60s old).
|
|
309
292
|
*/
|
|
310
293
|
touchLastLogin?(id: string): Promise<void>;
|
|
311
294
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/auth/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnE;;;OAGG;IACH,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE3E,iFAAiF;IACjF,YAAY,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CACzE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,UAAU;IAC1B
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/auth/interface.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -21,10 +21,7 @@ export interface AuthUser {
|
|
|
21
21
|
* - `last_admin` — refused; would leave zero `instance_admin` users
|
|
22
22
|
*/
|
|
23
23
|
export type UserManagementResult = 'ok' | 'not_found' | 'not_supported' | 'last_admin';
|
|
24
|
-
/**
|
|
25
|
-
* - `success` — credentials valid; includes session token the provider minted.
|
|
26
|
-
* - `failed` — credentials invalid, user disabled, or rate-limited.
|
|
27
|
-
*/
|
|
24
|
+
/** `success` includes the session token the provider minted. */
|
|
28
25
|
export type LoginResult = {
|
|
29
26
|
kind: 'success';
|
|
30
27
|
user: AuthUser;
|
package/dist/auth/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,WAAW,GAAG,eAAe,GAAG,YAAY,CAAC;AAEvF
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,WAAW,GAAG,eAAe,GAAG,YAAY,CAAC;AAEvF,gEAAgE;AAChE,MAAM,MAAM,WAAW,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,UAAU,GAAG,cAAc,CAAA;CAAE,CAAC"}
|
|
@@ -3,49 +3,36 @@
|
|
|
3
3
|
* in the schema. The host (selva app or a fork) supplies an implementation;
|
|
4
4
|
* the platform stays domain-agnostic.
|
|
5
5
|
*
|
|
6
|
-
* Keys are opaque strings
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Status: preliminary. The interface is expected to refine once we wire a
|
|
11
|
-
* real binding end-to-end (see docs/upstream-binding-prep PR plan). Current
|
|
12
|
-
* shape is the minimum needed to slot a host implementation behind
|
|
13
|
-
* `SelvaConfig.bindingResolver`.
|
|
6
|
+
* Keys are opaque strings namespaced by the host (e.g. 'capture.geometry',
|
|
7
|
+
* 'parcel.boundary') and interpreted however it likes — typically as an
|
|
8
|
+
* address into the host's own domain store.
|
|
14
9
|
*/
|
|
15
10
|
import type { RequestContext } from '../context.js';
|
|
16
11
|
export interface IBindingResolver {
|
|
17
12
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - `keys` is what the schema author wrote (`source.key`) — opaque to the
|
|
21
|
-
* platform, interpreted by the resolver. The author writes keys at
|
|
22
|
-
* design time, so the key should describe WHAT attribute to read, not
|
|
23
|
-
* WHICH entity to read it from.
|
|
24
|
-
* - `scope` is set by the calling route at solve time — opaque to the
|
|
25
|
-
* platform, supplies the "which entity" anchor that varies per
|
|
26
|
-
* request (capture id, parcel id, custom struct). Optional because
|
|
27
|
-
* not every host needs it.
|
|
13
|
+
* Resolves a batch of bound keys in one call.
|
|
28
14
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
15
|
+
* `keys` is what the schema author wrote (`source.key`) — describes WHAT
|
|
16
|
+
* attribute to read, not WHICH entity. `scope` is set by the calling
|
|
17
|
+
* route at solve time and supplies the "which entity" anchor that varies
|
|
18
|
+
* per request (capture id, parcel id, custom struct); optional because
|
|
19
|
+
* not every host needs it.
|
|
33
20
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
21
|
+
* Return only the keys that resolved successfully — an absent entry
|
|
22
|
+
* signals "missing" to the caller, which then errors the solve or falls
|
|
23
|
+
* back to the input's `default`. Throw only for resolver-wide failures
|
|
24
|
+
* (DB unreachable, configuration error); a missing individual key is not
|
|
25
|
+
* an error condition.
|
|
37
26
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* with a single DB round-trip.
|
|
27
|
+
* Batched because a single solve often binds multiple inputs from one
|
|
28
|
+
* domain object, and the resolver should do that in one DB round-trip.
|
|
41
29
|
*/
|
|
42
30
|
resolve(ctx: RequestContext, keys: readonly string[], scope?: unknown): Promise<Map<string, unknown>>;
|
|
43
31
|
}
|
|
44
32
|
/**
|
|
45
|
-
* Default resolver
|
|
46
|
-
* empty map for any request,
|
|
47
|
-
*
|
|
48
|
-
* via `SelvaConfig.bindingResolver` once the host has a real implementation.
|
|
33
|
+
* Default resolver for when the host hasn't configured one. Returns an
|
|
34
|
+
* empty map for any request, so every bound input fails at solve time —
|
|
35
|
+
* a loud signal that a resolver needs wiring up.
|
|
49
36
|
*/
|
|
50
37
|
export declare class NoopBindingResolver implements IBindingResolver {
|
|
51
38
|
resolve(): Promise<Map<string, unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/bindings/interface.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/bindings/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,WAAW,gBAAgB;IAChC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CACN,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,KAAK,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;IACrD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAG9C"}
|
|
@@ -3,20 +3,14 @@
|
|
|
3
3
|
* in the schema. The host (selva app or a fork) supplies an implementation;
|
|
4
4
|
* the platform stays domain-agnostic.
|
|
5
5
|
*
|
|
6
|
-
* Keys are opaque strings
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Status: preliminary. The interface is expected to refine once we wire a
|
|
11
|
-
* real binding end-to-end (see docs/upstream-binding-prep PR plan). Current
|
|
12
|
-
* shape is the minimum needed to slot a host implementation behind
|
|
13
|
-
* `SelvaConfig.bindingResolver`.
|
|
6
|
+
* Keys are opaque strings namespaced by the host (e.g. 'capture.geometry',
|
|
7
|
+
* 'parcel.boundary') and interpreted however it likes — typically as an
|
|
8
|
+
* address into the host's own domain store.
|
|
14
9
|
*/
|
|
15
10
|
/**
|
|
16
|
-
* Default resolver
|
|
17
|
-
* empty map for any request,
|
|
18
|
-
*
|
|
19
|
-
* via `SelvaConfig.bindingResolver` once the host has a real implementation.
|
|
11
|
+
* Default resolver for when the host hasn't configured one. Returns an
|
|
12
|
+
* empty map for any request, so every bound input fails at solve time —
|
|
13
|
+
* a loud signal that a resolver needs wiring up.
|
|
20
14
|
*/
|
|
21
15
|
export class NoopBindingResolver {
|
|
22
16
|
async resolve() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/bindings/interface.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/bindings/interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA8BH;;;;GAIG;AACH,MAAM,OAAO,mBAAmB;IAC/B,KAAK,CAAC,OAAO;QACZ,OAAO,IAAI,GAAG,EAAE,CAAC;IAClB,CAAC;CACD"}
|