@jini-ai/http-kit 0.3.1 → 0.3.3

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.
Files changed (74) hide show
  1. package/LICENSE +201 -0
  2. package/dist/delegated-tools.d.ts +89 -0
  3. package/dist/delegated-tools.d.ts.map +1 -1
  4. package/dist/delegated-tools.js +106 -1
  5. package/dist/delegated-tools.js.map +1 -1
  6. package/package.json +15 -15
  7. package/dist/express/run-stream.d.ts +0 -15
  8. package/dist/express/run-stream.d.ts.map +0 -1
  9. package/dist/express/run-stream.js +0 -11
  10. package/dist/express/run-stream.js.map +0 -1
  11. package/dist/express-index.d.ts +0 -32
  12. package/dist/express-index.d.ts.map +0 -1
  13. package/dist/express-index.js +0 -14
  14. package/dist/express-index.js.map +0 -1
  15. package/dist/fastify/adapter.d.ts +0 -31
  16. package/dist/fastify/adapter.d.ts.map +0 -1
  17. package/dist/fastify/adapter.js +0 -64
  18. package/dist/fastify/adapter.js.map +0 -1
  19. package/dist/fastify/agents.d.ts +0 -13
  20. package/dist/fastify/agents.d.ts.map +0 -1
  21. package/dist/fastify/agents.js +0 -7
  22. package/dist/fastify/agents.js.map +0 -1
  23. package/dist/fastify/api-security-middleware.d.ts +0 -64
  24. package/dist/fastify/api-security-middleware.d.ts.map +0 -1
  25. package/dist/fastify/api-security-middleware.js +0 -139
  26. package/dist/fastify/api-security-middleware.js.map +0 -1
  27. package/dist/fastify/compat.d.ts +0 -22
  28. package/dist/fastify/compat.d.ts.map +0 -1
  29. package/dist/fastify/compat.js +0 -16
  30. package/dist/fastify/compat.js.map +0 -1
  31. package/dist/fastify/daemon-status.d.ts +0 -22
  32. package/dist/fastify/daemon-status.d.ts.map +0 -1
  33. package/dist/fastify/daemon-status.js +0 -9
  34. package/dist/fastify/daemon-status.js.map +0 -1
  35. package/dist/fastify/host-tools.d.ts +0 -13
  36. package/dist/fastify/host-tools.d.ts.map +0 -1
  37. package/dist/fastify/host-tools.js +0 -8
  38. package/dist/fastify/host-tools.js.map +0 -1
  39. package/dist/fastify/index.d.ts +0 -36
  40. package/dist/fastify/index.d.ts.map +0 -1
  41. package/dist/fastify/index.js +0 -18
  42. package/dist/fastify/index.js.map +0 -1
  43. package/dist/fastify/local-daemon-request.d.ts +0 -43
  44. package/dist/fastify/local-daemon-request.d.ts.map +0 -1
  45. package/dist/fastify/local-daemon-request.js +0 -155
  46. package/dist/fastify/local-daemon-request.js.map +0 -1
  47. package/dist/fastify/origin.d.ts +0 -21
  48. package/dist/fastify/origin.d.ts.map +0 -1
  49. package/dist/fastify/origin.js +0 -14
  50. package/dist/fastify/origin.js.map +0 -1
  51. package/dist/fastify/request.d.ts +0 -20
  52. package/dist/fastify/request.d.ts.map +0 -1
  53. package/dist/fastify/request.js +0 -25
  54. package/dist/fastify/request.js.map +0 -1
  55. package/dist/fastify/response.d.ts +0 -20
  56. package/dist/fastify/response.d.ts.map +0 -1
  57. package/dist/fastify/response.js +0 -41
  58. package/dist/fastify/response.js.map +0 -1
  59. package/dist/fastify/route-registration-guard.d.ts +0 -70
  60. package/dist/fastify/route-registration-guard.d.ts.map +0 -1
  61. package/dist/fastify/route-registration-guard.js +0 -69
  62. package/dist/fastify/route-registration-guard.js.map +0 -1
  63. package/dist/fastify/run-stream.d.ts +0 -18
  64. package/dist/fastify/run-stream.d.ts.map +0 -1
  65. package/dist/fastify/run-stream.js +0 -10
  66. package/dist/fastify/run-stream.js.map +0 -1
  67. package/dist/fastify/runs.d.ts +0 -17
  68. package/dist/fastify/runs.d.ts.map +0 -1
  69. package/dist/fastify/runs.js +0 -33
  70. package/dist/fastify/runs.js.map +0 -1
  71. package/dist/run-stream.d.ts +0 -60
  72. package/dist/run-stream.d.ts.map +0 -1
  73. package/dist/run-stream.js +0 -108
  74. package/dist/run-stream.js.map +0 -1
