@graphorin/server 0.5.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +116 -0
  4. package/dist/app.d.ts +174 -0
  5. package/dist/app.d.ts.map +1 -0
  6. package/dist/app.js +684 -0
  7. package/dist/app.js.map +1 -0
  8. package/dist/commentary/audit-bridge.d.ts +57 -0
  9. package/dist/commentary/audit-bridge.d.ts.map +1 -0
  10. package/dist/commentary/audit-bridge.js +92 -0
  11. package/dist/commentary/audit-bridge.js.map +1 -0
  12. package/dist/commentary/built-in-patterns.d.ts +24 -0
  13. package/dist/commentary/built-in-patterns.d.ts.map +1 -0
  14. package/dist/commentary/built-in-patterns.js +62 -0
  15. package/dist/commentary/built-in-patterns.js.map +1 -0
  16. package/dist/commentary/index.d.ts +5 -0
  17. package/dist/commentary/index.js +5 -0
  18. package/dist/commentary/sanitizer.d.ts +37 -0
  19. package/dist/commentary/sanitizer.d.ts.map +1 -0
  20. package/dist/commentary/sanitizer.js +182 -0
  21. package/dist/commentary/sanitizer.js.map +1 -0
  22. package/dist/commentary/types.d.ts +120 -0
  23. package/dist/commentary/types.d.ts.map +1 -0
  24. package/dist/config.d.ts +760 -0
  25. package/dist/config.d.ts.map +1 -0
  26. package/dist/config.js +217 -0
  27. package/dist/config.js.map +1 -0
  28. package/dist/consolidator/daemon.d.ts +88 -0
  29. package/dist/consolidator/daemon.d.ts.map +1 -0
  30. package/dist/consolidator/daemon.js +54 -0
  31. package/dist/consolidator/daemon.js.map +1 -0
  32. package/dist/consolidator/index.d.ts +2 -0
  33. package/dist/consolidator/index.js +3 -0
  34. package/dist/errors/index.d.ts +104 -0
  35. package/dist/errors/index.d.ts.map +1 -0
  36. package/dist/errors/index.js +131 -0
  37. package/dist/errors/index.js.map +1 -0
  38. package/dist/health/checks.d.ts +120 -0
  39. package/dist/health/checks.d.ts.map +1 -0
  40. package/dist/health/checks.js +127 -0
  41. package/dist/health/checks.js.map +1 -0
  42. package/dist/health/index.d.ts +3 -0
  43. package/dist/health/index.js +4 -0
  44. package/dist/health/routes.d.ts +66 -0
  45. package/dist/health/routes.d.ts.map +1 -0
  46. package/dist/health/routes.js +96 -0
  47. package/dist/health/routes.js.map +1 -0
  48. package/dist/index.d.ts +88 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +86 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/internal/context.d.ts +66 -0
  53. package/dist/internal/context.d.ts.map +1 -0
  54. package/dist/internal/ids.js +21 -0
  55. package/dist/internal/ids.js.map +1 -0
  56. package/dist/internal/json.js +46 -0
  57. package/dist/internal/json.js.map +1 -0
  58. package/dist/lifecycle/hooks.d.ts +57 -0
  59. package/dist/lifecycle/hooks.d.ts.map +1 -0
  60. package/dist/lifecycle/index.d.ts +2 -0
  61. package/dist/lifecycle/index.js +3 -0
  62. package/dist/lifecycle/pre-bind.d.ts +38 -0
  63. package/dist/lifecycle/pre-bind.d.ts.map +1 -0
  64. package/dist/lifecycle/pre-bind.js +62 -0
  65. package/dist/lifecycle/pre-bind.js.map +1 -0
  66. package/dist/metrics/catalog.d.ts +34 -0
  67. package/dist/metrics/catalog.d.ts.map +1 -0
  68. package/dist/metrics/catalog.js +61 -0
  69. package/dist/metrics/catalog.js.map +1 -0
  70. package/dist/metrics/index.d.ts +3 -0
  71. package/dist/metrics/index.js +4 -0
  72. package/dist/metrics/registry.d.ts +63 -0
  73. package/dist/metrics/registry.d.ts.map +1 -0
  74. package/dist/metrics/registry.js +222 -0
  75. package/dist/metrics/registry.js.map +1 -0
  76. package/dist/middleware/audit.d.ts +47 -0
  77. package/dist/middleware/audit.d.ts.map +1 -0
  78. package/dist/middleware/audit.js +71 -0
  79. package/dist/middleware/audit.js.map +1 -0
  80. package/dist/middleware/auth.d.ts +50 -0
  81. package/dist/middleware/auth.d.ts.map +1 -0
  82. package/dist/middleware/auth.js +164 -0
  83. package/dist/middleware/auth.js.map +1 -0
  84. package/dist/middleware/cors.d.ts +15 -0
  85. package/dist/middleware/cors.d.ts.map +1 -0
  86. package/dist/middleware/cors.js +45 -0
  87. package/dist/middleware/cors.js.map +1 -0
  88. package/dist/middleware/csrf.d.ts +15 -0
  89. package/dist/middleware/csrf.d.ts.map +1 -0
  90. package/dist/middleware/csrf.js +77 -0
  91. package/dist/middleware/csrf.js.map +1 -0
  92. package/dist/middleware/idempotency.d.ts +41 -0
  93. package/dist/middleware/idempotency.d.ts.map +1 -0
  94. package/dist/middleware/idempotency.js +198 -0
  95. package/dist/middleware/idempotency.js.map +1 -0
  96. package/dist/middleware/index.d.ts +9 -0
  97. package/dist/middleware/index.js +10 -0
  98. package/dist/middleware/rate-limit.d.ts +17 -0
  99. package/dist/middleware/rate-limit.d.ts.map +1 -0
  100. package/dist/middleware/rate-limit.js +47 -0
  101. package/dist/middleware/rate-limit.js.map +1 -0
  102. package/dist/middleware/request-state.d.ts +27 -0
  103. package/dist/middleware/request-state.d.ts.map +1 -0
  104. package/dist/middleware/request-state.js +42 -0
  105. package/dist/middleware/request-state.js.map +1 -0
  106. package/dist/middleware/scope.d.ts +24 -0
  107. package/dist/middleware/scope.d.ts.map +1 -0
  108. package/dist/middleware/scope.js +50 -0
  109. package/dist/middleware/scope.js.map +1 -0
  110. package/dist/registry/index.d.ts +135 -0
  111. package/dist/registry/index.d.ts.map +1 -0
  112. package/dist/registry/index.js +96 -0
  113. package/dist/registry/index.js.map +1 -0
  114. package/dist/replay/index.d.ts +2 -0
  115. package/dist/replay/index.js +3 -0
  116. package/dist/replay/routes.d.ts +46 -0
  117. package/dist/replay/routes.d.ts.map +1 -0
  118. package/dist/replay/routes.js +189 -0
  119. package/dist/replay/routes.js.map +1 -0
  120. package/dist/routes/agents.d.ts +41 -0
  121. package/dist/routes/agents.d.ts.map +1 -0
  122. package/dist/routes/agents.js +213 -0
  123. package/dist/routes/agents.js.map +1 -0
  124. package/dist/routes/audit.d.ts +57 -0
  125. package/dist/routes/audit.d.ts.map +1 -0
  126. package/dist/routes/audit.js +116 -0
  127. package/dist/routes/audit.js.map +1 -0
  128. package/dist/routes/auth.d.ts +26 -0
  129. package/dist/routes/auth.d.ts.map +1 -0
  130. package/dist/routes/auth.js +54 -0
  131. package/dist/routes/auth.js.map +1 -0
  132. package/dist/routes/health.d.ts +22 -0
  133. package/dist/routes/health.d.ts.map +1 -0
  134. package/dist/routes/health.js +33 -0
  135. package/dist/routes/health.js.map +1 -0
  136. package/dist/routes/index.d.ts +10 -0
  137. package/dist/routes/index.js +12 -0
  138. package/dist/routes/mcp.d.ts +32 -0
  139. package/dist/routes/mcp.d.ts.map +1 -0
  140. package/dist/routes/mcp.js +61 -0
  141. package/dist/routes/mcp.js.map +1 -0
  142. package/dist/routes/memory.d.ts +141 -0
  143. package/dist/routes/memory.d.ts.map +1 -0
  144. package/dist/routes/memory.js +102 -0
  145. package/dist/routes/memory.js.map +1 -0
  146. package/dist/routes/sessions.d.ts +54 -0
  147. package/dist/routes/sessions.d.ts.map +1 -0
  148. package/dist/routes/sessions.js +135 -0
  149. package/dist/routes/sessions.js.map +1 -0
  150. package/dist/routes/skills.d.ts +34 -0
  151. package/dist/routes/skills.d.ts.map +1 -0
  152. package/dist/routes/skills.js +54 -0
  153. package/dist/routes/skills.js.map +1 -0
  154. package/dist/routes/tokens.d.ts +25 -0
  155. package/dist/routes/tokens.d.ts.map +1 -0
  156. package/dist/routes/tokens.js +87 -0
  157. package/dist/routes/tokens.js.map +1 -0
  158. package/dist/routes/workflows.d.ts +27 -0
  159. package/dist/routes/workflows.d.ts.map +1 -0
  160. package/dist/routes/workflows.js +220 -0
  161. package/dist/routes/workflows.js.map +1 -0
  162. package/dist/runtime/run-state.d.ts +158 -0
  163. package/dist/runtime/run-state.d.ts.map +1 -0
  164. package/dist/runtime/run-state.js +182 -0
  165. package/dist/runtime/run-state.js.map +1 -0
  166. package/dist/sse/events.d.ts +44 -0
  167. package/dist/sse/events.d.ts.map +1 -0
  168. package/dist/sse/events.js +200 -0
  169. package/dist/sse/events.js.map +1 -0
  170. package/dist/sse/index.d.ts +2 -0
  171. package/dist/sse/index.js +3 -0
  172. package/dist/triggers/daemon.d.ts +74 -0
  173. package/dist/triggers/daemon.d.ts.map +1 -0
  174. package/dist/triggers/daemon.js +114 -0
  175. package/dist/triggers/daemon.js.map +1 -0
  176. package/dist/triggers/index.d.ts +3 -0
  177. package/dist/triggers/index.js +4 -0
  178. package/dist/triggers/routes.d.ts +21 -0
  179. package/dist/triggers/routes.d.ts.map +1 -0
  180. package/dist/triggers/routes.js +117 -0
  181. package/dist/triggers/routes.js.map +1 -0
  182. package/dist/ws/dispatcher.d.ts +169 -0
  183. package/dist/ws/dispatcher.d.ts.map +1 -0
  184. package/dist/ws/dispatcher.js +303 -0
  185. package/dist/ws/dispatcher.js.map +1 -0
  186. package/dist/ws/index.d.ts +6 -0
  187. package/dist/ws/index.js +7 -0
  188. package/dist/ws/replay-buffer.d.ts +47 -0
  189. package/dist/ws/replay-buffer.d.ts.map +1 -0
  190. package/dist/ws/replay-buffer.js +88 -0
  191. package/dist/ws/replay-buffer.js.map +1 -0
  192. package/dist/ws/subjects.d.ts +71 -0
  193. package/dist/ws/subjects.d.ts.map +1 -0
  194. package/dist/ws/subjects.js +112 -0
  195. package/dist/ws/subjects.js.map +1 -0
  196. package/dist/ws/ticket.d.ts +74 -0
  197. package/dist/ws/ticket.d.ts.map +1 -0
  198. package/dist/ws/ticket.js +112 -0
  199. package/dist/ws/ticket.js.map +1 -0
  200. package/dist/ws/upgrade.d.ts +63 -0
  201. package/dist/ws/upgrade.d.ts.map +1 -0
  202. package/dist/ws/upgrade.js +324 -0
  203. package/dist/ws/upgrade.js.map +1 -0
  204. package/package.json +156 -0
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ import { DEFAULT_APPLY_TO_EVENTS, DEFAULT_DELIVERY_COMMENTARY_PATTERNS } from "./commentary/built-in-patterns.js";
2
+ import { createDeliveryCommentarySanitizer } from "./commentary/sanitizer.js";
3
+ import "./commentary/index.js";
4
+ import { AgentNotFoundError, ConfigInvalidError, GraphorinServerError, IdempotencyConflictError, IdempotencyKeyRequiredError, LifecycleDoubleStartError, LifecycleNotStartedError, MigrationFailedError, PrebindEncryptionPeerMissingError, PrebindEncryptionRequiredError, PrebindPepperMissingError, PrebindSecretUnresolvableError, RouteHandlerMissingError, ShutdownTimeoutError, WorkflowNotFoundError } from "./errors/index.js";
5
+ import { ServerConfigSchema, defineConfig, parseServerConfig } from "./config.js";
6
+ import { createConsolidatorDaemon } from "./consolidator/daemon.js";
7
+ import { collectHealth, rollup } from "./health/checks.js";
8
+ import { createScopeMiddleware } from "./middleware/scope.js";
9
+ import { createExtendedHealthRoutes, createMetricsRoutes, createSecretsHealthRoutes } from "./health/routes.js";
10
+ import "./health/index.js";
11
+ import { runPreBind } from "./lifecycle/pre-bind.js";
12
+ import "./lifecycle/index.js";
13
+ import { MetricRegistry } from "./metrics/registry.js";
14
+ import { SERVER_METRIC_NAMES, createServerMetricRegistry } from "./metrics/catalog.js";
15
+ import { HTTP_REQUEST_AUDIT_ACTION, createAuditMiddleware } from "./middleware/audit.js";
16
+ import { createAuthMiddleware } from "./middleware/auth.js";
17
+ import { createCorsMiddleware } from "./middleware/cors.js";
18
+ import { createCsrfMiddleware } from "./middleware/csrf.js";
19
+ import { createIdempotencyMiddleware } from "./middleware/idempotency.js";
20
+ import { createRateLimitMiddleware } from "./middleware/rate-limit.js";
21
+ import { createRequestStateMiddleware } from "./middleware/request-state.js";
22
+ import "./middleware/index.js";
23
+ import { AgentRegistry, WorkflowRegistry } from "./registry/index.js";
24
+ import { createReplayRoutes } from "./replay/routes.js";
25
+ import "./replay/index.js";
26
+ import { createAgentRoutes, createRunRoutes } from "./routes/agents.js";
27
+ import { createAuditRoutes } from "./routes/audit.js";
28
+ import { createAuthRoutes } from "./routes/auth.js";
29
+ import { createHealthRoutes } from "./routes/health.js";
30
+ import { createMcpRoutes } from "./routes/mcp.js";
31
+ import { createMemoryRoutes } from "./routes/memory.js";
32
+ import { createSessionRoutes } from "./routes/sessions.js";
33
+ import { createSkillsRoutes } from "./routes/skills.js";
34
+ import { createTokensRoutes } from "./routes/tokens.js";
35
+ import { createWorkflowRoutes } from "./routes/workflows.js";
36
+ import "./routes/index.js";
37
+ import { RunStateTracker } from "./runtime/run-state.js";
38
+ import { createSseRoutes } from "./sse/events.js";
39
+ import "./sse/index.js";
40
+ import { createTriggersDaemon, defaultCatchupPolicy } from "./triggers/daemon.js";
41
+ import { createTriggersRoutes } from "./triggers/routes.js";
42
+ import { createReplayBuffer } from "./ws/replay-buffer.js";
43
+ import { requiredScopeFor, tryParseSubject } from "./ws/subjects.js";
44
+ import { createWsDispatcher } from "./ws/dispatcher.js";
45
+ import { createWsTicketStore } from "./ws/ticket.js";
46
+ import { createWsUpgradeEvents } from "./ws/upgrade.js";
47
+ import "./ws/index.js";
48
+ import { createServer, ensureStoreAuditBinding } from "./app.js";
49
+ import "./metrics/index.js";
50
+ import "./triggers/index.js";
51
+
52
+ //#region src/index.ts
53
+ /**
54
+ * `@graphorin/server` — standalone server runtime for the Graphorin
55
+ * framework.
56
+ *
57
+ * Phase 14a entry point. Ships:
58
+ *
59
+ * - {@link createServer} — the single programmatic entry that wires
60
+ * the Hono app, the auth + scope + idempotency + audit middleware
61
+ * stack, REST endpoints (agents / workflows / sessions / memory /
62
+ * skills / mcp / tokens / audit / health), the lifecycle hooks
63
+ * (`beforeStart` / `onReady` / `beforeShutdown` / `onError`), the
64
+ * pre-bind secrets-resolution + storage-migration runner, and the
65
+ * graceful SIGTERM drain.
66
+ * - {@link defineConfig} + {@link parseServerConfig} — typed
67
+ * configuration loader with a Zod-validated schema; missing fields
68
+ * fall back to documented production-ready defaults.
69
+ * - {@link AgentRegistry} + {@link WorkflowRegistry} — read/write
70
+ * registries the route handlers consult to look up user-defined
71
+ * agents / workflows.
72
+ * - {@link RunStateTracker} — in-memory bookkeeping for in-flight
73
+ * runs (run id, status, AbortController). Phase 14b/c promote the
74
+ * tracker to a SQLite-backed durable variant.
75
+ * - The full middleware factory suite — re-exported from
76
+ * `@graphorin/server/middleware` so operators can compose a custom
77
+ * Hono app on top of the same primitives.
78
+ *
79
+ * @packageDocumentation
80
+ */
81
+ /** Canonical version constant. Mirrors the `package.json` version. */
82
+ const VERSION = "0.5.0";
83
+
84
+ //#endregion
85
+ export { AgentNotFoundError, AgentRegistry, ConfigInvalidError, DEFAULT_APPLY_TO_EVENTS, DEFAULT_DELIVERY_COMMENTARY_PATTERNS, GraphorinServerError, HTTP_REQUEST_AUDIT_ACTION, IdempotencyConflictError, IdempotencyKeyRequiredError, LifecycleDoubleStartError, LifecycleNotStartedError, MetricRegistry, MigrationFailedError, PrebindEncryptionPeerMissingError, PrebindEncryptionRequiredError, PrebindPepperMissingError, PrebindSecretUnresolvableError, RouteHandlerMissingError, RunStateTracker, SERVER_METRIC_NAMES, ServerConfigSchema, ShutdownTimeoutError, VERSION, WorkflowNotFoundError, WorkflowRegistry, collectHealth, createAgentRoutes, createAuditMiddleware, createAuditRoutes, createAuthMiddleware, createAuthRoutes, createConsolidatorDaemon, createCorsMiddleware, createCsrfMiddleware, createDeliveryCommentarySanitizer, createExtendedHealthRoutes, createHealthRoutes, createIdempotencyMiddleware, createMcpRoutes, createMemoryRoutes, createMetricsRoutes, createRateLimitMiddleware, createReplayBuffer, createReplayRoutes, createRequestStateMiddleware, createRunRoutes, createScopeMiddleware, createSecretsHealthRoutes, createServer, createServerMetricRegistry, createSessionRoutes, createSkillsRoutes, createSseRoutes, createTokensRoutes, createTriggersDaemon, createTriggersRoutes, createWorkflowRoutes, createWsDispatcher, createWsTicketStore, createWsUpgradeEvents, defaultCatchupPolicy, defineConfig, ensureStoreAuditBinding, parseServerConfig, requiredScopeFor, rollup, runPreBind, tryParseSubject };
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@graphorin/server` — standalone server runtime for the Graphorin\n * framework.\n *\n * Phase 14a entry point. Ships:\n *\n * - {@link createServer} — the single programmatic entry that wires\n * the Hono app, the auth + scope + idempotency + audit middleware\n * stack, REST endpoints (agents / workflows / sessions / memory /\n * skills / mcp / tokens / audit / health), the lifecycle hooks\n * (`beforeStart` / `onReady` / `beforeShutdown` / `onError`), the\n * pre-bind secrets-resolution + storage-migration runner, and the\n * graceful SIGTERM drain.\n * - {@link defineConfig} + {@link parseServerConfig} — typed\n * configuration loader with a Zod-validated schema; missing fields\n * fall back to documented production-ready defaults.\n * - {@link AgentRegistry} + {@link WorkflowRegistry} — read/write\n * registries the route handlers consult to look up user-defined\n * agents / workflows.\n * - {@link RunStateTracker} — in-memory bookkeeping for in-flight\n * runs (run id, status, AbortController). Phase 14b/c promote the\n * tracker to a SQLite-backed durable variant.\n * - The full middleware factory suite — re-exported from\n * `@graphorin/server/middleware` so operators can compose a custom\n * Hono app on top of the same primitives.\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant. Mirrors the `package.json` version. */\nexport const VERSION = '0.5.0';\n\nexport {\n type CreateServerOptions,\n createServer,\n ensureStoreAuditBinding,\n type GraphorinServer,\n type TriggersDaemonInput,\n} from './app.js';\nexport {\n createDeliveryCommentarySanitizer,\n DEFAULT_APPLY_TO_EVENTS,\n DEFAULT_DELIVERY_COMMENTARY_PATTERNS,\n type DeliveryCommentaryConfig,\n type DeliveryCommentaryDecision,\n type DeliveryCommentaryPattern,\n type DeliveryCommentaryPolicy,\n type DeliveryCommentaryReason,\n type DeliveryCommentarySanitizer,\n type DeliveryCommentarySink,\n type DeliveryCommentaryTransport,\n} from './commentary/index.js';\nexport {\n type DeliveryCommentaryPolicyConfig,\n defineConfig,\n type IdempotencyRequireKeyMode,\n parseServerConfig,\n type SecretRefString,\n type SecretsSource,\n type ServerConfigInput,\n ServerConfigSchema,\n type ServerConfigSpec,\n} from './config.js';\nexport {\n type ConsolidatorDaemon,\n type ConsolidatorLike,\n type ConsolidatorStatusLike,\n type CreateConsolidatorDaemonOptions,\n createConsolidatorDaemon,\n} from './consolidator/index.js';\nexport * from './errors/index.js';\nexport {\n type BaseHealthCheck,\n type ConsolidatorCheck,\n collectHealth,\n createExtendedHealthRoutes,\n createMetricsRoutes,\n createSecretsHealthRoutes,\n type EmbedderCheck,\n type EncryptionCheck,\n type HealthCheck,\n type HealthCheckOptions,\n type HealthChecks,\n type HealthRollup,\n type HealthRouteOptions,\n type HealthStatus,\n type HealthSummary,\n type MetricsRoutesOptions,\n type ReplayBufferCheck,\n type ReplayBufferProbe,\n rollup,\n type SecretsCheck,\n type StorageCheck,\n type TriggersCheck,\n} from './health/index.js';\nexport type { RequestToken, ServerRequestState, ServerVariables } from './internal/context.js';\nexport {\n type BeforeShutdownContext,\n type BeforeStartContext,\n type LifecycleHooks,\n type OnErrorContext,\n type OnReadyContext,\n type PreBindResult,\n type RunPreBindOptions,\n runPreBind,\n} from './lifecycle/index.js';\nexport {\n createServerMetricRegistry,\n type LabelSet,\n type MetricKind,\n MetricRegistry,\n SERVER_METRIC_NAMES,\n} from './metrics/index.js';\nexport {\n type AuditErrorSink,\n type AuditMiddlewareOptions,\n type AuthMiddlewareOptions,\n createAuditMiddleware,\n createAuthMiddleware,\n createCorsMiddleware,\n createCsrfMiddleware,\n createIdempotencyMiddleware,\n createRateLimitMiddleware,\n createRequestStateMiddleware,\n createScopeMiddleware,\n HTTP_REQUEST_AUDIT_ACTION,\n type IdempotencyMiddlewareOptions,\n type RequestStateMiddlewareOptions,\n type ScopeRequirement,\n} from './middleware/index.js';\nexport {\n type AgentRegistration,\n AgentRegistry,\n type AgentSummary,\n type ServerAgentLike,\n type ServerWorkflowLike,\n type WorkflowRegistration,\n WorkflowRegistry,\n type WorkflowSummary,\n} from './registry/index.js';\nexport {\n createReplayRoutes,\n type ReplayApi,\n type ReplayMode,\n type ReplayResponse,\n type ReplayRoutesDeps,\n} from './replay/index.js';\nexport {\n type AgentRoutesDeps,\n type AuditApi,\n type AuditRoutesDeps,\n type AuthRoutesDeps,\n createAgentRoutes,\n createAuditRoutes,\n createAuthRoutes,\n createHealthRoutes,\n createMcpRoutes,\n createMemoryRoutes,\n createRunRoutes,\n createSessionRoutes,\n createSkillsRoutes,\n createTokensRoutes,\n createWorkflowRoutes,\n type HealthRoutesDeps,\n type McpApi,\n type McpRoutesDeps,\n type MemoryApi,\n type MemoryRoutesDeps,\n type SessionApi,\n type SessionRoutesDeps,\n type SkillsApi,\n type SkillsRoutesDeps,\n type TokensRoutesDeps,\n type WorkflowRoutesDeps,\n} from './routes/index.js';\nexport {\n type RunDescriptor,\n type RunHandle,\n type RunStateSnapshot,\n RunStateTracker,\n type RunStatus,\n} from './runtime/run-state.js';\nexport { createSseRoutes, type SseRoutesDeps } from './sse/index.js';\nexport {\n type CreateTriggersDaemonOptions,\n createTriggersDaemon,\n createTriggersRoutes,\n defaultCatchupPolicy,\n type TriggersDaemon,\n type TriggersDaemonMetrics,\n type TriggersDaemonStatus,\n type TriggersRoutesDeps,\n} from './triggers/index.js';\nexport {\n type BareEventFrame,\n createReplayBuffer,\n createWsDispatcher,\n createWsTicketStore,\n createWsUpgradeEvents,\n type ParsedSubject,\n type ReplayBuffer,\n type ReplayBufferOptions,\n type ReplayBufferSlice,\n requiredScopeFor,\n type SubscribeResult,\n tryParseSubject,\n type WsDispatcher,\n type WsDispatcherOptions,\n type WsDispatcherWarning,\n type WsSubscriberHandle,\n type WsSubscriptionSnapshot,\n type WsTicket,\n type WsTicketConsumeResult,\n type WsTicketStore,\n type WsTicketStoreOptions,\n type WsUpgradeOptions,\n} from './ws/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,UAAU"}
@@ -0,0 +1,66 @@
1
+ import { ParsedScope, VerifiedToken } from "@graphorin/security/auth";
2
+
3
+ //#region src/internal/context.d.ts
4
+
5
+ /**
6
+ * Discriminator for the request authentication state.
7
+ *
8
+ * @stable
9
+ */
10
+ type AuthState = {
11
+ readonly kind: 'unauthenticated';
12
+ } | {
13
+ readonly kind: 'token';
14
+ readonly token: VerifiedToken;
15
+ readonly grantedScopes: ReadonlyArray<ParsedScope>;
16
+ } | {
17
+ readonly kind: 'anonymous';
18
+ readonly grantedScopes: ReadonlyArray<ParsedScope>;
19
+ };
20
+ /**
21
+ * Request-scoped variables surfaced through `c.var` in Hono. The
22
+ * server's middleware populates these fields incrementally; route
23
+ * handlers consume them through {@link getRequestState}.
24
+ *
25
+ * @stable
26
+ */
27
+ interface ServerRequestState {
28
+ readonly requestId: string;
29
+ readonly receivedAt: number;
30
+ readonly clientIp: string | undefined;
31
+ readonly auth: AuthState;
32
+ readonly idempotencyKey?: string;
33
+ readonly idempotencyReplay?: boolean;
34
+ }
35
+ /**
36
+ * Convenience snapshot of the verified token surfaced on `c.var.token`
37
+ * once the auth middleware has resolved the bearer credential. Mirrors
38
+ * the contract documented in the runtime architecture (Phase 14a §
39
+ * Authentication / authorization middleware: "populates `c.var.token:
40
+ * { id, label, scopes, env }`").
41
+ *
42
+ * Read this through {@link getRequestToken} so consumers do not have
43
+ * to remember the variable key.
44
+ *
45
+ * @stable
46
+ */
47
+ interface RequestToken {
48
+ readonly id: string;
49
+ readonly label: string | undefined;
50
+ readonly scopes: ReadonlyArray<ParsedScope>;
51
+ readonly env: string;
52
+ readonly expiresAt: number | undefined;
53
+ }
54
+ /**
55
+ * Hono variable map. Exported so consumers can type their own
56
+ * middleware against the same surface.
57
+ *
58
+ * @stable
59
+ */
60
+ interface ServerVariables extends Record<string, unknown> {
61
+ readonly state: ServerRequestState;
62
+ readonly token?: RequestToken;
63
+ }
64
+ //#endregion
65
+ export { RequestToken, ServerRequestState, ServerVariables };
66
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","names":[],"sources":["../../src/internal/context.ts"],"sourcesContent":[],"mappings":";;;;;;AAsCA;AAqBA;AAcA;AACkB,KA3DN,SAAA,GA2DM;EACC,SAAA,IAAA,EAAA,iBAAA;CAFsB,GAAA;EAAM,SAAA,IAAA,EAAA,OAAA;kBAtDzB;0BACQ,cAAc;;;0BAQd,cAAc;;;;;;;;;UAU3B,kBAAA;;;;iBAIA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;mBAGE,cAAc;;;;;;;;;;UAWhB,eAAA,SAAwB;kBACvB;mBACC"}
@@ -0,0 +1,21 @@
1
+ import { randomUUID } from "node:crypto";
2
+
3
+ //#region src/internal/ids.ts
4
+ /**
5
+ * Tiny id helpers shared across middleware + routes.
6
+ *
7
+ * @internal
8
+ */
9
+ /**
10
+ * Generate an opaque per-request id. UUID v4 keeps the surface area
11
+ * minimal — operators that already pin a different scheme (Datadog
12
+ * trace ids, AWS request ids, …) can override the generator on
13
+ * `createServer({ requestIdGenerator })`.
14
+ */
15
+ function newRequestId() {
16
+ return randomUUID();
17
+ }
18
+
19
+ //#endregion
20
+ export { newRequestId };
21
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","names":[],"sources":["../../src/internal/ids.ts"],"sourcesContent":["/**\n * Tiny id helpers shared across middleware + routes.\n *\n * @internal\n */\n\nimport { randomUUID } from 'node:crypto';\n\n/**\n * Generate an opaque per-request id. UUID v4 keeps the surface area\n * minimal — operators that already pin a different scheme (Datadog\n * trace ids, AWS request ids, …) can override the generator on\n * `createServer({ requestIdGenerator })`.\n */\nexport function newRequestId(): string {\n return randomUUID();\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,eAAuB;AACrC,QAAO,YAAY"}
@@ -0,0 +1,46 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ //#region src/internal/json.ts
4
+ /**
5
+ * Helpers for the strict JSON contract every REST endpoint speaks.
6
+ *
7
+ * @internal
8
+ */
9
+ /**
10
+ * Stable, recursive JSON canonicalisation: object keys sorted
11
+ * lexicographically, arrays preserved as-is. Used by the idempotency
12
+ * middleware so two semantically-identical bodies produce the same
13
+ * fingerprint.
14
+ */
15
+ function canonicalJson(value) {
16
+ return JSON.stringify(canonicalize(value));
17
+ }
18
+ function canonicalize(value) {
19
+ if (value === null) return null;
20
+ if (typeof value !== "object") return value;
21
+ if (Array.isArray(value)) return value.map(canonicalize);
22
+ const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
23
+ const out = {};
24
+ for (const [key, val] of entries) out[key] = canonicalize(val);
25
+ return out;
26
+ }
27
+ /**
28
+ * SHA-256 hex digest of the supplied bytes. Returns the lowercase
29
+ * hex string so it can be compared against the persisted fingerprint
30
+ * without further normalisation.
31
+ */
32
+ function sha256Hex(input) {
33
+ return createHash("sha256").update(input).digest("hex");
34
+ }
35
+ /**
36
+ * SHA-256 fingerprint of a (method, path, body) tuple. The body is
37
+ * canonicalised before hashing so trivial whitespace differences do
38
+ * not register as a payload mismatch.
39
+ */
40
+ function fingerprintRequest(method, path, body) {
41
+ return sha256Hex(`${method.toUpperCase()} ${path}\n${canonicalJson(body)}`);
42
+ }
43
+
44
+ //#endregion
45
+ export { fingerprintRequest };
46
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","names":["out: Record<string, unknown>"],"sources":["../../src/internal/json.ts"],"sourcesContent":["/**\n * Helpers for the strict JSON contract every REST endpoint speaks.\n *\n * @internal\n */\n\nimport { createHash } from 'node:crypto';\n\n/**\n * Stable, recursive JSON canonicalisation: object keys sorted\n * lexicographically, arrays preserved as-is. Used by the idempotency\n * middleware so two semantically-identical bodies produce the same\n * fingerprint.\n */\nexport function canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalize(value));\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (value === null) return null;\n if (typeof value !== 'object') return value;\n if (Array.isArray(value)) return value.map(canonicalize);\n const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0,\n );\n const out: Record<string, unknown> = {};\n for (const [key, val] of entries) out[key] = canonicalize(val);\n return out;\n}\n\n/**\n * SHA-256 hex digest of the supplied bytes. Returns the lowercase\n * hex string so it can be compared against the persisted fingerprint\n * without further normalisation.\n */\nexport function sha256Hex(input: string | Uint8Array): string {\n return createHash('sha256').update(input).digest('hex');\n}\n\n/**\n * SHA-256 fingerprint of a (method, path, body) tuple. The body is\n * canonicalised before hashing so trivial whitespace differences do\n * not register as a payload mismatch.\n */\nexport function fingerprintRequest(method: string, path: string, body: unknown): string {\n return sha256Hex(`${method.toUpperCase()} ${path}\\n${canonicalJson(body)}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,cAAc,OAAwB;AACpD,QAAO,KAAK,UAAU,aAAa,MAAM,CAAC;;AAG5C,SAAS,aAAa,OAAyB;AAC7C,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,MAAM,IAAI,aAAa;CACxD,MAAM,UAAU,OAAO,QAAQ,MAAiC,CAAC,MAAM,CAAC,IAAI,CAAC,OAC3E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,EAC1B;CACD,MAAMA,MAA+B,EAAE;AACvC,MAAK,MAAM,CAAC,KAAK,QAAQ,QAAS,KAAI,OAAO,aAAa,IAAI;AAC9D,QAAO;;;;;;;AAQT,SAAgB,UAAU,OAAoC;AAC5D,QAAO,WAAW,SAAS,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM;;;;;;;AAQzD,SAAgB,mBAAmB,QAAgB,MAAc,MAAuB;AACtF,QAAO,UAAU,GAAG,OAAO,aAAa,CAAC,GAAG,KAAK,IAAI,cAAc,KAAK,GAAG"}
@@ -0,0 +1,57 @@
1
+ import { ServerConfigSpec } from "../config.js";
2
+
3
+ //#region src/lifecycle/hooks.d.ts
4
+
5
+ /**
6
+ * Snapshot passed to {@link LifecycleHooks.beforeStart}.
7
+ *
8
+ * @stable
9
+ */
10
+ interface BeforeStartContext {
11
+ readonly config: ServerConfigSpec;
12
+ }
13
+ /**
14
+ * Snapshot passed to {@link LifecycleHooks.onReady}.
15
+ *
16
+ * @stable
17
+ */
18
+ interface OnReadyContext {
19
+ readonly config: ServerConfigSpec;
20
+ readonly listeningOn: {
21
+ readonly host: string;
22
+ readonly port: number;
23
+ };
24
+ }
25
+ /**
26
+ * Snapshot passed to {@link LifecycleHooks.beforeShutdown}.
27
+ *
28
+ * @stable
29
+ */
30
+ interface BeforeShutdownContext {
31
+ readonly config: ServerConfigSpec;
32
+ readonly inflight: number;
33
+ readonly drainTimeoutMs: number;
34
+ }
35
+ /**
36
+ * Snapshot passed to {@link LifecycleHooks.onError}. Errors raised
37
+ * outside the request hot path (lifecycle, audit append, etc.) flow
38
+ * here so operators can fan them into Sentry / Datadog / etc.
39
+ *
40
+ * @stable
41
+ */
42
+ interface OnErrorContext {
43
+ readonly error: unknown;
44
+ readonly phase: 'beforeStart' | 'onReady' | 'beforeShutdown' | 'request' | 'background';
45
+ }
46
+ /**
47
+ * @stable
48
+ */
49
+ interface LifecycleHooks {
50
+ readonly beforeStart?: (ctx: BeforeStartContext) => void | Promise<void>;
51
+ readonly onReady?: (ctx: OnReadyContext) => void | Promise<void>;
52
+ readonly beforeShutdown?: (ctx: BeforeShutdownContext) => void | Promise<void>;
53
+ readonly onError?: (ctx: OnErrorContext) => void | Promise<void>;
54
+ }
55
+ //#endregion
56
+ export { BeforeShutdownContext, BeforeStartContext, LifecycleHooks, OnErrorContext, OnReadyContext };
57
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","names":[],"sources":["../../src/lifecycle/hooks.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAoBiB,kBAAA;mBACE;;;;;;;UAQF,cAAA;mBACE;;;;;;;;;;;UASF,qBAAA;mBACE;;;;;;;;;;;UAYF,cAAA;;;;;;;UAQA,cAAA;+BACc,8BAA8B;2BAClC,0BAA0B;kCACnB,iCAAiC;2BACxC,0BAA0B"}
@@ -0,0 +1,2 @@
1
+ import { BeforeShutdownContext, BeforeStartContext, LifecycleHooks, OnErrorContext, OnReadyContext } from "./hooks.js";
2
+ import { PreBindResult, RunPreBindOptions, runPreBind } from "./pre-bind.js";
@@ -0,0 +1,3 @@
1
+ import { runPreBind } from "./pre-bind.js";
2
+
3
+ export { };
@@ -0,0 +1,38 @@
1
+ import { ServerConfigSpec } from "../config.js";
2
+ import { SecretValue } from "@graphorin/security";
3
+ import { GraphorinSqliteStore } from "@graphorin/store-sqlite";
4
+
5
+ //#region src/lifecycle/pre-bind.d.ts
6
+
7
+ /**
8
+ * Result returned by {@link runPreBind}. Consumers (`createServer`,
9
+ * tests) consume the resolved pepper + encryption decision when
10
+ * wiring the rest of the server.
11
+ *
12
+ * @stable
13
+ */
14
+ interface PreBindResult {
15
+ readonly pepper?: SecretValue;
16
+ readonly auditPath?: string;
17
+ readonly auditPassphrase?: SecretValue;
18
+ readonly storagePassphrase?: SecretValue;
19
+ }
20
+ /**
21
+ * @stable
22
+ */
23
+ interface RunPreBindOptions {
24
+ readonly config: ServerConfigSpec;
25
+ readonly store: GraphorinSqliteStore;
26
+ /**
27
+ * Optional override for the cipher-peer probe. Tests inject a stub
28
+ * that signals "missing peer" without uninstalling the real one.
29
+ */
30
+ readonly probeCipherPeer?: () => Promise<void>;
31
+ }
32
+ /**
33
+ * @stable
34
+ */
35
+ declare function runPreBind(options: RunPreBindOptions): Promise<PreBindResult>;
36
+ //#endregion
37
+ export { PreBindResult, RunPreBindOptions, runPreBind };
38
+ //# sourceMappingURL=pre-bind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-bind.d.ts","names":[],"sources":["../../src/lifecycle/pre-bind.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UA0CiB,aAAA;oBACG;;6BAES;+BACE;;;;;UAMd,iBAAA;mBACE;kBACD;;;;;mCAKiB;;;;;iBAcb,UAAA,UAAoB,oBAAoB,QAAQ"}
@@ -0,0 +1,62 @@
1
+ import { MigrationFailedError, PrebindEncryptionPeerMissingError, PrebindEncryptionRequiredError, PrebindPepperMissingError, PrebindSecretUnresolvableError } from "../errors/index.js";
2
+ import { resolveSecret } from "@graphorin/security/secrets";
3
+
4
+ //#region src/lifecycle/pre-bind.ts
5
+ async function resolveRef(path, raw) {
6
+ try {
7
+ return await resolveSecret(raw);
8
+ } catch (err) {
9
+ throw new PrebindSecretUnresolvableError(path, raw, err);
10
+ }
11
+ }
12
+ /**
13
+ * @stable
14
+ */
15
+ async function runPreBind(options) {
16
+ const { config, store } = options;
17
+ const out = {};
18
+ if (config.auth.kind === "token") {
19
+ if (config.auth.pepperRef === void 0 || config.auth.pepperRef.length === 0) throw new PrebindPepperMissingError();
20
+ const pepper = await resolveRef(["auth", "pepperRef"], config.auth.pepperRef);
21
+ if ((await pepper.useBuffer((b) => Buffer.from(b))).length === 0) throw new PrebindPepperMissingError();
22
+ out.pepper = pepper;
23
+ }
24
+ if (config.storage.encryption.enabled) {
25
+ if (config.storage.encryption.passphraseRef === void 0) throw new PrebindEncryptionRequiredError("storage.encryption.enabled is true but no passphraseRef is configured.");
26
+ out.storagePassphrase = await resolveRef([
27
+ "storage",
28
+ "encryption",
29
+ "passphraseRef"
30
+ ], config.storage.encryption.passphraseRef);
31
+ if (options.probeCipherPeer !== void 0) try {
32
+ await options.probeCipherPeer();
33
+ } catch (err) {
34
+ throw new PrebindEncryptionPeerMissingError(err);
35
+ }
36
+ }
37
+ if (config.audit.enabled) {
38
+ const passphraseRef = config.audit.passphraseRef ?? config.storage.encryption.passphraseRef;
39
+ if (passphraseRef === void 0) throw new PrebindEncryptionRequiredError("audit.enabled is true but no audit.passphraseRef (or storage.encryption.passphraseRef) is configured. Audit logs are mandatory-encrypted (DEC-124).");
40
+ out.auditPath = config.audit.path ?? deriveAuditPath(config.storage.path);
41
+ out.auditPassphrase = await resolveRef(["audit", "passphraseRef"], passphraseRef);
42
+ }
43
+ try {
44
+ await store.init();
45
+ } catch (err) {
46
+ throw new MigrationFailedError(`Storage migrations failed: ${describeError(err)}`, err);
47
+ }
48
+ return Object.freeze(out);
49
+ }
50
+ function deriveAuditPath(storagePath) {
51
+ const idx = storagePath.lastIndexOf("/");
52
+ if (idx < 0) return "audit.db";
53
+ return `${storagePath.slice(0, idx)}/audit.db`;
54
+ }
55
+ function describeError(err) {
56
+ if (err instanceof Error) return err.message;
57
+ return String(err);
58
+ }
59
+
60
+ //#endregion
61
+ export { runPreBind };
62
+ //# sourceMappingURL=pre-bind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-bind.js","names":["out: { -readonly [K in keyof PreBindResult]?: PreBindResult[K] }"],"sources":["../../src/lifecycle/pre-bind.ts"],"sourcesContent":["/**\n * Pre-bind validation. Runs *before* the HTTP listener attaches so a\n * misconfigured server never accepts a single request.\n *\n * Steps (fail-fast on every failure):\n *\n * 1. Resolve every `*Ref` field on the config through the\n * `@graphorin/security` resolver registry. Missing ref → exit 1.\n * 2. Confirm the server pepper resolved to non-empty bytes.\n * 3. Confirm the encryption peer is loadable when\n * `storage.encryption.enabled === true` (or `audit.enabled === true`).\n * 4. Run pending storage migrations — failures bubble up as\n * `MigrationFailedError`.\n *\n * The function is idempotent — calling it more than once for the\n * same {@link createSqliteStore} handle re-validates the secrets but\n * leaves the underlying database untouched.\n *\n * @packageDocumentation\n */\n\nimport type { SecretValue } from '@graphorin/security';\n\nimport { resolveSecret } from '@graphorin/security/secrets';\nimport type { GraphorinSqliteStore } from '@graphorin/store-sqlite';\n\nimport type { ServerConfigSpec } from '../config.js';\nimport {\n MigrationFailedError,\n PrebindEncryptionPeerMissingError,\n PrebindEncryptionRequiredError,\n PrebindPepperMissingError,\n PrebindSecretUnresolvableError,\n} from '../errors/index.js';\n\n/**\n * Result returned by {@link runPreBind}. Consumers (`createServer`,\n * tests) consume the resolved pepper + encryption decision when\n * wiring the rest of the server.\n *\n * @stable\n */\nexport interface PreBindResult {\n readonly pepper?: SecretValue;\n readonly auditPath?: string;\n readonly auditPassphrase?: SecretValue;\n readonly storagePassphrase?: SecretValue;\n}\n\n/**\n * @stable\n */\nexport interface RunPreBindOptions {\n readonly config: ServerConfigSpec;\n readonly store: GraphorinSqliteStore;\n /**\n * Optional override for the cipher-peer probe. Tests inject a stub\n * that signals \"missing peer\" without uninstalling the real one.\n */\n readonly probeCipherPeer?: () => Promise<void>;\n}\n\nasync function resolveRef(path: ReadonlyArray<string | number>, raw: string): Promise<SecretValue> {\n try {\n return await resolveSecret(raw);\n } catch (err) {\n throw new PrebindSecretUnresolvableError(path, raw, err);\n }\n}\n\n/**\n * @stable\n */\nexport async function runPreBind(options: RunPreBindOptions): Promise<PreBindResult> {\n const { config, store } = options;\n const out: { -readonly [K in keyof PreBindResult]?: PreBindResult[K] } = {};\n\n if (config.auth.kind === 'token') {\n if (config.auth.pepperRef === undefined || config.auth.pepperRef.length === 0) {\n throw new PrebindPepperMissingError();\n }\n const pepper = await resolveRef(['auth', 'pepperRef'], config.auth.pepperRef);\n const buf = await pepper.useBuffer((b) => Buffer.from(b));\n if (buf.length === 0) {\n throw new PrebindPepperMissingError();\n }\n out.pepper = pepper;\n }\n\n if (config.storage.encryption.enabled) {\n if (config.storage.encryption.passphraseRef === undefined) {\n throw new PrebindEncryptionRequiredError(\n 'storage.encryption.enabled is true but no passphraseRef is configured.',\n );\n }\n out.storagePassphrase = await resolveRef(\n ['storage', 'encryption', 'passphraseRef'],\n config.storage.encryption.passphraseRef,\n );\n if (options.probeCipherPeer !== undefined) {\n try {\n await options.probeCipherPeer();\n } catch (err) {\n throw new PrebindEncryptionPeerMissingError(err);\n }\n }\n }\n\n if (config.audit.enabled) {\n const passphraseRef = config.audit.passphraseRef ?? config.storage.encryption.passphraseRef;\n if (passphraseRef === undefined) {\n throw new PrebindEncryptionRequiredError(\n 'audit.enabled is true but no audit.passphraseRef (or storage.encryption.passphraseRef) is configured. Audit logs are mandatory-encrypted (DEC-124).',\n );\n }\n out.auditPath = config.audit.path ?? deriveAuditPath(config.storage.path);\n out.auditPassphrase = await resolveRef(['audit', 'passphraseRef'], passphraseRef);\n }\n\n try {\n await store.init();\n } catch (err) {\n throw new MigrationFailedError(`Storage migrations failed: ${describeError(err)}`, err);\n }\n\n return Object.freeze(out as PreBindResult);\n}\n\nfunction deriveAuditPath(storagePath: string): string {\n const idx = storagePath.lastIndexOf('/');\n if (idx < 0) return 'audit.db';\n return `${storagePath.slice(0, idx)}/audit.db`;\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n"],"mappings":";;;;AA8DA,eAAe,WAAW,MAAsC,KAAmC;AACjG,KAAI;AACF,SAAO,MAAM,cAAc,IAAI;UACxB,KAAK;AACZ,QAAM,IAAI,+BAA+B,MAAM,KAAK,IAAI;;;;;;AAO5D,eAAsB,WAAW,SAAoD;CACnF,MAAM,EAAE,QAAQ,UAAU;CAC1B,MAAMA,MAAmE,EAAE;AAE3E,KAAI,OAAO,KAAK,SAAS,SAAS;AAChC,MAAI,OAAO,KAAK,cAAc,UAAa,OAAO,KAAK,UAAU,WAAW,EAC1E,OAAM,IAAI,2BAA2B;EAEvC,MAAM,SAAS,MAAM,WAAW,CAAC,QAAQ,YAAY,EAAE,OAAO,KAAK,UAAU;AAE7E,OADY,MAAM,OAAO,WAAW,MAAM,OAAO,KAAK,EAAE,CAAC,EACjD,WAAW,EACjB,OAAM,IAAI,2BAA2B;AAEvC,MAAI,SAAS;;AAGf,KAAI,OAAO,QAAQ,WAAW,SAAS;AACrC,MAAI,OAAO,QAAQ,WAAW,kBAAkB,OAC9C,OAAM,IAAI,+BACR,yEACD;AAEH,MAAI,oBAAoB,MAAM,WAC5B;GAAC;GAAW;GAAc;GAAgB,EAC1C,OAAO,QAAQ,WAAW,cAC3B;AACD,MAAI,QAAQ,oBAAoB,OAC9B,KAAI;AACF,SAAM,QAAQ,iBAAiB;WACxB,KAAK;AACZ,SAAM,IAAI,kCAAkC,IAAI;;;AAKtD,KAAI,OAAO,MAAM,SAAS;EACxB,MAAM,gBAAgB,OAAO,MAAM,iBAAiB,OAAO,QAAQ,WAAW;AAC9E,MAAI,kBAAkB,OACpB,OAAM,IAAI,+BACR,sJACD;AAEH,MAAI,YAAY,OAAO,MAAM,QAAQ,gBAAgB,OAAO,QAAQ,KAAK;AACzE,MAAI,kBAAkB,MAAM,WAAW,CAAC,SAAS,gBAAgB,EAAE,cAAc;;AAGnF,KAAI;AACF,QAAM,MAAM,MAAM;UACX,KAAK;AACZ,QAAM,IAAI,qBAAqB,8BAA8B,cAAc,IAAI,IAAI,IAAI;;AAGzF,QAAO,OAAO,OAAO,IAAqB;;AAG5C,SAAS,gBAAgB,aAA6B;CACpD,MAAM,MAAM,YAAY,YAAY,IAAI;AACxC,KAAI,MAAM,EAAG,QAAO;AACpB,QAAO,GAAG,YAAY,MAAM,GAAG,IAAI,CAAC;;AAGtC,SAAS,cAAc,KAAsB;AAC3C,KAAI,eAAe,MAAO,QAAO,IAAI;AACrC,QAAO,OAAO,IAAI"}
@@ -0,0 +1,34 @@
1
+ import { MetricRegistry } from "./registry.js";
2
+
3
+ //#region src/metrics/catalog.d.ts
4
+
5
+ /**
6
+ * @stable
7
+ */
8
+ declare const SERVER_METRIC_NAMES: Readonly<{
9
+ readonly agentRunsTotal: "graphorin_agent_runs_total";
10
+ readonly agentRunDuration: "graphorin_agent_run_duration_seconds";
11
+ readonly storageWalSize: "graphorin_storage_wal_size_bytes";
12
+ readonly idempotencyCacheHitRatio: "graphorin_idempotency_cache_hit_ratio";
13
+ readonly triggersFiresTotal: "graphorin_triggers_fires_total";
14
+ readonly consolidatorQueueDepth: "graphorin_consolidator_queue_depth";
15
+ readonly consolidatorDlqSize: "graphorin_consolidator_dlq_size";
16
+ readonly consolidatorBudgetRemainingUsd: "graphorin_consolidator_budget_remaining_usd";
17
+ readonly consolidatorBudgetRemainingTokens: "graphorin_consolidator_budget_remaining_tokens";
18
+ readonly replayBufferEvents: "graphorin_replay_buffer_events";
19
+ readonly inflightRuns: "graphorin_inflight_runs";
20
+ readonly serverUptime: "graphorin_server_uptime_seconds";
21
+ readonly buildInfo: "graphorin_build_info";
22
+ }>;
23
+ /**
24
+ * Build a fully-registered {@link MetricRegistry} ready for the
25
+ * `/v1/metrics` exposition. The returned registry has every metric
26
+ * declared but no samples; the server runtime updates samples
27
+ * incrementally.
28
+ *
29
+ * @stable
30
+ */
31
+ declare function createServerMetricRegistry(): MetricRegistry;
32
+ //#endregion
33
+ export { SERVER_METRIC_NAMES, createServerMetricRegistry };
34
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","names":[],"sources":["../../src/metrics/catalog.ts"],"sourcesContent":[],"mappings":";;;;;;;cA0Ba,qBAAmB;;;;;;;;;;;;;;;;;;;;;;;iBAwBhB,0BAAA,CAAA,GAA8B"}
@@ -0,0 +1,61 @@
1
+ import { MetricRegistry } from "./registry.js";
2
+
3
+ //#region src/metrics/catalog.ts
4
+ /**
5
+ * Canonical metric inventory for the standalone server. Every metric
6
+ * the framework emits is registered here in one place so the
7
+ * exposition output is deterministic across builds.
8
+ *
9
+ * Metric naming follows the documented `graphorin_*` prefix
10
+ * discipline; label cardinality is bounded by construction (no PII
11
+ * labels — see DEC-141 cross-cut).
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /**
16
+ * @stable
17
+ */
18
+ const SERVER_METRIC_NAMES = Object.freeze({
19
+ agentRunsTotal: "graphorin_agent_runs_total",
20
+ agentRunDuration: "graphorin_agent_run_duration_seconds",
21
+ storageWalSize: "graphorin_storage_wal_size_bytes",
22
+ idempotencyCacheHitRatio: "graphorin_idempotency_cache_hit_ratio",
23
+ triggersFiresTotal: "graphorin_triggers_fires_total",
24
+ consolidatorQueueDepth: "graphorin_consolidator_queue_depth",
25
+ consolidatorDlqSize: "graphorin_consolidator_dlq_size",
26
+ consolidatorBudgetRemainingUsd: "graphorin_consolidator_budget_remaining_usd",
27
+ consolidatorBudgetRemainingTokens: "graphorin_consolidator_budget_remaining_tokens",
28
+ replayBufferEvents: "graphorin_replay_buffer_events",
29
+ inflightRuns: "graphorin_inflight_runs",
30
+ serverUptime: "graphorin_server_uptime_seconds",
31
+ buildInfo: "graphorin_build_info"
32
+ });
33
+ /**
34
+ * Build a fully-registered {@link MetricRegistry} ready for the
35
+ * `/v1/metrics` exposition. The returned registry has every metric
36
+ * declared but no samples; the server runtime updates samples
37
+ * incrementally.
38
+ *
39
+ * @stable
40
+ */
41
+ function createServerMetricRegistry() {
42
+ const registry = new MetricRegistry();
43
+ registry.registerCounter(SERVER_METRIC_NAMES.agentRunsTotal, "Total agent runs by terminal status.", ["status"]);
44
+ registry.registerSummary(SERVER_METRIC_NAMES.agentRunDuration, "Agent run duration in seconds.", []);
45
+ registry.registerGauge(SERVER_METRIC_NAMES.storageWalSize, "Current SQLite WAL size in bytes.");
46
+ registry.registerGauge(SERVER_METRIC_NAMES.idempotencyCacheHitRatio, "Idempotency LRU cache hit ratio in [0, 1].");
47
+ registry.registerCounter(SERVER_METRIC_NAMES.triggersFiresTotal, "Total trigger fires by trigger id and outcome.", ["trigger_id", "status"]);
48
+ registry.registerGauge(SERVER_METRIC_NAMES.consolidatorQueueDepth, "Pending consolidator items by phase.", ["phase"]);
49
+ registry.registerGauge(SERVER_METRIC_NAMES.consolidatorDlqSize, "Number of consolidator runs sitting in the dead-letter queue.");
50
+ registry.registerGauge(SERVER_METRIC_NAMES.consolidatorBudgetRemainingUsd, "Consolidator USD budget remaining for the current period.");
51
+ registry.registerGauge(SERVER_METRIC_NAMES.consolidatorBudgetRemainingTokens, "Consolidator token budget remaining for the current period.");
52
+ registry.registerGauge(SERVER_METRIC_NAMES.replayBufferEvents, "Number of events currently buffered for WebSocket replay.");
53
+ registry.registerGauge(SERVER_METRIC_NAMES.inflightRuns, "Number of in-flight agent / workflow runs.");
54
+ registry.registerGauge(SERVER_METRIC_NAMES.serverUptime, "Server process uptime in seconds.");
55
+ registry.registerGauge(SERVER_METRIC_NAMES.buildInfo, "Static `1` gauge carrying graphorin build labels.", ["version"]);
56
+ return registry;
57
+ }
58
+
59
+ //#endregion
60
+ export { SERVER_METRIC_NAMES, createServerMetricRegistry };
61
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","names":[],"sources":["../../src/metrics/catalog.ts"],"sourcesContent":["/**\n * Canonical metric inventory for the standalone server. Every metric\n * the framework emits is registered here in one place so the\n * exposition output is deterministic across builds.\n *\n * Metric naming follows the documented `graphorin_*` prefix\n * discipline; label cardinality is bounded by construction (no PII\n * labels — see DEC-141 cross-cut).\n *\n * @packageDocumentation\n */\n\nimport { MetricRegistry } from './registry.js';\n\n/**\n * @stable\n */\n// IP-15: the catalog lists only metrics the server actually moves. Five\n// previously-registered series — `graphorin_tool_calls_total`,\n// `graphorin_provider_tokens_total`, `graphorin_provider_cost_usd_total`,\n// `graphorin_redaction_drops_total` and `graphorin_oauth_tokens_freshness_seconds`\n// — had no producer anywhere in the monorepo (per-tool and provider usage live\n// in the agent runtime, not the server; redaction drops in the observability\n// layer; OAuth freshness needs an MCP token store the server does not own). A\n// permanently-empty series is worse than an absent one for dashboards, so they\n// are dropped until a real producer exists rather than advertised inert.\nexport const SERVER_METRIC_NAMES = Object.freeze({\n agentRunsTotal: 'graphorin_agent_runs_total',\n agentRunDuration: 'graphorin_agent_run_duration_seconds',\n storageWalSize: 'graphorin_storage_wal_size_bytes',\n idempotencyCacheHitRatio: 'graphorin_idempotency_cache_hit_ratio',\n triggersFiresTotal: 'graphorin_triggers_fires_total',\n consolidatorQueueDepth: 'graphorin_consolidator_queue_depth',\n consolidatorDlqSize: 'graphorin_consolidator_dlq_size',\n consolidatorBudgetRemainingUsd: 'graphorin_consolidator_budget_remaining_usd',\n consolidatorBudgetRemainingTokens: 'graphorin_consolidator_budget_remaining_tokens',\n replayBufferEvents: 'graphorin_replay_buffer_events',\n inflightRuns: 'graphorin_inflight_runs',\n serverUptime: 'graphorin_server_uptime_seconds',\n buildInfo: 'graphorin_build_info',\n} as const);\n\n/**\n * Build a fully-registered {@link MetricRegistry} ready for the\n * `/v1/metrics` exposition. The returned registry has every metric\n * declared but no samples; the server runtime updates samples\n * incrementally.\n *\n * @stable\n */\nexport function createServerMetricRegistry(): MetricRegistry {\n const registry = new MetricRegistry();\n\n registry.registerCounter(\n SERVER_METRIC_NAMES.agentRunsTotal,\n 'Total agent runs by terminal status.',\n ['status'],\n );\n registry.registerSummary(\n SERVER_METRIC_NAMES.agentRunDuration,\n 'Agent run duration in seconds.',\n [],\n );\n registry.registerGauge(SERVER_METRIC_NAMES.storageWalSize, 'Current SQLite WAL size in bytes.');\n registry.registerGauge(\n SERVER_METRIC_NAMES.idempotencyCacheHitRatio,\n 'Idempotency LRU cache hit ratio in [0, 1].',\n );\n registry.registerCounter(\n SERVER_METRIC_NAMES.triggersFiresTotal,\n 'Total trigger fires by trigger id and outcome.',\n ['trigger_id', 'status'],\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.consolidatorQueueDepth,\n 'Pending consolidator items by phase.',\n ['phase'],\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.consolidatorDlqSize,\n 'Number of consolidator runs sitting in the dead-letter queue.',\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.consolidatorBudgetRemainingUsd,\n 'Consolidator USD budget remaining for the current period.',\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.consolidatorBudgetRemainingTokens,\n 'Consolidator token budget remaining for the current period.',\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.replayBufferEvents,\n 'Number of events currently buffered for WebSocket replay.',\n );\n registry.registerGauge(\n SERVER_METRIC_NAMES.inflightRuns,\n 'Number of in-flight agent / workflow runs.',\n );\n registry.registerGauge(SERVER_METRIC_NAMES.serverUptime, 'Server process uptime in seconds.');\n registry.registerGauge(\n SERVER_METRIC_NAMES.buildInfo,\n 'Static `1` gauge carrying graphorin build labels.',\n ['version'],\n );\n\n return registry;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,MAAa,sBAAsB,OAAO,OAAO;CAC/C,gBAAgB;CAChB,kBAAkB;CAClB,gBAAgB;CAChB,0BAA0B;CAC1B,oBAAoB;CACpB,wBAAwB;CACxB,qBAAqB;CACrB,gCAAgC;CAChC,mCAAmC;CACnC,oBAAoB;CACpB,cAAc;CACd,cAAc;CACd,WAAW;CACZ,CAAU;;;;;;;;;AAUX,SAAgB,6BAA6C;CAC3D,MAAM,WAAW,IAAI,gBAAgB;AAErC,UAAS,gBACP,oBAAoB,gBACpB,wCACA,CAAC,SAAS,CACX;AACD,UAAS,gBACP,oBAAoB,kBACpB,kCACA,EAAE,CACH;AACD,UAAS,cAAc,oBAAoB,gBAAgB,oCAAoC;AAC/F,UAAS,cACP,oBAAoB,0BACpB,6CACD;AACD,UAAS,gBACP,oBAAoB,oBACpB,kDACA,CAAC,cAAc,SAAS,CACzB;AACD,UAAS,cACP,oBAAoB,wBACpB,wCACA,CAAC,QAAQ,CACV;AACD,UAAS,cACP,oBAAoB,qBACpB,gEACD;AACD,UAAS,cACP,oBAAoB,gCACpB,4DACD;AACD,UAAS,cACP,oBAAoB,mCACpB,8DACD;AACD,UAAS,cACP,oBAAoB,oBACpB,4DACD;AACD,UAAS,cACP,oBAAoB,cACpB,6CACD;AACD,UAAS,cAAc,oBAAoB,cAAc,oCAAoC;AAC7F,UAAS,cACP,oBAAoB,WACpB,qDACA,CAAC,UAAU,CACZ;AAED,QAAO"}
@@ -0,0 +1,3 @@
1
+ import { LabelSet, MetricKind, MetricRegistry } from "./registry.js";
2
+ import { SERVER_METRIC_NAMES, createServerMetricRegistry } from "./catalog.js";
3
+ export { type LabelSet, type MetricKind, MetricRegistry, SERVER_METRIC_NAMES, createServerMetricRegistry };
@@ -0,0 +1,4 @@
1
+ import { MetricRegistry } from "./registry.js";
2
+ import { SERVER_METRIC_NAMES, createServerMetricRegistry } from "./catalog.js";
3
+
4
+ export { MetricRegistry, SERVER_METRIC_NAMES, createServerMetricRegistry };
@@ -0,0 +1,63 @@
1
+ //#region src/metrics/registry.d.ts
2
+ /**
3
+ * Tiny Prometheus exposition layer. The framework intentionally does
4
+ * not pull in `prom-client` so the bundle stays lean and so the
5
+ * exposition is byte-stable across processes (`prom-client` adds
6
+ * default counters that drift between Node releases).
7
+ *
8
+ * The supported metric kinds are the three the runtime spec calls
9
+ * out: `counter`, `gauge`, and `summary` (with hard-coded p50/p95
10
+ * quantiles). Sample rendering follows Prometheus text exposition
11
+ * format v0.0.4 — every metric block is preceded by `# HELP` + `# TYPE`
12
+ * and labels are quoted-escaped per the spec.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ /** @stable */
17
+ type MetricKind = 'counter' | 'gauge' | 'summary';
18
+ /** @stable */
19
+ type LabelSet = Readonly<Record<string, string | number | boolean>>;
20
+ /**
21
+ * Lightweight Prometheus registry. Each instance owns its metric
22
+ * catalogue + per-label samples; `render()` emits the canonical text
23
+ * exposition block.
24
+ *
25
+ * @stable
26
+ */
27
+ declare class MetricRegistry {
28
+ #private;
29
+ registerCounter(name: string, help: string, labelNames?: ReadonlyArray<string>): void;
30
+ registerGauge(name: string, help: string, labelNames?: ReadonlyArray<string>): void;
31
+ registerSummary(name: string, help: string, labelNames?: ReadonlyArray<string>): void;
32
+ inc(name: string, labels?: LabelSet, by?: number): void;
33
+ set(name: string, value: number, labels?: LabelSet): void;
34
+ observe(name: string, value: number, labels?: LabelSet): void;
35
+ reset(): void;
36
+ /**
37
+ * Render the current snapshot in Prometheus text exposition
38
+ * format (v0.0.4). Never throws — incomplete sample buckets are
39
+ * skipped instead of failing the scrape.
40
+ */
41
+ render(): string;
42
+ contentType(): string;
43
+ /** Snapshot for tests / assertions. */
44
+ snapshot(): {
45
+ counters: Record<string, ReadonlyArray<{
46
+ labels: LabelSet;
47
+ value: number;
48
+ }>>;
49
+ gauges: Record<string, ReadonlyArray<{
50
+ labels: LabelSet;
51
+ value: number;
52
+ }>>;
53
+ summaries: Record<string, ReadonlyArray<{
54
+ labels: LabelSet;
55
+ count: number;
56
+ sum: number;
57
+ samples: ReadonlyArray<number>;
58
+ }>>;
59
+ };
60
+ }
61
+ //#endregion
62
+ export { LabelSet, MetricKind, MetricRegistry };
63
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","names":[],"sources":["../../src/metrics/registry.ts"],"sourcesContent":[],"mappings":";;AAgBA;AAGA;AAqCA;;;;;;;;;;;;AAkJY,KA1LA,UAAA,GA0LA,SAAA,GAAA,OAAA,GAAA,SAAA;;AAOK,KA9LL,QAAA,GAAW,QA8LN,CA9Le,MA8Lf,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,CAAA;;;;;;;;cAzJJ,cAAA;;2DAM6C;yDAKF;2DAKE;6BAK9B;4CAmBe;gDAWI;;;;;;;;;;;cA8FjC,eAAe;cAAwB;;;YACzC,eAAe;cAAwB;;;eACpC,eAET;cACU;;;eAGC"}