@run402/functions 3.1.0 → 3.2.1
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/dist/auth/errors.d.ts +13 -1
- package/dist/auth/errors.d.ts.map +1 -1
- package/dist/auth/errors.js +21 -0
- package/dist/auth/errors.js.map +1 -1
- package/dist/auth/index.d.ts +60 -8
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +287 -33
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/types.d.ts +45 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +32 -14
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/actor-context-verify.d.ts +17 -0
- package/dist/lib/actor-context-verify.d.ts.map +1 -1
- package/dist/lib/actor-context-verify.js +84 -5
- package/dist/lib/actor-context-verify.js.map +1 -1
- package/dist/runtime-context.d.ts.map +1 -1
- package/dist/runtime-context.js +43 -12
- package/dist/runtime-context.js.map +1 -1
- package/package.json +1 -1
package/dist/auth/errors.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the right thing. But framework code, middleware, and test harnesses
|
|
10
10
|
* occasionally need typed catches; that's what these classes are for.
|
|
11
11
|
*/
|
|
12
|
-
export type Run402AuthCode = "R402_AUTH_REQUIRED" | "R402_AUTH_INSUFFICIENT_ROLE" | "R402_AUTH_INSUFFICIENT_MEMBERSHIP" | "R402_AUTH_FRESHNESS_REQUIRED" | "R402_AUTH_PRERENDERED" | "R402_AUTH_FETCH_ABSOLUTE_URL" | "R402_AUTH_UNKNOWN_EXPORT" | "R402_AUTH_SESSION_BRIDGE_UNVERIFIED" | "R402_AUTH_IDENTITY_LINK_CONFLICT" | "R402_AUTH_UNKNOWN_IDENTITY" | "R402_AUTH_TENANT_SUFFIX_REQUIRED" | "R402_AUTH_RETURN_TO_INVALID" | "R402_AUTH_REDUNDANT_USER_FILTER" | "R402_AUTH_INVALID_CREDENTIALS" | "R402_AUTH_TENANT_SUBJECT_INVALID" | "R402_AUTH_UNTRUSTED_CONTEXT";
|
|
12
|
+
export type Run402AuthCode = "R402_AUTH_REQUIRED" | "R402_AUTH_INSUFFICIENT_ROLE" | "R402_AUTH_INSUFFICIENT_MEMBERSHIP" | "R402_AUTH_FRESHNESS_REQUIRED" | "R402_AUTH_PRERENDERED" | "R402_AUTH_FETCH_ABSOLUTE_URL" | "R402_AUTH_UNKNOWN_EXPORT" | "R402_AUTH_SESSION_BRIDGE_UNVERIFIED" | "R402_AUTH_IDENTITY_LINK_CONFLICT" | "R402_AUTH_UNKNOWN_IDENTITY" | "R402_AUTH_TENANT_SUFFIX_REQUIRED" | "R402_AUTH_RETURN_TO_INVALID" | "R402_AUTH_REDUNDANT_USER_FILTER" | "R402_AUTH_INVALID_CREDENTIALS" | "R402_AUTH_TENANT_SUBJECT_INVALID" | "R402_AUTH_UNTRUSTED_CONTEXT" | "R402_AUTH_RENAMED_EXPORT";
|
|
13
13
|
export declare class Run402AuthError extends Error {
|
|
14
14
|
readonly code: Run402AuthCode;
|
|
15
15
|
readonly status: number;
|
|
@@ -94,6 +94,18 @@ export declare class UnknownIdentityError extends Run402AuthError {
|
|
|
94
94
|
export declare class InvalidCredentialsError extends Run402AuthError {
|
|
95
95
|
constructor();
|
|
96
96
|
}
|
|
97
|
+
/** A shipped export that has been renamed/moved. Distinct from
|
|
98
|
+
* `UnknownExportError` (never-existed names): this one teaches the specific
|
|
99
|
+
* move for a name that used to work. Used for `auth.identities.link` →
|
|
100
|
+
* `auth.account.identities.startLink`. */
|
|
101
|
+
export declare class RenamedExportError extends Run402AuthError {
|
|
102
|
+
readonly oldName: string;
|
|
103
|
+
readonly newName: string;
|
|
104
|
+
constructor(opts: {
|
|
105
|
+
oldName: string;
|
|
106
|
+
newName: string;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
97
109
|
/** Rejects a tenant-assertion mint whose `user` lacks a stable `id` (e.g. a
|
|
98
110
|
* bare email). The `fix` shows the required `{ tenant, user: { id, email, ... },
|
|
99
111
|
* method }` shape. SDK-side fast-feedback twin of the gateway's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,cAAc,GACtB,oBAAoB,GACpB,6BAA6B,GAC7B,mCAAmC,GACnC,8BAA8B,GAC9B,uBAAuB,GACvB,8BAA8B,GAC9B,0BAA0B,GAC1B,qCAAqC,GACrC,kCAAkC,GAClC,4BAA4B,GAC5B,kCAAkC,GAClC,6BAA6B,GAC7B,iCAAiC,GACjC,+BAA+B,GAC/B,kCAAkC,GAClC,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/errors.js
CHANGED
|
@@ -185,6 +185,27 @@ export class InvalidCredentialsError extends Run402AuthError {
|
|
|
185
185
|
this.name = "InvalidCredentialsError";
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
+
/** A shipped export that has been renamed/moved. Distinct from
|
|
189
|
+
* `UnknownExportError` (never-existed names): this one teaches the specific
|
|
190
|
+
* move for a name that used to work. Used for `auth.identities.link` →
|
|
191
|
+
* `auth.account.identities.startLink`. */
|
|
192
|
+
export class RenamedExportError extends Run402AuthError {
|
|
193
|
+
oldName;
|
|
194
|
+
newName;
|
|
195
|
+
constructor(opts) {
|
|
196
|
+
super({
|
|
197
|
+
code: "R402_AUTH_RENAMED_EXPORT",
|
|
198
|
+
status: 400,
|
|
199
|
+
message: `${opts.oldName} has moved to ${opts.newName}.`,
|
|
200
|
+
details: { old_name: opts.oldName, new_name: opts.newName },
|
|
201
|
+
suggestedFix: `Use: ${opts.newName}`,
|
|
202
|
+
docs: "https://run402.com/errors/#R402_AUTH_RENAMED_EXPORT",
|
|
203
|
+
});
|
|
204
|
+
this.name = "RenamedExportError";
|
|
205
|
+
this.oldName = opts.oldName;
|
|
206
|
+
this.newName = opts.newName;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
188
209
|
/** Rejects a tenant-assertion mint whose `user` lacks a stable `id` (e.g. a
|
|
189
210
|
* bare email). The `fix` shows the required `{ tenant, user: { id, email, ... },
|
|
190
211
|
* method }` shape. SDK-side fast-feedback twin of the gateway's
|
package/dist/auth/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -29,18 +29,26 @@
|
|
|
29
29
|
* - HTML-vs-JSON failure decisions are made by the gateway middleware
|
|
30
30
|
* (303 redirect for HTML, 401/403 envelope for JSON). The SDK throws
|
|
31
31
|
* a typed Error subclass; framework code OR the gateway translates.
|
|
32
|
-
* - `requireRole`
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
* - `requireRole` reads the gate-resolved role from the routed-function
|
|
33
|
+
* envelope header (`x-run402-user-role`) that the gateway's
|
|
34
|
+
* `function-role-gates` middleware sets after resolving the caller
|
|
35
|
+
* against the project's OWN role table — the one named in that
|
|
36
|
+
* function's deploy-spec `requireRole` gate. It therefore REQUIRES the
|
|
37
|
+
* deploy-spec gate: with no gate declared the header is absent and
|
|
38
|
+
* `requireRole` throws (fail-closed, indistinguishable from a real
|
|
39
|
+
* role mismatch). The gateway role lookup is TTL-cached (default 60s;
|
|
40
|
+
* set the gate's `cacheTtl: 0` for a fresh read per request), so
|
|
41
|
+
* revocation lag is bounded by that TTL — it is NOT instant.
|
|
42
|
+
* - `requireMembership` reads `x-run402-user-membership` symmetrically,
|
|
43
|
+
* but the gateway producer for that header is not shipped yet, so it
|
|
44
|
+
* currently always throws. Forward API surface only.
|
|
37
45
|
* - `requireFresh` consults the per-method `amr_times` on the Actor —
|
|
38
46
|
* a recent password proof does NOT satisfy `{amr: ["passkey"]}`.
|
|
39
47
|
*
|
|
40
48
|
* @see openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md
|
|
41
49
|
*/
|
|
42
50
|
import { InvalidCredentialsError } from "./errors.js";
|
|
43
|
-
import type { Actor, CreateResponseFromIdentityOptions, CreateResponseFromTenantAssertionOptions, IdentityLinkOptions } from "./types.js";
|
|
51
|
+
import type { AccountSecurity, Actor, CreateResponseFromIdentityOptions, CreateResponseFromTenantAssertionOptions, IdentityLinkOptions } from "./types.js";
|
|
44
52
|
interface RequireFreshOptions {
|
|
45
53
|
/** Human-friendly window expression. Accepted forms: `"10m"`, `"1h"`,
|
|
46
54
|
* `"5m30s"`, integer seconds (`"600"`). Anything that fails to parse
|
|
@@ -76,6 +84,50 @@ interface AuthNamespace {
|
|
|
76
84
|
/** Canonical invalid-credentials failure for the tenant-owned credential
|
|
77
85
|
* case. A function (not a constructor): `throw auth.invalidCredentials()`. */
|
|
78
86
|
invalidCredentials(): InvalidCredentialsError;
|
|
87
|
+
/** Account security (§4). `getSecurity`/`requireSecurity` are the everyday
|
|
88
|
+
* rich read; the §4.4 advanced mutation tier (callee-enforced freshness,
|
|
89
|
+
* context-actor only) backs the same flows as `<AccountSecurity>`. */
|
|
90
|
+
account: {
|
|
91
|
+
getSecurity(): Promise<AccountSecurity | null>;
|
|
92
|
+
requireSecurity(): Promise<AccountSecurity>;
|
|
93
|
+
setPassword(newPassword: string, opts?: {
|
|
94
|
+
maxAge?: string;
|
|
95
|
+
}): Promise<void>;
|
|
96
|
+
signOutEverywhere(): Promise<{
|
|
97
|
+
revoked_count: number;
|
|
98
|
+
}>;
|
|
99
|
+
passkeys: {
|
|
100
|
+
list(): Promise<unknown[]>;
|
|
101
|
+
remove(passkeyId: string): Promise<void>;
|
|
102
|
+
add(): never;
|
|
103
|
+
};
|
|
104
|
+
identities: {
|
|
105
|
+
list(): Promise<unknown[]>;
|
|
106
|
+
/** §4.5 — begin the OAuth link-to-existing-account ceremony for the
|
|
107
|
+
* context actor. Mints a short-lived actor JWT and asks the gateway
|
|
108
|
+
* (`intent:"link"`) for a provider authorization URL bound to the
|
|
109
|
+
* signed-in user; the caller redirects the browser there. After the
|
|
110
|
+
* provider round-trip the identity is written against THIS account
|
|
111
|
+
* (not a new sign-in). `redirectUrl` must be an allowed origin for the
|
|
112
|
+
* project. This is link-to-existing — distinct from sign-in-with. */
|
|
113
|
+
startLink(opts: {
|
|
114
|
+
provider: string;
|
|
115
|
+
redirectUrl: string;
|
|
116
|
+
mode?: "redirect" | "popup";
|
|
117
|
+
}): Promise<{
|
|
118
|
+
authorizationUrl: string;
|
|
119
|
+
expiresIn: number;
|
|
120
|
+
}>;
|
|
121
|
+
unlink(opts: {
|
|
122
|
+
provider: string;
|
|
123
|
+
subject: string;
|
|
124
|
+
}): Promise<void>;
|
|
125
|
+
};
|
|
126
|
+
sessions: {
|
|
127
|
+
list(): Promise<unknown[]>;
|
|
128
|
+
revoke(sessionId: string): Promise<void>;
|
|
129
|
+
};
|
|
130
|
+
};
|
|
79
131
|
identities: {
|
|
80
132
|
link(opts: IdentityLinkOptions): Promise<void>;
|
|
81
133
|
};
|
|
@@ -107,6 +159,6 @@ export declare function currentUser(): never;
|
|
|
107
159
|
export declare function getCurrentUser(): never;
|
|
108
160
|
/** @deprecated Use `auth.user()`. */
|
|
109
161
|
export declare function getServerSession(): never;
|
|
110
|
-
export type { Actor, IdentityProof, TenantUser, CreateResponseFromTenantAssertionOptions, } from "./types.js";
|
|
111
|
-
export { AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, InvalidCredentialsError, TenantSubjectInvalidError, Run402AuthError, } from "./errors.js";
|
|
162
|
+
export type { Actor, IdentityProof, TenantUser, CreateResponseFromTenantAssertionOptions, AccountSecurity, Run402Identity, TenantAssertionRef, } from "./types.js";
|
|
163
|
+
export { AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, InvalidCredentialsError, TenantSubjectInvalidError, RenamedExportError, Run402AuthError, } from "./errors.js";
|
|
112
164
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.js
CHANGED
|
@@ -29,11 +29,19 @@
|
|
|
29
29
|
* - HTML-vs-JSON failure decisions are made by the gateway middleware
|
|
30
30
|
* (303 redirect for HTML, 401/403 envelope for JSON). The SDK throws
|
|
31
31
|
* a typed Error subclass; framework code OR the gateway translates.
|
|
32
|
-
* - `requireRole`
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
* - `requireRole` reads the gate-resolved role from the routed-function
|
|
33
|
+
* envelope header (`x-run402-user-role`) that the gateway's
|
|
34
|
+
* `function-role-gates` middleware sets after resolving the caller
|
|
35
|
+
* against the project's OWN role table — the one named in that
|
|
36
|
+
* function's deploy-spec `requireRole` gate. It therefore REQUIRES the
|
|
37
|
+
* deploy-spec gate: with no gate declared the header is absent and
|
|
38
|
+
* `requireRole` throws (fail-closed, indistinguishable from a real
|
|
39
|
+
* role mismatch). The gateway role lookup is TTL-cached (default 60s;
|
|
40
|
+
* set the gate's `cacheTtl: 0` for a fresh read per request), so
|
|
41
|
+
* revocation lag is bounded by that TTL — it is NOT instant.
|
|
42
|
+
* - `requireMembership` reads `x-run402-user-membership` symmetrically,
|
|
43
|
+
* but the gateway producer for that header is not shipped yet, so it
|
|
44
|
+
* currently always throws. Forward API surface only.
|
|
37
45
|
* - `requireFresh` consults the per-method `amr_times` on the Actor —
|
|
38
46
|
* a recent password proof does NOT satisfy `{amr: ["passkey"]}`.
|
|
39
47
|
*
|
|
@@ -42,7 +50,7 @@
|
|
|
42
50
|
import { getCurrentContext, requireActiveContext, taintCacheBypass, } from "../runtime-context.js";
|
|
43
51
|
import { config } from "../config.js";
|
|
44
52
|
import jwt from "../lib/jwt.js";
|
|
45
|
-
import { AuthRequiredError, FetchAbsoluteUrlError, FreshnessRequiredError, InsufficientMembershipError, InsufficientRoleError, InvalidCredentialsError, TenantSubjectInvalidError, UnknownExportError, } from "./errors.js";
|
|
53
|
+
import { AuthRequiredError, FetchAbsoluteUrlError, FreshnessRequiredError, InsufficientMembershipError, InsufficientRoleError, InvalidCredentialsError, RenamedExportError, TenantSubjectInvalidError, UnknownExportError, } from "./errors.js";
|
|
46
54
|
import { validateAuthFetchInput } from "./url-validation.js";
|
|
47
55
|
import crypto from "node:crypto";
|
|
48
56
|
// ---------------------------------------------------------------------------
|
|
@@ -144,10 +152,13 @@ async function requireUser() {
|
|
|
144
152
|
}
|
|
145
153
|
async function requireRole(role) {
|
|
146
154
|
const actor = await requireUser();
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
//
|
|
155
|
+
// Read the gate-resolved role from the routed-function envelope header the
|
|
156
|
+
// gateway's `function-role-gates` middleware (gateway middleware/role-gate.ts)
|
|
157
|
+
// sets after resolving the caller against the project's OWN role table.
|
|
158
|
+
// This header is present ONLY when the function declares a `requireRole`
|
|
159
|
+
// deploy-spec gate; without it `headerRole` is undefined and we throw below
|
|
160
|
+
// (fail-closed). There is no `internal.role_grants` table — the role lives
|
|
161
|
+
// in the tenant's own schema, named by the gate spec.
|
|
151
162
|
const ctx = requireActiveContext("auth.requireRole");
|
|
152
163
|
const headerRole = readHeader(ctx.request.headers, "x-run402-user-role");
|
|
153
164
|
if (headerRole === role) {
|
|
@@ -161,9 +172,10 @@ function readHeader(headers, name) {
|
|
|
161
172
|
}
|
|
162
173
|
async function requireMembership(membership) {
|
|
163
174
|
const actor = await requireUser();
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
175
|
+
// Symmetric to requireRole, reading `x-run402-user-membership`. NOTE: the
|
|
176
|
+
// gateway producer for this header is not shipped yet, so the header is
|
|
177
|
+
// always absent and this helper always throws today. Forward API surface;
|
|
178
|
+
// don't build on it until the membership gate lands.
|
|
167
179
|
const ctx = requireActiveContext("auth.requireMembership");
|
|
168
180
|
const headerMembership = readHeader(ctx.request.headers, "x-run402-user-membership");
|
|
169
181
|
if (headerMembership === membership) {
|
|
@@ -415,31 +427,272 @@ async function endResponse() {
|
|
|
415
427
|
// ---------------------------------------------------------------------------
|
|
416
428
|
// Identity linking.
|
|
417
429
|
// ---------------------------------------------------------------------------
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
430
|
+
/** §4.5: the shipped top-level `auth.identities.link` is renamed/moved to
|
|
431
|
+
* `auth.account.identities.startLink` (the redirect+proof ceremony that links
|
|
432
|
+
* an OAuth identity to the already-signed-in account). Throws
|
|
433
|
+
* `R402_AUTH_RENAMED_EXPORT` teaching the move. (It also fetched a gateway
|
|
434
|
+
* route that never existed — see #429 — so it was non-functional regardless.) */
|
|
435
|
+
async function linkIdentity(_opts) {
|
|
436
|
+
throw new RenamedExportError({
|
|
437
|
+
oldName: "auth.identities.link",
|
|
438
|
+
newName: "auth.account.identities.startLink",
|
|
427
439
|
});
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
440
|
+
}
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
// Account security (§4). `getSecurity()` is the everyday rich read; the
|
|
443
|
+
// advanced mutation tier (setPassword / passkeys / sessions / identities) is
|
|
444
|
+
// demoted and lands in a follow-up increment.
|
|
445
|
+
// ---------------------------------------------------------------------------
|
|
446
|
+
/**
|
|
447
|
+
* The rich settings/security read for the current actor (§4.3). Distinct from
|
|
448
|
+
* the cheap per-request `auth.user()` — returns the ownership-qualified
|
|
449
|
+
* `AccountSecurity` projection (has_run402_password, run402_passkey_count,
|
|
450
|
+
* run402_identities, tenant_assertions, …) or `null` when anonymous.
|
|
451
|
+
*
|
|
452
|
+
* Resolves the actor exactly like `auth.user()` (cookie envelope on browser
|
|
453
|
+
* SSR; Bearer on direct/machine — §4.7/D15), mints a short-lived actor JWT
|
|
454
|
+
* (the same channel `db()` uses), and fetches the gateway projection route.
|
|
455
|
+
*/
|
|
456
|
+
async function getSecurity() {
|
|
457
|
+
const ctx = getCurrentContext();
|
|
458
|
+
if (!ctx)
|
|
459
|
+
return null;
|
|
460
|
+
const actor = await user();
|
|
461
|
+
if (!actor)
|
|
462
|
+
return null;
|
|
463
|
+
if (!config.JWT_SECRET)
|
|
464
|
+
return null;
|
|
465
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
466
|
+
let token;
|
|
467
|
+
try {
|
|
468
|
+
token = jwt.sign({
|
|
469
|
+
sub: actor.id,
|
|
470
|
+
role: "authenticated",
|
|
471
|
+
email: actor.email,
|
|
472
|
+
project_id: actor.projectId,
|
|
473
|
+
iss: "agentdb",
|
|
474
|
+
iat: nowSec,
|
|
475
|
+
exp: nowSec + 60,
|
|
476
|
+
}, config.JWT_SECRET);
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
// Fetch the gateway (config.API_BASE = RUN402_API_BASE) directly — NOT the
|
|
482
|
+
// public tenant subdomain (ctx.host). The /auth/v1/account/* routes live on
|
|
483
|
+
// the gateway; a Lambda-to-subdomain round-trip via CloudFront does not reach
|
|
484
|
+
// them. `app_origin` still carries the tenant host for rpId validation.
|
|
485
|
+
const appOrigin = `https://${ctx.host}`;
|
|
486
|
+
let res;
|
|
487
|
+
try {
|
|
488
|
+
res = await fetch(`${config.API_BASE}/auth/v1/account/security?app_origin=${encodeURIComponent(appOrigin)}`, {
|
|
489
|
+
headers: {
|
|
490
|
+
apikey: config.ANON_KEY ?? "",
|
|
491
|
+
authorization: `Bearer ${token}`,
|
|
492
|
+
accept: "application/json",
|
|
493
|
+
},
|
|
494
|
+
redirect: "manual",
|
|
434
495
|
});
|
|
435
496
|
}
|
|
497
|
+
catch {
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
if (!res.ok)
|
|
501
|
+
return null;
|
|
502
|
+
const data = (await res.json().catch(() => null));
|
|
503
|
+
if (!data)
|
|
504
|
+
return null;
|
|
505
|
+
// The route returns a `user` projection; the SDK overlays the richer Actor.
|
|
506
|
+
return { ...data, user: actor };
|
|
507
|
+
}
|
|
508
|
+
/** Throwing variant of `getSecurity()` (§4.3). */
|
|
509
|
+
async function requireSecurity() {
|
|
510
|
+
const security = await getSecurity();
|
|
511
|
+
if (!security)
|
|
512
|
+
throw new AuthRequiredError();
|
|
513
|
+
return security;
|
|
514
|
+
}
|
|
515
|
+
// ---------------------------------------------------------------------------
|
|
516
|
+
// §4.4 advanced account-security mutation tier. Server-side, context-actor
|
|
517
|
+
// only. Each method mints a short-lived actor JWT (same channel as
|
|
518
|
+
// getSecurity) — including `auth_time` so the gateway can enforce freshness
|
|
519
|
+
// callee-side — and calls the Bearer-authed /auth/v1/account/* routes. NOT in
|
|
520
|
+
// the everyday docs; the everyday path is the <AccountSecurity> component.
|
|
521
|
+
// ---------------------------------------------------------------------------
|
|
522
|
+
/** Mint a short-lived actor JWT for an advanced-tier account call. Includes
|
|
523
|
+
* `auth_time` (the actor's last-auth from the verified browser-session
|
|
524
|
+
* envelope) so the gateway's sensitive-mutation freshness gate can read it. */
|
|
525
|
+
function mintAdvancedActorToken(actor) {
|
|
526
|
+
if (!config.JWT_SECRET)
|
|
527
|
+
return null;
|
|
528
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
529
|
+
try {
|
|
530
|
+
return jwt.sign({
|
|
531
|
+
sub: actor.id,
|
|
532
|
+
role: "authenticated",
|
|
533
|
+
email: actor.email,
|
|
534
|
+
project_id: actor.projectId,
|
|
535
|
+
iss: "agentdb",
|
|
536
|
+
iat: nowSec,
|
|
537
|
+
exp: nowSec + 60,
|
|
538
|
+
auth_time: actor.authTime,
|
|
539
|
+
}, config.JWT_SECRET);
|
|
540
|
+
}
|
|
541
|
+
catch {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/** Call a Bearer-authed /auth/v1/account/* route with the context actor's
|
|
546
|
+
* minted JWT. Throws AuthRequiredError when anonymous / outside a request,
|
|
547
|
+
* FreshnessRequiredError on a freshness 401, and a generic error otherwise. */
|
|
548
|
+
async function accountAdvancedFetch(path, init) {
|
|
549
|
+
const ctx = getCurrentContext();
|
|
550
|
+
const actor = ctx ? await user() : null;
|
|
551
|
+
if (!ctx || !actor)
|
|
552
|
+
throw new AuthRequiredError();
|
|
553
|
+
const token = mintAdvancedActorToken(actor);
|
|
554
|
+
if (!token)
|
|
555
|
+
throw new AuthRequiredError();
|
|
556
|
+
// Gateway directly (config.API_BASE), NOT the tenant subdomain (ctx.host) —
|
|
557
|
+
// the /auth/v1/account/* routes live on the gateway and a Lambda-to-subdomain
|
|
558
|
+
// round-trip via CloudFront does not reach them (see getSecurity).
|
|
559
|
+
const res = await fetch(`${config.API_BASE}${path}`, {
|
|
560
|
+
method: init.method,
|
|
561
|
+
headers: {
|
|
562
|
+
apikey: config.ANON_KEY ?? "",
|
|
563
|
+
authorization: `Bearer ${token}`,
|
|
564
|
+
accept: "application/json",
|
|
565
|
+
...(init.body !== undefined ? { "content-type": "application/json" } : {}),
|
|
566
|
+
},
|
|
567
|
+
body: init.body !== undefined ? JSON.stringify(init.body) : undefined,
|
|
568
|
+
redirect: "manual",
|
|
569
|
+
});
|
|
570
|
+
if (res.status === 401) {
|
|
571
|
+
const data = (await res.json().catch(() => null));
|
|
572
|
+
if (data?.code === "R402_AUTH_FRESHNESS_REQUIRED") {
|
|
573
|
+
throw new FreshnessRequiredError({ maxAge: "5m", amr: [] });
|
|
574
|
+
}
|
|
575
|
+
throw new AuthRequiredError();
|
|
576
|
+
}
|
|
436
577
|
if (!res.ok) {
|
|
437
|
-
|
|
438
|
-
throw new (await import("./errors.js")).SessionBridgeUnverifiedError({
|
|
439
|
-
reason: body.code ?? `link failed: ${res.status}`,
|
|
440
|
-
});
|
|
578
|
+
throw new Error(`auth.account.* request to ${path} failed: ${res.status}`);
|
|
441
579
|
}
|
|
580
|
+
return (await res.json().catch(() => ({})));
|
|
442
581
|
}
|
|
582
|
+
/** §4.4 — set or change the signed-in user's Run402 password. Callee-enforced
|
|
583
|
+
* freshness (re-auth within 5 min) — throws FreshnessRequiredError otherwise.
|
|
584
|
+
* On success the gateway rotates (revokes) the user's other sessions. */
|
|
585
|
+
async function setPassword(newPassword, _opts) {
|
|
586
|
+
await accountAdvancedFetch("/auth/v1/account/password", {
|
|
587
|
+
method: "POST",
|
|
588
|
+
body: { new_password: newPassword },
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
/** §4.4 — sign out of every browser session for the context actor. */
|
|
592
|
+
async function signOutEverywhere() {
|
|
593
|
+
const out = (await accountAdvancedFetch("/auth/v1/account/sign-out-everywhere", {
|
|
594
|
+
method: "POST",
|
|
595
|
+
body: {},
|
|
596
|
+
}));
|
|
597
|
+
return { revoked_count: typeof out.revoked_count === "number" ? out.revoked_count : 0 };
|
|
598
|
+
}
|
|
599
|
+
const accountPasskeys = {
|
|
600
|
+
list: async () => {
|
|
601
|
+
const out = (await accountAdvancedFetch("/auth/v1/account/passkeys", { method: "GET" }));
|
|
602
|
+
return out.passkeys ?? [];
|
|
603
|
+
},
|
|
604
|
+
remove: async (passkeyId) => {
|
|
605
|
+
await accountAdvancedFetch("/auth/v1/account/passkeys/remove", {
|
|
606
|
+
method: "POST",
|
|
607
|
+
body: { passkey_id: passkeyId },
|
|
608
|
+
});
|
|
609
|
+
},
|
|
610
|
+
/** Passkey registration is a browser WebAuthn ceremony — it cannot run
|
|
611
|
+
* server-side. Use `<AccountSecurity sections={["passkeys"]}/>` or the
|
|
612
|
+
* hosted `/auth/passkeys/register` flow. */
|
|
613
|
+
add: () => {
|
|
614
|
+
throw new Error("auth.account.passkeys.add() can't run server-side: passkey registration is a browser WebAuthn ceremony. Use <AccountSecurity sections={[\"passkeys\"]}/> or the hosted /auth/passkeys/register flow.");
|
|
615
|
+
},
|
|
616
|
+
};
|
|
617
|
+
const accountIdentities = {
|
|
618
|
+
list: async () => {
|
|
619
|
+
const out = (await accountAdvancedFetch("/auth/v1/account/identities", { method: "GET" }));
|
|
620
|
+
return out.identities ?? [];
|
|
621
|
+
},
|
|
622
|
+
/** §4.5 — begin the OAuth link-to-existing-account ceremony. Mints the
|
|
623
|
+
* context actor's JWT and calls the gateway `intent:"link"` start route,
|
|
624
|
+
* returning the provider authorization URL for the caller to redirect to.
|
|
625
|
+
* The resulting identity is written against the signed-in account (NOT a
|
|
626
|
+
* new sign-in). `redirectUrl` must be a project-allowed origin. */
|
|
627
|
+
startLink: async (opts) => {
|
|
628
|
+
if (!opts?.provider)
|
|
629
|
+
throw new Error("auth.account.identities.startLink: provider is required");
|
|
630
|
+
if (!opts?.redirectUrl)
|
|
631
|
+
throw new Error("auth.account.identities.startLink: redirectUrl is required");
|
|
632
|
+
const out = (await accountAdvancedFetch(`/auth/v1/oauth/${opts.provider}/start`, {
|
|
633
|
+
method: "POST",
|
|
634
|
+
body: { intent: "link", redirect_url: opts.redirectUrl, mode: opts.mode ?? "redirect" },
|
|
635
|
+
}));
|
|
636
|
+
if (!out.authorization_url) {
|
|
637
|
+
throw new Error("auth.account.identities.startLink: gateway returned no authorization_url");
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
authorizationUrl: out.authorization_url,
|
|
641
|
+
expiresIn: typeof out.expires_in === "number" ? out.expires_in : 600,
|
|
642
|
+
};
|
|
643
|
+
},
|
|
644
|
+
unlink: async (opts) => {
|
|
645
|
+
await accountAdvancedFetch("/auth/v1/account/identities/unlink", {
|
|
646
|
+
method: "POST",
|
|
647
|
+
body: { provider: opts.provider, subject: opts.subject },
|
|
648
|
+
});
|
|
649
|
+
},
|
|
650
|
+
};
|
|
651
|
+
const accountSessions = {
|
|
652
|
+
list: async () => {
|
|
653
|
+
const out = (await accountAdvancedFetch("/auth/v1/account/sessions", { method: "GET" }));
|
|
654
|
+
return out.sessions ?? [];
|
|
655
|
+
},
|
|
656
|
+
revoke: async (sessionId) => {
|
|
657
|
+
await accountAdvancedFetch("/auth/v1/account/sessions/revoke", {
|
|
658
|
+
method: "POST",
|
|
659
|
+
body: { session_id: sessionId },
|
|
660
|
+
});
|
|
661
|
+
},
|
|
662
|
+
};
|
|
663
|
+
/** `auth.account.*` proxy — `getSecurity`/`requireSecurity` (everyday read) +
|
|
664
|
+
* the §4.4 advanced mutation members (`setPassword`, `passkeys`, `identities`,
|
|
665
|
+
* `sessions`, `signOutEverywhere`) are the real members; the shipped throwing
|
|
666
|
+
* names (`get`, `signIn`, `login`, `currentUser`) and typos throw the
|
|
667
|
+
* structured unknown-export error (§4.6). */
|
|
668
|
+
const ACCOUNT_HALLUCINATED_NAMES = {
|
|
669
|
+
get: "auth.account.getSecurity() / auth.account.requireSecurity()",
|
|
670
|
+
signIn: "auth.sessions.createResponseFromTenantAssertion({...}) / createResponseFromIdentity({...})",
|
|
671
|
+
login: "auth.sessions.createResponseFromTenantAssertion({...})",
|
|
672
|
+
currentUser: "auth.user()",
|
|
673
|
+
user: "auth.user()",
|
|
674
|
+
};
|
|
675
|
+
const baseAccount = {
|
|
676
|
+
getSecurity,
|
|
677
|
+
requireSecurity,
|
|
678
|
+
setPassword,
|
|
679
|
+
signOutEverywhere,
|
|
680
|
+
passkeys: accountPasskeys,
|
|
681
|
+
identities: accountIdentities,
|
|
682
|
+
sessions: accountSessions,
|
|
683
|
+
};
|
|
684
|
+
const account = new Proxy(baseAccount, {
|
|
685
|
+
get(target, prop, receiver) {
|
|
686
|
+
if (typeof prop === "string" && !(prop in target)) {
|
|
687
|
+
throw new UnknownExportError({
|
|
688
|
+
attemptedName: `auth.account.${prop}`,
|
|
689
|
+
canonicalName: ACCOUNT_HALLUCINATED_NAMES[prop] ??
|
|
690
|
+
"auth.account.getSecurity() / auth.account.requireSecurity()",
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
return Reflect.get(target, prop, receiver);
|
|
694
|
+
},
|
|
695
|
+
});
|
|
443
696
|
// ---------------------------------------------------------------------------
|
|
444
697
|
// SDK proxy intercepting hallucinated names.
|
|
445
698
|
// ---------------------------------------------------------------------------
|
|
@@ -503,6 +756,7 @@ const baseAuth = {
|
|
|
503
756
|
csrfToken,
|
|
504
757
|
csrfField,
|
|
505
758
|
invalidCredentials,
|
|
759
|
+
account,
|
|
506
760
|
identities: {
|
|
507
761
|
link: linkIdentity,
|
|
508
762
|
},
|
|
@@ -581,5 +835,5 @@ function currentReturnTo() {
|
|
|
581
835
|
return undefined;
|
|
582
836
|
return ctx.request.url;
|
|
583
837
|
}
|
|
584
|
-
export { AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, InvalidCredentialsError, TenantSubjectInvalidError, Run402AuthError, } from "./errors.js";
|
|
838
|
+
export { AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, InvalidCredentialsError, TenantSubjectInvalidError, RenamedExportError, Run402AuthError, } from "./errors.js";
|
|
585
839
|
//# sourceMappingURL=index.js.map
|