@@ -1,31 +0,0 @@
1
- /**
2
- * The module's top orchestration layer: wires request parsing, the same-origin guard, a route's
3
- * `handle`, and response serialization into a single Fastify route handler. This is the only file
4
- * in this subtree that knows about Fastify's `request`/`reply` on the mounting side. Same job as
5
- * `../express/adapter.ts`'s `mountJsonRoute`, registered through Fastify's native
6
- * `fastify.route({ method, url, handler })` instead of Express's `app[method](path, handler)`.
7
- */
8
- import type { FastifyInstance } from 'fastify';
9
- import { type OriginContext } from './origin.js';
10
- import type { JsonRouteSpec } from '../types.js';
11
- /** Server startup state a mounted route needs to evaluate its same-origin guard. */
12
- export interface AdapterContext extends OriginContext {
13
- }
14
- /**
15
- * Identity function that pins a route spec's generic parameters at the definition site so
16
- * callers do not have to repeat them. The returned spec is consumed by `mountJsonRoute` (live)
17
- * and by tests (direct invocation of `route.parse` / `route.handle`).
18
- */
19
- export declare function defineJsonRoute<Input, Output, Deps>(spec: JsonRouteSpec<Input, Output, Deps>): JsonRouteSpec<Input, Output, Deps>;
20
- /**
21
- * Mounts one JsonRouteSpec on a Fastify instance. The Adapter is the only code here that knows
22
- * about request/reply; the route's parse and handle functions operate on `RouteInputContext` and
23
- * `Deps` respectively, so they are unit testable without Fastify.
24
- *
25
- * `exposeHeadRoute: false` is passed explicitly so a `GET` spec does not also register Fastify's
26
- * automatic `HEAD` sibling route — the Express version never registers one either, and a spec's
27
- * `handle` is not written to answer a bodyless `HEAD` request correctly (e.g. `daemonStatusRoute`
28
- * always returns a JSON body).
29
- */
30
- export declare function mountJsonRoute<Input, Output, Deps>(app: FastifyInstance, spec: JsonRouteSpec<Input, Output, Deps>, deps: Deps, adapter: AdapterContext): void;
31
- //# sourceMappingURL=adapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/fastify/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAI7E,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D,oFAAoF;AACpF,MAAM,WAAW,cAAe,SAAQ,aAAa;CAAG;AAExD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EACjD,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,GACvC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAEpC;AAWD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAChD,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EACxC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,GACtB,IAAI,CA+BN"}
@@ -1,64 +0,0 @@
1
- import { createApiError } from '@jini/protocol';
2
- import { rawInput } from './request.js';
3
- import { sendApiError, sendJson, statusForError } from './response.js';
4
- import { guardSameOrigin } from './origin.js';
5
- /**
6
- * Identity function that pins a route spec's generic parameters at the definition site so
7
- * callers do not have to repeat them. The returned spec is consumed by `mountJsonRoute` (live)
8
- * and by tests (direct invocation of `route.parse` / `route.handle`).
9
- */
10
- export function defineJsonRoute(spec) {
11
- return spec;
12
- }
13
- /** Maps the shared, lower-case `HttpMethod` union to the upper-case method literal Fastify's `route()` expects. */
14
- const FASTIFY_METHOD = {
15
- get: 'GET',
16
- post: 'POST',
17
- put: 'PUT',
18
- delete: 'DELETE',
19
- patch: 'PATCH',
20
- };
21
- /**
22
- * Mounts one JsonRouteSpec on a Fastify instance. The Adapter is the only code here that knows
23
- * about request/reply; the route's parse and handle functions operate on `RouteInputContext` and
24
- * `Deps` respectively, so they are unit testable without Fastify.
25
- *
26
- * `exposeHeadRoute: false` is passed explicitly so a `GET` spec does not also register Fastify's
27
- * automatic `HEAD` sibling route — the Express version never registers one either, and a spec's
28
- * `handle` is not written to answer a bodyless `HEAD` request correctly (e.g. `daemonStatusRoute`
29
- * always returns a JSON body).
30
- */
31
- export function mountJsonRoute(app, spec, deps, adapter) {
32
- app.route({
33
- method: FASTIFY_METHOD[spec.method],
34
- url: spec.path,
35
- exposeHeadRoute: false,
36
- handler: async (req, reply) => {
37
- try {
38
- if (spec.requireSameOrigin) {
39
- const origin = guardSameOrigin(req, adapter);
40
- if (!origin.ok) {
41
- sendApiError(reply, statusForError(origin.error), origin.error);
42
- return;
43
- }
44
- }
45
- const parsed = spec.parse(rawInput(req));
46
- if (!parsed.ok) {
47
- sendApiError(reply, statusForError(parsed.error), parsed.error);
48
- return;
49
- }
50
- const result = await spec.handle(parsed.value, deps);
51
- if (!result.ok) {
52
- sendApiError(reply, statusForError(result.error), result.error);
53
- return;
54
- }
55
- sendJson(reply, spec.successStatus ?? 200, result.value);
56
- }
57
- catch (e) {
58
- const message = e instanceof Error ? e.message : String(e);
59
- sendApiError(reply, 500, createApiError('INTERNAL_ERROR', message));
60
- }
61
- },
62
- });
63
- }
64
- //# sourceMappingURL=adapter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/fastify/adapter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,eAAe,EAAsB,MAAM,aAAa,CAAC;AAMlE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAwC;IAExC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mHAAmH;AACnH,MAAM,cAAc,GAAoE;IACtF,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAoB,EACpB,IAAwC,EACxC,IAAU,EACV,OAAuB;IAEvB,GAAG,CAAC,KAAK,CAAC;QACR,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QACnC,GAAG,EAAE,IAAI,CAAC,IAAI;QACd,eAAe,EAAE,KAAK;QACtB,OAAO,EAAE,KAAK,EAAE,GAAmB,EAAE,KAAmB,EAAE,EAAE;YAC1D,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC3B,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBAC7C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;wBACf,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;wBAChE,OAAO;oBACT,CAAC;gBACH,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;oBAChE,OAAO;gBACT,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;oBAChE,OAAO;gBACT,CAAC;gBACD,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,IAAI,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC3D,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,cAAc,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1,13 +0,0 @@
1
- /**
2
- * @module fastify/agents
3
- *
4
- * Fastify-mounting glue for `../agents.js`'s `agentListRoute` — the exact same `JsonRouteSpec`
5
- * the Express mounting in `../agents.js` uses, just mounted through this subtree's own
6
- * `mountJsonRoute` instead.
7
- */
8
- import type { FastifyInstance } from 'fastify';
9
- import { type AgentsHttpDeps } from '../agents.js';
10
- import { type AdapterContext } from './adapter.js';
11
- /** Mounts `GET /api/agents` on `app` — the Fastify-native equivalent of `../agents.js`'s `registerAgentRoutes`. */
12
- export declare function registerAgentRoutes(app: FastifyInstance, deps: AgentsHttpDeps, adapter: AdapterContext): void;
13
- //# sourceMappingURL=agents.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/fastify/agents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,mHAAmH;AACnH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAE7G"}
@@ -1,7 +0,0 @@
1
- import { agentListRoute } from '../agents.js';
2
- import { mountJsonRoute } from './adapter.js';
3
- /** Mounts `GET /api/agents` on `app` — the Fastify-native equivalent of `../agents.js`'s `registerAgentRoutes`. */
4
- export function registerAgentRoutes(app, deps, adapter) {
5
- mountJsonRoute(app, agentListRoute, deps, adapter);
6
- }
7
- //# sourceMappingURL=agents.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/fastify/agents.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AAEnE,mHAAmH;AACnH,MAAM,UAAU,mBAAmB,CAAC,GAAoB,EAAE,IAAoB,EAAE,OAAuB;IACrG,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC"}
@@ -1,64 +0,0 @@
1
- /**
2
- * @module fastify/api-security-middleware
3
- *
4
- * The two `/api` request gates a locally-bound daemon needs before any route handler runs:
5
- * bearer-token authentication (optional, active only when a token is configured) and cross-origin
6
- * rejection (always active). Same job and decision logic as `../express/api-security-middleware.ts`
7
- * (see that file's own doc for the full drop-list this was genericized from), reimplemented on
8
- * Fastify's native `onRequest` lifecycle hook (`app.addHook('onRequest', ...)`) in place of
9
- * Express's `app.use('/api', ...)` path-scoped middleware. Fastify has no first-class "scope this
10
- * hook to a URL prefix" primitive at the plain-instance level (that requires nesting the routes
11
- * themselves inside a `.register()` plugin with a `prefix`, which `mountPackHttp`'s pack-agnostic
12
- * mounting does not do), so both hooks below scope themselves manually by checking the request's
13
- * own path against the `/api` prefix before applying either gate — the observable behavior is
14
- * identical to the Express version's `app.use('/api', ...)` scoping.
15
- */
16
- import type { FastifyInstance } from 'fastify';
17
- import { type ApiTokenAuthEnvConfig } from '@jini/core';
18
- export interface ApiBearerAuthMiddlewareDeps {
19
- /** Env var names for the token/disable flags. Defaults to `JINI_API_TOKEN` / `JINI_DISABLE_API_AUTH`. */
20
- tokenConfig?: ApiTokenAuthEnvConfig;
21
- /** Defaults to `process.env`. Threaded through so tests never have to mutate real process env. */
22
- env?: NodeJS.ProcessEnv;
23
- }
24
- /**
25
- * Registers a bearer-token gate on every `/api/*` route, active only when
26
- * {@link isApiTokenMiddlewareEnabled} says a token is configured and auth hasn't been disabled.
27
- * When active: open-probe paths and loopback peers skip the check unconditionally; every other
28
- * request must send `Authorization: Bearer <token>` matching the configured token exactly, or the
29
- * request is rejected with 401 before reaching any route handler.
30
- *
31
- * @param app - The Fastify instance to register the gate on.
32
- * @param deps - See {@link ApiBearerAuthMiddlewareDeps}. Both fields are optional; omitting `deps`
33
- * entirely reads `JINI_API_TOKEN`/`JINI_DISABLE_API_AUTH` from real `process.env`.
34
- * @returns Nothing. Registers zero hooks (a deliberate no-op, not a bug) when no token is configured.
35
- * @complexity Setup is O(1). Each gated request is O(1) (one Set lookup, one regex match).
36
- * @overallScore 100/100
37
- */
38
- export declare function registerApiBearerAuthMiddleware(app: FastifyInstance, deps?: ApiBearerAuthMiddlewareDeps): void;
39
- export interface ApiOriginGuardMiddlewareDeps {
40
- /** The host this daemon is bound to — compared against a request's `Host`/`Origin` headers. */
41
- host: string;
42
- /** Extra allow-listed origins (e.g. a reverse-proxy's public origin). Defaults to none. */
43
- extraAllowedOrigins?: readonly string[];
44
- /** Returns the daemon's resolved listen port, or a falsy value before it has resolved. */
45
- getResolvedPort: () => number | null | undefined;
46
- /** Defaults to `process.env`. Threaded through so `JINI_WEB_PORT` is testable without mutating real process env. */
47
- env?: NodeJS.ProcessEnv;
48
- }
49
- /**
50
- * Registers an unconditional cross-origin gate on every `/api/*` route: non-browser clients (no
51
- * `Origin` header) and requests whose `Origin` resolves to a loopback, private-LAN, or explicitly
52
- * allow-listed origin are let through; everything else is rejected with 403. `Origin: null`
53
- * (typically a sandboxed iframe) is always rejected — see the Express version's doc for why the
54
- * origin daemon's safe-GET exemption for that case was dropped.
55
- *
56
- * @param app - The Fastify instance to register the gate on.
57
- * @param deps - See {@link ApiOriginGuardMiddlewareDeps}.
58
- * @returns Nothing. Unlike the bearer-token gate, this always registers its hook — there is
59
- * no "disabled" state.
60
- * @complexity Setup is O(1). Each gated request is O(p) in the number of allowed ports (typically 1-2).
61
- * @overallScore 100/100
62
- */
63
- export declare function registerApiOriginGuardMiddleware(app: FastifyInstance, deps: ApiOriginGuardMiddlewareDeps): void;
64
- //# sourceMappingURL=api-security-middleware.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-security-middleware.d.ts","sourceRoot":"","sources":["../../src/fastify/api-security-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,YAAY,CAAC;AAgBpB,MAAM,WAAW,2BAA2B;IAC1C,yGAAyG;IACzG,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,kGAAkG;IAClG,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,GAAE,2BAAgC,GAAG,IAAI,CAmClH;AAED,MAAM,WAAW,4BAA4B;IAC3C,+FAA+F;IAC/F,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,0FAA0F;IAC1F,eAAe,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,oHAAoH;IACpH,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,4BAA4B,GAAG,IAAI,CAyC/G"}
@@ -1,139 +0,0 @@
1
- import { apiTokenFromEnv, isApiTokenMiddlewareEnabled, } from '@jini/core';
2
- import { isLoopbackPeerAddress } from './local-daemon-request.js';
3
- import { allowedBrowserPorts, isAllowedBrowserOrigin } from '../origin-validation.js';
4
- /** Health/readiness/version probes stay reachable without a bearer token so monitoring never needs one. Both the mount-relative and `/api`-prefixed forms are kept for parity with the Express version's set (only the `/api`-prefixed forms are ever reachable here, since both hooks below already require the path to start with `/api` before this set is even consulted). */
5
- const OPEN_PROBE_PATHS = new Set([
6
- '/health',
7
- '/api/health',
8
- '/ready',
9
- '/api/ready',
10
- '/version',
11
- '/api/version',
12
- ]);
13
- const BEARER_TOKEN_PATTERN = /^Bearer\s+(\S+)\s*$/i;
14
- const DEFAULT_TOKEN_CONFIG = {
15
- tokenEnvVar: 'JINI_API_TOKEN',
16
- disableEnvVar: 'JINI_DISABLE_API_AUTH',
17
- };
18
- /**
19
- * The request path with no query string — Fastify's `request.url` (unlike Express's
20
- * `request.path`) always includes the query string, so this strips it to match Express's
21
- * comparison semantics. `req.url` is typed as a required `string` on `FastifyRequest`
22
- * (never `undefined`), and `String.prototype.split` on a string separator always returns an
23
- * array with at least one element, so the `[0]` index is provably defined — the non-null
24
- * assertion documents that guarantee instead of masking it behind an unreachable `?? ''` fallback
25
- * that could never be exercised by a real request.
26
- */
27
- function requestPath(req) {
28
- return req.url.split('?')[0];
29
- }
30
- /**
31
- * Registers a bearer-token gate on every `/api/*` route, active only when
32
- * {@link isApiTokenMiddlewareEnabled} says a token is configured and auth hasn't been disabled.
33
- * When active: open-probe paths and loopback peers skip the check unconditionally; every other
34
- * request must send `Authorization: Bearer <token>` matching the configured token exactly, or the
35
- * request is rejected with 401 before reaching any route handler.
36
- *
37
- * @param app - The Fastify instance to register the gate on.
38
- * @param deps - See {@link ApiBearerAuthMiddlewareDeps}. Both fields are optional; omitting `deps`
39
- * entirely reads `JINI_API_TOKEN`/`JINI_DISABLE_API_AUTH` from real `process.env`.
40
- * @returns Nothing. Registers zero hooks (a deliberate no-op, not a bug) when no token is configured.
41
- * @complexity Setup is O(1). Each gated request is O(1) (one Set lookup, one regex match).
42
- * @overallScore 100/100
43
- */
44
- export function registerApiBearerAuthMiddleware(app, deps = {}) {
45
- const tokenConfig = deps.tokenConfig ?? DEFAULT_TOKEN_CONFIG;
46
- const env = deps.env ?? process.env;
47
- if (!isApiTokenMiddlewareEnabled(tokenConfig, env))
48
- return;
49
- const apiToken = apiTokenFromEnv(tokenConfig, env);
50
- app.addHook('onRequest', (req, reply, done) => {
51
- const path = requestPath(req);
52
- if (!path.startsWith('/api')) {
53
- done();
54
- return;
55
- }
56
- if (OPEN_PROBE_PATHS.has(path)) {
57
- done();
58
- return;
59
- }
60
- // Loopback short-circuit: the desktop UI / local CLI never carry a bearer, and a reverse
61
- // proxy in front of a non-loopback bind must always forward the real bearer itself — so this
62
- // is intentionally not fooled by a proxied `X-Forwarded-For` header.
63
- if (isLoopbackPeerAddress(req.socket?.remoteAddress)) {
64
- done();
65
- return;
66
- }
67
- const match = BEARER_TOKEN_PATTERN.exec(req.headers.authorization ?? '');
68
- if (!match || match[1] !== apiToken) {
69
- reply.code(401).send({
70
- error: {
71
- code: 'API_TOKEN_REQUIRED',
72
- message: `Authorization: Bearer <${tokenConfig.tokenEnvVar}> required`,
73
- },
74
- });
75
- return;
76
- }
77
- done();
78
- });
79
- }
80
- /**
81
- * Chrome may strip the port from the `Origin` header on same-origin GET requests. Used only as a
82
- * narrow fallback for safe, idempotent GET requests once the exact-match check below has already
83
- * failed — mutating routes always require an exact origin/host match.
84
- */
85
- function isPortlessLoopbackOrigin(origin) {
86
- return /^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])$/.test(origin);
87
- }
88
- /**
89
- * Registers an unconditional cross-origin gate on every `/api/*` route: non-browser clients (no
90
- * `Origin` header) and requests whose `Origin` resolves to a loopback, private-LAN, or explicitly
91
- * allow-listed origin are let through; everything else is rejected with 403. `Origin: null`
92
- * (typically a sandboxed iframe) is always rejected — see the Express version's doc for why the
93
- * origin daemon's safe-GET exemption for that case was dropped.
94
- *
95
- * @param app - The Fastify instance to register the gate on.
96
- * @param deps - See {@link ApiOriginGuardMiddlewareDeps}.
97
- * @returns Nothing. Unlike the bearer-token gate, this always registers its hook — there is
98
- * no "disabled" state.
99
- * @complexity Setup is O(1). Each gated request is O(p) in the number of allowed ports (typically 1-2).
100
- * @overallScore 100/100
101
- */
102
- export function registerApiOriginGuardMiddleware(app, deps) {
103
- const { host, getResolvedPort } = deps;
104
- const extraAllowedOrigins = deps.extraAllowedOrigins ?? [];
105
- const env = deps.env ?? process.env;
106
- app.addHook('onRequest', (req, reply, done) => {
107
- const path = requestPath(req);
108
- if (!path.startsWith('/api')) {
109
- done();
110
- return;
111
- }
112
- const origin = req.headers.origin;
113
- if (origin == null || origin === '') {
114
- done();
115
- return;
116
- }
117
- if (origin === 'null') {
118
- reply.code(403).send({ error: 'Origin: null not allowed for this route' });
119
- return;
120
- }
121
- // Fail-closed: block every browser origin until the daemon's real listen port is known, so a
122
- // request arriving in the brief window before `.listen()` resolves can never be compared
123
- // against a wrong or default port.
124
- const resolvedPort = getResolvedPort();
125
- if (!resolvedPort) {
126
- reply.code(403).send({ error: 'Server initializing' });
127
- return;
128
- }
129
- const ports = allowedBrowserPorts(resolvedPort, env);
130
- if (!isAllowedBrowserOrigin(origin, req.headers.host, ports, host, [...extraAllowedOrigins])) {
131
- if (req.method !== 'GET' || !isPortlessLoopbackOrigin(String(origin))) {
132
- reply.code(403).send({ error: 'Cross-origin requests are not allowed' });
133
- return;
134
- }
135
- }
136
- done();
137
- });
138
- }
139
- //# sourceMappingURL=api-security-middleware.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-security-middleware.js","sourceRoot":"","sources":["../../src/fastify/api-security-middleware.ts"],"names":[],"mappings":"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"}
@@ -1,22 +0,0 @@
1
- /**
2
- * Legacy-shaped error helpers: build/send an `ApiError` from separate `code`/`message`/`init`
3
- * arguments, matching call sites that predate `JsonRouteSpec`/`mountJsonRoute` (e.g. a host
4
- * application's own hand-mounted routes). No internal dependencies. `sendApiError` here is
5
- * deliberately the same name as `response.ts`'s `ApiError`-object-taking `sendApiError` — they
6
- * are different signatures for the same "send an error" job at two call-site generations; the
7
- * package's `fastify/index.ts` barrel re-exports this one as `sendCompatApiError` to keep both
8
- * addressable without a collision. Deliberately duplicated from `../express/compat.ts` — see
9
- * `./response.ts`'s top-of-module doc for why this subtree does not import from `express/`.
10
- */
11
- import type { ApiError, ApiErrorCode, ApiErrorResponse } from '@jini/protocol';
12
- import type { FastifyReply } from 'fastify';
13
- /** Builds an `ApiError` from separate `code`/`message`/`init` arguments (legacy call shape). */
14
- export declare function createCompatApiError(code: ApiErrorCode, message: string, init?: Omit<ApiError, 'code' | 'message'>): ApiError;
15
- /** Wraps `createCompatApiError`'s result in the standard `{ error }` envelope. */
16
- export declare function createCompatApiErrorResponse(code: ApiErrorCode, message: string, init?: Omit<ApiError, 'code' | 'message'>): ApiErrorResponse;
17
- /**
18
- * Writes an `ApiError` response built from separate `code`/`message`/`init` arguments (legacy
19
- * call shape) with the given status code. Exported from `fastify/index.ts` as `sendCompatApiError`.
20
- */
21
- export declare function sendApiError(reply: FastifyReply, status: number, code: ApiErrorCode, message: string, init?: Omit<ApiError, 'code' | 'message'>): FastifyReply;
22
- //# sourceMappingURL=compat.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/fastify/compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,gGAAgG;AAChG,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAM,GAC5C,QAAQ,CAEV;AAED,kFAAkF;AAClF,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAM,GAC5C,gBAAgB,CAElB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAM,GAC5C,YAAY,CAEd"}
@@ -1,16 +0,0 @@
1
- /** Builds an `ApiError` from separate `code`/`message`/`init` arguments (legacy call shape). */
2
- export function createCompatApiError(code, message, init = {}) {
3
- return { code, message, ...init };
4
- }
5
- /** Wraps `createCompatApiError`'s result in the standard `{ error }` envelope. */
6
- export function createCompatApiErrorResponse(code, message, init = {}) {
7
- return { error: createCompatApiError(code, message, init) };
8
- }
9
- /**
10
- * Writes an `ApiError` response built from separate `code`/`message`/`init` arguments (legacy
11
- * call shape) with the given status code. Exported from `fastify/index.ts` as `sendCompatApiError`.
12
- */
13
- export function sendApiError(reply, status, code, message, init = {}) {
14
- return reply.code(status).send(createCompatApiErrorResponse(code, message, init));
15
- }
16
- //# sourceMappingURL=compat.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compat.js","sourceRoot":"","sources":["../../src/fastify/compat.ts"],"names":[],"mappings":"AAaA,gGAAgG;AAChG,MAAM,UAAU,oBAAoB,CAClC,IAAkB,EAClB,OAAe,EACf,OAA2C,EAAE;IAE7C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,4BAA4B,CAC1C,IAAkB,EAClB,OAAe,EACf,OAA2C,EAAE;IAE7C,OAAO,EAAE,KAAK,EAAE,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAmB,EACnB,MAAc,EACd,IAAkB,EAClB,OAAe,EACf,OAA2C,EAAE;IAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC"}
@@ -1,22 +0,0 @@
1
- /**
2
- * @module fastify/daemon-status
3
- *
4
- * Mounts the generic daemon status + shutdown routes through the Fastify Adapter. The route
5
- * SPECS themselves (`daemonStatusRoute`/`daemonShutdownRoute` — pure `defineJsonRoute`-shaped
6
- * data plus framework-agnostic `parse`/`handle` functions, see `../daemon-status.ts`'s own doc
7
- * for their full provenance) are intentionally NOT duplicated here: they never reference Express
8
- * at runtime (`../daemon-status.ts` only imports `type { Express }` for its own
9
- * `registerDaemonStatusRoutes`'s parameter — a type-only import that TypeScript's
10
- * `verbatimModuleSyntax` erases from the compiled output entirely, so importing the specs from
11
- * that module does not pull the `express` package into this subtree at runtime). This file's own
12
- * job is only the Fastify-specific mounting wrapper, calling `./adapter.js`'s Fastify
13
- * `mountJsonRoute` instead of the Express one.
14
- */
15
- import type { FastifyInstance } from 'fastify';
16
- import { daemonShutdownRoute, daemonStatusRoute, type DaemonShutdownResponse, type DaemonStatusDeps, type DaemonStatusResponse } from '../daemon-status.js';
17
- import { type AdapterContext } from './adapter.js';
18
- export { daemonShutdownRoute, daemonStatusRoute };
19
- export type { DaemonShutdownResponse, DaemonStatusDeps, DaemonStatusResponse };
20
- /** Mounts both daemon-status routes on `app`. A pack's `http(app, services)` calls this directly. */
21
- export declare function registerDaemonStatusRoutes(app: FastifyInstance, deps: DaemonStatusDeps, adapter: AdapterContext): void;
22
- //# sourceMappingURL=daemon-status.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daemon-status.d.ts","sourceRoot":"","sources":["../../src/fastify/daemon-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;AAClD,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;AAE/E,qGAAqG;AACrG,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAGtH"}
@@ -1,9 +0,0 @@
1
- import { daemonShutdownRoute, daemonStatusRoute, } from '../daemon-status.js';
2
- import { mountJsonRoute } from './adapter.js';
3
- export { daemonShutdownRoute, daemonStatusRoute };
4
- /** Mounts both daemon-status routes on `app`. A pack's `http(app, services)` calls this directly. */
5
- export function registerDaemonStatusRoutes(app, deps, adapter) {
6
- mountJsonRoute(app, daemonStatusRoute, deps, adapter);
7
- mountJsonRoute(app, daemonShutdownRoute, deps, adapter);
8
- }
9
- //# sourceMappingURL=daemon-status.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"daemon-status.js","sourceRoot":"","sources":["../../src/fastify/daemon-status.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,mBAAmB,EACnB,iBAAiB,GAIlB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AAEnE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;AAGlD,qGAAqG;AACrG,MAAM,UAAU,0BAA0B,CAAC,GAAoB,EAAE,IAAsB,EAAE,OAAuB;IAC9G,cAAc,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD,cAAc,CAAC,GAAG,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC"}
@@ -1,13 +0,0 @@
1
- /**
2
- * @module fastify/host-tools
3
- *
4
- * Fastify-mounting glue for `../host-tools.js`'s `hostEditorsRoute`/`openResourceInEditorRoute` —
5
- * the exact same `JsonRouteSpec` objects the Express mounting in `../host-tools.js` uses, just
6
- * mounted through this subtree's own `mountJsonRoute` instead.
7
- */
8
- import type { FastifyInstance } from 'fastify';
9
- import { type HostToolsOpenInDeps } from '../host-tools.js';
10
- import { type AdapterContext } from './adapter.js';
11
- /** Mounts `GET /api/editors` and `POST /api/resources/:resourceRef/open-in` on `app` — the Fastify-native equivalent of `../host-tools.js`'s `registerHostToolsRoutes`. */
12
- export declare function registerHostToolsRoutes(app: FastifyInstance, adapter: AdapterContext, openInDeps?: HostToolsOpenInDeps): void;
13
- //# sourceMappingURL=host-tools.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-tools.d.ts","sourceRoot":"","sources":["../../src/fastify/host-tools.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAA+C,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,2KAA2K;AAC3K,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,eAAe,EACpB,OAAO,EAAE,cAAc,EACvB,UAAU,GAAE,mBAAwB,GACnC,IAAI,CAGN"}
@@ -1,8 +0,0 @@
1
- import { hostEditorsRoute, openResourceInEditorRoute } from '../host-tools.js';
2
- import { mountJsonRoute } from './adapter.js';
3
- /** Mounts `GET /api/editors` and `POST /api/resources/:resourceRef/open-in` on `app` — the Fastify-native equivalent of `../host-tools.js`'s `registerHostToolsRoutes`. */
4
- export function registerHostToolsRoutes(app, adapter, openInDeps = {}) {
5
- mountJsonRoute(app, hostEditorsRoute, {}, adapter);
6
- mountJsonRoute(app, openResourceInEditorRoute, openInDeps, adapter);
7
- }
8
- //# sourceMappingURL=host-tools.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"host-tools.js","sourceRoot":"","sources":["../../src/fastify/host-tools.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAA4B,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AAEnE,2KAA2K;AAC3K,MAAM,UAAU,uBAAuB,CACrC,GAAoB,EACpB,OAAuB,EACvB,aAAkC,EAAE;IAEpC,cAAc,CAAC,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACnD,cAAc,CAAC,GAAG,EAAE,yBAAyB,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC"}
@@ -1,36 +0,0 @@
1
- /**
2
- * @module @jini/http/fastify
3
- *
4
- * The Fastify-native transport implementation: request parsing, response serialization, the
5
- * Fastify-mounting Adapter (`defineJsonRoute`/`mountJsonRoute`, built on `fastify.route(...)`),
6
- * the `/api` bearer-auth and origin-guard `onRequest` hooks, a loopback-only request guard, a
7
- * route-registration inventory/guard built on Fastify's native `onRoute` application hook, legacy-
8
- * shaped compat error helpers, the generic daemon-status/shutdown routes, and full Fastify
9
- * mounting for the runs/agents/host-tools route packs (`registerRunRoutes` including its SSE
10
- * event stream, `registerAgentRoutes`, `registerHostToolsRoutes`) — every one mounting the exact
11
- * same `JsonRouteSpec` objects (and, for the SSE stream, the exact same
12
- * `handleRunEventStreamRequest` core) the `express`/root-barrel Express mounting uses, so
13
- * `transport: 'fastify'` serves identical routes to the Express default, not a reduced set. Every
14
- * export here operates on Fastify's `FastifyRequest`/`FastifyReply`/`FastifyInstance` types.
15
- * Import the shared, framework-agnostic pieces (`Result`, `JsonRouteSpec`, origin-validation
16
- * predicates, `mountPackHttp`) from the package root instead of duplicating them here.
17
- */
18
- export type { AdapterContext } from './adapter.js';
19
- export { defineJsonRoute, mountJsonRoute } from './adapter.js';
20
- export type { ApiBearerAuthMiddlewareDeps, ApiOriginGuardMiddlewareDeps } from './api-security-middleware.js';
21
- export { registerApiBearerAuthMiddleware, registerApiOriginGuardMiddleware } from './api-security-middleware.js';
22
- export { createCompatApiError, createCompatApiErrorResponse, sendApiError as sendCompatApiError, } from './compat.js';
23
- export type { DaemonShutdownResponse, DaemonStatusDeps, DaemonStatusResponse, } from './daemon-status.js';
24
- export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
25
- export { isLoopbackHostname, isLoopbackPeerAddress, localOriginFromHeader, normalizeLocalAuthority, requireLocalDaemonRequest, validateLocalDaemonRequest, } from './local-daemon-request.js';
26
- export type { OriginContext } from './origin.js';
27
- export { guardSameOrigin } from './origin.js';
28
- export { rawInput, validationError } from './request.js';
29
- export { registerRunStreamRoute } from './run-stream.js';
30
- export { sendApiError, sendJson, statusForError } from './response.js';
31
- export type { InstallRouteRegistrationGuardOptions, RouteRegistration } from './route-registration-guard.js';
32
- export { getRouteRegistrationInventory, guardedRouteKey, installRouteRegistrationGuard, } from './route-registration-guard.js';
33
- export { registerRunEventStream, registerRunRoutes } from './runs.js';
34
- export { registerAgentRoutes } from './agents.js';
35
- export { registerHostToolsRoutes } from './host-tools.js';
36
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE/D,YAAY,EAAE,2BAA2B,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC9G,OAAO,EAAE,+BAA+B,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAMjH,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,YAAY,IAAI,kBAAkB,GACnC,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAExG,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,YAAY,EAAE,oCAAoC,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC7G,OAAO,EACL,6BAA6B,EAC7B,eAAe,EACf,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,18 +0,0 @@
1
- export { defineJsonRoute, mountJsonRoute } from './adapter.js';
2
- export { registerApiBearerAuthMiddleware, registerApiOriginGuardMiddleware } from './api-security-middleware.js';
3
- // Legacy-shaped compat error helpers (separate code/message/init call shape). `sendApiError`
4
- // below (from `response.ts`) takes a single `ApiError` object; this compat `sendApiError` takes
5
- // `(code, message, init)` — same job, different call-site generation, so it is re-exported here
6
- // under a distinct name to avoid a duplicate export.
7
- export { createCompatApiError, createCompatApiErrorResponse, sendApiError as sendCompatApiError, } from './compat.js';
8
- export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
9
- export { isLoopbackHostname, isLoopbackPeerAddress, localOriginFromHeader, normalizeLocalAuthority, requireLocalDaemonRequest, validateLocalDaemonRequest, } from './local-daemon-request.js';
10
- export { guardSameOrigin } from './origin.js';
11
- export { rawInput, validationError } from './request.js';
12
- export { registerRunStreamRoute } from './run-stream.js';
13
- export { sendApiError, sendJson, statusForError } from './response.js';
14
- export { getRouteRegistrationInventory, guardedRouteKey, installRouteRegistrationGuard, } from './route-registration-guard.js';
15
- export { registerRunEventStream, registerRunRoutes } from './runs.js';
16
- export { registerAgentRoutes } from './agents.js';
17
- export { registerHostToolsRoutes } from './host-tools.js';
18
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG/D,OAAO,EAAE,+BAA+B,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAEjH,6FAA6F;AAC7F,gGAAgG;AAChG,gGAAgG;AAChG,qDAAqD;AACrD,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,YAAY,IAAI,kBAAkB,GACnC,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAExG,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGvE,OAAO,EACL,6BAA6B,EAC7B,eAAe,EACf,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,43 +0,0 @@
1
- import type { FastifyReply, FastifyRequest } from 'fastify';
2
- interface LocalAuthority {
3
- hostname: string;
4
- port: string;
5
- }
6
- interface LocalDaemonValidation {
7
- ok: true;
8
- origin: string | null;
9
- }
10
- interface LocalDaemonValidationError {
11
- ok: false;
12
- message: string;
13
- details: Record<string, string>;
14
- }
15
- /** Parses a `Host`-header-shaped authority string, rejecting anything with a path/userinfo/query. */
16
- export declare function normalizeLocalAuthority(value: unknown): LocalAuthority | null;
17
- /** True when `hostname` is `localhost`, an IPv6 loopback literal, or a `127.0.0.0/8` IPv4 literal. */
18
- export declare function isLoopbackHostname(hostname: unknown): boolean;
19
- /** True when `address` (typically `req.socket.remoteAddress`) is a loopback peer, unwrapping an IPv4-mapped IPv6 prefix first. */
20
- export declare function isLoopbackPeerAddress(address: unknown): boolean;
21
- /** Parses an `Origin` header value into its origin string, requiring a bare `scheme://loopback-host[:port]` with no path/query/userinfo. */
22
- export declare function localOriginFromHeader(value: unknown): string | null;
23
- /**
24
- * Validates that `req` is a loopback request: the TCP peer address, the `Host` header, and (when
25
- * present) the `Origin` header must all resolve to a loopback host.
26
- *
27
- * @param req - The incoming request.
28
- * @returns `{ ok: true, origin }` on success (`origin` is the validated `Origin` header value, or
29
- * `null` when the request carried none); otherwise `{ ok: false, message, details }` naming which
30
- * check failed.
31
- */
32
- export declare function validateLocalDaemonRequest(req: FastifyRequest): LocalDaemonValidation | LocalDaemonValidationError;
33
- /**
34
- * Fastify `onRequest` hook that rejects any non-loopback request with a 403, and otherwise sets
35
- * permissive same-machine CORS headers before calling `done()`.
36
- *
37
- * @param req - The incoming request.
38
- * @param reply - The reply to reject on, or set CORS headers on before continuing.
39
- * @param done - Called (with no error) when the request validates as loopback, continuing the hook chain.
40
- */
41
- export declare function requireLocalDaemonRequest(req: FastifyRequest, reply: FastifyReply, done: (err?: Error) => void): void;
42
- export {};
43
- //# sourceMappingURL=local-daemon-request.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"local-daemon-request.d.ts","sourceRoot":"","sources":["../../src/fastify/local-daemon-request.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG5D,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,qBAAqB;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,UAAU,0BAA0B;IAClC,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,qGAAqG;AACrG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAkB7E;AAED,sGAAsG;AACtG,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAS7D;AAED,kIAAkI;AAClI,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ/D;AAED,4IAA4I;AAC5I,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAcnE;AAOD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,cAAc,GAAG,qBAAqB,GAAG,0BAA0B,CA4BlH;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAerH"}