@run402/functions 2.5.1 → 2.6.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.d.ts CHANGED
@@ -9,4 +9,9 @@ export { assets } from "./assets.js";
9
9
  export type { AssetPutOptions, AssetPutSource, AssetPutSourceInput, AssetRef, AssetVisibility, AssetVariant, AssetListRow, AssetsListFilter, AssetsListOptions, AssetsListResult, AssetsListSort, ImageInfo, } from "./assets.js";
10
10
  export { bytes, isRequest, json, routedHttp, text } from "./routed-http.js";
11
11
  export type { RoutedHttpHeaderList, RoutedHttpRequestV1, RoutedHttpResponseInit, RoutedHttpResponseV1, } from "./routed-http.js";
12
+ export { cache } from "./cache.js";
13
+ export type { Cache, CacheInvalidateResult, InvalidatePrefixOptions, InvalidateAllOptions, } from "./cache.js";
14
+ export { CacheInvalidationHostRequiredError, CacheInvalidationHostForbiddenError, } from "./cache.js";
15
+ export { als, getCurrentContext, runWithContext, requireActiveContext, taintCacheBypass, withPaymentTaint, PAYMENT_PRIMITIVES, Run402OutsideRequestContextError, } from "./runtime-context.js";
16
+ export type { RunRequestContext } from "./runtime-context.js";
12
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","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;AACxD,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,YAAY,EAEZ,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","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;AACxD,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,YAAY,EAEZ,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EACV,KAAK,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,gCAAgC,GACjC,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -4,4 +4,14 @@ export { email } from "./email.js";
4
4
  export { ai } from "./ai.js";
5
5
  export { assets } from "./assets.js";
6
6
  export { bytes, isRequest, json, routedHttp, text } from "./routed-http.js";
