@farthershore/backend
Runtime gateway-verification and usage metering for builder upstreams.
Runtime gateway-verification and usage metering for builder upstreams.
@farthershore/backend is the runtime SDK for your upstream. Install one package,
set one token (FS_RUNTIME_TOKEN), and Farther Shore handles signed
gateway-to-upstream request verification plus response-bound usage reporting.
Pin it in lockstep with @farthershore/product and
@farthershore/farthershore-js.
npm install @farthershore/backend
Mint the token with the CLI — it's returned once:
farthershore backend tokens create croncloud --backend <backendId> --format json
fartherShore.initFromEnv() derives everything — product/backend ids, the
JWKS URL, the metering endpoint, verification config, transport — from
FS_RUNTIME_TOKEN via POST /v1/runtime/bootstrap (cached in memory, refreshed
lazily). The builder configures exactly one thing. See
environment variables.
import { fartherShore, withUsage } from "@farthershore/backend";
const fs = fartherShore.initFromEnv();
export async function POST(request: Request) {
const url = new URL(request.url);
const body = new Uint8Array(await request.clone().arrayBuffer());
// Fail-closed: throws FartherShoreError (→ 401) on any verification failure.
await fs.verifyRequest({
method: request.method,
path: url.pathname,
query: url.search,
headers: request.headers,
body,
});
const result = await runWorkflow(await request.json());
return withUsage(request, Response.json(result), {
tokens_used: result.tokensUsed, // matches a dynamic @Meter key in the product
});
}
import { fartherShore } from "@farthershore/backend";
const fs = fartherShore.initFromEnv();
app.use(fs.middleware()); // fail-closed verify → req.fartherShore
await fs.ready(app); // boot-time route reconciliation (fail-open)
app.post("/v1/cron-jobs", handler);
app.listen(3000);
process.on("SIGTERM", () => void fs.shutdown());
The gateway signs each request with Ed25519; the SDK recomputes the canonical
signing string from the actual request and verifies the signature against a
JWKS-resolved key. The plaintext X-FS-* headers are untrusted — identity comes
only from a signature whose claims match the real request. Every failure
(missing / malformed / bad-signature / stale / clock-skew / wrong-route /
body-hash-mismatch / replayed-nonce / unknown-kid / jwks-unavailable) throws and
maps to HTTP 401 (413 for oversized bodies). There is no fail-open branch.
Three ways to report usage. The meter key is not hardcoded by the SDK — it
must match a dynamic @Meter declared in the product.
| Helper | When | Network call? |
|---|---|---|
withUsage(request, response, usage, options?) | Usage known while returning a gateway-handled response. | No — signs usage into response headers; the gateway verifies, settles, and strips them. |
createUsage(request, options?) | Same, but build usage incrementally (.report(meter, value).wrap(response)). | No. |
fs.meter(meter, qty, { requestId, routeId }) | Async / background usage not tied to a response. | Yes — POSTs an idempotent event to /v1/metering/events. At-least-once. |
return withUsage(request, Response.json(result), { tokens_used: result.tokensUsed }, {
measureContext: { model: result.model }, // free-form pricing/analytics context
creditUnitsConsumed: { credits: result.creditsUsed }, // credit-wallet products
});
Plain request counting (from @Requests()) is platform-managed and needs no
upstream code.
fartherShore instance| Member | Description |
|---|---|
fartherShore.initFromEnv(options?) | Construct an instance; derive everything from FS_RUNTIME_TOKEN. Throws missing_token / invalid_token eagerly. |
fs.middleware(options?) | Express middleware: fail-closed verify → req.fartherShore. |
fs.verifyRequest(input) | Framework-neutral verification primitive ({ method, path, query, headers, body }). |
fs.meter(meter, qty, options?) | Record billing-only usage (POST /v1/metering/events). |
fs.ready(app?) | Boot-time route reconciliation against the declared lock; reports drift. Fail-open — never blocks boot. |
fs.start() | Start the embedded cloudflared runner for a tunnel backend; no-op otherwise. |
fs.health() | Local runtime health report. |
fs.shutdown() | Graceful: flush metering + send a stopping heartbeat. |
fs.onShutdown(hook) | Register an additional shutdown hook. |
initFromEnv(options) accepts runtimeToken, coreUrl, env, fetchImpl,
verification: { enabled }, metering: { enabled }, tunnel, and instanceId
for tests and advanced opt-outs — but the default DX is everything on, token only.
| Export | What it is |
|---|---|
fartherShore, initFromEnv | The conceptual entrypoint and its top-level convenience twin. |
FartherShore, FartherShoreInstance | The runtime class and its augmented type. |
withUsage, createUsage | Response-bound metering signers. |
MeteringError, UsageMap, UsageReporter, MeteringOptions | Response-metering error + types. |
FartherShoreError, statusForCode | The typed verification error and its HTTP-status mapper. |
verifyRequest, FartherShoreRequestContext, VerifyRequestInput | The standalone verification primitive + types. |
createExpressMiddleware, ExpressMiddleware, MiddlewareOptions | Express adapter. |
JwksClient, NonceCache, BootstrapClient, MeteringClient | The lower-level clients initFromEnv composes. |
CloudflaredSupervisor, nodeSpawn, FartherShoreTunnelOptions | The embedded tunnel runner (BYO-backend). |
buildHealthReport, reportHealth, ShutdownManager | Health + shutdown helpers. |
FS_RUNTIME_TOKEN_ENV, RUNTIME_TOKEN_CAPABILITIES, RUNTIME_HEADER_NAMES, MAX_BODY_BYTES, RUNTIME_CLOCK_SKEW_SECONDS, RUNTIME_REPLAY_WINDOW_SECONDS, RUNTIME_ERROR_CODES | Shared contract constants (mirrors @farthershore/contracts/runtime). |
hashBody, buildCanonicalSigningString, signCanonicalString, verifyCanonicalSignature, canonicalizeQuery | Signing primitives (one source of truth across SDKs and the gateway). |
METERING_PAYLOAD_HEADER, METERING_SIGNATURE_HEADER, METERING_TOKEN_HEADER, DEFAULT_TOKEN_ENV | Response-metering header-contract constants. |
A backend is declared in the product via @Backend. Bind routes to it with a
route's backend; a single backend is the default, otherwise mark one
default: true.
import { Backend, Feature } from "@farthershore/product";
@Backend("prod-origin", {
transport: { mode: "direct" },
verification: { required: true },
default: true,
})
prodOrigin!: unknown;
@Feature("cron-jobs", {
backend: "prod-origin", // feature-wide default
routes: { "POST /v1/cron-jobs": { backend: "prod-origin" } }, // per-route override
})
cronJobs!: unknown;
@Backend options: name, slug, transport: { mode: "direct" | "tunnel", runner }, verification: { required }, meters (allow-list), default,
originUrl, originHostname. A route that meters a dimension the backend's
meters allow-list excludes is rejected at build time.