@farthershore/backend 0.16.0 → 0.18.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/CHANGELOG.md CHANGED
@@ -4,6 +4,37 @@ All notable changes to the runtime backend SDK are documented here. This SDK
4
4
  versions independently from the frontend and business SDKs. Pre-1.0: minor
5
5
  versions may include breaking changes.
6
6
 
7
+ ## [0.18.0]
8
+
9
+ ### Added
10
+
11
+ - `createExpressMiddleware` accepts `onVerificationError`, called when
12
+ verification REJECTS a request with the diagnostic detail the response body
13
+ deliberately withholds (`{ code, message, status, method, path }`).
14
+
15
+ The wire body stays `{ error: <code> }` — several distinct causes share one
16
+ code (`route_mismatch` covers a business mismatch, a backend mismatch, AND an
17
+ unserved route id) and the specifics must not leak to an unauthenticated
18
+ caller. Previously they were discarded entirely, leaving the operator no way
19
+ to tell which cause fired even in their own logs. Defaults to a one-line
20
+ `console.warn`; pass a function to route it into a structured logger, or
21
+ `() => {}` to silence it. A throwing reporter cannot turn a 401 into a 500.
22
+
23
+ ## [0.17.0]
24
+
25
+ ### Changed — BREAKING
26
+
27
+ - `RUNTIME_TOKEN_CAPABILITIES` is renamed `RUNTIME_TOKEN_OPERATIONS`, and the
28
+ type `RuntimeTokenCapability` is renamed `RuntimeTokenOperation`. The values
29
+ are operations, not capabilities, and the old names contradicted the runtime
30
+ contract they mirror. Update imports; no behaviour change.
31
+
32
+ ### Added
33
+
34
+ - `credentialKind()` and `isPortalSession()` — route-surface credential-kind
35
+ derivation from the signed principal. No new claim is required; both are
36
+ derived from what the gateway already signs.
37
+
7
38
  ## [0.16.0]
8
39
 
9
40
  Consumer-principal runtime. Every verified request now carries a typed
package/README.md CHANGED
@@ -12,7 +12,7 @@ graceful lifecycle (health + shutdown). Everything else — your business, backe
12
12
  and environment ids, the verification keys, and the metering endpoint — is
13
13
  fetched automatically from the token at startup.
14
14
 
15
- > **Status: `0.16.0`.** Pre-1.0: minor releases may include breaking changes, so
15
+ > **Status: `0.18.0`.** Pre-1.0: minor releases may include breaking changes, so
16
16
  > pin this package to an exact version (or a patch-only range) and upgrade
17
17
  > deliberately.
18
18
 
@@ -18,7 +18,9 @@ var FartherShoreError = class extends Error {
18
18
  }
19
19
  };
20
20
  function statusForCode(code) {
21
- return code === "body_too_large" ? 413 : 401;
21
+ if (code === "body_too_large") return 413;
22
+ if (code === "surface_not_allowed") return 403;
23
+ return 401;
22
24
  }
23
25
 
24
26
  // src/core/permissions.ts
@@ -83,15 +85,27 @@ async function runMiddleware(fs, options, req, res, next) {
83
85
  stripFartherShoreHeaders(req);
84
86
  next();
85
87
  } catch (error) {
86
- fail(res, error);
88
+ fail(res, error, options, req);
87
89
  }
88
90
  }
