npm.io
0.1.0 • Published 4d agoCLI

@opsimathically/forwarddynamic-node

Licence
MIT OR Apache-2.0
Version
0.1.0
Deps
1
Size
73 kB
Vulns
0
Weekly
0

@opsimathically/forwarddynamic-node

Typed, fail-closed access to request metadata produced by ForwardDynamic. The package does not implement the mTLS backhaul; the core has no runtime dependencies, while the Fastify subpath uses fastify-plugin to preserve hook encapsulation semantics. It supports Node.js 22, 24, and 26 and is ESM-only in v1.

Install

npm install @opsimathically/forwarddynamic-node

Express 5 and Fastify 5 are optional peer dependencies. Install only the framework adapter your application uses. The native Node integration has no framework peer requirement. TypeScript projects should use node16, nodenext, or bundler module resolution; legacy node resolution does not understand package export maps.

Native Node example

import { createServer } from "node:http";
import { createForwardDynamicIntegration } from "@opsimathically/forwarddynamic-node";
import {
  requireForwardDynamicContext,
  writeForwardDynamicError,
} from "@opsimathically/forwarddynamic-node/native";

const integration = createForwardDynamicIntegration({
  mode: "required",
  requiredContractVersion: 1,
  expectedServiceIds: ["photos"],
  expectedPublicAuthorities: ["photos.example.com"],
});

createServer((request, response) => {
  try {
    const context = requireForwardDynamicContext(request, integration);
    response.end(`request ${context.requestId}`);
  } catch (error) {
    if (!writeForwardDynamicError(response, error)) response.destroy();
  }
}).listen(3000, "127.0.0.1");

trusted: true means the metadata followed the expected ForwardDynamic path. It does not authenticate the visitor, hostname, Cloudflare account, or user. The package accepts the immediate proxy only on loopback; keep the application bound to loopback and keep the service agent's management endpoint private.

Modes are explicit:

  • disabled ignores every reserved header and is safe before migration or during a complete Rust rollback.
  • optional returns an untrusted result for absent context or a non-loopback peer, but rejects malformed or partial context arriving from loopback.
  • required fails closed for every missing, untrusted, malformed, wrong-service, or wrong-authority request.

The parser never consults Forwarded, X-Forwarded-*, X-Real-IP, or raw Cloudflare headers. Express middleware does not set trust proxy; Fastify does not change global server options. Import adapters from their dedicated export paths. Lifecycle helpers install no signal handlers and never consume bodies.

Public module import paths (not HTTP routes)

The paths below are JavaScript and TypeScript package exports used in import statements. They are not URL paths or automatically registered HTTP routes. Installing this package does not create a server, open a port, or expose an endpoint to the internet.

  • The package root creates and parses the versioned context.
  • /native provides native node:http parsing, required-mode, error-writing, and handler helpers.
  • /express and /fastify provide framework adapters without changing global proxy-trust settings.
  • /health provides bounded readiness, contract-probe, and drain controllers.
  • /server validates and applies defensive native HTTP server settings.
  • /manifest validates an application manifest against the authoritative deployment description emitted by the Rust CLI.
  • /testing creates synthetic contract headers for unit tests only. These headers never authenticate a production request and must not be used as an end-to-end ForwardDynamic test substitute.

The health and contract-probe modules return handler functions but do not mount them. A handler becomes reachable only if the application explicitly attaches it to an HTTP route. Keep operational health routes on a private management listener or protect them with appropriate access controls; mounting one on an internet-facing server makes it reachable according to that server's routing and authorization policy.

Manifest validation

The manifest records hostPolicy (origin, preserve, or override) and hostOverridePresent; validation fails when these differ from the authoritative Rust service configuration. The declared origin must be loopback.

Rust remains the only TOML parser:

forwarddynamic config inspect --forward forward.toml --service service.toml \
  --format json > forwarddynamic-deployment.json
forwarddynamic-node validate-manifest --manifest forwarddynamic.app.json \
  --deployment forwarddynamic-deployment.json

See contracts/application-proxy/v1 in the ForwardDynamic repository for the normative contract and docs/APPLICATION_PROXY_ROLLOUT.md for rollout and rollback order.

Support and source

Source, issues, the normative contract, and integration evidence live in the ForwardDynamic repository. The package is dual-licensed under MIT or Apache-2.0.

Keywords