@run402/functions 2.9.0 → 3.1.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/dist/index.js CHANGED
@@ -1,5 +1,19 @@
1
1
  export { db, adminDb, QueryBuilder } from "./db.js";
2
2
  export { getUser, getUserId, getRole } from "./auth.js";
3
+ // Capability `auth-aware-ssr` (v3.0). The canonical server-side auth
4
+ // namespace. `auth.user()` / `auth.requireUser()` / `auth.requireRole(...)`
5
+ // / `auth.requireMembership(...)` / `auth.requireFresh({...})` /
6
+ // `auth.fetch(...)` / `auth.csrfField()` / `auth.sessions.*` /
7
+ // `auth.identities.link(...)` are the only documented identity surfaces.
8
+ // See openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md.
9
+ export { auth } from "./auth/index.js";
10
+ export { Run402AuthError, AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, InvalidCredentialsError, TenantSubjectInvalidError, } from "./auth/index.js";
11
+ // Throwing-sentinel exports for the top legacy bare-name imports. These
12
+ // fire `R402_AUTH_UNKNOWN_EXPORT` at runtime with a structured fix-it,
13
+ // catching the case where `run402 doctor` and the ESLint rule didn't run
14
+ // (e.g. agent paste straight into a route handler). Excluded from public
15
+ // docs intentionally — they exist to fail loudly, not as API.
16
+ export { getSession, currentUser, getCurrentUser, getServerSession } from "./auth/index.js";
3
17
  export { email } from "./email.js";
4
18
  export { ai } from "./ai.js";
5
19
  export { assets } from "./assets.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAS7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,qEAAqE;AACrE,yEAAyE;AACzE,8BAA8B;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,qEAAqE;AACrE,gEAAgE;AAChE,qEAAqE;AACrE,2EAA2E;AAC3E,2DAA2D;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiBxD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAO5E,0CAA0C;AAC1C,mEAAmE;AACnE,2DAA2D;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOnC,OAAO,EACL,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,YAAY,CAAC;AACpB,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE;AACxE,iDAAiD;AACjD,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,gCAAgC,GACjC,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGxD,qEAAqE;AACrE,4EAA4E;AAC5E,iEAAiE;AACjE,+DAA+D;AAC/D,yEAAyE;AACzE,wEAAwE;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAOvC,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,wEAAwE;AACxE,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,8DAA8D;AAC9D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAS7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,qEAAqE;AACrE,yEAAyE;AACzE,8BAA8B;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,qEAAqE;AACrE,gEAAgE;AAChE,qEAAqE;AACrE,2EAA2E;AAC3E,2DAA2D;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiBxD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAO5E,0CAA0C;AAC1C,mEAAmE;AACnE,2DAA2D;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOnC,OAAO,EACL,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,YAAY,CAAC;AACpB,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE;AACxE,iDAAiD;AACjD,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,gCAAgC,GACjC,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SDK runtime verifier for the gateway-signed actor-context envelope.