89
- function fail(res, error) {
90
- if (error instanceof FartherShoreError) {
91
- res.status(error.status).json({ error: error.code });
92
- return;
91
+ function fail(res, error, options, req) {
92
+ const code = error instanceof FartherShoreError ? error.code : "bad_signature";
93
+ const status = error instanceof FartherShoreError ? error.status : 401;
94
+ const message = error instanceof Error && error.message ? error.message : code;
95
+ const report = options.onVerificationError ?? ((d) => {
96
+ console.warn(`[farthershore] request rejected (${d.code}): ${d.message}`);
97
+ });
98
+ try {
99
+ report({
100
+ code,
101
+ message,
102
+ status,
103
+ method: req.method ?? "",
104
+ path: req.url ?? ""
105
+ });
106
+ } catch {
93
107
  }
94
- res.status(401).json({ error: "bad_signature" });
108
+ res.status(status).json({ error: code });
95
109
  }
96
110
  function stripFartherShoreHeaders(req) {
97
111
  const headers = req.headers;
@@ -166,7 +166,8 @@ var RUNTIME_ERROR_CODES = {
166
166
  invalidToken: "invalid_token",
167
167
  contextUnverified: "context_unverified",
168
168
  memberSubjectRequired: "member_subject_required",
169
- serviceSubjectRequired: "service_subject_required"
169
+ serviceSubjectRequired: "service_subject_required",
170
+ surfaceNotAllowed: "surface_not_allowed"
170
171
  };
171
172
  var RUNTIME_METERING_CONTRACT = {
172
173
  endpoint: "/v1/metering/events",
package/dist/index.js CHANGED
@@ -217,7 +217,8 @@ var RUNTIME_ERROR_CODES = {
217
217
  invalidToken: "invalid_token",
218
218
  contextUnverified: "context_unverified",
219
219
  memberSubjectRequired: "member_subject_required",
220
- serviceSubjectRequired: "service_subject_required"
220
+ serviceSubjectRequired: "service_subject_required",
221
+ surfaceNotAllowed: "surface_not_allowed"
221
222
  };
222
223
  var RUNTIME_RESPONSE_METERING_CONTRACT = {
223
224
  headers: {
@@ -284,7 +285,9 @@ var RUNTIME_ERROR_CODE_TO_ERROR_CODE = {
284
285
  [RUNTIME_ERROR_CODES.bodyTooLarge]: "VALIDATION_ERROR",
285
286
  // Consumer-principal wave — route subject-requirement faults → FORBIDDEN (403).
286
287
  [RUNTIME_ERROR_CODES.memberSubjectRequired]: "FORBIDDEN",
287
- [RUNTIME_ERROR_CODES.serviceSubjectRequired]: "FORBIDDEN"
288
+ [RUNTIME_ERROR_CODES.serviceSubjectRequired]: "FORBIDDEN",
289
+ // A visible route whose surface set excludes the caller → 403.
290
+ [RUNTIME_ERROR_CODES.surfaceNotAllowed]: "FORBIDDEN"
288
291
  };
289
292
  function runtimeErrorToErrorCode(code) {
290
293
  return RUNTIME_ERROR_CODE_TO_ERROR_CODE[code] ?? "INTERNAL_ERROR";
@@ -294,16 +297,16 @@ var RUNTIME_TOKEN_PREFIXES = {
294
297
  live: "fsrt_live_",
295
298
  test: "fsrt_test_"
296
299
  };
297
- var RUNTIME_TOKEN_CAPABILITIES = [
300
+ var RUNTIME_TOKEN_OPERATIONS = [
298
301
  "gateway_verification",
299
302
  "metering",
300
303
  "health",
301
304
  "tunnel",
302
- // Hand-maintained mirror of @farthershore/contracts RUNTIME_TOKEN_CAPABILITIES
305
+ // Hand-maintained mirror of @farthershore/contracts RUNTIME_TOKEN_OPERATIONS
303
306
  // (`runtime.ts`). Bound to that source by the SET-EQUALITY + ORDER assertions
304
307
  // in `deny-taxonomy-drift.test.ts` (test-only contracts devDep) — NOT by the
305
308
  // generated runtime-contract.ts, which mirrors only RUNTIME_ERROR_CODES.
306
- // `drift_report` is the opt-in capability for reporting route drift.
309
+ // `drift_report` is the opt-in operation for reporting route drift.
307
310
  "drift_report"
308
311
  ];
309
312
  var RUNTIME_HEADER_NAMES = {
@@ -457,7 +460,9 @@ var FartherShoreError = class extends Error {
457
460
  }
458
461
  };
459
462
  function statusForCode(code) {
460
- return code === "body_too_large" ? 413 : 401;
463
+ if (code === "body_too_large") return 413;
464
+ if (code === "surface_not_allowed") return 403;
465
+ return 401;
461
466
  }
462
467
 
463
468
  // src/core/bootstrap.ts
@@ -1913,8 +1918,7 @@ function headerGetter(headers) {
1913
1918
 
1914
1919
  // src/core/runtime.ts
1915
1920
  var DEFAULT_CORE_URL = "https://core.farthershore.com";
1916
- var SDK_VERSION = "0.16.0".length > 0 ? "0.16.0" : "0.0.0-dev";
1917
- var CONTRACTS_FP = "c3961d4ea07ff178".length > 0 ? "c3961d4ea07ff178" : "0000000000000000";
1921
+ var SDK_VERSION = "0.18.0".length > 0 ? "0.18.0" : "0.0.0-dev";
1918
1922
  var FartherShore = class {
1919
1923
  bootstrapClient;
1920
1924
  fetchImpl;
@@ -2272,15 +2276,27 @@ async function runMiddleware(fs, options, req, res, next) {
2272
2276
  stripFartherShoreHeaders(req);
2273
2277
  next();
2274
2278
  } catch (error) {
2275
- fail(res, error);
2279
+ fail(res, error, options, req);
2276
2280
  }
2277
2281
  }
2278
- function fail(res, error) {
2279
- if (error instanceof FartherShoreError) {
2280
- res.status(error.status).json({ error: error.code });
2281
- return;
2282
+ function fail(res, error, options, req) {
2283
+ const code = error instanceof FartherShoreError ? error.code : "bad_signature";
2284
+ const status = error instanceof FartherShoreError ? error.status : 401;
2285
+ const message = error instanceof Error && error.message ? error.message : code;
2286
+ const report = options.onVerificationError ?? ((d) => {
2287
+ console.warn(`[farthershore] request rejected (${d.code}): ${d.message}`);
2288
+ });
2289
+ try {
2290
+ report({
2291
+ code,
2292
+ message,
2293
+ status,
2294
+ method: req.method ?? "",
2295
+ path: req.url ?? ""
2296
+ });
2297
+ } catch {
2282
2298
  }
2283
- res.status(401).json({ error: "bad_signature" });
2299
+ res.status(status).json({ error: code });
2284
2300
  }
2285
2301
  function stripFartherShoreHeaders(req) {
2286
2302
  const headers = req.headers;
@@ -2378,6 +2394,16 @@ function requireService(ctx) {
2378
2394
  }
2379
2395
  return subject;
2380
2396
  }
2397
+ function credentialKind(ctx) {
2398
+ const subject = ctx.principal?.subject;
2399
+ if (!subject) return void 0;
2400
+ if (subject.kind === "service") return "api_key";
2401
+ return subject.via === "session" ? "portal_session" : "api_key";
2402
+ }
2403
+ function isPortalSession(ctx) {
2404
+ const kind = credentialKind(ctx);
2405
+ return kind === void 0 ? void 0 : kind === "portal_session";
2406
+ }
2381
2407
 
2382
2408
  // src/testing/signers.ts
2383
2409
  import { generateKeyPairSync, randomBytes } from "node:crypto";
@@ -2652,7 +2678,7 @@ function createDevGateway(options) {
2652
2678
  name: "Dev Backend"
2653
2679
  },
2654
2680
  environment: { id: null, kind: "test" },
2655
- capabilities: ["gateway_verification", "metering", "health"],
2681
+ operations: ["gateway_verification", "metering", "health"],
2656
2682
  verification: {
2657
2683
  required: options.mode === "simulated",
2658
2684
  jwksUrl: DEV_JWKS_URL,
@@ -3185,7 +3211,7 @@ export {
3185
3211
  RUNTIME_ERROR_CODE_TO_ERROR_CODE,
3186
3212
  RUNTIME_HEADER_NAMES,
3187
3213
  RUNTIME_REPLAY_WINDOW_SECONDS,
3188
- RUNTIME_TOKEN_CAPABILITIES,
3214
+ RUNTIME_TOKEN_OPERATIONS,
3189
3215
  RUNTIME_TOKEN_PREFIXES,
3190
3216
  STREAMING_EXEMPT_BODY_HASH,
3191
3217
  ShutdownManager,
@@ -3196,11 +3222,13 @@ export {
3196
3222
  createExpressHandler,
3197
3223
  createExpressMiddleware,
3198
3224
  createUsage,
3225
+ credentialKind,
3199
3226
  decodeContextClaims,
3200
3227
  fartherShore,
3201
3228
  hasPermission,
3202
3229
  hashBody2 as hashBody,
3203
3230
  initFromEnv2 as initFromEnv,
3231
+ isPortalSession,
3204
3232
  nodeSpawn,
3205
3233
  permissionGrants,
3206
3234
  permissionSatisfies,
@@ -220,7 +220,8 @@ var RUNTIME_ERROR_CODES = {
220
220
  invalidToken: "invalid_token",
221
221
  contextUnverified: "context_unverified",
222
222
  memberSubjectRequired: "member_subject_required",
223
- serviceSubjectRequired: "service_subject_required"
223
+ serviceSubjectRequired: "service_subject_required",
224
+ surfaceNotAllowed: "surface_not_allowed"
224
225
  };
225
226
  var RUNTIME_RESPONSE_METERING_CONTRACT = {
226
227
  headers: {
@@ -287,7 +288,9 @@ var RUNTIME_ERROR_CODE_TO_ERROR_CODE = {
287
288
  [RUNTIME_ERROR_CODES.bodyTooLarge]: "VALIDATION_ERROR",
288
289
  // Consumer-principal wave — route subject-requirement faults → FORBIDDEN (403).
289
290
  [RUNTIME_ERROR_CODES.memberSubjectRequired]: "FORBIDDEN",
290
- [RUNTIME_ERROR_CODES.serviceSubjectRequired]: "FORBIDDEN"
291
+ [RUNTIME_ERROR_CODES.serviceSubjectRequired]: "FORBIDDEN",
292
+ // A visible route whose surface set excludes the caller → 403.
293
+ [RUNTIME_ERROR_CODES.surfaceNotAllowed]: "FORBIDDEN"
291
294
  };
292
295
  var FS_RUNTIME_TOKEN_ENV = "FS_RUNTIME_TOKEN";
293
296
  var RUNTIME_TOKEN_PREFIXES = {
@@ -444,7 +447,9 @@ var FartherShoreError = class extends Error {
444
447
  }
445
448
  };
446
449
  function statusForCode(code) {
447
- return code === "body_too_large" ? 413 : 401;
450
+ if (code === "body_too_large") return 413;
451
+ if (code === "surface_not_allowed") return 403;
452
+ return 401;
448
453
  }
449
454
 
450
455
  // src/core/jwks.ts
@@ -868,7 +873,7 @@ function createDevGateway(options) {
868
873
  name: "Dev Backend"
869
874
  },
870
875
  environment: { id: null, kind: "test" },
871
- capabilities: ["gateway_verification", "metering", "health"],
876
+ operations: ["gateway_verification", "metering", "health"],
872
877
  verification: {
873
878
  required: options.mode === "simulated",
874
879
  jwksUrl: DEV_JWKS_URL,
@@ -2144,8 +2149,7 @@ function headerGetter(headers) {
2144
2149
 
2145
2150
  // src/core/runtime.ts
2146
2151
  var DEFAULT_CORE_URL = "https://core.farthershore.com";
2147
- var SDK_VERSION = "0.16.0".length > 0 ? "0.16.0" : "0.0.0-dev";
2148
- var CONTRACTS_FP = "c3961d4ea07ff178".length > 0 ? "c3961d4ea07ff178" : "0000000000000000";
2152
+ var SDK_VERSION = "0.18.0".length > 0 ? "0.18.0" : "0.0.0-dev";
2149
2153
  var FartherShore = class {
2150
2154
  bootstrapClient;
2151
2155
  fetchImpl;
@@ -2498,15 +2502,27 @@ async function runMiddleware(fs, options, req, res, next) {
2498
2502
  stripFartherShoreHeaders(req);
2499
2503
  next();
2500
2504
  } catch (error) {
2501
- fail(res, error);
2505
+ fail(res, error, options, req);
2502
2506
  }
2503
2507
  }
2504
- function fail(res, error) {
2505
- if (error instanceof FartherShoreError) {
2506
- res.status(error.status).json({ error: error.code });
2507
- return;
2508
+ function fail(res, error, options, req) {
2509
+ const code = error instanceof FartherShoreError ? error.code : "bad_signature";
2510
+ const status = error instanceof FartherShoreError ? error.status : 401;
2511
+ const message = error instanceof Error && error.message ? error.message : code;
2512
+ const report = options.onVerificationError ?? ((d) => {
2513
+ console.warn(`[farthershore] request rejected (${d.code}): ${d.message}`);
2514
+ });
2515
+ try {
2516
+ report({
2517
+ code,
2518
+ message,
2519
+ status,
2520
+ method: req.method ?? "",
2521
+ path: req.url ?? ""
2522
+ });
2523
+ } catch {
2508
2524
  }
2509
- res.status(401).json({ error: "bad_signature" });
2525
+ res.status(status).json({ error: code });
2510
2526
  }
2511
2527
  function stripFartherShoreHeaders(req) {
2512
2528
  const headers = req.headers;
@@ -36,6 +36,27 @@ export type MiddlewareOptions = {
36
36
  * consumes no identity; the secure default is strict.
37
37
  */
38
38
  always?: boolean;
39
+ /**
40
+ * Called when verification REJECTS a request, with the diagnostic detail that
41
+ * is deliberately withheld from the response body.
42
+ *
43
+ * The wire response is only `{ error: <code> }` — several distinct causes
44
+ * share one code (`route_mismatch` covers a business mismatch, a backend
45
+ * mismatch, AND an unserved route id), and the specifics must not leak to an
46
+ * unauthenticated caller. But discarding them entirely leaves the operator
47
+ * with no way to tell which cause fired, in their OWN logs, for their OWN
48
+ * server. That is what this hook restores.
49
+ *
50
+ * Defaults to a one-line `console.warn`. Pass a function to route it into a
51
+ * structured logger, or `() => {}` to silence it.
52
+ */
53
+ onVerificationError?: (detail: {
54
+ code: string;
55
+ message: string;
56
+ status: number;
57
+ method: string;
58
+ path: string;
59
+ }) => void;
39
60
  };
40
61
  /**
41
62
  * A verified request context whose {@link ConsumerPrincipal} is GUARANTEED
@@ -21,6 +21,9 @@ export declare class FartherShoreError extends Error {
21
21
  }
22
22
  /**
23
23
  * Map a runtime error code to its fail-closed HTTP status. Oversized bodies are
24
- * the only non-401 (413); all other verification failures are 401.
24
+ * 413; a wrong-credential-surface denial is 403 (the caller IS authenticated,
25
+ * just not on a surface this route admits — mirrors the canonical
26
+ * `surface_not_allowed → FORBIDDEN` mapping in contracts/error-codes.ts);
27
+ * all other verification failures are 401.
25
28
  */
26
29
  export declare function statusForCode(code: RuntimeErrorCode): number;
@@ -69,7 +69,6 @@ export type FartherShoreInitOptions = {
69
69
  nonceStore?: NonceStore;
70
70
  };
71
71
  export declare const SDK_VERSION: string;
72
- export declare const CONTRACTS_FP: string;
73
72
  /**
74
73
  * The runtime instance. Lazily bootstraps; holds the JWKS client, nonce cache,
75
74
  * metering buffer, and shutdown hooks.
@@ -23,3 +23,23 @@ export declare function requireMember(ctx: PrincipalCarrier): MemberSubject;
23
23
  * Throws `service_subject_required` when the subject is a member (or absent).
24
24
  */
25
25
  export declare function requireService(ctx: PrincipalCarrier): ServiceSubject;
26
+ /**
27
+ * The credential SURFACE behind a verified request, DERIVED from the signed
28
+ * principal (route-surfaces wave) — no new claim, no spoofable header. A member
29
+ * subject carries `via`; a service subject is always key-borne. Returns
30
+ * `undefined` when the request carried no verified principal (identity-less), so
31
+ * a caller can distinguish "not a portal session" from "unknown".
32
+ *
33
+ * - `"portal_session"` ⟺ a member via a browser session (`fsc_`).
34
+ * - `"api_key"` ⟺ a member's personal key OR any service key (`fsk_`).
35
+ */
36
+ export declare function credentialKind(ctx: PrincipalCarrier): "portal_session" | "api_key" | undefined;
37
+ /**
38
+ * True when the verified request came from the managed portal UI (a member
39
+ * browser session), false when it came from an API key, and `undefined` when
40
+ * there is no verified principal. Convenience over {@link credentialKind} for
41
+ * the common portal-vs-API branch (e.g. richer UI payloads for portal callers).
42
+ * The gateway's `enforce-surface` middleware is the SECURITY boundary; this is
43
+ * for in-handler ergonomics.
44
+ */
45
+ export declare function isPortalSession(ctx: PrincipalCarrier): boolean | undefined;
@@ -140,6 +140,7 @@ export declare const RUNTIME_ERROR_CODES: {
140
140
  readonly contextUnverified: "context_unverified";
141
141
  readonly memberSubjectRequired: "member_subject_required";
142
142
  readonly serviceSubjectRequired: "service_subject_required";
143
+ readonly surfaceNotAllowed: "surface_not_allowed";
143
144
  };
144
145
  export type RuntimeErrorCode = (typeof RUNTIME_ERROR_CODES)[keyof typeof RUNTIME_ERROR_CODES];
145
146
  export declare const RUNTIME_METERING_CONTRACT: {
@@ -6,7 +6,7 @@ export { FartherShoreError, statusForCode } from "./core/errors.js";
6
6
  export { verifyRequest, type VerifyRequestInput, type VerifyRequestDeps, type FartherShoreRequestContext, type HeadersLike, } from "./core/verifyRequest.js";
7
7
  export { verifyContext, decodeContextClaims, principalFromContextClaims, } from "./core/verifyContext.js";
8
8
  export type { FartherShoreSignedContext, ConsumerPrincipal, } from "./core/verifyContext.js";
9
- export { requireMember, requireService, type MemberSubject, type ServiceSubject, type PrincipalCarrier, } from "./core/subject.js";
9
+ export { requireMember, requireService, credentialKind, isPortalSession, type MemberSubject, type ServiceSubject, type PrincipalCarrier, } from "./core/subject.js";
10
10
  export { hasPermission, requirePermission, permissionGrants, permissionSatisfies, FartherShorePermissionError, type PermissionCarrier, } from "./core/permissions.js";
11
11
  export { JwksClient, type Jwk, type JwksClientOptions } from "./core/jwks.js";
12
12
  export { NonceCache, type NonceCacheOptions, type NonceStore, } from "./core/nonceCache.js";
@@ -18,7 +18,7 @@ export { ShutdownManager, type ShutdownHook } from "./core/shutdown.js";
18
18
  export { CloudflaredSupervisor, nodeSpawn, REDACTED_TOKEN, type SpawnFn, type SpawnedTunnelProcess, type CloudflaredSupervisorOptions, type TunnelState, type TunnelStatus, } from "./core/tunnel.js";
19
19
  export type { FartherShoreTunnelOptions } from "./core/runtime.js";
20
20
  export { createExpressMiddleware, createExpressHandler, type ExpressMiddleware, type ExpressRequestLike, type ExpressResponseLike, type ExpressNext, type MiddlewareOptions, type VerifiedExpressHandler, type VerifiedPrincipalContext, } from "./adapters/express.js";
21
- export { FS_RUNTIME_TOKEN_ENV, RUNTIME_TOKEN_PREFIXES, RUNTIME_TOKEN_CAPABILITIES, RUNTIME_HEADER_NAMES, RUNTIME_CLOCK_SKEW_SECONDS, RUNTIME_REPLAY_WINDOW_SECONDS, EMPTY_BODY_SHA256, STREAMING_EXEMPT_BODY_HASH, MAX_BODY_BYTES, type RuntimeErrorCode, type RuntimeTokenCapability, type CanonicalSigningInput, type RuntimeBootstrapResponse, type RuntimeMeteringEvent, type RuntimeHealthReport, type TransportMode, RUNTIME_ERROR_CODE_TO_ERROR_CODE, runtimeErrorToErrorCode, type LimitDescriptor, type RuntimeMappedErrorCode, } from "./runtime-types.js";
21
+ export { FS_RUNTIME_TOKEN_ENV, RUNTIME_TOKEN_PREFIXES, RUNTIME_TOKEN_OPERATIONS, RUNTIME_HEADER_NAMES, RUNTIME_CLOCK_SKEW_SECONDS, RUNTIME_REPLAY_WINDOW_SECONDS, EMPTY_BODY_SHA256, STREAMING_EXEMPT_BODY_HASH, MAX_BODY_BYTES, type RuntimeErrorCode, type RuntimeTokenOperation, type CanonicalSigningInput, type RuntimeBootstrapResponse, type RuntimeMeteringEvent, type RuntimeHealthReport, type TransportMode, RUNTIME_ERROR_CODE_TO_ERROR_CODE, runtimeErrorToErrorCode, type LimitDescriptor, type RuntimeMappedErrorCode, } from "./runtime-types.js";
22
22
  export { RUNTIME_ERROR_CODES } from "./generated/runtime-contract.js";
23
23
  export { hashBody, buildCanonicalSigningString, canonicalizeQuery, signCanonicalString, verifyCanonicalSignature, runtimeTokenKind, } from "./runtime-signing.js";
24
24
  export { createUsage, withUsage, computeMeteringHeaders, MeteringError, METERING_PAYLOAD_HEADER, METERING_SIGNATURE_HEADER, METERING_TOKEN_HEADER, DEFAULT_TOKEN_ENV, type UsageMap, type UsageReporter, type MeteringOptions, type MeteringHeaders, type ComputeMeteringOptions, type ResponseMeteringUsagePayload, } from "./response-metering.js";
@@ -119,8 +119,8 @@ export declare const RUNTIME_TOKEN_PREFIXES: {
119
119
  readonly test: "fsrt_test_";
120
120
  };
121
121
  export type RuntimeTokenKind = keyof typeof RUNTIME_TOKEN_PREFIXES;
122
- export declare const RUNTIME_TOKEN_CAPABILITIES: readonly ["gateway_verification", "metering", "health", "tunnel", "drift_report"];
123
- export type RuntimeTokenCapability = (typeof RUNTIME_TOKEN_CAPABILITIES)[number];
122
+ export declare const RUNTIME_TOKEN_OPERATIONS: readonly ["gateway_verification", "metering", "health", "tunnel", "drift_report"];
123
+ export type RuntimeTokenOperation = (typeof RUNTIME_TOKEN_OPERATIONS)[number];
124
124
  export declare const RUNTIME_HEADER_NAMES: {
125
125
  readonly signature: "x-fs-signature";
126
126
  readonly keyId: "x-fs-key-id";
@@ -237,7 +237,7 @@ export type RuntimeBootstrapResponse = {
237
237
  id: string | null;
238
238
  kind: RuntimeEnvironmentKind;
239
239
  };
240
- capabilities: RuntimeTokenCapability[];
240
+ operations: RuntimeTokenOperation[];
241
241
  verification: RuntimeVerificationConfig;
242
242
  metering: RuntimeMeteringConfig;
243
243
  transport: RuntimeTransportConfig;
@@ -273,8 +273,6 @@ export type RuntimePostStreamUsageEvent = {
273
273
  measureContext?: Record<string, unknown>;
274
274
  signature: string;
275
275
  };
276
- export declare const RUNTIME_READINESS_STATES: readonly ["UNKNOWN", "WAITING", "READY", "DEGRADED", "OFFLINE"];
277
- export type RuntimeReadinessState = (typeof RUNTIME_READINESS_STATES)[number];
278
276
  export type RuntimeHealthReport = {
279
277
  runtimeToken: boolean;
280
278
  bootstrap: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farthershore/backend",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Farther Shore backend SDK for builder upstreams: signed response usage, fail-closed gateway request verification, health, and lifecycle from FS_RUNTIME_TOKEN",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,8 +39,8 @@
39
39
  "optionalDependencies": {
40
40
  "@farthershore/cloudflared-linux-x64": "0.0.0",
41
41
  "@farthershore/cloudflared-linux-arm64": "0.0.0",
42
- "@farthershore/cloudflared-darwin-x64": "0.0.0",
43
- "@farthershore/cloudflared-darwin-arm64": "0.0.0"
42
+ "@farthershore/cloudflared-darwin-arm64": "0.0.0",
43
+ "@farthershore/cloudflared-darwin-x64": "0.0.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "express": "^4.0.0 || ^5.0.0"