7
+ // Capability `astro-ssr-runtime` (v1.52).
8
+ // `cache.*` — sub-second admin-edit visibility via origin-side ISR
9
+ // cache invalidation. Server-side (function-context) only.
10
+ export { cache } from "./cache.js";
11
+ export { CacheInvalidationHostRequiredError, CacheInvalidationHostForbiddenError, } from "./cache.js";
12
+ // Runtime context primitives — used internally by SDK functions to read
13
+ // the current SSR request from AsyncLocalStorage. The SSR Lambda runtime
14
+ // (in @run402/astro) uses `runWithContext` to establish the store; user
15
+ // code typically does not import these directly.
16
+ export { als, getCurrentContext, runWithContext, requireActiveContext, taintCacheBypass, withPaymentTaint, PAYMENT_PRIMITIVES, Run402OutsideRequestContextError, } from "./runtime-context.js";
7
17
  //# sourceMappingURL=index.js.map
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;AAgBrC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,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;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAS7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAgBrC,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,55 @@
1
+ /**
2
+ * Minimal HS256/HS512 JWT sign + verify built directly on `node:crypto`.
3
+ *
4
+ * Used internally by `@run402/functions` to verify project JWTs in
5
+ * `getUser`. Replaces a runtime dependency on the `jsonwebtoken` package
6
+ * (and its transitive tree `jws` / `jwa` / `ecdsa-sig-formatter` /
7
+ * `lodash.*` / `ms` / `semver` / `safe-buffer`), so this published SDK
8
+ * has zero crypto deps beyond `node:crypto`. The companion file in
9
+ * the private gateway package (`packages/gateway/src/lib/jwt.ts`) is
10
+ * intentionally a verbatim duplicate — the published SDK cannot pull
11
+ * from the workspace-private `@run402/shared`.
12
+ */
13
+ export interface JwtPayload {
14
+ [key: string]: unknown;
15
+ iat?: number;
16
+ exp?: number;
17
+ nbf?: number;
18
+ iss?: string;
19
+ aud?: string | string[];
20
+ sub?: string;
21
+ jti?: string;
22
+ }
23
+ export type SupportedAlgorithm = "HS256" | "HS512";
24
+ export interface SignOptions {
25
+ algorithm?: SupportedAlgorithm;
26
+ expiresIn?: string | number;
27
+ noTimestamp?: boolean;
28
+ }
29
+ export interface VerifyOptions {
30
+ algorithms?: ReadonlyArray<SupportedAlgorithm>;
31
+ issuer?: string;
32
+ audience?: string | string[];
33
+ clockTolerance?: number;
34
+ }
35
+ export declare class JsonWebTokenError extends Error {
36
+ constructor(message: string);
37
+ }
38
+ export declare class TokenExpiredError extends JsonWebTokenError {
39
+ expiredAt: Date;
40
+ constructor(message: string, expiredAt: Date);
41
+ }
42
+ export declare class NotBeforeError extends JsonWebTokenError {
43
+ date: Date;
44
+ constructor(message: string, date: Date);
45
+ }
46
+ export declare function sign(payload: object, secret: string, options?: SignOptions): string;
47
+ export declare function verify<T = JwtPayload>(token: string, secret: string, options?: VerifyOptions): T;
48
+ export declare function decode<T = JwtPayload>(token: string): T | null;
49
+ declare const jwt: {
50
+ sign: typeof sign;
51
+ verify: typeof verify;
52
+ decode: typeof decode;
53
+ };
54
+ export default jwt;
55
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,iBAAkB,SAAQ,iBAAiB;IACtD,SAAS,EAAE,IAAI,CAAC;gBACJ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI;CAK7C;AAED,qBAAa,cAAe,SAAQ,iBAAiB;IACnD,IAAI,EAAE,IAAI,CAAC;gBACC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;CAKxC;AAqCD,wBAAgB,IAAI,CAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,WAAW,GACpB,MAAM,CAmCR;AAED,wBAAgB,MAAM,CAAC,CAAC,GAAG,UAAU,EACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,aAAa,GACtB,CAAC,CA4EH;AAED,wBAAgB,MAAM,CAAC,CAAC,GAAG,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAW9D;AAED,QAAA,MAAM,GAAG;;;;CAA2B,CAAC;AACrC,eAAe,GAAG,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Minimal HS256/HS512 JWT sign + verify built directly on `node:crypto`.
3
+ *
4
+ * Used internally by `@run402/functions` to verify project JWTs in
5
+ * `getUser`. Replaces a runtime dependency on the `jsonwebtoken` package
6
+ * (and its transitive tree `jws` / `jwa` / `ecdsa-sig-formatter` /
7
+ * `lodash.*` / `ms` / `semver` / `safe-buffer`), so this published SDK
8
+ * has zero crypto deps beyond `node:crypto`. The companion file in
9
+ * the private gateway package (`packages/gateway/src/lib/jwt.ts`) is
10
+ * intentionally a verbatim duplicate — the published SDK cannot pull
11
+ * from the workspace-private `@run402/shared`.
12
+ */
13
+ import { createHmac, timingSafeEqual } from "node:crypto";
14
+ export class JsonWebTokenError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = "JsonWebTokenError";
18
+ }
19
+ }
20
+ export class TokenExpiredError extends JsonWebTokenError {
21
+ expiredAt;
22
+ constructor(message, expiredAt) {
23
+ super(message);
24
+ this.name = "TokenExpiredError";
25
+ this.expiredAt = expiredAt;
26
+ }
27
+ }
28
+ export class NotBeforeError extends JsonWebTokenError {
29
+ date;
30
+ constructor(message, date) {
31
+ super(message);
32
+ this.name = "NotBeforeError";
33
+ this.date = date;
34
+ }
35
+ }
36
+ function b64urlEncode(input) {
37
+ const buf = typeof input === "string" ? Buffer.from(input, "utf8") : input;
38
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
39
+ }
40
+ function b64urlDecodeToBuffer(input) {
41
+ if (!/^[A-Za-z0-9_-]*$/.test(input))
42
+ throw new JsonWebTokenError("invalid token");
43
+ const norm = input.replace(/-/g, "+").replace(/_/g, "/");
44
+ const pad = norm.length % 4 === 0 ? "" : "=".repeat(4 - (norm.length % 4));
45
+ return Buffer.from(norm + pad, "base64");
46
+ }
47
+ const DURATION_RE = /^(-?\d+(?:\.\d+)?)\s*(s|sec|secs|seconds?|m|min|mins|minutes?|h|hr|hrs|hours?|d|days?|w|weeks?|y|years?)?$/i;
48
+ function parseDurationSeconds(input) {
49
+ if (typeof input === "number") {
50
+ if (!Number.isFinite(input))
51
+ throw new TypeError(`Invalid expiresIn: ${input}`);
52
+ return Math.floor(input);
53
+ }
54
+ const m = DURATION_RE.exec(input.trim());
55
+ if (!m)
56
+ throw new TypeError(`Invalid expiresIn duration: ${input}`);
57
+ const n = parseFloat(m[1]);
58
+ const unit = (m[2] ?? "s").toLowerCase();
59
+ if (unit.startsWith("y"))
60
+ return Math.floor(n * 31_557_600);
61
+ if (unit.startsWith("w"))
62
+ return Math.floor(n * 604_800);
63
+ if (unit.startsWith("d"))
64
+ return Math.floor(n * 86_400);
65
+ if (unit.startsWith("h"))
66
+ return Math.floor(n * 3_600);
67
+ if (unit === "m" || unit.startsWith("min"))
68
+ return Math.floor(n * 60);
69
+ return Math.floor(n);
70
+ }
71
+ function hmacForAlg(alg) {
72
+ return alg === "HS256" ? "sha256" : "sha512";
73
+ }
74
+ export function sign(payload, secret, options) {
75
+ const alg = options?.algorithm ?? "HS256";
76
+ if (alg !== "HS256" && alg !== "HS512") {
77
+ throw new JsonWebTokenError(`Unsupported algorithm: ${alg}`);
78
+ }
79
+ if (typeof secret !== "string" || secret.length === 0) {
80
+ throw new JsonWebTokenError("secretOrPrivateKey must be provided");
81
+ }
82
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
83
+ throw new JsonWebTokenError("payload must be a plain object");
84
+ }
85
+ const claims = { ...payload };
86
+ const noTimestamp = options?.noTimestamp ?? false;
87
+ if (!noTimestamp && claims.iat === undefined) {
88
+ claims.iat = Math.floor(Date.now() / 1000);
89
+ }
90
+ if (options?.expiresIn !== undefined) {
91
+ if (claims.exp !== undefined) {
92
+ throw new JsonWebTokenError("Bad options.expiresIn option the payload already has an exp property");
93
+ }
94
+ const offset = parseDurationSeconds(options.expiresIn);
95
+ const iatRef = typeof claims.iat === "number" ? claims.iat : Math.floor(Date.now() / 1000);
96
+ claims.exp = iatRef + offset;
97
+ }
98
+ const header = { alg, typ: "JWT" };
99
+ const headerB64 = b64urlEncode(JSON.stringify(header));
100
+ const payloadB64 = b64urlEncode(JSON.stringify(claims));
101
+ const sig = createHmac(hmacForAlg(alg), secret)
102
+ .update(`${headerB64}.${payloadB64}`)
103
+ .digest();
104
+ return `${headerB64}.${payloadB64}.${b64urlEncode(sig)}`;
105
+ }
106
+ export function verify(token, secret, options) {
107
+ if (typeof token !== "string" || token.length === 0) {
108
+ throw new JsonWebTokenError("jwt must be provided");
109
+ }
110
+ if (typeof secret !== "string" || secret.length === 0) {
111
+ throw new JsonWebTokenError("secret must be provided");
112
+ }
113
+ const parts = token.split(".");
114
+ if (parts.length !== 3)
115
+ throw new JsonWebTokenError("jwt malformed");
116
+ const [headerB64, payloadB64, sigB64] = parts;
117
+ let header;
118
+ try {
119
+ header = JSON.parse(b64urlDecodeToBuffer(headerB64).toString("utf8"));
120
+ }
121
+ catch {
122
+ throw new JsonWebTokenError("invalid token");
123
+ }
124
+ const allowed = (options?.algorithms ?? ["HS256"]);
125
+ if (typeof header.alg !== "string" || !allowed.includes(header.alg)) {
126
+ throw new JsonWebTokenError("invalid algorithm");
127
+ }
128
+ if (header.alg !== "HS256" && header.alg !== "HS512") {
129
+ throw new JsonWebTokenError("invalid algorithm");
130
+ }
131
+ const expected = createHmac(hmacForAlg(header.alg), secret)
132
+ .update(`${headerB64}.${payloadB64}`)
133
+ .digest();
134
+ let got;
135
+ try {
136
+ got = b64urlDecodeToBuffer(sigB64);
137
+ }
138
+ catch {
139
+ throw new JsonWebTokenError("invalid signature");
140
+ }
141
+ if (got.length !== expected.length || !timingSafeEqual(got, expected)) {
142
+ throw new JsonWebTokenError("invalid signature");
143
+ }
144
+ let payload;
145
+ try {
146
+ payload = JSON.parse(b64urlDecodeToBuffer(payloadB64).toString("utf8"));
147
+ }
148
+ catch {
149
+ throw new JsonWebTokenError("invalid token");
150
+ }
151
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
152
+ throw new JsonWebTokenError("invalid token");
153
+ }
154
+ const clockTolerance = options?.clockTolerance ?? 0;
155
+ const now = Math.floor(Date.now() / 1000);
156
+ if (typeof payload.exp === "number" && payload.exp + clockTolerance < now) {
157
+ throw new TokenExpiredError("jwt expired", new Date(payload.exp * 1000));
158
+ }
159
+ if (typeof payload.nbf === "number" && payload.nbf - clockTolerance > now) {
160
+ throw new NotBeforeError("jwt not active", new Date(payload.nbf * 1000));
161
+ }
162
+ if (options?.issuer !== undefined && payload.iss !== options.issuer) {
163
+ throw new JsonWebTokenError(`jwt issuer invalid. expected: ${options.issuer}`);
164
+ }
165
+ if (options?.audience !== undefined) {
166
+ const wantArr = Array.isArray(options.audience) ? options.audience : [options.audience];
167
+ const haveArr = Array.isArray(payload.aud)
168
+ ? payload.aud
169
+ : payload.aud !== undefined
170
+ ? [payload.aud]
171
+ : [];
172
+ if (!wantArr.some((w) => haveArr.includes(w))) {
173
+ throw new JsonWebTokenError("jwt audience invalid");
174
+ }
175
+ }
176
+ return payload;
177
+ }
178
+ export function decode(token) {
179
+ if (typeof token !== "string")
180
+ return null;
181
+ const parts = token.split(".");
182
+ if (parts.length !== 3)
183
+ return null;
184
+ try {
185
+ const decoded = JSON.parse(b64urlDecodeToBuffer(parts[1]).toString("utf8"));
186
+ if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded))
187
+ return null;
188
+ return decoded;
189
+ }
190
+ catch {
191
+ return null;
192
+ }
193
+ }
194
+ const jwt = { sign, verify, decode };
195
+ export default jwt;
196
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/lib/jwt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * SSR request context primitive — capability `functions-sdk-auth-model`.
3
+ *
4
+ * The SSR Lambda runtime establishes this context via `als.run(...)`
5
+ * BEFORE importing or executing the Astro server bundle (or any other
6
+ * user-supplied code). SDK functions that need request-scoped state
7
+ * (`db()`, `getUser()`, `cache.*`, `assets.*`, `email.*`, `ai.*`) read
8
+ * from `getCurrentContext()` rather than requiring explicit context
9
+ * parameters at the call site.
10
+ *
11
+ * The `active` flag exists because Node's AsyncLocalStorage propagates
12
+ * into timers, microtasks, and unawaited promises created inside
13
+ * `als.run()`. Without an explicit flag, a `setTimeout(() => db()..., 60_000)`
14
+ * scheduled inside a handler would, when the timer fires later, still
15
+ * observe an `als.getStore()` pointing at the (now-completed) request —
16
+ * leading to stale or incorrect SDK behavior. The SSR runtime sets
17
+ * `active.value = false` IMMEDIATELY after the response body is fully
18
+ * materialized; SDK functions check the flag and throw
19
+ * `R402_SDK_OUTSIDE_REQUEST_CONTEXT` when it's false.
20
+ *
21
+ * Likewise `cacheBypassTainted.value` is set to `true` by `getUser()`
22
+ * and payment-primitive SDK calls during render; the SSR runtime returns
23
+ * its final value to the gateway in the Lambda response metadata envelope
24
+ * (NOT via in-process ALS — the gateway runs in a different process).
25
+ *
26
+ * @see openspec/changes/astro-ssr-runtime/specs/functions-sdk-auth-model/spec.md
27
+ * @see openspec/changes/astro-ssr-runtime/specs/routed-http-functions/spec.md
28
+ */
29
+ import { AsyncLocalStorage } from "node:async_hooks";
30
+ /** The shape stored in AsyncLocalStorage. See the spec referenced above
31
+ * for the canonical definition. */
32
+ export interface RunRequestContext {
33
+ /** Unique per-request id; matches `x-run402-request-id`. */
34
+ requestId: string;
35
+ projectId: string;
36
+ releaseId: string;
37
+ /** v1.49-negotiated locale string. `null` when the active release has
38
+ * no i18n slice. */
39
+ locale: string | null;
40
+ /** Echoed verbatim from the active release's `i18n.defaultLocale`,
41
+ * `null` when the release has no i18n slice. */
42
+ defaultLocale: string | null;
43
+ /** Validated host from the routed-function envelope — NOT the raw
44
+ * `Host` header. Cache-key host comes from here. */
45
+ host: string;
46
+ /** Request information SDK functions need (cookies for `getUser()`,
47
+ * url for invalidate path-form, etc.). Body is intentionally absent
48
+ * — user code reads body via the standard Web Request API passed to
49
+ * the handler. */
50
+ request: {
51
+ method: string;
52
+ url: string;
53
+ headers: Record<string, string | string[] | undefined>;
54
+ };
55
+ /** Mutable ref: SDK functions that read request-scoped auth or invoke
56
+ * payment primitives set `value = true`. The SSR Lambda runtime
57
+ * returns the final value to the gateway in the response metadata
58
+ * envelope. */
59
+ cacheBypassTainted: {
60
+ value: boolean;
61
+ };
62
+ /** Mutable ref: SSR runtime sets `value = false` after the response
63
+ * body has been fully materialized. SDK functions check this AND
64
+ * the store presence; either being false produces
65
+ * `R402_SDK_OUTSIDE_REQUEST_CONTEXT`. */
66
+ active: {
67
+ value: boolean;
68
+ };
69
+ }
70
+ /** The shared ALS instance. Modules in @run402/functions read from
71
+ * this; the SSR Lambda runtime (in @run402/astro) writes to it. */
72
+ export declare const als: AsyncLocalStorage<RunRequestContext>;
73
+ /**
74
+ * Read the current request context, or `undefined` if no SSR request
75
+ * is in flight. SDK functions check both this AND `active.value` to
76
+ * decide whether to honor the call.
77
+ */
78
+ export declare function getCurrentContext(): RunRequestContext | undefined;
79
+ /**
80
+ * Establish a request context and run a callback inside it. The SSR
81
+ * Lambda runtime calls this exactly once per invocation, wrapping the
82
+ * full `App.render(request)` + body-materialization sequence.
83
+ *
84
+ * The `active` flag is set to `true` initially; the caller (the SSR
85
+ * runtime) flips it to `false` after the response body is materialized.
86
+ * Don't call this from user code — it's the runtime's primitive.
87
+ */
88
+ export declare function runWithContext<T>(context: Omit<RunRequestContext, "cacheBypassTainted" | "active"> & Partial<Pick<RunRequestContext, "cacheBypassTainted" | "active">>, callback: () => Promise<T> | T): Promise<T> | T;
89
+ /**
90
+ * Throw a structured `R402_SDK_OUTSIDE_REQUEST_CONTEXT` error. Used by
91
+ * SDK functions when they're invoked with no ALS store OR while the
92
+ * context has been marked inactive.
93
+ *
94
+ * Per the api-error-envelope spec, the thrown error carries:
95
+ * - `code: 'R402_SDK_OUTSIDE_REQUEST_CONTEXT'`
96
+ * - `message`: names the SDK function and the cause
97
+ * - `suggestedFix`: recommends moving the call inside a handler OR
98
+ * not scheduling background work that outlives the response
99
+ * - `docs`: `https://docs.run402.com/sdk/errors#outside-request-context`
100
+ */
101
+ export declare class Run402OutsideRequestContextError extends Error {
102
+ readonly code = "R402_SDK_OUTSIDE_REQUEST_CONTEXT";
103
+ readonly docs = "https://docs.run402.com/sdk/errors#outside-request-context";
104
+ readonly suggestedFix: string;
105
+ readonly sdkFunction: string;
106
+ readonly cause: "no_context" | "context_inactive";
107
+ constructor(sdkFunction: string, cause: "no_context" | "context_inactive");
108
+ }
109
+ /**
110
+ * Assert that a request context is active. Returns the context on
111
+ * success; throws `Run402OutsideRequestContextError` on failure.
112
+ *
113
+ * SDK functions call this as the first line, e.g.:
114
+ *
115
+ * const ctx = requireActiveContext("db");
116
+ * // use ctx.projectId, ctx.request.headers, etc.
117
+ */
118
+ export declare function requireActiveContext(sdkFunction: string): RunRequestContext;
119
+ /**
120
+ * Flip the cache-bypass taint flag on the current context. Called by
121
+ * `getUser()` and payment-primitive SDK calls to signal that the
122
+ * rendered response depends on request-scoped auth state and therefore
123
+ * MUST NOT be cached publicly.
124
+ *
125
+ * No-op if there is no active context (rather than throwing — the taint
126
+ * is moot when there's no cache layer to inform).
127
+ */
128
+ export declare function taintCacheBypass(): void;
129
+ /**
130
+ * Canonical registry of SDK functions that are "payment primitives" for
131
+ * cache-taint purposes. Calling any of these inside an active request
132
+ * context MUST flip `cacheBypassTainted.value = true`. The set is
133
+ * defined here so the spec, runtime, and docs share one source of truth.
134
+ *
135
+ * To add a new payment primitive: append to this set AND ensure the
136
+ * function's implementation calls `taintCacheBypass()` on every entry.
137
+ *
138
+ * @see openspec/changes/astro-ssr-runtime/specs/functions-sdk-auth-model/spec.md
139
+ */
140
+ export declare const PAYMENT_PRIMITIVES: ReadonlySet<string>;
141
+ /**
142
+ * Helper for payment-primitive implementations. Wraps the body in a
143
+ * taint-on-entry call so the registry contract is enforced at the
144
+ * SDK layer rather than relying on each implementation to remember.
145
+ *
146
+ * Example:
147
+ * export const requirePayment = withPaymentTaint("payments.require", async (opts) => {
148
+ * // ... actual implementation
149
+ * });
150
+ */
151
+ export declare function withPaymentTaint<TArgs extends unknown[], TReturn>(name: string, impl: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
152
+ //# sourceMappingURL=runtime-context.d.ts.map
@@ -0,0 +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,gEAAgE;IAC7E,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"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * SSR request context primitive — capability `functions-sdk-auth-model`.
3
+ *
4
+ * The SSR Lambda runtime establishes this context via `als.run(...)`
5
+ * BEFORE importing or executing the Astro server bundle (or any other
6
+ * user-supplied code). SDK functions that need request-scoped state
7
+ * (`db()`, `getUser()`, `cache.*`, `assets.*`, `email.*`, `ai.*`) read
8
+ * from `getCurrentContext()` rather than requiring explicit context
9
+ * parameters at the call site.
10
+ *
11
+ * The `active` flag exists because Node's AsyncLocalStorage propagates
12
+ * into timers, microtasks, and unawaited promises created inside
13
+ * `als.run()`. Without an explicit flag, a `setTimeout(() => db()..., 60_000)`
14
+ * scheduled inside a handler would, when the timer fires later, still
15
+ * observe an `als.getStore()` pointing at the (now-completed) request —
16
+ * leading to stale or incorrect SDK behavior. The SSR runtime sets
17
+ * `active.value = false` IMMEDIATELY after the response body is fully
18
+ * materialized; SDK functions check the flag and throw
19
+ * `R402_SDK_OUTSIDE_REQUEST_CONTEXT` when it's false.
20
+ *
21
+ * Likewise `cacheBypassTainted.value` is set to `true` by `getUser()`
22
+ * and payment-primitive SDK calls during render; the SSR runtime returns
23
+ * its final value to the gateway in the Lambda response metadata envelope
24
+ * (NOT via in-process ALS — the gateway runs in a different process).
25
+ *
26
+ * @see openspec/changes/astro-ssr-runtime/specs/functions-sdk-auth-model/spec.md
27
+ * @see openspec/changes/astro-ssr-runtime/specs/routed-http-functions/spec.md
28
+ */
29
+ import { AsyncLocalStorage } from "node:async_hooks";
30
+ /** The shared ALS instance. Modules in @run402/functions read from
31
+ * this; the SSR Lambda runtime (in @run402/astro) writes to it. */
32
+ export const als = new AsyncLocalStorage();
33
+ /**
34
+ * Read the current request context, or `undefined` if no SSR request
35
+ * is in flight. SDK functions check both this AND `active.value` to
36
+ * decide whether to honor the call.
37
+ */
38
+ export function getCurrentContext() {
39
+ return als.getStore();
40
+ }
41
+ /**
42
+ * Establish a request context and run a callback inside it. The SSR
43
+ * Lambda runtime calls this exactly once per invocation, wrapping the
44
+ * full `App.render(request)` + body-materialization sequence.
45
+ *
46
+ * The `active` flag is set to `true` initially; the caller (the SSR
47
+ * runtime) flips it to `false` after the response body is materialized.
48
+ * Don't call this from user code — it's the runtime's primitive.
49
+ */
50
+ export function runWithContext(context, callback) {
51
+ const full = {
52
+ ...context,
53
+ cacheBypassTainted: context.cacheBypassTainted ?? { value: false },
54
+ active: context.active ?? { value: true },
55
+ };
56
+ return als.run(full, callback);
57
+ }
58
+ /**
59
+ * Throw a structured `R402_SDK_OUTSIDE_REQUEST_CONTEXT` error. Used by
60
+ * SDK functions when they're invoked with no ALS store OR while the
61
+ * context has been marked inactive.
62
+ *
63
+ * Per the api-error-envelope spec, the thrown error carries:
64
+ * - `code: 'R402_SDK_OUTSIDE_REQUEST_CONTEXT'`
65
+ * - `message`: names the SDK function and the cause
66
+ * - `suggestedFix`: recommends moving the call inside a handler OR
67
+ * not scheduling background work that outlives the response
68
+ * - `docs`: `https://docs.run402.com/sdk/errors#outside-request-context`
69
+ */
70
+ export class Run402OutsideRequestContextError extends Error {
71
+ code = "R402_SDK_OUTSIDE_REQUEST_CONTEXT";
72
+ docs = "https://docs.run402.com/sdk/errors#outside-request-context";
73
+ suggestedFix;
74
+ sdkFunction;
75
+ cause;
76
+ constructor(sdkFunction, cause) {
77
+ const causeMsg = cause === "no_context"
78
+ ? "no active request context (called from module scope or outside a handler)"
79
+ : "request context marked inactive (called from a timer or unawaited promise after response completion)";
80
+ super(`${sdkFunction}: ${causeMsg}`);
81
+ this.name = "Run402OutsideRequestContextError";
82
+ this.sdkFunction = sdkFunction;
83
+ this.cause = cause;
84
+ this.suggestedFix =
85
+ cause === "no_context"
86
+ ? `Move the ${sdkFunction} call inside an HTTP request handler or Astro frontmatter. SDK functions cannot resolve project context outside an active request.`
87
+ : `The request that called ${sdkFunction} has already returned. Don't schedule SDK calls in setTimeout / setInterval / unawaited promises that outlive the handler.`;
88
+ }
89
+ }
90
+ /**
91
+ * Assert that a request context is active. Returns the context on
92
+ * success; throws `Run402OutsideRequestContextError` on failure.
93
+ *
94
+ * SDK functions call this as the first line, e.g.:
95
+ *
96
+ * const ctx = requireActiveContext("db");
97
+ * // use ctx.projectId, ctx.request.headers, etc.
98
+ */
99
+ export function requireActiveContext(sdkFunction) {
100
+ const ctx = als.getStore();
101
+ if (ctx === undefined) {
102
+ throw new Run402OutsideRequestContextError(sdkFunction, "no_context");
103
+ }
104
+ if (!ctx.active.value) {
105
+ throw new Run402OutsideRequestContextError(sdkFunction, "context_inactive");
106
+ }
107
+ return ctx;
108
+ }
109
+ /**
110
+ * Flip the cache-bypass taint flag on the current context. Called by
111
+ * `getUser()` and payment-primitive SDK calls to signal that the
112
+ * rendered response depends on request-scoped auth state and therefore
113
+ * MUST NOT be cached publicly.
114
+ *
115
+ * No-op if there is no active context (rather than throwing — the taint
116
+ * is moot when there's no cache layer to inform).
117
+ */
118
+ export function taintCacheBypass() {
119
+ const ctx = als.getStore();
120
+ if (ctx !== undefined) {
121
+ ctx.cacheBypassTainted.value = true;
122
+ }
123
+ }
124
+ /**
125
+ * Canonical registry of SDK functions that are "payment primitives" for
126
+ * cache-taint purposes. Calling any of these inside an active request
127
+ * context MUST flip `cacheBypassTainted.value = true`. The set is
128
+ * defined here so the spec, runtime, and docs share one source of truth.
129
+ *
130
+ * To add a new payment primitive: append to this set AND ensure the
131
+ * function's implementation calls `taintCacheBypass()` on every entry.
132
+ *
133
+ * @see openspec/changes/astro-ssr-runtime/specs/functions-sdk-auth-model/spec.md
134
+ */
135
+ export const PAYMENT_PRIMITIVES = new Set([
136
+ // None implemented yet — the registry exists so the contract is
137
+ // explicit and discoverable. Payment-primitive SDK functions added
138
+ // in future changes (per Run402 x402/MPP roadmap) will register here
139
+ // as they land.
140
+ // Example future entries (commented to keep the set actually empty
141
+ // until the helpers ship):
142
+ // "payments.require",
143
+ // "payments.gate",
144
+ // "payments.fulfill",
145
+ ]);
146
+ /**
147
+ * Helper for payment-primitive implementations. Wraps the body in a
148
+ * taint-on-entry call so the registry contract is enforced at the
149
+ * SDK layer rather than relying on each implementation to remember.
150
+ *
151
+ * Example:
152
+ * export const requirePayment = withPaymentTaint("payments.require", async (opts) => {
153
+ * // ... actual implementation
154
+ * });
155
+ */
156
+ export function withPaymentTaint(name, impl) {
157
+ if (!PAYMENT_PRIMITIVES.has(name)) {
158
+ // Doesn't throw — adding a new primitive is a code change and the
159
+ // dev sees this on first invocation. Throwing would block legitimate
160
+ // experimentation. But emit a warning so the registry stays correct.
161
+ // eslint-disable-next-line no-console
162
+ console.warn(`[run402] withPaymentTaint("${name}") called but "${name}" is not in PAYMENT_PRIMITIVES. ` +
163
+ `Add it to packages/functions/src/runtime-context.ts to keep the cache-taint registry consistent.`);
164
+ }
165
+ return (...args) => {
166
+ taintCacheBypass();
167
+ return impl(...args);
168
+ };
169
+ }
170
+ //# sourceMappingURL=runtime-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"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"}