3
+ *
4
+ * Why this lives in `packages/functions/src/lib/` (vendored shape):
5
+ * - `@run402/functions` is published independently; it must NOT depend
6
+ * on `@run402/gateway` types or runtime.
7
+ * - The verifier is small, deterministic, and security-critical — easier
8
+ * to audit when it lives next to the consumer.
9
+ * - Matches the convention used for `jwt.ts` (vendored upstream copy of
10
+ * the verifier we trust).
11
+ *
12
+ * Contract — the encoded envelope is `base64url(canonical_json) + "." +
13
+ * base64url(hmac_sha256)`. Canonical JSON has a fixed key order; the
14
+ * verifier doesn't re-canonicalise, it just rehmac's the body bytes that
15
+ * were base64-decoded. (Trying to re-derive canonical JSON from the parsed
16
+ * object would re-introduce key-order brittleness; verify the bytes you
17
+ * received, parse only to read fields.)
18
+ *
19
+ * Lookup of `actor_context_signing_key[kid]`:
20
+ * 1. `ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON` env (`{kid: base64}` JSON).
21
+ * 2. `ACTOR_CONTEXT_SIGNING_KEY_<KID_UPPER>` env (one var per kid).
22
+ * 3. Test injection via `_setActorContextKeyMapForTest` on this module.
23
+ *
24
+ * Verification failure modes (mirrors the gateway side):
25
+ * - "malformed" — encoded shape rejected before parse
26
+ * - "unknown_kid" — envelope's kid not in the verifier map
27
+ * - "bad_signature" — HMAC mismatch
28
+ * - "iss_mismatch" — envelope.iss !== "run402-gateway"
29
+ * - "aud_mismatch" — envelope.aud !== "run402-functions-runtime"
30
+ * - "expired" — envelope.exp <= now
31
+ * - "lifetime_too_long" — envelope.exp - envelope.iat > 60s
32
+ * - "project_id_mismatch" — envelope.project_id !== request's
33
+ * - "request_id_mismatch" — envelope.request_id !== request's
34
+ * - "method_mismatch" — different HTTP method
35
+ * - "host_mismatch" — different host (after default-port normalise)
36
+ * - "path_mismatch" — different path (compared by sha256)
37
+ * - "version_mismatch" — schema version not what we compiled
38
+ *
39
+ * On ANY failure the SDK runtime treats the request as anonymous AND
40
+ * logs `R402_AUTH_ACTOR_HEADER_SPOOF` so spoofs / replays are visible
41
+ * in observability.
42
+ *
43
+ * @see openspec/changes/auth-aware-ssr/specs/routed-http-functions/spec.md
44
+ */
45
+ export declare const ACTOR_CONTEXT_ENVELOPE_VERSION: 1;
46
+ export declare const ACTOR_CONTEXT_ENVELOPE_ISS = "run402-gateway";
47
+ export declare const ACTOR_CONTEXT_ENVELOPE_AUD = "run402-functions-runtime";
48
+ export declare const ACTOR_CONTEXT_MAX_LIFETIME_SEC = 60;
49
+ /** Inbound header carrying the encoded envelope. The runtime reads from
50
+ * the request headers in `RunRequestContext.request.headers`. */
51
+ export declare const ACTOR_CONTEXT_HEADER = "x-run402-actor-context";
52
+ export interface VerifiedActorPayload {
53
+ id: string;
54
+ email: string;
55
+ emailVerified: boolean;
56
+ authTime: number;
57
+ amr: string[];
58
+ amrTimes: Record<string, number>;
59
+ authzVersion: number;
60
+ }
61
+ export interface VerifiedEnvelope {
62
+ v: 1;
63
+ kid: string;
64
+ iss: typeof ACTOR_CONTEXT_ENVELOPE_ISS;
65
+ aud: typeof ACTOR_CONTEXT_ENVELOPE_AUD;
66
+ project_id: string;
67
+ request_id: string;
68
+ method: string;
69
+ host: string;
70
+ path_hash: string;
71
+ iat: number;
72
+ exp: number;
73
+ actor: VerifiedActorPayload;
74
+ }
75
+ export interface VerifyRequestContext {
76
+ projectId: string;
77
+ requestId: string;
78
+ method: string;
79
+ host: string;
80
+ path: string;
81
+ /** Override for tests; production uses `new Date()`. */
82
+ now?: Date;
83
+ }
84
+ export type VerifyFailureReason = "malformed" | "unknown_kid" | "bad_signature" | "iss_mismatch" | "aud_mismatch" | "expired" | "lifetime_too_long" | "project_id_mismatch" | "request_id_mismatch" | "method_mismatch" | "host_mismatch" | "path_mismatch" | "version_mismatch";
85
+ export type VerifyOutcome = {
86
+ ok: true;
87
+ envelope: VerifiedEnvelope;
88
+ } | {
89
+ ok: false;
90
+ reason: VerifyFailureReason;
91
+ };
92
+ /** Test injection. NEVER call from production code. */
93
+ export declare function _setActorContextKeyMapForTest(map: Record<string, Buffer | string> | null): void;
94
+ export declare function verifyActorContextEnvelope(encoded: string, ctx: VerifyRequestContext): VerifyOutcome;
95
+ //# sourceMappingURL=actor-context-verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-context-verify.d.ts","sourceRoot":"","sources":["../../src/lib/actor-context-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAIH,eAAO,MAAM,8BAA8B,EAAG,CAAU,CAAC;AACzD,eAAO,MAAM,0BAA0B,mBAAmB,CAAC;AAC3D,eAAO,MAAM,0BAA0B,6BAA6B,CAAC;AACrE,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD;kEACkE;AAClE,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,0BAA0B,CAAC;IACvC,GAAG,EAAE,OAAO,0BAA0B,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,GACd,cAAc,GACd,SAAS,GACT,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,iBAAiB,GACjB,eAAe,GACf,eAAe,GACf,kBAAkB,CAAC;AAEvB,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAqD/C,uDAAuD;AACvD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,IAAI,GAC1C,IAAI,CAcN;AAMD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,oBAAoB,GACxB,aAAa,CA0Ef"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * SDK runtime verifier for the gateway-signed actor-context envelope.
3
+ *
4
+ * Why this lives in `packages/functions/src/lib/` (vendored shape):
5
+ * - `@run402/functions` is published independently; it must NOT depend
6
+ * on `@run402/gateway` types or runtime.
7
+ * - The verifier is small, deterministic, and security-critical — easier
8
+ * to audit when it lives next to the consumer.
9
+ * - Matches the convention used for `jwt.ts` (vendored upstream copy of
10
+ * the verifier we trust).
11
+ *
12
+ * Contract — the encoded envelope is `base64url(canonical_json) + "." +
13
+ * base64url(hmac_sha256)`. Canonical JSON has a fixed key order; the
14
+ * verifier doesn't re-canonicalise, it just rehmac's the body bytes that
15
+ * were base64-decoded. (Trying to re-derive canonical JSON from the parsed
16
+ * object would re-introduce key-order brittleness; verify the bytes you
17
+ * received, parse only to read fields.)
18
+ *
19
+ * Lookup of `actor_context_signing_key[kid]`:
20
+ * 1. `ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON` env (`{kid: base64}` JSON).
21
+ * 2. `ACTOR_CONTEXT_SIGNING_KEY_<KID_UPPER>` env (one var per kid).
22
+ * 3. Test injection via `_setActorContextKeyMapForTest` on this module.
23
+ *
24
+ * Verification failure modes (mirrors the gateway side):
25
+ * - "malformed" — encoded shape rejected before parse
26
+ * - "unknown_kid" — envelope's kid not in the verifier map
27
+ * - "bad_signature" — HMAC mismatch
28
+ * - "iss_mismatch" — envelope.iss !== "run402-gateway"
29
+ * - "aud_mismatch" — envelope.aud !== "run402-functions-runtime"
30
+ * - "expired" — envelope.exp <= now
31
+ * - "lifetime_too_long" — envelope.exp - envelope.iat > 60s
32
+ * - "project_id_mismatch" — envelope.project_id !== request's
33
+ * - "request_id_mismatch" — envelope.request_id !== request's
34
+ * - "method_mismatch" — different HTTP method
35
+ * - "host_mismatch" — different host (after default-port normalise)
36
+ * - "path_mismatch" — different path (compared by sha256)
37
+ * - "version_mismatch" — schema version not what we compiled
38
+ *
39
+ * On ANY failure the SDK runtime treats the request as anonymous AND
40
+ * logs `R402_AUTH_ACTOR_HEADER_SPOOF` so spoofs / replays are visible
41
+ * in observability.
42
+ *
43
+ * @see openspec/changes/auth-aware-ssr/specs/routed-http-functions/spec.md
44
+ */
45
+ import crypto from "node:crypto";
46
+ export const ACTOR_CONTEXT_ENVELOPE_VERSION = 1;
47
+ export const ACTOR_CONTEXT_ENVELOPE_ISS = "run402-gateway";
48
+ export const ACTOR_CONTEXT_ENVELOPE_AUD = "run402-functions-runtime";
49
+ export const ACTOR_CONTEXT_MAX_LIFETIME_SEC = 60;
50
+ /** Inbound header carrying the encoded envelope. The runtime reads from
51
+ * the request headers in `RunRequestContext.request.headers`. */
52
+ export const ACTOR_CONTEXT_HEADER = "x-run402-actor-context";
53
+ // ---------------------------------------------------------------------------
54
+ // Key store (env-loaded, test-injectable)
55
+ // ---------------------------------------------------------------------------
56
+ const KEY_MIN_BYTES = 32;
57
+ let keyMap = null;
58
+ function loadKeyMap() {
59
+ if (keyMap)
60
+ return keyMap;
61
+ const map = new Map();
62
+ const mapJson = process.env.ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON;
63
+ if (mapJson) {
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(mapJson);
67
+ }
68
+ catch (err) {
69
+ throw new Error(`ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON is not valid JSON: ${err.message}`);
70
+ }
71
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
72
+ throw new Error("ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON must be an object {kid: base64}");
73
+ }
74
+ for (const [kid, b64] of Object.entries(parsed)) {
75
+ if (typeof b64 !== "string")
76
+ continue;
77
+ const buf = Buffer.from(b64, "base64");
78
+ if (buf.length >= KEY_MIN_BYTES)
79
+ map.set(kid, buf);
80
+ }
81
+ }
82
+ for (const [envName, envValue] of Object.entries(process.env)) {
83
+ const match = envName.match(/^ACTOR_CONTEXT_SIGNING_KEY_([A-Z0-9_-]+)$/);
84
+ if (!match)
85
+ continue;
86
+ if (envName === "ACTOR_CONTEXT_SIGNING_KEY_CURRENT_KID" ||
87
+ envName === "ACTOR_CONTEXT_SIGNING_KEY_MAP_JSON") {
88
+ continue;
89
+ }
90
+ if (typeof envValue !== "string" || envValue.length === 0)
91
+ continue;
92
+ const kid = match[1].toLowerCase().replace(/_/g, "-");
93
+ if (map.has(kid))
94
+ continue;
95
+ const buf = Buffer.from(envValue, "base64");
96
+ if (buf.length >= KEY_MIN_BYTES)
97
+ map.set(kid, buf);
98
+ }
99
+ keyMap = map;
100
+ return map;
101
+ }
102
+ /** Test injection. NEVER call from production code. */
103
+ export function _setActorContextKeyMapForTest(map) {
104
+ if (map === null) {
105
+ keyMap = null;
106
+ return;
107
+ }
108
+ const m = new Map();
109
+ for (const [kid, value] of Object.entries(map)) {
110
+ const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, "base64");
111
+ if (buf.length < KEY_MIN_BYTES) {
112
+ throw new Error(`Actor-context key for kid "${kid}" is too short`);
113
+ }
114
+ m.set(kid, buf);
115
+ }
116
+ keyMap = m;
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Verifier
120
+ // ---------------------------------------------------------------------------
121
+ export function verifyActorContextEnvelope(encoded, ctx) {
122
+ if (typeof encoded !== "string" || encoded.length === 0) {
123
+ return { ok: false, reason: "malformed" };
124
+ }
125
+ const dot = encoded.indexOf(".");
126
+ if (dot <= 0 || dot === encoded.length - 1) {
127
+ return { ok: false, reason: "malformed" };
128
+ }
129
+ const bodyB64 = encoded.slice(0, dot);
130
+ const sigB64 = encoded.slice(dot + 1);
131
+ if (!/^[A-Za-z0-9_-]+$/.test(bodyB64) || !/^[A-Za-z0-9_-]+$/.test(sigB64)) {
132
+ return { ok: false, reason: "malformed" };
133
+ }
134
+ let bodyBuf;
135
+ let envelope;
136
+ try {
137
+ bodyBuf = Buffer.from(bodyB64, "base64url");
138
+ envelope = JSON.parse(bodyBuf.toString("utf8"));
139
+ }
140
+ catch {
141
+ return { ok: false, reason: "malformed" };
142
+ }
143
+ if (!envelope || typeof envelope !== "object") {
144
+ return { ok: false, reason: "malformed" };
145
+ }
146
+ if (envelope.v !== ACTOR_CONTEXT_ENVELOPE_VERSION) {
147
+ return { ok: false, reason: "version_mismatch" };
148
+ }
149
+ if (typeof envelope.kid !== "string")
150
+ return { ok: false, reason: "malformed" };
151
+ const key = loadKeyMap().get(envelope.kid);
152
+ if (!key)
153
+ return { ok: false, reason: "unknown_kid" };
154
+ const sigBuf = Buffer.from(sigB64, "base64url");
155
+ const expectedSig = crypto.createHmac("sha256", key).update(bodyBuf).digest();
156
+ if (sigBuf.length !== expectedSig.length) {
157
+ return { ok: false, reason: "bad_signature" };
158
+ }
159
+ if (!crypto.timingSafeEqual(sigBuf, expectedSig)) {
160
+ return { ok: false, reason: "bad_signature" };
161
+ }
162
+ if (envelope.iss !== ACTOR_CONTEXT_ENVELOPE_ISS) {
163
+ return { ok: false, reason: "iss_mismatch" };
164
+ }
165
+ if (envelope.aud !== ACTOR_CONTEXT_ENVELOPE_AUD) {
166
+ return { ok: false, reason: "aud_mismatch" };
167
+ }
168
+ if (typeof envelope.iat !== "number" || typeof envelope.exp !== "number") {
169
+ return { ok: false, reason: "malformed" };
170
+ }
171
+ if (envelope.exp - envelope.iat > ACTOR_CONTEXT_MAX_LIFETIME_SEC) {
172
+ return { ok: false, reason: "lifetime_too_long" };
173
+ }
174
+ const nowSec = Math.floor((ctx.now ?? new Date()).getTime() / 1000);
175
+ if (envelope.exp <= nowSec)
176
+ return { ok: false, reason: "expired" };
177
+ if (envelope.project_id !== ctx.projectId) {
178
+ return { ok: false, reason: "project_id_mismatch" };
179
+ }
180
+ if (envelope.request_id !== ctx.requestId) {
181
+ return { ok: false, reason: "request_id_mismatch" };
182
+ }
183
+ if (envelope.method !== ctx.method.toUpperCase()) {
184
+ return { ok: false, reason: "method_mismatch" };
185
+ }
186
+ if (envelope.host !== normaliseHost(ctx.host)) {
187
+ return { ok: false, reason: "host_mismatch" };
188
+ }
189
+ if (envelope.path_hash !== sha256Hex(ctx.path)) {
190
+ return { ok: false, reason: "path_mismatch" };
191
+ }
192
+ return { ok: true, envelope };
193
+ }
194
+ function normaliseHost(host) {
195
+ return host.toLowerCase().replace(/:80$/, "").replace(/:443$/, "");
196
+ }
197
+ function sha256Hex(s) {
198
+ return crypto.createHash("sha256").update(s, "utf8").digest("hex");
199
+ }
200
+ //# sourceMappingURL=actor-context-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-context-verify.js","sourceRoot":"","sources":["../../src/lib/actor-context-verify.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,15 @@
27
27
  * @see openspec/changes/astro-ssr-runtime/specs/routed-http-functions/spec.md
28
28
  */
29
29
  import { AsyncLocalStorage } from "node:async_hooks";
30
+ import { type VerifiedActorPayload } from "./lib/actor-context-verify.js";
31
+ /** Capability `auth-aware-ssr`: the verified actor payload the SDK
32
+ * exposes via `auth.user()` etc. Populated by `runWithContext` after
33
+ * it verifies the inbound actor-context envelope. `null` when the
34
+ * request is anonymous OR when verification failed (defense in depth:
35
+ * forged envelopes never surface as a non-null actor). */
36
+ export type ActorContext = VerifiedActorPayload & {
37
+ sessionId: string;
38
+ };
30
39
  /** The shape stored in AsyncLocalStorage. See the spec referenced above
31
40
  * for the canonical definition. */
32
41
  export interface RunRequestContext {
@@ -52,6 +61,19 @@ export interface RunRequestContext {
52
61
  url: string;
53
62
  headers: Record<string, string | string[] | undefined>;
54
63
  };
64
+ /** Capability `auth-aware-ssr`: actor populated from the verified
65
+ * gateway-signed envelope. The SDK's `auth.user()` returns this
66
+ * verbatim; consumer code never sees the raw envelope. */
67
+ actor: ActorContext | null;
68
+ /** Capability `auth-hosted-surface-parity`: invocation class. For
69
+ * `"routed_http"` (browser SSR) the actor is resolved ONLY from the
70
+ * verified cookie envelope above — `auth.user()` does NOT fall back
71
+ * to decoding an `Authorization: Bearer` header, so the
72
+ * "cookie is the only browser actor input" invariant holds. For
73
+ * `"direct"` (machine / mobile / CI function invocation) the Bearer
74
+ * fallback is preserved. Defaults to `"direct"` when unset so
75
+ * pre-existing callers keep the machine contract. */
76
+ invocationKind: "routed_http" | "direct";
55
77
  /** Mutable ref: SDK functions that read request-scoped auth or invoke
56
78
  * payment primitives set `value = true`. The SSR Lambda runtime
57
79
  * returns the final value to the gateway in the response metadata
@@ -85,7 +107,7 @@ export declare function getCurrentContext(): RunRequestContext | undefined;
85
107
  * runtime) flips it to `false` after the response body is materialized.
86
108
  * Don't call this from user code — it's the runtime's primitive.
87
109
  */
88
- export declare function runWithContext<T>(context: Omit<RunRequestContext, "cacheBypassTainted" | "active"> & Partial<Pick<RunRequestContext, "cacheBypassTainted" | "active">>, callback: () => Promise<T> | T): Promise<T> | T;
110
+ export declare function runWithContext<T>(context: Omit<RunRequestContext, "cacheBypassTainted" | "active" | "actor" | "invocationKind"> & Partial<Pick<RunRequestContext, "cacheBypassTainted" | "active" | "actor" | "invocationKind">>, callback: () => Promise<T> | T): Promise<T> | T;
89
111
  /**
90
112
  * Throw a structured `R402_SDK_OUTSIDE_REQUEST_CONTEXT` error. Used by
91
113
  * SDK functions when they're invoked with no ALS store OR while the
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;oCACoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;yBACqB;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;qDACiD;IACjD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;yDACqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb;;;uBAGmB;IACnB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;KACxD,CAAC;IACF;;;oBAGgB;IAChB,kBAAkB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACvC;;;8CAG0C;IAC1C,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;CAC5B;AAED;oEACoE;AACpE,eAAO,MAAM,GAAG,sCAA6C,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,GAAG,SAAS,CAEjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,GAAG,QAAQ,CAAC,CAAC,EACrI,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAOhB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,sCAAsC;IACnD,QAAQ,CAAC,IAAI,iEAAiE;IAC9E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,kBAAkB,CAAC;gBAEtC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,kBAAkB;CAc1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,CAS3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAUjD,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,OAAO,EAAE,EAAE,OAAO,EAC/D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,GAChC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAe7B"}
1
+ {"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,+BAA+B,CAAC;AAEvC;;;;2DAI2D;AAC3D,MAAM,MAAM,YAAY,GAAG,oBAAoB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE;oCACoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;yBACqB;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;qDACiD;IACjD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;yDACqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb;;;uBAGmB;IACnB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;KACxD,CAAC;IACF;;+DAE2D;IAC3D,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B;;;;;;;0DAOsD;IACtD,cAAc,EAAE,aAAa,GAAG,QAAQ,CAAC;IACzC;;;oBAGgB;IAChB,kBAAkB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACvC;;;8CAG0C;IAC1C,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;CAC5B;AAED;oEACoE;AACpE,eAAO,MAAM,GAAG,sCAA6C,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,GAAG,SAAS,CAEjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,IAAI,CACX,iBAAiB,EACjB,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,gBAAgB,CAC7D,GACC,OAAO,CACL,IAAI,CACF,iBAAiB,EACjB,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,gBAAgB,CAC7D,CACF,EACH,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAoBhB;AA6DD;;;;;;;;;;;GAWG;AACH,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,sCAAsC;IACnD,QAAQ,CAAC,IAAI,iEAAiE;IAC9E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,kBAAkB,CAAC;gBAEtC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,kBAAkB;CAc1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,CAS3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAUjD,CAAC;AAEH;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,OAAO,EAAE,EAAE,OAAO,EAC/D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,GAChC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAe7B"}
@@ -27,6 +27,7 @@
27
27
  * @see openspec/changes/astro-ssr-runtime/specs/routed-http-functions/spec.md
28
28
  */
29
29
  import { AsyncLocalStorage } from "node:async_hooks";
30
+ import { verifyActorContextEnvelope, ACTOR_CONTEXT_HEADER, } from "./lib/actor-context-verify.js";
30
31
  /** The shared ALS instance. Modules in @run402/functions read from
31
32
  * this; the SSR Lambda runtime (in @run402/astro) writes to it. */
32
33
  export const als = new AsyncLocalStorage();
@@ -48,13 +49,76 @@ export function getCurrentContext() {
48
49
  * Don't call this from user code — it's the runtime's primitive.
49
50
  */
50
51
  export function runWithContext(context, callback) {
52
+ // Resolve the actor either from the caller-provided override (tests, the
53
+ // SSR runtime when it has pre-verified the envelope) or by verifying the
54
+ // inbound actor-context header against the request bound to this context.
55
+ // Failure is non-fatal: the request becomes anonymous AND we log
56
+ // `R402_AUTH_ACTOR_HEADER_SPOOF` so spoof attempts surface in metrics.
57
+ const actor = context.actor !== undefined
58
+ ? context.actor
59
+ : verifyEnvelopeFromRequest(context);
51
60
  const full = {
52
61
  ...context,
62
+ actor,
63
+ // Default to "direct" so pre-existing callers (and tests) keep the
64
+ // machine Bearer-fallback contract; the gateway's routed-HTTP path
65
+ // sets "routed_http" explicitly.
66
+ invocationKind: context.invocationKind ?? "direct",
53
67
  cacheBypassTainted: context.cacheBypassTainted ?? { value: false },
54
68
  active: context.active ?? { value: true },
55
69
  };
56
70
  return als.run(full, callback);
57
71
  }
72
+ function verifyEnvelopeFromRequest(ctx) {
73
+ const headers = ctx.request.headers;
74
+ const headerValue = headers[ACTOR_CONTEXT_HEADER];
75
+ const encoded = Array.isArray(headerValue) ? headerValue[0] : headerValue;
76
+ if (!encoded || typeof encoded !== "string")
77
+ return null;
78
+ // The runtime sees `request.url` as a full path-only string from the
79
+ // SSR Lambda envelope (e.g. `/forum/topic-1?q=astro`). The signing side
80
+ // hashed the path-only URL, so we hash the same here. The query string
81
+ // is part of the binding so `/forum?topic=1` and `/forum?topic=2` can't
82
+ // accept the same envelope.
83
+ const path = ctx.request.url;
84
+ const outcome = verifyActorContextEnvelope(encoded, {
85
+ projectId: ctx.projectId,
86
+ requestId: ctx.requestId,
87
+ method: ctx.request.method,
88
+ host: ctx.host,
89
+ path,
90
+ });
91
+ if (!outcome.ok) {
92
+ logActorContextSpoof(outcome.reason, ctx.requestId);
93
+ return null;
94
+ }
95
+ return {
96
+ id: outcome.envelope.actor.id,
97
+ email: outcome.envelope.actor.email,
98
+ emailVerified: outcome.envelope.actor.emailVerified,
99
+ authTime: outcome.envelope.actor.authTime,
100
+ amr: outcome.envelope.actor.amr,
101
+ amrTimes: outcome.envelope.actor.amrTimes,
102
+ authzVersion: outcome.envelope.actor.authzVersion,
103
+ // session_id is NOT in the envelope — it's gateway-internal state.
104
+ // For now we mint a deterministic-by-request id so downstream code
105
+ // has a string to hang `db()` set_config on. Once the gateway adds
106
+ // session_id to the envelope (planned in section 4 of the spec),
107
+ // populate it here from outcome.envelope.actor.sessionId.
108
+ sessionId: outcome.envelope.request_id,
109
+ };
110
+ }
111
+ function logActorContextSpoof(reason, requestId) {
112
+ // Structured one-line log so observability can alert on rate. The
113
+ // SDK runs in Lambda; CloudWatch picks this up.
114
+ // eslint-disable-next-line no-console
115
+ console.warn(JSON.stringify({
116
+ level: "warn",
117
+ event: "R402_AUTH_ACTOR_HEADER_SPOOF",
118
+ reason,
119
+ request_id: requestId,
120
+ }));
121
+ }
58
122
  /**
59
123
  * Throw a structured `R402_SDK_OUTSIDE_REQUEST_CONTEXT` error. Used by
60
124
  * SDK functions when they're invoked with no ALS store OR while the
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAuCrD;oEACoE;AACpE,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,iBAAiB,EAAqB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAqI,EACrI,QAA8B;IAE9B,MAAM,IAAI,GAAsB;QAC9B,GAAG,OAAO;QACV,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;QAClE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;KAC1C,CAAC;IACF,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,gCAAiC,SAAQ,KAAK;IAChD,IAAI,GAAG,kCAAkC,CAAC;IAC1C,IAAI,GAAG,6DAA6D,CAAC;IACrE,YAAY,CAAS;IACrB,WAAW,CAAS;IACpB,KAAK,CAAoC;IAElD,YAAY,WAAmB,EAAE,KAAwC;QACvE,MAAM,QAAQ,GACZ,KAAK,KAAK,YAAY;YACpB,CAAC,CAAC,2EAA2E;YAC7E,CAAC,CAAC,sGAAsG,CAAC;QAC7G,KAAK,CAAC,GAAG,WAAW,KAAK,QAAQ,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,kCAAkC,CAAC;QAC/C,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY;YACf,KAAK,KAAK,YAAY;gBACpB,CAAC,CAAC,YAAY,WAAW,oIAAoI;gBAC7J,CAAC,CAAC,2BAA2B,WAAW,4HAA4H,CAAC;IAC3K,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,gCAAgC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,gCAAgC,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,GAAG,CAAC,kBAAkB,CAAC,KAAK,GAAG,IAAI,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;AAC7D,gEAAgE;AAChE,mEAAmE;AACnE,qEAAqE;AACrE,gBAAgB;AAChB,mEAAmE;AACnE,2BAA2B;AAC3B,wBAAwB;AACxB,qBAAqB;AACrB,wBAAwB;CACzB,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,IAAiC;IAEjC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,kEAAkE;QAClE,qEAAqE;QACrE,qEAAqE;QACrE,sCAAsC;QACtC,OAAO,CAAC,IAAI,CACV,8BAA8B,IAAI,kBAAkB,IAAI,kCAAkC;YACxF,kGAAkG,CACrG,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,IAAW,EAAW,EAAE;QACjC,gBAAgB,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@run402/functions",
3
- "version": "2.9.0",
3
+ "version": "3.1.0",
4
4
  "description": "In-function helper library for Run402 serverless functions — db, adminDb, getUser, email, ai, assets, verifyWebhook. Auto-bundled into deployed functions; also installable for local TypeScript autocomplete.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "tsc",
21
- "test": "node --experimental-test-module-mocks --test --import tsx src/db.test.ts src/auth.test.ts src/ai.test.ts src/email.test.ts src/assets.test.ts src/routed-http.test.ts"
21
+ "test": "node --experimental-test-module-mocks --test --import tsx src/db.test.ts src/auth.test.ts src/auth/index.test.ts src/ai.test.ts src/email.test.ts src/assets.test.ts src/routed-http.test.ts src/request-context.test.ts src/runtime-context.test.ts src/lib/actor-context-verify.test.ts src/verify-webhook.test.ts"
22
22
  },
23
23
  "engines": {
24
24
  "node": ">=18"