@parmanasystems/server 1.14.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -217,9 +217,11 @@ function registerExecuteRoute(app2, deps) {
|
|
|
217
217
|
verifier2,
|
|
218
218
|
replayStore
|
|
219
219
|
);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
if ("attestation" in execution && execution.attestation) {
|
|
221
|
+
auditDb2?.recordDecision(
|
|
222
|
+
execution.attestation
|
|
223
|
+
);
|
|
224
|
+
}
|
|
223
225
|
req.log.info(
|
|
224
226
|
{
|
|
225
227
|
reqId: req.id,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/runtime.ts","../src/auth.ts","../src/routes.ts","../src/routes/execute.ts","../src/routes/verify.ts","../src/routes/audit.ts","../src/middleware/audit.ts","../src/index.ts"],"sourcesContent":["import Fastify, { type FastifyInstance } from \"fastify\";\r\nimport { createHash, randomUUID } from \"node:crypto\";\r\nimport rateLimit from \"@fastify/rate-limit\";\r\nimport cors from \"@fastify/cors\";\r\nimport helmet from \"@fastify/helmet\";\r\n\r\nimport { signer, verifier, runtimeManifest } from \"./runtime.js\";\r\nimport { authHook } from \"./auth.js\";\r\nimport { registerRoutes } from \"./routes.js\";\r\nimport { AuditDb } from \"@parmanasystems/audit-db\";\r\nimport { createAuditMiddleware } from \"./middleware/audit.js\";\r\n\r\n/**\r\n * Creates and configures the parmanasystems Fastify HTTP server.\r\n *\r\n * When `AUDIT_DATABASE_URL` is set the server additionally:\r\n * - Runs schema migrations on startup (non-blocking; logs failure and continues).\r\n * - Fires an `onResponse` hook that records every request to `audit_api_access`\r\n * and auth failures to `audit_security_events` — both fire-and-forget.\r\n * - Records each `/execute` decision and `/verify` result fire-and-forget.\r\n * - Exposes four read-only `/audit/*` query routes.\r\n *\r\n * Key points:\r\n * - The signer/verifier/runtimeManifest are resolved from environment variables,\r\n * dev-keys on disk, or an ephemeral Ed25519 key pair in that order.\r\n * - Set `Parmana_API_KEY` to enable authentication; omit it for dev mode.\r\n */\r\nexport interface ServerInstance {\r\n app: FastifyInstance;\r\n auditDb?: AuditDb;\r\n}\r\n\r\nexport function createServer(): ServerInstance {\r\n const app = Fastify({\r\n bodyLimit: 1048576, // 1 MB global default\r\n logger: {\r\n level: process.env.LOG_LEVEL ?? (process.env.NODE_ENV === \"production\" ? \"info\" : \"debug\"),\r\n redact: {\r\n paths: [\r\n \"req.headers.authorization\",\r\n \"req.body.signature\",\r\n \"req.body.attestation.signature\",\r\n ],\r\n censor: \"[REDACTED]\",\r\n },\r\n serializers: {\r\n req(req) {\r\n const fwd = req.headers[\"x-forwarded-for\"];\r\n return {\r\n method: req.method,\r\n url: req.url,\r\n reqId: req.id,\r\n remoteAddress: (Array.isArray(fwd) ? fwd[0] : fwd) ?? req.socket?.remoteAddress,\r\n };\r\n },\r\n res(res) {\r\n return {\r\n statusCode: res.statusCode,\r\n };\r\n },\r\n },\r\n },\r\n genReqId: (req: import(\"node:http\").IncomingMessage) =>\r\n (req.headers[\"x-request-id\"] as string | undefined) ?? randomUUID(),\r\n });\r\n\r\n const corsOriginEnv = process.env.CORS_ORIGIN;\r\n const corsOrigin: string | string[] | boolean =\r\n corsOriginEnv === \"*\" ? true :\r\n corsOriginEnv ? corsOriginEnv.split(\",\").map(o => o.trim()) :\r\n [\"http://localhost:5173\", \"http://localhost:8080\"];\r\n\r\n app.register(cors, {\r\n origin: corsOrigin,\r\n methods: [\"GET\", \"POST\"],\r\n allowedHeaders: [\"Content-Type\", \"Authorization\", \"X-Request-ID\"],\r\n exposedHeaders: [\"X-Request-ID\", \"X-RateLimit-Limit\", \"X-RateLimit-Remaining\", \"X-RateLimit-Reset\"],\r\n credentials: true,\r\n maxAge: 86400,\r\n });\r\n\r\n app.register(helmet, {\r\n contentSecurityPolicy: {\r\n directives: {\r\n defaultSrc: [\"'none'\"],\r\n frameAncestors: [\"'none'\"],\r\n },\r\n },\r\n crossOriginEmbedderPolicy: false,\r\n crossOriginResourcePolicy: { policy: \"cross-origin\" },\r\n dnsPrefetchControl: { allow: false },\r\n frameguard: { action: \"deny\" },\r\n hsts: {\r\n maxAge: 31536000,\r\n includeSubDomains: true,\r\n preload: true,\r\n },\r\n ieNoOpen: true,\r\n noSniff: true,\r\n referrerPolicy: { policy: \"no-referrer\" },\r\n xssFilter: true,\r\n });\r\n\r\n const auditDb = process.env.AUDIT_DATABASE_URL\r\n ? new AuditDb(process.env.AUDIT_DATABASE_URL)\r\n : undefined;\r\n\r\n if (auditDb) {\r\n auditDb.migrate().catch((err: unknown) =>\r\n app.log.error({ err }, \"audit-db migration failed — continuing without audit persistence\"),\r\n );\r\n app.addHook(\"onResponse\", createAuditMiddleware(auditDb));\r\n }\r\n\r\n app.addHook(\"onSend\", async (req, reply) => {\r\n reply.header(\"X-Request-ID\", req.id);\r\n });\r\n\r\n app.addHook(\"onSend\", async (_req, reply) => {\r\n reply.removeHeader(\"X-Powered-By\");\r\n });\r\n\r\n app.addHook(\"preHandler\", authHook);\r\n\r\n // Precompute API key hash once at startup — used as the per-key rate limit bucket\r\n const apiKeyHash = process.env.Parmana_API_KEY\r\n ? createHash(\"sha256\").update(process.env.Parmana_API_KEY).digest(\"hex\")\r\n : null;\r\n\r\n app.register(rateLimit, {\r\n keyGenerator(req) {\r\n if (apiKeyHash) return apiKeyHash;\r\n const forwarded = req.headers[\"x-forwarded-for\"];\r\n const forwardedStr = Array.isArray(forwarded) ? forwarded[0] : forwarded;\r\n const forwardedIp = forwardedStr?.split(\",\")[0]?.trim();\r\n const realIp = req.headers[\"x-real-ip\"];\r\n const realIpStr = Array.isArray(realIp) ? realIp[0] : realIp;\r\n return forwardedIp ?? realIpStr ?? req.ip;\r\n },\r\n errorResponseBuilder(_req, context) {\r\n return {\r\n error: \"Rate limit exceeded\",\r\n limit: context.max,\r\n remaining: 0,\r\n reset: Math.floor(Date.now() / 1000) + Math.ceil(context.ttl / 1000),\r\n };\r\n },\r\n });\r\n\r\n registerRoutes(app, { signer, verifier, runtimeManifest, auditDb });\r\n\r\n return { app, auditDb };\r\n}\r\n","import * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n LocalSigner,\r\n LocalVerifier,\r\n getRuntimeManifest,\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n loadPrivateKey,\r\n loadPublicKey,\r\n} from \"@parmanasystems/crypto\";\r\n\r\nexport type SigningKeySource = \"env\" | \"disk\" | \"ephemeral\";\r\n\r\n/**\r\n * Resolves the Ed25519 key pair for the server in priority order:\r\n * 1. `Parmana_PRIVATE_KEY` + `Parmana_PUBLIC_KEY` environment variables.\r\n * 2. Dev keys on disk at `./dev-keys/bundle_signing_key{,.pub}`.\r\n * 3. Ephemeral in-process key pair (new on every restart — dev only).\r\n */\r\nfunction resolveKeyPair(): { privateKey: string; publicKey: string; source: SigningKeySource } {\r\n if (process.env.Parmana_PRIVATE_KEY && process.env.Parmana_PUBLIC_KEY) {\r\n return {\r\n privateKey: process.env.Parmana_PRIVATE_KEY,\r\n publicKey: process.env.Parmana_PUBLIC_KEY,\r\n source: \"env\",\r\n };\r\n }\r\n\r\n try {\r\n return {\r\n privateKey: loadPrivateKey(),\r\n publicKey: loadPublicKey(),\r\n source: \"disk\",\r\n };\r\n } catch {\r\n // no dev keys on disk — fall through to ephemeral\r\n }\r\n\r\n const { privateKey, publicKey } = crypto.generateKeyPairSync(\"ed25519\", {\r\n privateKeyEncoding: { type: \"pkcs8\", format: \"pem\" },\r\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\r\n });\r\n\r\n return { privateKey, publicKey, source: \"ephemeral\" };\r\n}\r\n\r\nconst keys = resolveKeyPair();\r\n\r\nexport const signingKeySource: SigningKeySource = keys.source;\r\nexport const signer = new LocalSigner(keys.privateKey);\r\nexport const verifier = new LocalVerifier(keys.publicKey);\r\nexport const runtimeManifest = getRuntimeManifest();\r\n","import type { FastifyRequest, FastifyReply } from \"fastify\";\r\n\r\n/**\r\n * Fastify pre-handler hook that enforces Bearer token authentication.\r\n *\r\n * When `Parmana_API_KEY` is set in the environment, every request must supply\r\n * the header `Authorization: Bearer <key>`. If the key is absent or wrong the\r\n * hook sends `401 Unauthorized` and terminates the request.\r\n *\r\n * When `Parmana_API_KEY` is unset (dev mode), all requests pass through\r\n * without authentication.\r\n */\r\nexport async function authHook(\r\n req: FastifyRequest,\r\n reply: FastifyReply\r\n): Promise<void> {\r\n const apiKey = process.env.Parmana_API_KEY;\r\n if (!apiKey) return; // dev mode — skip auth\r\n\r\n const auth = req.headers.authorization;\r\n if (auth !== `Bearer ${apiKey}`) {\r\n req.log.warn({ reqId: req.id, reason: \"auth_failure\" }, \"auth_failure\");\r\n reply.code(401).send({ error: \"Unauthorized\" });\r\n }\r\n}\r\n","import type {\r\n FastifyInstance,\r\n FastifyRequest,\r\n FastifyReply,\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport { getRuntimeManifest, type Signer, type Verifier, type RuntimeManifest } from \"@parmanasystems/execution\";\r\nimport { existsSync } from \"node:fs\";\r\n\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nimport { registerExecuteRoute } from \"./routes/execute.js\";\r\nimport { registerVerifyRoute } from \"./routes/verify.js\";\r\nimport { registerAuditRoutes } from \"./routes/audit.js\";\r\n\r\n// ── Reusable JSON Schema fragments (stubs only — active routes own their schemas) ──\r\n\r\nconst S_ERROR = {\r\n type: \"object\",\r\n properties: { error: { type: \"string\" } },\r\n required: [\"error\"],\r\n};\r\n\r\nconst S_NOT_IMPLEMENTED = {\r\n ...S_ERROR,\r\n properties: { error: { type: \"string\", enum: [\"Not implemented\"] } },\r\n};\r\n\r\n// ── Health check helpers ──────────────────────────────────────────────────────\r\n\r\nfunction checkRuntime(): \"ok\" | \"error\" {\r\n try { getRuntimeManifest(); return \"ok\"; } catch { return \"error\"; }\r\n}\r\n\r\nfunction checkSigningKey(): \"ok\" | \"unconfigured\" {\r\n if (process.env.Parmana_PRIVATE_KEY) return \"ok\";\r\n if (existsSync(\"./dev-keys/bundle_signing_key\")) return \"ok\";\r\n return \"unconfigured\";\r\n}\r\n\r\nasync function checkAuditDb(db: AuditDb | undefined): Promise<\"ok\" | \"unavailable\" | \"unconfigured\"> {\r\n if (!db) return \"unconfigured\";\r\n try { await db.ping(); return \"ok\"; } catch { return \"unavailable\"; }\r\n}\r\n\r\n// ── Deps ──────────────────────────────────────────────────────────────────────\r\n\r\n/** Runtime dependencies injected into each route handler at registration time. */\r\nexport interface RouteDeps {\r\n /** Signer used to produce attestations in the `/execute` route. */\r\n signer: Signer;\r\n /** Verifier used to check attestation signatures in the `/verify` route. */\r\n verifier: Verifier;\r\n /** Active runtime manifest embedded in every execution result. */\r\n runtimeManifest: RuntimeManifest;\r\n /** Optional audit database client. When present, all decisions and verifications\r\n * are recorded fire-and-forget and audit query routes are registered. */\r\n auditDb?: AuditDb;\r\n}\r\n\r\n// ── Route registration ────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Registers all governance API routes on `app`.\r\n *\r\n * Active routes (fully implemented):\r\n * - `GET /health` — runtime health and version.\r\n * - `POST /execute` — deterministic governance decision with signed attestation.\r\n * - `POST /verify` — independent attestation verification.\r\n *\r\n * Audit routes (registered when `auditDb` is configured):\r\n * - `GET /audit/decisions` — decision timeline (paginated).\r\n * - `GET /audit/decisions/:executionId` — single decision detail.\r\n * - `GET /audit/security` — security event dashboard.\r\n * - `GET /audit/verifications/:executionId` — verification history.\r\n *\r\n * Stub routes (return `501 Not Implemented`):\r\n * - `GET /runtime/manifest` — signed runtime bundle manifest.\r\n * - `GET /runtime/capabilities` — runtime capability declarations.\r\n * - `POST /evaluate` — policy dry-run (no attestation).\r\n * - `POST /simulate` — full pipeline dry-run (no side effects).\r\n */\r\nexport function registerRoutes(\r\n app: FastifyInstance,\r\n deps: RouteDeps,\r\n): void {\r\n const { signer, verifier, runtimeManifest, auditDb } = deps;\r\n\r\n // GET /health ──────────────────────────────────────────────────────────────\r\n\r\n app.get(\"/health\", {\r\n config: { rateLimit: { max: 300, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Health check\",\r\n response: {\r\n 200: {\r\n description: \"Server health status with per-subsystem checks\",\r\n type: \"object\",\r\n properties: {\r\n status: { type: \"string\", enum: [\"ok\", \"degraded\"] },\r\n version: { type: \"string\" },\r\n timestamp: { type: \"string\", format: \"date-time\" },\r\n checks: {\r\n type: \"object\",\r\n properties: {\r\n runtime_manifest: { type: \"string\", enum: [\"ok\", \"error\"] },\r\n signing_key: { type: \"string\", enum: [\"ok\", \"unconfigured\"] },\r\n audit_db: { type: \"string\", enum: [\"ok\", \"unavailable\", \"unconfigured\"] },\r\n },\r\n required: [\"runtime_manifest\", \"signing_key\", \"audit_db\"],\r\n },\r\n },\r\n required: [\"status\", \"version\", \"timestamp\", \"checks\"],\r\n },\r\n },\r\n },\r\n }, async () => {\r\n const checks = {\r\n runtime_manifest: checkRuntime(),\r\n signing_key: checkSigningKey(),\r\n audit_db: await checkAuditDb(auditDb),\r\n };\r\n const degraded = Object.values(checks).some(v => v === \"error\" || v === \"unavailable\");\r\n return {\r\n status: degraded ? \"degraded\" as const : \"ok\" as const,\r\n version: \"1.2.3\",\r\n timestamp: new Date().toISOString(),\r\n checks,\r\n };\r\n });\r\n\r\n // POST /execute ────────────────────────────────────────────────────────────\r\n\r\n registerExecuteRoute(app, { signer, verifier, auditDb });\r\n\r\n // POST /verify ─────────────────────────────────────────────────────────────\r\n\r\n registerVerifyRoute(app, { verifier, runtimeManifest, auditDb });\r\n\r\n // GET /audit/* (only when an audit database is configured) ─────────────────\r\n\r\n if (auditDb) {\r\n registerAuditRoutes(app, auditDb);\r\n }\r\n\r\n // ── 501 stubs ──────────────────────────────────────────────────────────────\r\n\r\n const stub = async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n reply.code(501).send({ error: \"Not implemented\" });\r\n };\r\n\r\n app.get(\"/runtime/manifest\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Runtime bundle manifest\",\r\n description: \"Returns the signed bundle manifest for the active governance runtime.\",\r\n security: [{ bearerAuth: [] }],\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.get(\"/runtime/capabilities\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Runtime capability declarations\",\r\n description: \"Lists the capabilities supported by this runtime instance.\",\r\n security: [{ bearerAuth: [] }],\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.post(\"/evaluate\", {\r\n bodyLimit: 65536,\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Execution\"],\r\n summary: \"Evaluate a policy without executing\",\r\n description: \"Dry-run policy evaluation — computes a decision without issuing an attestation or consuming a replay slot.\",\r\n security: [{ bearerAuth: [] }],\r\n body: { type: \"object\" },\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.post(\"/simulate\", {\r\n bodyLimit: 65536,\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Execution\"],\r\n summary: \"Simulate a governance decision dry-run\",\r\n description: \"Runs the full execution pipeline in simulation mode — no side effects, no attestation produced.\",\r\n security: [{ bearerAuth: [] }],\r\n body: { type: \"object\" },\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n}\r\n","import type {\r\n\r\n FastifyInstance,\r\n\r\n FastifyRequest,\r\n\r\n FastifyReply,\r\n\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type {\r\n\r\n Signer,\r\n\r\n Verifier,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n\r\n executeFromSignals,\r\n\r\n RedisReplayStore,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport type {\r\n\r\n AuditDb,\r\n\r\n} from \"@parmanasystems/audit-db\";\r\n\r\n// --------------------------------------------------\r\n// Canonical execution response schema\r\n// --------------------------------------------------\r\nconst S_EXECUTION_OUTPUT = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n status: {\r\n type: \"string\"\r\n },\r\n\r\n execution_id: {\r\n type: \"string\"\r\n },\r\n\r\n decision: {\r\n type: \"object\"\r\n },\r\n\r\n execution_state: {\r\n type: \"string\"\r\n },\r\n\r\n requires_override: {\r\n type: \"boolean\"\r\n },\r\n\r\n signature: {\r\n type: \"string\"\r\n },\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n};\r\n\r\nconst S_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n\r\n required: [\r\n \"error\"\r\n ],\r\n};\r\n\r\nconst S_RATE_LIMIT_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n\r\n limit: {\r\n type: \"integer\"\r\n },\r\n\r\n remaining: {\r\n type: \"integer\"\r\n },\r\n\r\n reset: {\r\n\r\n type: \"integer\",\r\n\r\n description:\r\n \"Unix timestamp when the rate limit resets\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"error\",\r\n\r\n \"limit\",\r\n\r\n \"remaining\",\r\n\r\n \"reset\",\r\n ],\r\n};\r\n\r\nexport interface ExecuteRouteDeps {\r\n\r\n signer: Signer;\r\n\r\n verifier: Verifier;\r\n\r\n auditDb?: AuditDb;\r\n}\r\n\r\ninterface ExecuteBody {\r\n\r\n policyId: string;\r\n\r\n policyVersion: string;\r\n\r\n signals: Record<string, unknown>;\r\n}\r\n\r\nexport function registerExecuteRoute(\r\n\r\n app: FastifyInstance,\r\n\r\n deps: ExecuteRouteDeps,\r\n\r\n): void {\r\n\r\n const {\r\n\r\n signer,\r\n\r\n verifier,\r\n\r\n auditDb,\r\n\r\n } = deps;\r\n\r\n // ----------------------------------------------\r\n // Shared replay store\r\n // ----------------------------------------------\r\n const replayStore =\r\n new RedisReplayStore(\r\n \"redis://127.0.0.1:6379\"\r\n );\r\n\r\n app.post<{\r\n Body: ExecuteBody\r\n }>(\r\n \"/execute\",\r\n {\r\n\r\n bodyLimit: 65536,\r\n\r\n config: {\r\n rateLimit: {\r\n max: 100,\r\n timeWindow: \"1 minute\",\r\n },\r\n },\r\n\r\n schema: {\r\n\r\n tags: [\r\n \"Execution\"\r\n ],\r\n\r\n summary:\r\n \"Execute deterministic governance decision\",\r\n\r\n description:\r\n \"Executes deterministic governance evaluation using governed signals and replay-safe execution semantics.\",\r\n\r\n security: [\r\n { bearerAuth: [] }\r\n ],\r\n\r\n body: {\r\n\r\n type: \"object\",\r\n\r\n additionalProperties: false,\r\n\r\n properties: {\r\n\r\n policyId: {\r\n\r\n type: \"string\",\r\n\r\n description:\r\n \"Policy identifier\",\r\n },\r\n\r\n policyVersion: {\r\n\r\n type: \"string\",\r\n\r\n description:\r\n \"Policy version\",\r\n },\r\n\r\n signals: {\r\n\r\n type: \"object\",\r\n\r\n description:\r\n \"Governed deterministic input signals\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"policyId\",\r\n\r\n \"policyVersion\",\r\n\r\n \"signals\",\r\n ],\r\n },\r\n\r\n response: {\r\n\r\n 200: {\r\n\r\n description:\r\n \"Deterministic execution result\",\r\n\r\n ...S_EXECUTION_OUTPUT,\r\n },\r\n\r\n 400: {\r\n\r\n description:\r\n \"Invalid request body\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 413: {\r\n\r\n description:\r\n \"Request body too large\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 422: {\r\n\r\n description:\r\n \"Execution failure\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 429: {\r\n\r\n description:\r\n \"Rate limit exceeded\",\r\n\r\n ...S_RATE_LIMIT_ERROR,\r\n },\r\n },\r\n },\r\n },\r\n\r\n async (\r\n req: FastifyRequest<{\r\n Body: ExecuteBody\r\n }>,\r\n\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n\r\n const {\r\n\r\n policyId,\r\n\r\n policyVersion,\r\n\r\n signals,\r\n\r\n } = req.body;\r\n\r\n try {\r\n\r\n const execution =\r\n await executeFromSignals(\r\n\r\n {\r\n policyId,\r\n\r\n policyVersion,\r\n\r\n signals,\r\n },\r\n\r\n signer,\r\n\r\n verifier,\r\n\r\n replayStore\r\n );\r\n\r\n auditDb?.recordDecision(\r\n execution as any\r\n );\r\n\r\n req.log.info(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n policyId,\r\n\r\n policyVersion,\r\n },\r\n\r\n \"execute:success\"\r\n );\r\n\r\n reply.send(\r\n execution\r\n );\r\n\r\n } catch (err) {\r\n\r\n req.log.warn(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n error:\r\n (err as Error).message,\r\n },\r\n\r\n \"execute:failure\"\r\n );\r\n\r\n reply.code(422).send({\r\n\r\n error:\r\n (err as Error).message,\r\n });\r\n }\r\n }\r\n );\r\n}\r\n","import type {\r\n FastifyInstance,\r\n FastifyRequest,\r\n FastifyReply\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type {\r\n\r\n Verifier,\r\n\r\n RuntimeManifest,\r\n\r\n ExecutionAttestation,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n\r\n verifyAttestation,\r\n\r\n} from \"@parmanasystems/verifier\";\r\n\r\nimport type {\r\n\r\n AuditDb,\r\n\r\n} from \"@parmanasystems/audit-db\";\r\n\r\n// --------------------------------------------------\r\n// Canonical flattened attestation schema\r\n// --------------------------------------------------\r\nconst S_ATTESTATION = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n execution_id: {\r\n type: \"string\"\r\n },\r\n\r\n decision: {\r\n type: \"object\"\r\n },\r\n\r\n execution_state: {\r\n type: \"string\"\r\n },\r\n\r\n runtime_hash: {\r\n type: \"string\"\r\n },\r\n\r\n signature: {\r\n type: \"string\",\r\n\r\n description:\r\n \"Base64 Ed25519 signature over the canonical attestation payload\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"execution_id\",\r\n\r\n \"decision\",\r\n\r\n \"execution_state\",\r\n\r\n \"runtime_hash\",\r\n\r\n \"signature\",\r\n ],\r\n};\r\n\r\nconst S_VERIFICATION_RESULT = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n valid: {\r\n type: \"boolean\"\r\n },\r\n\r\n checks: {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n signature_verified: {\r\n type: \"boolean\"\r\n },\r\n\r\n runtime_verified: {\r\n type: \"boolean\"\r\n },\r\n\r\n schema_compatible: {\r\n type: \"boolean\"\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"signature_verified\",\r\n\r\n \"runtime_verified\",\r\n\r\n \"schema_compatible\",\r\n ],\r\n },\r\n },\r\n\r\n required: [\r\n \"valid\",\r\n \"checks\",\r\n ],\r\n};\r\n\r\nconst S_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n\r\n required: [\r\n \"error\"\r\n ],\r\n};\r\n\r\nconst S_RATE_LIMIT_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n\r\n limit: {\r\n type: \"integer\"\r\n },\r\n\r\n remaining: {\r\n type: \"integer\"\r\n },\r\n\r\n reset: {\r\n\r\n type: \"integer\",\r\n\r\n description:\r\n \"Unix timestamp when the rate limit resets\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"error\",\r\n\r\n \"limit\",\r\n\r\n \"remaining\",\r\n\r\n \"reset\",\r\n ],\r\n};\r\n\r\nexport interface VerifyRouteDeps {\r\n\r\n verifier: Verifier;\r\n\r\n runtimeManifest:\r\n RuntimeManifest;\r\n\r\n auditDb?: AuditDb;\r\n}\r\n\r\nexport function registerVerifyRoute(\r\n\r\n app: FastifyInstance,\r\n\r\n deps: VerifyRouteDeps,\r\n\r\n): void {\r\n\r\n const {\r\n\r\n verifier,\r\n\r\n runtimeManifest,\r\n\r\n auditDb,\r\n\r\n } = deps;\r\n\r\n app.post<{\r\n Body: ExecutionAttestation\r\n }>(\r\n \"/verify\",\r\n {\r\n\r\n bodyLimit: 65536,\r\n\r\n config: {\r\n rateLimit: {\r\n max: 200,\r\n timeWindow: \"1 minute\",\r\n },\r\n },\r\n\r\n schema: {\r\n\r\n tags: [\r\n \"Verification\"\r\n ],\r\n\r\n summary:\r\n \"Verify an execution attestation\",\r\n\r\n description:\r\n \"Checks the cryptographic signature and runtime provenance of a deterministic execution attestation.\",\r\n\r\n security: [\r\n { bearerAuth: [] }\r\n ],\r\n\r\n body: {\r\n\r\n ...S_ATTESTATION,\r\n\r\n additionalProperties: false,\r\n\r\n description:\r\n \"Canonical flattened ExecutionAttestation\",\r\n },\r\n\r\n response: {\r\n\r\n 200: {\r\n\r\n description:\r\n \"Verification result with per-check breakdown\",\r\n\r\n ...S_VERIFICATION_RESULT,\r\n },\r\n\r\n 400: {\r\n\r\n description:\r\n \"Malformed attestation body\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 413: {\r\n\r\n description:\r\n \"Request body too large\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 422: {\r\n\r\n description:\r\n \"Verification threw an unexpected error\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 429: {\r\n\r\n description:\r\n \"Rate limit exceeded\",\r\n\r\n ...S_RATE_LIMIT_ERROR,\r\n },\r\n },\r\n },\r\n },\r\n\r\n async (\r\n req: FastifyRequest<{\r\n Body: ExecutionAttestation\r\n }>,\r\n\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n\r\n const body =\r\n req.body;\r\n\r\n // --------------------------------------------\r\n // Flattened attestation validation\r\n // --------------------------------------------\r\n if (\r\n\r\n typeof body?.execution_id !==\r\n \"string\" ||\r\n\r\n typeof body?.signature !==\r\n \"string\"\r\n ) {\r\n\r\n reply.code(400).send({\r\n\r\n error:\r\n \"Body must be a valid ExecutionAttestation\",\r\n });\r\n\r\n return;\r\n }\r\n\r\n try {\r\n\r\n const result =\r\n verifyAttestation(\r\n body,\r\n verifier,\r\n runtimeManifest\r\n );\r\n\r\n auditDb?.recordVerification(\r\n body.execution_id,\r\n result\r\n );\r\n\r\n req.log.info(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n valid:\r\n result.valid,\r\n\r\n checks:\r\n result.checks,\r\n },\r\n\r\n \"verify:success\"\r\n );\r\n\r\n reply.send(result);\r\n\r\n } catch (err) {\r\n\r\n reply.code(422).send({\r\n\r\n error:\r\n (err as Error).message,\r\n });\r\n }\r\n }\r\n );\r\n}\r\n","import type { FastifyInstance, FastifyRequest, FastifyReply } from \"fastify\";\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nconst S_ERROR = {\r\n type: \"object\",\r\n properties: { error: { type: \"string\" } },\r\n required: [\"error\"],\r\n};\r\n\r\nexport function registerAuditRoutes(\r\n app: FastifyInstance,\r\n auditDb: AuditDb,\r\n): void {\r\n\r\n // GET /audit/decisions?limit=50&offset=0&policy_id=...&decision=...&from=...&to=...\r\n app.get<{\r\n Querystring: {\r\n limit?: number;\r\n offset?: number;\r\n policy_id?: string;\r\n decision?: \"approve\" | \"deny\" | \"any\";\r\n from?: string;\r\n to?: string;\r\n };\r\n }>(\"/audit/decisions\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Decision timeline\",\r\n description:\r\n \"Returns a paginated, filtered list of governance decisions joined with their \" +\r\n \"latest verification status. Ordered by executed_at descending.\",\r\n security: [{ bearerAuth: [] }],\r\n querystring: {\r\n type: \"object\",\r\n properties: {\r\n limit: { type: \"integer\", minimum: 1, maximum: 1000, default: 50,\r\n description: \"Max rows (default 50, max 1000)\" },\r\n offset: { type: \"integer\", minimum: 0, default: 0,\r\n description: \"Row offset for pagination (default 0)\" },\r\n policy_id: { type: \"string\", maxLength: 200,\r\n description: \"Filter by exact policy_id\" },\r\n decision: { type: \"string\", enum: [\"approve\", \"deny\", \"any\"],\r\n description: \"Filter by decision value; 'any' returns all\" },\r\n from: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 lower bound on executed_at (inclusive)\" },\r\n to: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 upper bound on executed_at (inclusive)\" },\r\n },\r\n },\r\n response: {\r\n 200: { description: \"Decision timeline rows\", type: \"array\", items: { type: \"object\" } },\r\n 400: { description: \"Invalid query parameters\", ...S_ERROR },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (req, reply: FastifyReply): Promise<void> => {\r\n const { limit, offset: _offset, policy_id, decision, from, to } = req.query;\r\n const parsedLimit = parseInt(String(limit ?? 50), 10);\r\n const normalizedDecision = decision === \"any\" ? undefined : decision;\r\n try {\r\n reply.send(await auditDb.getDecisionTimeline(parsedLimit, {\r\n policy_id: policy_id || undefined,\r\n decision: normalizedDecision,\r\n from_date: from || undefined,\r\n to_date: to || undefined,\r\n }));\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/decisions/:executionId\r\n app.get<{ Params: { executionId: string } }>(\"/audit/decisions/:executionId\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Decision detail\",\r\n description: \"Returns the full audit record for a single governance decision, including the stored attestation JSONB.\",\r\n security: [{ bearerAuth: [] }],\r\n params: {\r\n type: \"object\",\r\n properties: { executionId: { type: \"string\", minLength: 1, maxLength: 200 } },\r\n required: [\"executionId\"],\r\n },\r\n response: {\r\n 200: { description: \"Audit decision record\", type: \"object\" },\r\n 400: { description: \"Invalid path parameters\", ...S_ERROR },\r\n 404: S_ERROR,\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (\r\n req: FastifyRequest<{ Params: { executionId: string } }>,\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n try {\r\n const decision = await auditDb.getDecisionById(req.params.executionId);\r\n if (!decision) {\r\n reply.code(404).send({ error: \"Decision not found\" });\r\n return;\r\n }\r\n reply.send(decision);\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/security?from=...&to=...&limit=50\r\n app.get<{\r\n Querystring: {\r\n from?: string;\r\n to?: string;\r\n limit?: number;\r\n };\r\n }>(\"/audit/security\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Security dashboard\",\r\n description:\r\n \"Returns aggregated security event counts grouped by event_type and severity, \" +\r\n \"ordered by event_count descending.\",\r\n security: [{ bearerAuth: [] }],\r\n querystring: {\r\n type: \"object\",\r\n properties: {\r\n from: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 lower bound on occurred_at (inclusive)\" },\r\n to: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 upper bound on occurred_at (inclusive)\" },\r\n limit: { type: \"integer\", minimum: 1, maximum: 1000, default: 50,\r\n description: \"Max rows (default 50, max 1000)\" },\r\n },\r\n },\r\n response: {\r\n 200: { description: \"Security event summary\", type: \"array\", items: { type: \"object\" } },\r\n 400: { description: \"Invalid query parameters\", ...S_ERROR },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getSecurityDashboard());\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/stats\r\n app.get(\"/audit/stats\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Audit statistics\",\r\n description:\r\n \"Returns aggregate counts across all audit tables: total decisions, decisions today, \" +\r\n \"verifications (valid/invalid), security events, and API access calls.\",\r\n security: [{ bearerAuth: [] }],\r\n response: {\r\n 200: { description: \"Aggregate audit statistics\", type: \"object\" },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getStats());\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/verifications/:executionId\r\n app.get<{ Params: { executionId: string } }>(\"/audit/verifications/:executionId\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Verification history\",\r\n description: \"Returns all verification attempts for a given execution ID, newest first.\",\r\n security: [{ bearerAuth: [] }],\r\n params: {\r\n type: \"object\",\r\n properties: { executionId: { type: \"string\", format: \"uuid\" } },\r\n required: [\"executionId\"],\r\n },\r\n response: {\r\n 200: { description: \"Verification records\", type: \"array\", items: { type: \"object\" } },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (\r\n req: FastifyRequest<{ Params: { executionId: string } }>,\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getVerificationsByExecution(req.params.executionId));\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n}\r\n","import type { FastifyRequest, FastifyReply } from \"fastify\";\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nexport function createAuditMiddleware(auditDb: AuditDb) {\r\n return async function onResponse(\r\n req: FastifyRequest,\r\n reply: FastifyReply,\r\n ): Promise<void> {\r\n auditDb.recordApiAccess({\r\n method: req.method,\r\n path: req.url,\r\n status_code: reply.statusCode,\r\n response_time_ms: Number.isFinite(reply.elapsedTime)\r\n ? Math.round(reply.elapsedTime)\r\n : undefined,\r\n ip_address: req.ip,\r\n user_agent: req.headers[\"user-agent\"],\r\n });\r\n\r\n if (reply.statusCode === 401) {\r\n auditDb.recordSecurityEvent({\r\n event_type: \"auth_failure\",\r\n severity: \"medium\",\r\n ip_address: req.ip,\r\n path: req.url,\r\n method: req.method,\r\n user_agent: req.headers[\"user-agent\"],\r\n details: { status_code: 401 },\r\n });\r\n }\r\n };\r\n}\r\n","import { createServer } from \"./server.js\";\r\nimport { signingKeySource } from \"./runtime.js\";\r\n\r\nconst port = parseInt(process.env.PORT ?? \"3000\", 10);\r\nconst host = process.env.HOST ?? \"0.0.0.0\";\r\n\r\nconst { app, auditDb } = createServer();\r\n\r\nasync function shutdown(signal: string): Promise<void> {\r\n app.log.info(`Shutdown signal received (${signal}), closing server...`);\r\n\r\n const shutdownTimeout = setTimeout(() => {\r\n app.log.error(\"Graceful shutdown timed out, forcing exit\");\r\n process.exit(1);\r\n }, 10000);\r\n\r\n shutdownTimeout.unref();\r\n\r\n try {\r\n await app.close();\r\n\r\n if (auditDb) {\r\n await auditDb.disconnect();\r\n }\r\n\r\n clearTimeout(shutdownTimeout);\r\n\r\n app.log.info(\"Server closed cleanly\");\r\n\r\n process.exit(0);\r\n\r\n } catch (err) {\r\n app.log.error({ err }, \"Error during shutdown\");\r\n\r\n process.exit(1);\r\n }\r\n}\r\n\r\nprocess.on(\"SIGTERM\", () => {\r\n void shutdown(\"SIGTERM\");\r\n});\r\n\r\nprocess.on(\"SIGINT\", () => {\r\n void shutdown(\"SIGINT\");\r\n});\r\n\r\nexport async function startServer(): Promise<void> {\r\n try {\r\n await app.listen({ port, host });\r\n\r\n app.log.info(`Server listening on http://${host}:${port}`);\r\n\r\n if (auditDb) {\r\n app.log.info(\"Audit DB connected\");\r\n } else {\r\n app.log.info(\"Audit DB not configured\");\r\n }\r\n\r\n const keyMsg: Record<typeof signingKeySource, string> = {\r\n env: \"Signing key loaded from env\",\r\n disk: \"Signing key loaded from disk\",\r\n ephemeral: \"Using ephemeral signing key\",\r\n };\r\n\r\n app.log.info(keyMsg[signingKeySource]);\r\n\r\n } catch (err) {\r\n app.log.error(err);\r\n\r\n process.exit(1);\r\n }\r\n}\r\n\r\nexport { app };\r\n"],"mappings":";AAAA,OAAO,aAAuC;AAC9C,SAAS,YAAY,kBAAkB;AACvC,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,YAAY;;;ACJnB,YAAY,YAAY;AAExB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAUP,SAAS,iBAAsF;AAC7F,MAAI,QAAQ,IAAI,uBAAuB,QAAQ,IAAI,oBAAoB;AACrE,WAAO;AAAA,MACL,YAAY,QAAQ,IAAI;AAAA,MACxB,WAAW,QAAQ,IAAI;AAAA,MACvB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI;AACF,WAAO;AAAA,MACL,YAAY,eAAe;AAAA,MAC3B,WAAW,cAAc;AAAA,MACzB,QAAQ;AAAA,IACV;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,EAAE,YAAY,UAAU,IAAW,2BAAoB,WAAW;AAAA,IACtE,oBAAoB,EAAE,MAAM,SAAS,QAAQ,MAAM;AAAA,IACnD,mBAAmB,EAAE,MAAM,QAAQ,QAAQ,MAAM;AAAA,EACnD,CAAC;AAED,SAAO,EAAE,YAAY,WAAW,QAAQ,YAAY;AACtD;AAEA,IAAM,OAAO,eAAe;AAErB,IAAM,mBAAqC,KAAK;AAChD,IAAM,SAAS,IAAI,YAAY,KAAK,UAAU;AAC9C,IAAM,WAAW,IAAI,cAAc,KAAK,SAAS;AACjD,IAAM,kBAAkB,mBAAmB;;;ACzClD,eAAsB,SACpB,KACA,OACe;AACf,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,OAAQ;AAEb,QAAM,OAAO,IAAI,QAAQ;AACzB,MAAI,SAAS,UAAU,MAAM,IAAI;AAC/B,QAAI,IAAI,KAAK,EAAE,OAAO,IAAI,IAAI,QAAQ,eAAe,GAAG,cAAc;AACtE,UAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,EAChD;AACF;;;AChBA,SAAS,sBAAAA,2BAA4E;AACrF,SAAS,kBAAkB;;;ACW3B;AAAA,EAEE;AAAA,EAEA;AAAA,OAEK;AAWP,IAAM,qBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,QAAQ;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IAEA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IAEA,mBAAmB;AAAA,MACjB,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAM,UAAU;AAAA,EAEd,MAAM;AAAA,EAEN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAM,qBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MAEL,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAoBO,SAAS,qBAEdC,MAEA,MAEM;AAEN,QAAM;AAAA,IAEJ,QAAAC;AAAA,IAEA,UAAAC;AAAA,IAEA,SAAAC;AAAA,EAEF,IAAI;AAKJ,QAAM,cACJ,IAAI;AAAA,IACF;AAAA,EACF;AAEF,EAAAH,KAAI;AAAA,IAGF;AAAA,IACA;AAAA,MAEE,WAAW;AAAA,MAEX,QAAQ;AAAA,QACN,WAAW;AAAA,UACT,KAAK;AAAA,UACL,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MAEA,QAAQ;AAAA,QAEN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,QAEA,SACE;AAAA,QAEF,aACE;AAAA,QAEF,UAAU;AAAA,UACR,EAAE,YAAY,CAAC,EAAE;AAAA,QACnB;AAAA,QAEA,MAAM;AAAA,UAEJ,MAAM;AAAA,UAEN,sBAAsB;AAAA,UAEtB,YAAY;AAAA,YAEV,UAAU;AAAA,cAER,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,YAEA,eAAe;AAAA,cAEb,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,YAEA,SAAS;AAAA,cAEP,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,UACF;AAAA,UAEA,UAAU;AAAA,YAER;AAAA,YAEA;AAAA,YAEA;AAAA,UACF;AAAA,QACF;AAAA,QAEA,UAAU;AAAA,UAER,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OACE,KAIA,UACkB;AAElB,YAAM;AAAA,QAEJ;AAAA,QAEA;AAAA,QAEA;AAAA,MAEF,IAAI,IAAI;AAER,UAAI;AAEF,cAAM,YACJ,MAAM;AAAA,UAEJ;AAAA,YACE;AAAA,YAEA;AAAA,YAEA;AAAA,UACF;AAAA,UAEAC;AAAA,UAEAC;AAAA,UAEA;AAAA,QACF;AAEF,QAAAC,UAAS;AAAA,UACP;AAAA,QACF;AAEA,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN;AAAA,YAEA;AAAA,UACF;AAAA,UAEA;AAAA,QACF;AAEA,cAAM;AAAA,UACJ;AAAA,QACF;AAAA,MAEF,SAAS,KAAK;AAEZ,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN,OACG,IAAc;AAAA,UACnB;AAAA,UAEA;AAAA,QACF;AAEA,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACG,IAAc;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACjWA;AAAA,EAEE;AAAA,OAEK;AAWP,IAAM,gBAAgB;AAAA,EAEpB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IAEA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAEA,IAAM,wBAAwB;AAAA,EAE5B,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,QAAQ;AAAA,MAEN,MAAM;AAAA,MAEN,YAAY;AAAA,QAEV,oBAAoB;AAAA,UAClB,MAAM;AAAA,QACR;AAAA,QAEA,kBAAkB;AAAA,UAChB,MAAM;AAAA,QACR;AAAA,QAEA,mBAAmB;AAAA,UACjB,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,UAAU;AAAA,QAER;AAAA,QAEA;AAAA,QAEA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAMC,WAAU;AAAA,EAEd,MAAM;AAAA,EAEN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAMC,sBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MAEL,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAYO,SAAS,oBAEdC,MAEA,MAEM;AAEN,QAAM;AAAA,IAEJ,UAAAC;AAAA,IAEA,iBAAAC;AAAA,IAEA,SAAAC;AAAA,EAEF,IAAI;AAEJ,EAAAH,KAAI;AAAA,IAGF;AAAA,IACA;AAAA,MAEE,WAAW;AAAA,MAEX,QAAQ;AAAA,QACN,WAAW;AAAA,UACT,KAAK;AAAA,UACL,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MAEA,QAAQ;AAAA,QAEN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,QAEA,SACE;AAAA,QAEF,aACE;AAAA,QAEF,UAAU;AAAA,UACR,EAAE,YAAY,CAAC,EAAE;AAAA,QACnB;AAAA,QAEA,MAAM;AAAA,UAEJ,GAAG;AAAA,UAEH,sBAAsB;AAAA,UAEtB,aACE;AAAA,QACJ;AAAA,QAEA,UAAU;AAAA,UAER,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGF;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGA;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGA;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGC;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OACE,KAIA,UACkB;AAElB,YAAM,OACJ,IAAI;AAKN,UAEE,OAAO,MAAM,iBACX,YAEF,OAAO,MAAM,cACX,UACF;AAEA,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACE;AAAA,QACJ,CAAC;AAED;AAAA,MACF;AAEA,UAAI;AAEF,cAAM,SACJ;AAAA,UACE;AAAA,UACAE;AAAA,UACAC;AAAA,QACF;AAEF,QAAAC,UAAS;AAAA,UACP,KAAK;AAAA,UACL;AAAA,QACF;AAEA,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN,OACE,OAAO;AAAA,YAET,QACE,OAAO;AAAA,UACX;AAAA,UAEA;AAAA,QACF;AAEA,cAAM,KAAK,MAAM;AAAA,MAEnB,SAAS,KAAK;AAEZ,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACG,IAAc;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACvWA,IAAMC,WAAU;AAAA,EACd,MAAM;AAAA,EACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,EACxC,UAAU,CAAC,OAAO;AACpB;AAEO,SAAS,oBACdC,MACAC,UACM;AAGN,EAAAD,KAAI,IASD,oBAAoB;AAAA,IACrB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAW;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YAAM,SAAS;AAAA,YACrD,aAAa;AAAA,UAAkC;AAAA,UAC5D,QAAW;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YACtC,aAAa;AAAA,UAAwC;AAAA,UAClE,WAAW;AAAA,YAAE,MAAM;AAAA,YAAU,WAAW;AAAA,YAC3B,aAAa;AAAA,UAA4B;AAAA,UACtD,UAAW;AAAA,YAAE,MAAM;AAAA,YAAU,MAAM,CAAC,WAAW,QAAQ,KAAK;AAAA,YAC/C,aAAa;AAAA,UAA8C;AAAA,UACxE,MAAW;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UAC5E,IAAW;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,QAC9E;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,0BAA0B,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACvF,KAAK,EAAE,aAAa,4BAA4B,GAAGD,SAAQ;AAAA,QAC3D,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,KAAK,UAAuC;AACpD,UAAM,EAAE,OAAO,QAAQ,SAAS,WAAW,UAAU,MAAM,GAAG,IAAI,IAAI;AACtE,UAAM,cAAc,SAAS,OAAO,SAAS,EAAE,GAAG,EAAE;AACpD,UAAM,qBAAqB,aAAa,QAAQ,SAAY;AAC5D,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,oBAAoB,aAAa;AAAA,QACxD,WAAW,aAAa;AAAA,QACxB,UAAW;AAAA,QACX,WAAW,QAAQ;AAAA,QACnB,SAAW,MAAQ;AAAA,MACrB,CAAC,CAAC;AAAA,IACJ,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAyC,iCAAiC;AAAA,IAC5E,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,WAAW,GAAG,WAAW,IAAI,EAAE;AAAA,QAC5E,UAAU,CAAC,aAAa;AAAA,MAC1B;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,yBAAyB,MAAM,SAAS;AAAA,QAC5D,KAAK,EAAE,aAAa,2BAA2B,GAAGD,SAAQ;AAAA,QAC1D,KAAKA;AAAA,QACL,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OACD,KACA,UACkB;AAClB,QAAI;AACF,YAAM,WAAW,MAAME,SAAQ,gBAAgB,IAAI,OAAO,WAAW;AACrE,UAAI,CAAC,UAAU;AACb,cAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AACpD;AAAA,MACF;AACA,YAAM,KAAK,QAAQ;AAAA,IACrB,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAMD,mBAAmB;AAAA,IACpB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAO;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UACxE,IAAO;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UACxE,OAAO;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YAAM,SAAS;AAAA,YACrD,aAAa;AAAA,UAAkC;AAAA,QAC1D;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,0BAA0B,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACvF,KAAK,EAAE,aAAa,4BAA4B,GAAGD,SAAQ;AAAA,QAC3D,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,MAAsB,UAAuC;AACrE,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,qBAAqB,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAI,gBAAgB;AAAA,IACtB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,8BAA8B,MAAM,SAAS;AAAA,QACjE,KAAKD;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,MAAsB,UAAuC;AACrE,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,SAAS,CAAC;AAAA,IACrC,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAyC,qCAAqC;AAAA,IAChF,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,QAAQ,OAAO,EAAE;AAAA,QAC9D,UAAU,CAAC,aAAa;AAAA,MAC1B;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,wBAAwB,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACrF,KAAKD;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OACD,KACA,UACkB;AAClB,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,4BAA4B,IAAI,OAAO,WAAW,CAAC;AAAA,IAC9E,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AACH;;;AHvLA,IAAMC,WAAU;AAAA,EACd,MAAM;AAAA,EACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,EACxC,UAAU,CAAC,OAAO;AACpB;AAEA,IAAM,oBAAoB;AAAA,EACxB,GAAGA;AAAA,EACH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,MAAM,CAAC,iBAAiB,EAAE,EAAE;AACrE;AAIA,SAAS,eAA+B;AACtC,MAAI;AAAE,IAAAC,oBAAmB;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAS;AACrE;AAEA,SAAS,kBAAyC;AAChD,MAAI,QAAQ,IAAI,oBAAqB,QAAO;AAC5C,MAAI,WAAW,+BAA+B,EAAG,QAAO;AACxD,SAAO;AACT;AAEA,eAAe,aAAa,IAAyE;AACnG,MAAI,CAAC,GAAI,QAAO;AAChB,MAAI;AAAE,UAAM,GAAG,KAAK;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAe;AACtE;AAuCO,SAAS,eACdC,MACA,MACM;AACN,QAAM,EAAE,QAAAC,SAAQ,UAAAC,WAAU,iBAAAC,kBAAiB,SAAAC,SAAQ,IAAI;AAIvD,EAAAJ,KAAI,IAAI,WAAW;AAAA,IACjB,QAAQ,EAAE,WAAW,EAAE,KAAK,KAAK,YAAY,WAAW,EAAE;AAAA,IAC1D,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,QACR,KAAK;AAAA,UACH,aAAa;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,YACV,QAAW,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,UAAU,EAAE;AAAA,YACtD,SAAW,EAAE,MAAM,SAAS;AAAA,YAC5B,WAAW,EAAE,MAAM,UAAU,QAAQ,YAAY;AAAA,YACjD,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,YAAY;AAAA,gBACV,kBAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,OAAO,EAAE;AAAA,gBAC1D,aAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,cAAc,EAAE;AAAA,gBACjE,UAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,eAAe,cAAc,EAAE;AAAA,cAClF;AAAA,cACA,UAAU,CAAC,oBAAoB,eAAe,UAAU;AAAA,YAC1D;AAAA,UACF;AAAA,UACA,UAAU,CAAC,UAAU,WAAW,aAAa,QAAQ;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,YAAY;AACb,UAAM,SAAS;AAAA,MACb,kBAAkB,aAAa;AAAA,MAC/B,aAAkB,gBAAgB;AAAA,MAClC,UAAkB,MAAM,aAAaI,QAAO;AAAA,IAC9C;AACA,UAAM,WAAW,OAAO,OAAO,MAAM,EAAE,KAAK,OAAK,MAAM,WAAW,MAAM,aAAa;AACrF,WAAO;AAAA,MACL,QAAW,WAAW,aAAsB;AAAA,MAC5C,SAAW;AAAA,MACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAC;AAID,uBAAqBJ,MAAK,EAAE,QAAAC,SAAQ,UAAAC,WAAU,SAAAE,SAAQ,CAAC;AAIvD,sBAAoBJ,MAAK,EAAE,UAAAE,WAAU,iBAAAC,kBAAiB,SAAAC,SAAQ,CAAC;AAI/D,MAAIA,UAAS;AACX,wBAAoBJ,MAAKI,QAAO;AAAA,EAClC;AAIA,QAAM,OAAO,OAAO,MAAsB,UAAuC;AAC/E,UAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,EACnD;AAEA,EAAAJ,KAAI,IAAI,qBAAqB;AAAA,IAC3B,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,IAAI,yBAAyB;AAAA,IAC/B,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,KAAK,aAAa;AAAA,IACpB,WAAW;AAAA,IACX,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,WAAW;AAAA,MAClB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,KAAK,aAAa;AAAA,IACpB,WAAW;AAAA,IACX,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,WAAW;AAAA,MAClB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AACT;;;AHhMA,SAAS,eAAe;;;AONjB,SAAS,sBAAsBK,UAAkB;AACtD,SAAO,eAAe,WACpB,KACA,OACe;AACf,IAAAA,SAAQ,gBAAgB;AAAA,MACtB,QAAiB,IAAI;AAAA,MACrB,MAAiB,IAAI;AAAA,MACrB,aAAiB,MAAM;AAAA,MACvB,kBAAkB,OAAO,SAAS,MAAM,WAAW,IAC/C,KAAK,MAAM,MAAM,WAAW,IAC5B;AAAA,MACJ,YAAY,IAAI;AAAA,MAChB,YAAY,IAAI,QAAQ,YAAY;AAAA,IACtC,CAAC;AAED,QAAI,MAAM,eAAe,KAAK;AAC5B,MAAAA,SAAQ,oBAAoB;AAAA,QAC1B,YAAY;AAAA,QACZ,UAAY;AAAA,QACZ,YAAY,IAAI;AAAA,QAChB,MAAY,IAAI;AAAA,QAChB,QAAY,IAAI;AAAA,QAChB,YAAY,IAAI,QAAQ,YAAY;AAAA,QACpC,SAAY,EAAE,aAAa,IAAI;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;APCO,SAAS,eAA+B;AAC7C,QAAMC,OAAM,QAAQ;AAAA,IAClB,WAAW;AAAA;AAAA,IACX,QAAQ;AAAA,MACN,OAAO,QAAQ,IAAI,cAAc,QAAQ,IAAI,aAAa,eAAe,SAAS;AAAA,MAClF,QAAQ;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,MACA,aAAa;AAAA,QACX,IAAI,KAAK;AACP,gBAAM,MAAM,IAAI,QAAQ,iBAAiB;AACzC,iBAAO;AAAA,YACL,QAAQ,IAAI;AAAA,YACZ,KAAK,IAAI;AAAA,YACT,OAAO,IAAI;AAAA,YACX,gBAAgB,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,QAAQ,IAAI,QAAQ;AAAA,UACpE;AAAA,QACF;AAAA,QACA,IAAI,KAAK;AACP,iBAAO;AAAA,YACL,YAAY,IAAI;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,CAAC,QACR,IAAI,QAAQ,cAAc,KAA4B,WAAW;AAAA,EACtE,CAAC;AAED,QAAM,gBAAgB,QAAQ,IAAI;AAClC,QAAM,aACJ,kBAAkB,MAAM,OACxB,gBAAwB,cAAc,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC,IAC1C,CAAC,yBAAyB,uBAAuB;AAE3E,EAAAA,KAAI,SAAS,MAAM;AAAA,IACjB,QAAgB;AAAA,IAChB,SAAgB,CAAC,OAAO,MAAM;AAAA,IAC9B,gBAAgB,CAAC,gBAAgB,iBAAiB,cAAc;AAAA,IAChE,gBAAgB,CAAC,gBAAgB,qBAAqB,yBAAyB,mBAAmB;AAAA,IAClG,aAAgB;AAAA,IAChB,QAAgB;AAAA,EAClB,CAAC;AAED,EAAAA,KAAI,SAAS,QAAQ;AAAA,IACnB,uBAAuB;AAAA,MACrB,YAAY;AAAA,QACV,YAAY,CAAC,QAAQ;AAAA,QACrB,gBAAgB,CAAC,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,IAC3B,2BAA2B,EAAE,QAAQ,eAAe;AAAA,IACpD,oBAAoB,EAAE,OAAO,MAAM;AAAA,IACnC,YAAY,EAAE,QAAQ,OAAO;AAAA,IAC7B,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,SAAS;AAAA,IACX;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA,IACT,gBAAgB,EAAE,QAAQ,cAAc;AAAA,IACxC,WAAW;AAAA,EACb,CAAC;AAED,QAAMC,WAAU,QAAQ,IAAI,qBACxB,IAAI,QAAQ,QAAQ,IAAI,kBAAkB,IAC1C;AAEJ,MAAIA,UAAS;AACX,IAAAA,SAAQ,QAAQ,EAAE;AAAA,MAAM,CAAC,QACvBD,KAAI,IAAI,MAAM,EAAE,IAAI,GAAG,uEAAkE;AAAA,IAC3F;AACA,IAAAA,KAAI,QAAQ,cAAc,sBAAsBC,QAAO,CAAC;AAAA,EAC1D;AAEA,EAAAD,KAAI,QAAQ,UAAU,OAAO,KAAK,UAAU;AAC1C,UAAM,OAAO,gBAAgB,IAAI,EAAE;AAAA,EACrC,CAAC;AAED,EAAAA,KAAI,QAAQ,UAAU,OAAO,MAAM,UAAU;AAC3C,UAAM,aAAa,cAAc;AAAA,EACnC,CAAC;AAED,EAAAA,KAAI,QAAQ,cAAc,QAAQ;AAGlC,QAAM,aAAa,QAAQ,IAAI,kBAC3B,WAAW,QAAQ,EAAE,OAAO,QAAQ,IAAI,eAAe,EAAE,OAAO,KAAK,IACrE;AAEJ,EAAAA,KAAI,SAAS,WAAW;AAAA,IACtB,aAAa,KAAK;AAChB,UAAI,WAAY,QAAO;AACvB,YAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,YAAM,eAAe,MAAM,QAAQ,SAAS,IAAI,UAAU,CAAC,IAAI;AAC/D,YAAM,cAAc,cAAc,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AACtD,YAAM,SAAS,IAAI,QAAQ,WAAW;AACtC,YAAM,YAAY,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AACtD,aAAO,eAAe,aAAa,IAAI;AAAA,IACzC;AAAA,IACA,qBAAqB,MAAM,SAAS;AAClC,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ;AAAA,QACf,WAAW;AAAA,QACX,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,KAAK,KAAK,QAAQ,MAAM,GAAI;AAAA,MACrE;AAAA,IACF;AAAA,EACF,CAAC;AAED,iBAAeA,MAAK,EAAE,QAAQ,UAAU,iBAAiB,SAAAC,SAAQ,CAAC;AAElE,SAAO,EAAE,KAAAD,MAAK,SAAAC,SAAQ;AACxB;;;AQrJA,IAAM,OAAO,SAAS,QAAQ,IAAI,QAAQ,QAAQ,EAAE;AACpD,IAAM,OAAO,QAAQ,IAAI,QAAQ;AAEjC,IAAM,EAAE,KAAK,QAAQ,IAAI,aAAa;AAEtC,eAAe,SAAS,QAA+B;AACrD,MAAI,IAAI,KAAK,6BAA6B,MAAM,sBAAsB;AAEtE,QAAM,kBAAkB,WAAW,MAAM;AACvC,QAAI,IAAI,MAAM,2CAA2C;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB,GAAG,GAAK;AAER,kBAAgB,MAAM;AAEtB,MAAI;AACF,UAAM,IAAI,MAAM;AAEhB,QAAI,SAAS;AACX,YAAM,QAAQ,WAAW;AAAA,IAC3B;AAEA,iBAAa,eAAe;AAE5B,QAAI,IAAI,KAAK,uBAAuB;AAEpC,YAAQ,KAAK,CAAC;AAAA,EAEhB,SAAS,KAAK;AACZ,QAAI,IAAI,MAAM,EAAE,IAAI,GAAG,uBAAuB;AAE9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,QAAQ,GAAG,WAAW,MAAM;AAC1B,OAAK,SAAS,SAAS;AACzB,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,OAAK,SAAS,QAAQ;AACxB,CAAC;AAED,eAAsB,cAA6B;AACjD,MAAI;AACF,UAAM,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC;AAE/B,QAAI,IAAI,KAAK,8BAA8B,IAAI,IAAI,IAAI,EAAE;AAEzD,QAAI,SAAS;AACX,UAAI,IAAI,KAAK,oBAAoB;AAAA,IACnC,OAAO;AACL,UAAI,IAAI,KAAK,yBAAyB;AAAA,IACxC;AAEA,UAAM,SAAkD;AAAA,MACtD,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAEA,QAAI,IAAI,KAAK,OAAO,gBAAgB,CAAC;AAAA,EAEvC,SAAS,KAAK;AACZ,QAAI,IAAI,MAAM,GAAG;AAEjB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":["getRuntimeManifest","app","signer","verifier","auditDb","S_ERROR","S_RATE_LIMIT_ERROR","app","verifier","runtimeManifest","auditDb","S_ERROR","app","auditDb","S_ERROR","getRuntimeManifest","app","signer","verifier","runtimeManifest","auditDb","auditDb","app","auditDb"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/runtime.ts","../src/auth.ts","../src/routes.ts","../src/routes/execute.ts","../src/routes/verify.ts","../src/routes/audit.ts","../src/middleware/audit.ts","../src/index.ts"],"sourcesContent":["import Fastify, { type FastifyInstance } from \"fastify\";\r\nimport { createHash, randomUUID } from \"node:crypto\";\r\nimport rateLimit from \"@fastify/rate-limit\";\r\nimport cors from \"@fastify/cors\";\r\nimport helmet from \"@fastify/helmet\";\r\n\r\nimport { signer, verifier, runtimeManifest } from \"./runtime.js\";\r\nimport { authHook } from \"./auth.js\";\r\nimport { registerRoutes } from \"./routes.js\";\r\nimport { AuditDb } from \"@parmanasystems/audit-db\";\r\nimport { createAuditMiddleware } from \"./middleware/audit.js\";\r\n\r\n/**\r\n * Creates and configures the parmanasystems Fastify HTTP server.\r\n *\r\n * When `AUDIT_DATABASE_URL` is set the server additionally:\r\n * - Runs schema migrations on startup (non-blocking; logs failure and continues).\r\n * - Fires an `onResponse` hook that records every request to `audit_api_access`\r\n * and auth failures to `audit_security_events` — both fire-and-forget.\r\n * - Records each `/execute` decision and `/verify` result fire-and-forget.\r\n * - Exposes four read-only `/audit/*` query routes.\r\n *\r\n * Key points:\r\n * - The signer/verifier/runtimeManifest are resolved from environment variables,\r\n * dev-keys on disk, or an ephemeral Ed25519 key pair in that order.\r\n * - Set `Parmana_API_KEY` to enable authentication; omit it for dev mode.\r\n */\r\nexport interface ServerInstance {\r\n app: FastifyInstance;\r\n auditDb?: AuditDb;\r\n}\r\n\r\nexport function createServer(): ServerInstance {\r\n const app = Fastify({\r\n bodyLimit: 1048576, // 1 MB global default\r\n logger: {\r\n level: process.env.LOG_LEVEL ?? (process.env.NODE_ENV === \"production\" ? \"info\" : \"debug\"),\r\n redact: {\r\n paths: [\r\n \"req.headers.authorization\",\r\n \"req.body.signature\",\r\n \"req.body.attestation.signature\",\r\n ],\r\n censor: \"[REDACTED]\",\r\n },\r\n serializers: {\r\n req(req) {\r\n const fwd = req.headers[\"x-forwarded-for\"];\r\n return {\r\n method: req.method,\r\n url: req.url,\r\n reqId: req.id,\r\n remoteAddress: (Array.isArray(fwd) ? fwd[0] : fwd) ?? req.socket?.remoteAddress,\r\n };\r\n },\r\n res(res) {\r\n return {\r\n statusCode: res.statusCode,\r\n };\r\n },\r\n },\r\n },\r\n genReqId: (req: import(\"node:http\").IncomingMessage) =>\r\n (req.headers[\"x-request-id\"] as string | undefined) ?? randomUUID(),\r\n });\r\n\r\n const corsOriginEnv = process.env.CORS_ORIGIN;\r\n const corsOrigin: string | string[] | boolean =\r\n corsOriginEnv === \"*\" ? true :\r\n corsOriginEnv ? corsOriginEnv.split(\",\").map(o => o.trim()) :\r\n [\"http://localhost:5173\", \"http://localhost:8080\"];\r\n\r\n app.register(cors, {\r\n origin: corsOrigin,\r\n methods: [\"GET\", \"POST\"],\r\n allowedHeaders: [\"Content-Type\", \"Authorization\", \"X-Request-ID\"],\r\n exposedHeaders: [\"X-Request-ID\", \"X-RateLimit-Limit\", \"X-RateLimit-Remaining\", \"X-RateLimit-Reset\"],\r\n credentials: true,\r\n maxAge: 86400,\r\n });\r\n\r\n app.register(helmet, {\r\n contentSecurityPolicy: {\r\n directives: {\r\n defaultSrc: [\"'none'\"],\r\n frameAncestors: [\"'none'\"],\r\n },\r\n },\r\n crossOriginEmbedderPolicy: false,\r\n crossOriginResourcePolicy: { policy: \"cross-origin\" },\r\n dnsPrefetchControl: { allow: false },\r\n frameguard: { action: \"deny\" },\r\n hsts: {\r\n maxAge: 31536000,\r\n includeSubDomains: true,\r\n preload: true,\r\n },\r\n ieNoOpen: true,\r\n noSniff: true,\r\n referrerPolicy: { policy: \"no-referrer\" },\r\n xssFilter: true,\r\n });\r\n\r\n const auditDb = process.env.AUDIT_DATABASE_URL\r\n ? new AuditDb(process.env.AUDIT_DATABASE_URL)\r\n : undefined;\r\n\r\n if (auditDb) {\r\n auditDb.migrate().catch((err: unknown) =>\r\n app.log.error({ err }, \"audit-db migration failed — continuing without audit persistence\"),\r\n );\r\n app.addHook(\"onResponse\", createAuditMiddleware(auditDb));\r\n }\r\n\r\n app.addHook(\"onSend\", async (req, reply) => {\r\n reply.header(\"X-Request-ID\", req.id);\r\n });\r\n\r\n app.addHook(\"onSend\", async (_req, reply) => {\r\n reply.removeHeader(\"X-Powered-By\");\r\n });\r\n\r\n app.addHook(\"preHandler\", authHook);\r\n\r\n // Precompute API key hash once at startup — used as the per-key rate limit bucket\r\n const apiKeyHash = process.env.Parmana_API_KEY\r\n ? createHash(\"sha256\").update(process.env.Parmana_API_KEY).digest(\"hex\")\r\n : null;\r\n\r\n app.register(rateLimit, {\r\n keyGenerator(req) {\r\n if (apiKeyHash) return apiKeyHash;\r\n const forwarded = req.headers[\"x-forwarded-for\"];\r\n const forwardedStr = Array.isArray(forwarded) ? forwarded[0] : forwarded;\r\n const forwardedIp = forwardedStr?.split(\",\")[0]?.trim();\r\n const realIp = req.headers[\"x-real-ip\"];\r\n const realIpStr = Array.isArray(realIp) ? realIp[0] : realIp;\r\n return forwardedIp ?? realIpStr ?? req.ip;\r\n },\r\n errorResponseBuilder(_req, context) {\r\n return {\r\n error: \"Rate limit exceeded\",\r\n limit: context.max,\r\n remaining: 0,\r\n reset: Math.floor(Date.now() / 1000) + Math.ceil(context.ttl / 1000),\r\n };\r\n },\r\n });\r\n\r\n registerRoutes(app, { signer, verifier, runtimeManifest, auditDb });\r\n\r\n return { app, auditDb };\r\n}\r\n","import * as crypto from \"node:crypto\";\r\n\r\nimport {\r\n LocalSigner,\r\n LocalVerifier,\r\n getRuntimeManifest,\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n loadPrivateKey,\r\n loadPublicKey,\r\n} from \"@parmanasystems/crypto\";\r\n\r\nexport type SigningKeySource = \"env\" | \"disk\" | \"ephemeral\";\r\n\r\n/**\r\n * Resolves the Ed25519 key pair for the server in priority order:\r\n * 1. `Parmana_PRIVATE_KEY` + `Parmana_PUBLIC_KEY` environment variables.\r\n * 2. Dev keys on disk at `./dev-keys/bundle_signing_key{,.pub}`.\r\n * 3. Ephemeral in-process key pair (new on every restart — dev only).\r\n */\r\nfunction resolveKeyPair(): { privateKey: string; publicKey: string; source: SigningKeySource } {\r\n if (process.env.Parmana_PRIVATE_KEY && process.env.Parmana_PUBLIC_KEY) {\r\n return {\r\n privateKey: process.env.Parmana_PRIVATE_KEY,\r\n publicKey: process.env.Parmana_PUBLIC_KEY,\r\n source: \"env\",\r\n };\r\n }\r\n\r\n try {\r\n return {\r\n privateKey: loadPrivateKey(),\r\n publicKey: loadPublicKey(),\r\n source: \"disk\",\r\n };\r\n } catch {\r\n // no dev keys on disk — fall through to ephemeral\r\n }\r\n\r\n const { privateKey, publicKey } = crypto.generateKeyPairSync(\"ed25519\", {\r\n privateKeyEncoding: { type: \"pkcs8\", format: \"pem\" },\r\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\r\n });\r\n\r\n return { privateKey, publicKey, source: \"ephemeral\" };\r\n}\r\n\r\nconst keys = resolveKeyPair();\r\n\r\nexport const signingKeySource: SigningKeySource = keys.source;\r\nexport const signer = new LocalSigner(keys.privateKey);\r\nexport const verifier = new LocalVerifier(keys.publicKey);\r\nexport const runtimeManifest = getRuntimeManifest();\r\n","import type { FastifyRequest, FastifyReply } from \"fastify\";\r\n\r\n/**\r\n * Fastify pre-handler hook that enforces Bearer token authentication.\r\n *\r\n * When `Parmana_API_KEY` is set in the environment, every request must supply\r\n * the header `Authorization: Bearer <key>`. If the key is absent or wrong the\r\n * hook sends `401 Unauthorized` and terminates the request.\r\n *\r\n * When `Parmana_API_KEY` is unset (dev mode), all requests pass through\r\n * without authentication.\r\n */\r\nexport async function authHook(\r\n req: FastifyRequest,\r\n reply: FastifyReply\r\n): Promise<void> {\r\n const apiKey = process.env.Parmana_API_KEY;\r\n if (!apiKey) return; // dev mode — skip auth\r\n\r\n const auth = req.headers.authorization;\r\n if (auth !== `Bearer ${apiKey}`) {\r\n req.log.warn({ reqId: req.id, reason: \"auth_failure\" }, \"auth_failure\");\r\n reply.code(401).send({ error: \"Unauthorized\" });\r\n }\r\n}\r\n","import type {\r\n FastifyInstance,\r\n FastifyRequest,\r\n FastifyReply,\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport { getRuntimeManifest, type Signer, type Verifier, type RuntimeManifest } from \"@parmanasystems/execution\";\r\nimport { existsSync } from \"node:fs\";\r\n\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nimport { registerExecuteRoute } from \"./routes/execute.js\";\r\nimport { registerVerifyRoute } from \"./routes/verify.js\";\r\nimport { registerAuditRoutes } from \"./routes/audit.js\";\r\n\r\n// ── Reusable JSON Schema fragments (stubs only — active routes own their schemas) ──\r\n\r\nconst S_ERROR = {\r\n type: \"object\",\r\n properties: { error: { type: \"string\" } },\r\n required: [\"error\"],\r\n};\r\n\r\nconst S_NOT_IMPLEMENTED = {\r\n ...S_ERROR,\r\n properties: { error: { type: \"string\", enum: [\"Not implemented\"] } },\r\n};\r\n\r\n// ── Health check helpers ──────────────────────────────────────────────────────\r\n\r\nfunction checkRuntime(): \"ok\" | \"error\" {\r\n try { getRuntimeManifest(); return \"ok\"; } catch { return \"error\"; }\r\n}\r\n\r\nfunction checkSigningKey(): \"ok\" | \"unconfigured\" {\r\n if (process.env.Parmana_PRIVATE_KEY) return \"ok\";\r\n if (existsSync(\"./dev-keys/bundle_signing_key\")) return \"ok\";\r\n return \"unconfigured\";\r\n}\r\n\r\nasync function checkAuditDb(db: AuditDb | undefined): Promise<\"ok\" | \"unavailable\" | \"unconfigured\"> {\r\n if (!db) return \"unconfigured\";\r\n try { await db.ping(); return \"ok\"; } catch { return \"unavailable\"; }\r\n}\r\n\r\n// ── Deps ──────────────────────────────────────────────────────────────────────\r\n\r\n/** Runtime dependencies injected into each route handler at registration time. */\r\nexport interface RouteDeps {\r\n /** Signer used to produce attestations in the `/execute` route. */\r\n signer: Signer;\r\n /** Verifier used to check attestation signatures in the `/verify` route. */\r\n verifier: Verifier;\r\n /** Active runtime manifest embedded in every execution result. */\r\n runtimeManifest: RuntimeManifest;\r\n /** Optional audit database client. When present, all decisions and verifications\r\n * are recorded fire-and-forget and audit query routes are registered. */\r\n auditDb?: AuditDb;\r\n}\r\n\r\n// ── Route registration ────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Registers all governance API routes on `app`.\r\n *\r\n * Active routes (fully implemented):\r\n * - `GET /health` — runtime health and version.\r\n * - `POST /execute` — deterministic governance decision with signed attestation.\r\n * - `POST /verify` — independent attestation verification.\r\n *\r\n * Audit routes (registered when `auditDb` is configured):\r\n * - `GET /audit/decisions` — decision timeline (paginated).\r\n * - `GET /audit/decisions/:executionId` — single decision detail.\r\n * - `GET /audit/security` — security event dashboard.\r\n * - `GET /audit/verifications/:executionId` — verification history.\r\n *\r\n * Stub routes (return `501 Not Implemented`):\r\n * - `GET /runtime/manifest` — signed runtime bundle manifest.\r\n * - `GET /runtime/capabilities` — runtime capability declarations.\r\n * - `POST /evaluate` — policy dry-run (no attestation).\r\n * - `POST /simulate` — full pipeline dry-run (no side effects).\r\n */\r\nexport function registerRoutes(\r\n app: FastifyInstance,\r\n deps: RouteDeps,\r\n): void {\r\n const { signer, verifier, runtimeManifest, auditDb } = deps;\r\n\r\n // GET /health ──────────────────────────────────────────────────────────────\r\n\r\n app.get(\"/health\", {\r\n config: { rateLimit: { max: 300, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Health check\",\r\n response: {\r\n 200: {\r\n description: \"Server health status with per-subsystem checks\",\r\n type: \"object\",\r\n properties: {\r\n status: { type: \"string\", enum: [\"ok\", \"degraded\"] },\r\n version: { type: \"string\" },\r\n timestamp: { type: \"string\", format: \"date-time\" },\r\n checks: {\r\n type: \"object\",\r\n properties: {\r\n runtime_manifest: { type: \"string\", enum: [\"ok\", \"error\"] },\r\n signing_key: { type: \"string\", enum: [\"ok\", \"unconfigured\"] },\r\n audit_db: { type: \"string\", enum: [\"ok\", \"unavailable\", \"unconfigured\"] },\r\n },\r\n required: [\"runtime_manifest\", \"signing_key\", \"audit_db\"],\r\n },\r\n },\r\n required: [\"status\", \"version\", \"timestamp\", \"checks\"],\r\n },\r\n },\r\n },\r\n }, async () => {\r\n const checks = {\r\n runtime_manifest: checkRuntime(),\r\n signing_key: checkSigningKey(),\r\n audit_db: await checkAuditDb(auditDb),\r\n };\r\n const degraded = Object.values(checks).some(v => v === \"error\" || v === \"unavailable\");\r\n return {\r\n status: degraded ? \"degraded\" as const : \"ok\" as const,\r\n version: \"1.2.3\",\r\n timestamp: new Date().toISOString(),\r\n checks,\r\n };\r\n });\r\n\r\n // POST /execute ────────────────────────────────────────────────────────────\r\n\r\n registerExecuteRoute(app, { signer, verifier, auditDb });\r\n\r\n // POST /verify ─────────────────────────────────────────────────────────────\r\n\r\n registerVerifyRoute(app, { verifier, runtimeManifest, auditDb });\r\n\r\n // GET /audit/* (only when an audit database is configured) ─────────────────\r\n\r\n if (auditDb) {\r\n registerAuditRoutes(app, auditDb);\r\n }\r\n\r\n // ── 501 stubs ──────────────────────────────────────────────────────────────\r\n\r\n const stub = async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n reply.code(501).send({ error: \"Not implemented\" });\r\n };\r\n\r\n app.get(\"/runtime/manifest\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Runtime bundle manifest\",\r\n description: \"Returns the signed bundle manifest for the active governance runtime.\",\r\n security: [{ bearerAuth: [] }],\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.get(\"/runtime/capabilities\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Runtime\"],\r\n summary: \"Runtime capability declarations\",\r\n description: \"Lists the capabilities supported by this runtime instance.\",\r\n security: [{ bearerAuth: [] }],\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.post(\"/evaluate\", {\r\n bodyLimit: 65536,\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Execution\"],\r\n summary: \"Evaluate a policy without executing\",\r\n description: \"Dry-run policy evaluation — computes a decision without issuing an attestation or consuming a replay slot.\",\r\n security: [{ bearerAuth: [] }],\r\n body: { type: \"object\" },\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n\r\n app.post(\"/simulate\", {\r\n bodyLimit: 65536,\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Execution\"],\r\n summary: \"Simulate a governance decision dry-run\",\r\n description: \"Runs the full execution pipeline in simulation mode — no side effects, no attestation produced.\",\r\n security: [{ bearerAuth: [] }],\r\n body: { type: \"object\" },\r\n response: { 501: { description: \"Not yet implemented\", ...S_NOT_IMPLEMENTED } },\r\n },\r\n }, stub);\r\n}\r\n","import type {\r\n ExecutionAttestation\r\n} from \"@parmanasystems/execution\";\r\nimport type {\r\n\r\n FastifyInstance,\r\n\r\n FastifyRequest,\r\n\r\n FastifyReply,\r\n\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type {\r\n\r\n Signer,\r\n\r\n Verifier,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n\r\n executeFromSignals,\r\n\r\n RedisReplayStore,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport type {\r\n\r\n AuditDb,\r\n\r\n} from \"@parmanasystems/audit-db\";\r\n\r\n// --------------------------------------------------\r\n// Canonical execution response schema\r\n// --------------------------------------------------\r\nconst S_EXECUTION_OUTPUT = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n status: {\r\n type: \"string\"\r\n },\r\n\r\n execution_id: {\r\n type: \"string\"\r\n },\r\n\r\n decision: {\r\n type: \"object\"\r\n },\r\n\r\n execution_state: {\r\n type: \"string\"\r\n },\r\n\r\n requires_override: {\r\n type: \"boolean\"\r\n },\r\n\r\n signature: {\r\n type: \"string\"\r\n },\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n};\r\n\r\nconst S_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n\r\n required: [\r\n \"error\"\r\n ],\r\n};\r\n\r\nconst S_RATE_LIMIT_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n\r\n limit: {\r\n type: \"integer\"\r\n },\r\n\r\n remaining: {\r\n type: \"integer\"\r\n },\r\n\r\n reset: {\r\n\r\n type: \"integer\",\r\n\r\n description:\r\n \"Unix timestamp when the rate limit resets\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"error\",\r\n\r\n \"limit\",\r\n\r\n \"remaining\",\r\n\r\n \"reset\",\r\n ],\r\n};\r\n\r\nexport interface ExecuteRouteDeps {\r\n\r\n signer: Signer;\r\n\r\n verifier: Verifier;\r\n\r\n auditDb?: AuditDb;\r\n}\r\n\r\ninterface ExecuteBody {\r\n\r\n policyId: string;\r\n\r\n policyVersion: string;\r\n\r\n signals: Record<string, unknown>;\r\n}\r\n\r\nexport function registerExecuteRoute(\r\n\r\n app: FastifyInstance,\r\n\r\n deps: ExecuteRouteDeps,\r\n\r\n): void {\r\n\r\n const {\r\n\r\n signer,\r\n\r\n verifier,\r\n\r\n auditDb,\r\n\r\n } = deps;\r\n\r\n // ----------------------------------------------\r\n // Shared replay store\r\n // ----------------------------------------------\r\n const replayStore =\r\n new RedisReplayStore(\r\n \"redis://127.0.0.1:6379\"\r\n );\r\n\r\n app.post<{\r\n Body: ExecuteBody\r\n }>(\r\n \"/execute\",\r\n {\r\n\r\n bodyLimit: 65536,\r\n\r\n config: {\r\n rateLimit: {\r\n max: 100,\r\n timeWindow: \"1 minute\",\r\n },\r\n },\r\n\r\n schema: {\r\n\r\n tags: [\r\n \"Execution\"\r\n ],\r\n\r\n summary:\r\n \"Execute deterministic governance decision\",\r\n\r\n description:\r\n \"Executes deterministic governance evaluation using governed signals and replay-safe execution semantics.\",\r\n\r\n security: [\r\n { bearerAuth: [] }\r\n ],\r\n\r\n body: {\r\n\r\n type: \"object\",\r\n\r\n additionalProperties: false,\r\n\r\n properties: {\r\n\r\n policyId: {\r\n\r\n type: \"string\",\r\n\r\n description:\r\n \"Policy identifier\",\r\n },\r\n\r\n policyVersion: {\r\n\r\n type: \"string\",\r\n\r\n description:\r\n \"Policy version\",\r\n },\r\n\r\n signals: {\r\n\r\n type: \"object\",\r\n\r\n description:\r\n \"Governed deterministic input signals\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"policyId\",\r\n\r\n \"policyVersion\",\r\n\r\n \"signals\",\r\n ],\r\n },\r\n\r\n response: {\r\n\r\n 200: {\r\n\r\n description:\r\n \"Deterministic execution result\",\r\n\r\n ...S_EXECUTION_OUTPUT,\r\n },\r\n\r\n 400: {\r\n\r\n description:\r\n \"Invalid request body\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 413: {\r\n\r\n description:\r\n \"Request body too large\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 422: {\r\n\r\n description:\r\n \"Execution failure\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 429: {\r\n\r\n description:\r\n \"Rate limit exceeded\",\r\n\r\n ...S_RATE_LIMIT_ERROR,\r\n },\r\n },\r\n },\r\n },\r\n\r\n async (\r\n req: FastifyRequest<{\r\n Body: ExecuteBody\r\n }>,\r\n\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n\r\n const {\r\n\r\n policyId,\r\n\r\n policyVersion,\r\n\r\n signals,\r\n\r\n } = req.body;\r\n\r\n try {\r\n\r\n const execution =\r\n await executeFromSignals(\r\n\r\n {\r\n policyId,\r\n\r\n policyVersion,\r\n\r\n signals,\r\n },\r\n\r\n signer,\r\n\r\n verifier,\r\n\r\n replayStore\r\n );\r\n\r\n if (\r\n \"attestation\" in execution &&\r\n execution.attestation\r\n) {\r\n\r\n auditDb?.recordDecision(\r\n execution.attestation as ExecutionAttestation\r\n );\r\n}\r\n\r\n req.log.info(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n policyId,\r\n\r\n policyVersion,\r\n },\r\n\r\n \"execute:success\"\r\n );\r\n\r\n reply.send(\r\n execution\r\n );\r\n\r\n } catch (err) {\r\n\r\n req.log.warn(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n error:\r\n (err as Error).message,\r\n },\r\n\r\n \"execute:failure\"\r\n );\r\n\r\n reply.code(422).send({\r\n\r\n error:\r\n (err as Error).message,\r\n });\r\n }\r\n }\r\n );\r\n}","import type {\r\n FastifyInstance,\r\n FastifyRequest,\r\n FastifyReply\r\n} from \"fastify\";\r\n\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type {\r\n\r\n Verifier,\r\n\r\n RuntimeManifest,\r\n\r\n ExecutionAttestation,\r\n\r\n} from \"@parmanasystems/execution\";\r\n\r\nimport {\r\n\r\n verifyAttestation,\r\n\r\n} from \"@parmanasystems/verifier\";\r\n\r\nimport type {\r\n\r\n AuditDb,\r\n\r\n} from \"@parmanasystems/audit-db\";\r\n\r\n// --------------------------------------------------\r\n// Canonical flattened attestation schema\r\n// --------------------------------------------------\r\nconst S_ATTESTATION = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n execution_id: {\r\n type: \"string\"\r\n },\r\n\r\n decision: {\r\n type: \"object\"\r\n },\r\n\r\n execution_state: {\r\n type: \"string\"\r\n },\r\n\r\n runtime_hash: {\r\n type: \"string\"\r\n },\r\n\r\n signature: {\r\n type: \"string\",\r\n\r\n description:\r\n \"Base64 Ed25519 signature over the canonical attestation payload\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"execution_id\",\r\n\r\n \"decision\",\r\n\r\n \"execution_state\",\r\n\r\n \"runtime_hash\",\r\n\r\n \"signature\",\r\n ],\r\n};\r\n\r\nconst S_VERIFICATION_RESULT = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n valid: {\r\n type: \"boolean\"\r\n },\r\n\r\n checks: {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n signature_verified: {\r\n type: \"boolean\"\r\n },\r\n\r\n runtime_verified: {\r\n type: \"boolean\"\r\n },\r\n\r\n schema_compatible: {\r\n type: \"boolean\"\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"signature_verified\",\r\n\r\n \"runtime_verified\",\r\n\r\n \"schema_compatible\",\r\n ],\r\n },\r\n },\r\n\r\n required: [\r\n \"valid\",\r\n \"checks\",\r\n ],\r\n};\r\n\r\nconst S_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n error: {\r\n type: \"string\"\r\n },\r\n },\r\n\r\n required: [\r\n \"error\"\r\n ],\r\n};\r\n\r\nconst S_RATE_LIMIT_ERROR = {\r\n\r\n type: \"object\",\r\n\r\n properties: {\r\n\r\n error: {\r\n type: \"string\"\r\n },\r\n\r\n limit: {\r\n type: \"integer\"\r\n },\r\n\r\n remaining: {\r\n type: \"integer\"\r\n },\r\n\r\n reset: {\r\n\r\n type: \"integer\",\r\n\r\n description:\r\n \"Unix timestamp when the rate limit resets\",\r\n },\r\n },\r\n\r\n required: [\r\n\r\n \"error\",\r\n\r\n \"limit\",\r\n\r\n \"remaining\",\r\n\r\n \"reset\",\r\n ],\r\n};\r\n\r\nexport interface VerifyRouteDeps {\r\n\r\n verifier: Verifier;\r\n\r\n runtimeManifest:\r\n RuntimeManifest;\r\n\r\n auditDb?: AuditDb;\r\n}\r\n\r\nexport function registerVerifyRoute(\r\n\r\n app: FastifyInstance,\r\n\r\n deps: VerifyRouteDeps,\r\n\r\n): void {\r\n\r\n const {\r\n\r\n verifier,\r\n\r\n runtimeManifest,\r\n\r\n auditDb,\r\n\r\n } = deps;\r\n\r\n app.post<{\r\n Body: ExecutionAttestation\r\n }>(\r\n \"/verify\",\r\n {\r\n\r\n bodyLimit: 65536,\r\n\r\n config: {\r\n rateLimit: {\r\n max: 200,\r\n timeWindow: \"1 minute\",\r\n },\r\n },\r\n\r\n schema: {\r\n\r\n tags: [\r\n \"Verification\"\r\n ],\r\n\r\n summary:\r\n \"Verify an execution attestation\",\r\n\r\n description:\r\n \"Checks the cryptographic signature and runtime provenance of a deterministic execution attestation.\",\r\n\r\n security: [\r\n { bearerAuth: [] }\r\n ],\r\n\r\n body: {\r\n\r\n ...S_ATTESTATION,\r\n\r\n additionalProperties: false,\r\n\r\n description:\r\n \"Canonical flattened ExecutionAttestation\",\r\n },\r\n\r\n response: {\r\n\r\n 200: {\r\n\r\n description:\r\n \"Verification result with per-check breakdown\",\r\n\r\n ...S_VERIFICATION_RESULT,\r\n },\r\n\r\n 400: {\r\n\r\n description:\r\n \"Malformed attestation body\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 413: {\r\n\r\n description:\r\n \"Request body too large\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 422: {\r\n\r\n description:\r\n \"Verification threw an unexpected error\",\r\n\r\n ...S_ERROR,\r\n },\r\n\r\n 429: {\r\n\r\n description:\r\n \"Rate limit exceeded\",\r\n\r\n ...S_RATE_LIMIT_ERROR,\r\n },\r\n },\r\n },\r\n },\r\n\r\n async (\r\n req: FastifyRequest<{\r\n Body: ExecutionAttestation\r\n }>,\r\n\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n\r\n const body =\r\n req.body;\r\n\r\n // --------------------------------------------\r\n // Flattened attestation validation\r\n // --------------------------------------------\r\n if (\r\n\r\n typeof body?.execution_id !==\r\n \"string\" ||\r\n\r\n typeof body?.signature !==\r\n \"string\"\r\n ) {\r\n\r\n reply.code(400).send({\r\n\r\n error:\r\n \"Body must be a valid ExecutionAttestation\",\r\n });\r\n\r\n return;\r\n }\r\n\r\n try {\r\n\r\n const result =\r\n verifyAttestation(\r\n body,\r\n verifier,\r\n runtimeManifest\r\n );\r\n\r\n auditDb?.recordVerification(\r\n body.execution_id,\r\n result\r\n );\r\n\r\n req.log.info(\r\n {\r\n reqId:\r\n req.id,\r\n\r\n valid:\r\n result.valid,\r\n\r\n checks:\r\n result.checks,\r\n },\r\n\r\n \"verify:success\"\r\n );\r\n\r\n reply.send(result);\r\n\r\n } catch (err) {\r\n\r\n reply.code(422).send({\r\n\r\n error:\r\n (err as Error).message,\r\n });\r\n }\r\n }\r\n );\r\n}\r\n","import type { FastifyInstance, FastifyRequest, FastifyReply } from \"fastify\";\r\nimport type {} from \"@fastify/swagger\";\r\n\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nconst S_ERROR = {\r\n type: \"object\",\r\n properties: { error: { type: \"string\" } },\r\n required: [\"error\"],\r\n};\r\n\r\nexport function registerAuditRoutes(\r\n app: FastifyInstance,\r\n auditDb: AuditDb,\r\n): void {\r\n\r\n // GET /audit/decisions?limit=50&offset=0&policy_id=...&decision=...&from=...&to=...\r\n app.get<{\r\n Querystring: {\r\n limit?: number;\r\n offset?: number;\r\n policy_id?: string;\r\n decision?: \"approve\" | \"deny\" | \"any\";\r\n from?: string;\r\n to?: string;\r\n };\r\n }>(\"/audit/decisions\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Decision timeline\",\r\n description:\r\n \"Returns a paginated, filtered list of governance decisions joined with their \" +\r\n \"latest verification status. Ordered by executed_at descending.\",\r\n security: [{ bearerAuth: [] }],\r\n querystring: {\r\n type: \"object\",\r\n properties: {\r\n limit: { type: \"integer\", minimum: 1, maximum: 1000, default: 50,\r\n description: \"Max rows (default 50, max 1000)\" },\r\n offset: { type: \"integer\", minimum: 0, default: 0,\r\n description: \"Row offset for pagination (default 0)\" },\r\n policy_id: { type: \"string\", maxLength: 200,\r\n description: \"Filter by exact policy_id\" },\r\n decision: { type: \"string\", enum: [\"approve\", \"deny\", \"any\"],\r\n description: \"Filter by decision value; 'any' returns all\" },\r\n from: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 lower bound on executed_at (inclusive)\" },\r\n to: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 upper bound on executed_at (inclusive)\" },\r\n },\r\n },\r\n response: {\r\n 200: { description: \"Decision timeline rows\", type: \"array\", items: { type: \"object\" } },\r\n 400: { description: \"Invalid query parameters\", ...S_ERROR },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (req, reply: FastifyReply): Promise<void> => {\r\n const { limit, offset: _offset, policy_id, decision, from, to } = req.query;\r\n const parsedLimit = parseInt(String(limit ?? 50), 10);\r\n const normalizedDecision = decision === \"any\" ? undefined : decision;\r\n try {\r\n reply.send(await auditDb.getDecisionTimeline(parsedLimit, {\r\n policy_id: policy_id || undefined,\r\n decision: normalizedDecision,\r\n from_date: from || undefined,\r\n to_date: to || undefined,\r\n }));\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/decisions/:executionId\r\n app.get<{ Params: { executionId: string } }>(\"/audit/decisions/:executionId\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Decision detail\",\r\n description: \"Returns the full audit record for a single governance decision, including the stored attestation JSONB.\",\r\n security: [{ bearerAuth: [] }],\r\n params: {\r\n type: \"object\",\r\n properties: { executionId: { type: \"string\", minLength: 1, maxLength: 200 } },\r\n required: [\"executionId\"],\r\n },\r\n response: {\r\n 200: { description: \"Audit decision record\", type: \"object\" },\r\n 400: { description: \"Invalid path parameters\", ...S_ERROR },\r\n 404: S_ERROR,\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (\r\n req: FastifyRequest<{ Params: { executionId: string } }>,\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n try {\r\n const decision = await auditDb.getDecisionById(req.params.executionId);\r\n if (!decision) {\r\n reply.code(404).send({ error: \"Decision not found\" });\r\n return;\r\n }\r\n reply.send(decision);\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/security?from=...&to=...&limit=50\r\n app.get<{\r\n Querystring: {\r\n from?: string;\r\n to?: string;\r\n limit?: number;\r\n };\r\n }>(\"/audit/security\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Security dashboard\",\r\n description:\r\n \"Returns aggregated security event counts grouped by event_type and severity, \" +\r\n \"ordered by event_count descending.\",\r\n security: [{ bearerAuth: [] }],\r\n querystring: {\r\n type: \"object\",\r\n properties: {\r\n from: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 lower bound on occurred_at (inclusive)\" },\r\n to: { type: \"string\", format: \"date-time\",\r\n description: \"ISO 8601 upper bound on occurred_at (inclusive)\" },\r\n limit: { type: \"integer\", minimum: 1, maximum: 1000, default: 50,\r\n description: \"Max rows (default 50, max 1000)\" },\r\n },\r\n },\r\n response: {\r\n 200: { description: \"Security event summary\", type: \"array\", items: { type: \"object\" } },\r\n 400: { description: \"Invalid query parameters\", ...S_ERROR },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getSecurityDashboard());\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/stats\r\n app.get(\"/audit/stats\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Audit statistics\",\r\n description:\r\n \"Returns aggregate counts across all audit tables: total decisions, decisions today, \" +\r\n \"verifications (valid/invalid), security events, and API access calls.\",\r\n security: [{ bearerAuth: [] }],\r\n response: {\r\n 200: { description: \"Aggregate audit statistics\", type: \"object\" },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (_req: FastifyRequest, reply: FastifyReply): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getStats());\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n\r\n // GET /audit/verifications/:executionId\r\n app.get<{ Params: { executionId: string } }>(\"/audit/verifications/:executionId\", {\r\n config: { rateLimit: { max: 60, timeWindow: \"1 minute\" } },\r\n schema: {\r\n tags: [\"Audit\"],\r\n summary: \"Verification history\",\r\n description: \"Returns all verification attempts for a given execution ID, newest first.\",\r\n security: [{ bearerAuth: [] }],\r\n params: {\r\n type: \"object\",\r\n properties: { executionId: { type: \"string\", format: \"uuid\" } },\r\n required: [\"executionId\"],\r\n },\r\n response: {\r\n 200: { description: \"Verification records\", type: \"array\", items: { type: \"object\" } },\r\n 500: S_ERROR,\r\n },\r\n },\r\n }, async (\r\n req: FastifyRequest<{ Params: { executionId: string } }>,\r\n reply: FastifyReply,\r\n ): Promise<void> => {\r\n try {\r\n reply.send(await auditDb.getVerificationsByExecution(req.params.executionId));\r\n } catch (err) {\r\n reply.code(500).send({ error: (err as Error).message });\r\n }\r\n });\r\n}\r\n","import type { FastifyRequest, FastifyReply } from \"fastify\";\r\nimport type { AuditDb } from \"@parmanasystems/audit-db\";\r\n\r\nexport function createAuditMiddleware(auditDb: AuditDb) {\r\n return async function onResponse(\r\n req: FastifyRequest,\r\n reply: FastifyReply,\r\n ): Promise<void> {\r\n auditDb.recordApiAccess({\r\n method: req.method,\r\n path: req.url,\r\n status_code: reply.statusCode,\r\n response_time_ms: Number.isFinite(reply.elapsedTime)\r\n ? Math.round(reply.elapsedTime)\r\n : undefined,\r\n ip_address: req.ip,\r\n user_agent: req.headers[\"user-agent\"],\r\n });\r\n\r\n if (reply.statusCode === 401) {\r\n auditDb.recordSecurityEvent({\r\n event_type: \"auth_failure\",\r\n severity: \"medium\",\r\n ip_address: req.ip,\r\n path: req.url,\r\n method: req.method,\r\n user_agent: req.headers[\"user-agent\"],\r\n details: { status_code: 401 },\r\n });\r\n }\r\n };\r\n}\r\n","import { createServer } from \"./server.js\";\r\nimport { signingKeySource } from \"./runtime.js\";\r\n\r\nconst port = parseInt(process.env.PORT ?? \"3000\", 10);\r\nconst host = process.env.HOST ?? \"0.0.0.0\";\r\n\r\nconst { app, auditDb } = createServer();\r\n\r\nasync function shutdown(signal: string): Promise<void> {\r\n app.log.info(`Shutdown signal received (${signal}), closing server...`);\r\n\r\n const shutdownTimeout = setTimeout(() => {\r\n app.log.error(\"Graceful shutdown timed out, forcing exit\");\r\n process.exit(1);\r\n }, 10000);\r\n\r\n shutdownTimeout.unref();\r\n\r\n try {\r\n await app.close();\r\n\r\n if (auditDb) {\r\n await auditDb.disconnect();\r\n }\r\n\r\n clearTimeout(shutdownTimeout);\r\n\r\n app.log.info(\"Server closed cleanly\");\r\n\r\n process.exit(0);\r\n\r\n } catch (err) {\r\n app.log.error({ err }, \"Error during shutdown\");\r\n\r\n process.exit(1);\r\n }\r\n}\r\n\r\nprocess.on(\"SIGTERM\", () => {\r\n void shutdown(\"SIGTERM\");\r\n});\r\n\r\nprocess.on(\"SIGINT\", () => {\r\n void shutdown(\"SIGINT\");\r\n});\r\n\r\nexport async function startServer(): Promise<void> {\r\n try {\r\n await app.listen({ port, host });\r\n\r\n app.log.info(`Server listening on http://${host}:${port}`);\r\n\r\n if (auditDb) {\r\n app.log.info(\"Audit DB connected\");\r\n } else {\r\n app.log.info(\"Audit DB not configured\");\r\n }\r\n\r\n const keyMsg: Record<typeof signingKeySource, string> = {\r\n env: \"Signing key loaded from env\",\r\n disk: \"Signing key loaded from disk\",\r\n ephemeral: \"Using ephemeral signing key\",\r\n };\r\n\r\n app.log.info(keyMsg[signingKeySource]);\r\n\r\n } catch (err) {\r\n app.log.error(err);\r\n\r\n process.exit(1);\r\n }\r\n}\r\n\r\nexport { app };\r\n"],"mappings":";AAAA,OAAO,aAAuC;AAC9C,SAAS,YAAY,kBAAkB;AACvC,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,YAAY;;;ACJnB,YAAY,YAAY;AAExB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAUP,SAAS,iBAAsF;AAC7F,MAAI,QAAQ,IAAI,uBAAuB,QAAQ,IAAI,oBAAoB;AACrE,WAAO;AAAA,MACL,YAAY,QAAQ,IAAI;AAAA,MACxB,WAAW,QAAQ,IAAI;AAAA,MACvB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI;AACF,WAAO;AAAA,MACL,YAAY,eAAe;AAAA,MAC3B,WAAW,cAAc;AAAA,MACzB,QAAQ;AAAA,IACV;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,EAAE,YAAY,UAAU,IAAW,2BAAoB,WAAW;AAAA,IACtE,oBAAoB,EAAE,MAAM,SAAS,QAAQ,MAAM;AAAA,IACnD,mBAAmB,EAAE,MAAM,QAAQ,QAAQ,MAAM;AAAA,EACnD,CAAC;AAED,SAAO,EAAE,YAAY,WAAW,QAAQ,YAAY;AACtD;AAEA,IAAM,OAAO,eAAe;AAErB,IAAM,mBAAqC,KAAK;AAChD,IAAM,SAAS,IAAI,YAAY,KAAK,UAAU;AAC9C,IAAM,WAAW,IAAI,cAAc,KAAK,SAAS;AACjD,IAAM,kBAAkB,mBAAmB;;;ACzClD,eAAsB,SACpB,KACA,OACe;AACf,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,OAAQ;AAEb,QAAM,OAAO,IAAI,QAAQ;AACzB,MAAI,SAAS,UAAU,MAAM,IAAI;AAC/B,QAAI,IAAI,KAAK,EAAE,OAAO,IAAI,IAAI,QAAQ,eAAe,GAAG,cAAc;AACtE,UAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,EAChD;AACF;;;AChBA,SAAS,sBAAAA,2BAA4E;AACrF,SAAS,kBAAkB;;;ACc3B;AAAA,EAEE;AAAA,EAEA;AAAA,OAEK;AAWP,IAAM,qBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,QAAQ;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IAEA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IAEA,mBAAmB;AAAA,MACjB,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAM,UAAU;AAAA,EAEd,MAAM;AAAA,EAEN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAM,qBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MAEL,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAoBO,SAAS,qBAEdC,MAEA,MAEM;AAEN,QAAM;AAAA,IAEJ,QAAAC;AAAA,IAEA,UAAAC;AAAA,IAEA,SAAAC;AAAA,EAEF,IAAI;AAKJ,QAAM,cACJ,IAAI;AAAA,IACF;AAAA,EACF;AAEF,EAAAH,KAAI;AAAA,IAGF;AAAA,IACA;AAAA,MAEE,WAAW;AAAA,MAEX,QAAQ;AAAA,QACN,WAAW;AAAA,UACT,KAAK;AAAA,UACL,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MAEA,QAAQ;AAAA,QAEN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,QAEA,SACE;AAAA,QAEF,aACE;AAAA,QAEF,UAAU;AAAA,UACR,EAAE,YAAY,CAAC,EAAE;AAAA,QACnB;AAAA,QAEA,MAAM;AAAA,UAEJ,MAAM;AAAA,UAEN,sBAAsB;AAAA,UAEtB,YAAY;AAAA,YAEV,UAAU;AAAA,cAER,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,YAEA,eAAe;AAAA,cAEb,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,YAEA,SAAS;AAAA,cAEP,MAAM;AAAA,cAEN,aACE;AAAA,YACJ;AAAA,UACF;AAAA,UAEA,UAAU;AAAA,YAER;AAAA,YAEA;AAAA,YAEA;AAAA,UACF;AAAA,QACF;AAAA,QAEA,UAAU;AAAA,UAER,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OACE,KAIA,UACkB;AAElB,YAAM;AAAA,QAEJ;AAAA,QAEA;AAAA,QAEA;AAAA,MAEF,IAAI,IAAI;AAER,UAAI;AAEF,cAAM,YACJ,MAAM;AAAA,UAEJ;AAAA,YACE;AAAA,YAEA;AAAA,YAEA;AAAA,UACF;AAAA,UAEAC;AAAA,UAEAC;AAAA,UAEA;AAAA,QACF;AAEF,YACN,iBAAiB,aACjB,UAAU,aACV;AAEA,UAAAC,UAAS;AAAA,YACP,UAAU;AAAA,UACZ;AAAA,QACF;AAEQ,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN;AAAA,YAEA;AAAA,UACF;AAAA,UAEA;AAAA,QACF;AAEA,cAAM;AAAA,UACJ;AAAA,QACF;AAAA,MAEF,SAAS,KAAK;AAEZ,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN,OACG,IAAc;AAAA,UACnB;AAAA,UAEA;AAAA,QACF;AAEA,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACG,IAAc;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;AC1WA;AAAA,EAEE;AAAA,OAEK;AAWP,IAAM,gBAAgB;AAAA,EAEpB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IAEA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAEA,IAAM,wBAAwB;AAAA,EAE5B,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,QAAQ;AAAA,MAEN,MAAM;AAAA,MAEN,YAAY;AAAA,QAEV,oBAAoB;AAAA,UAClB,MAAM;AAAA,QACR;AAAA,QAEA,kBAAkB;AAAA,UAChB,MAAM;AAAA,QACR;AAAA,QAEA,mBAAmB;AAAA,UACjB,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,UAAU;AAAA,QAER;AAAA,QAEA;AAAA,QAEA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAMC,WAAU;AAAA,EAEd,MAAM;AAAA,EAEN,YAAY;AAAA,IACV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAMC,sBAAqB;AAAA,EAEzB,MAAM;AAAA,EAEN,YAAY;AAAA,IAEV,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA,IACR;AAAA,IAEA,OAAO;AAAA,MAEL,MAAM;AAAA,MAEN,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IAER;AAAA,IAEA;AAAA,IAEA;AAAA,IAEA;AAAA,EACF;AACF;AAYO,SAAS,oBAEdC,MAEA,MAEM;AAEN,QAAM;AAAA,IAEJ,UAAAC;AAAA,IAEA,iBAAAC;AAAA,IAEA,SAAAC;AAAA,EAEF,IAAI;AAEJ,EAAAH,KAAI;AAAA,IAGF;AAAA,IACA;AAAA,MAEE,WAAW;AAAA,MAEX,QAAQ;AAAA,QACN,WAAW;AAAA,UACT,KAAK;AAAA,UACL,YAAY;AAAA,QACd;AAAA,MACF;AAAA,MAEA,QAAQ;AAAA,QAEN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,QAEA,SACE;AAAA,QAEF,aACE;AAAA,QAEF,UAAU;AAAA,UACR,EAAE,YAAY,CAAC,EAAE;AAAA,QACnB;AAAA,QAEA,MAAM;AAAA,UAEJ,GAAG;AAAA,UAEH,sBAAsB;AAAA,UAEtB,aACE;AAAA,QACJ;AAAA,QAEA,UAAU;AAAA,UAER,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAG;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGF;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGA;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGA;AAAA,UACL;AAAA,UAEA,KAAK;AAAA,YAEH,aACE;AAAA,YAEF,GAAGC;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OACE,KAIA,UACkB;AAElB,YAAM,OACJ,IAAI;AAKN,UAEE,OAAO,MAAM,iBACX,YAEF,OAAO,MAAM,cACX,UACF;AAEA,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACE;AAAA,QACJ,CAAC;AAED;AAAA,MACF;AAEA,UAAI;AAEF,cAAM,SACJ;AAAA,UACE;AAAA,UACAE;AAAA,UACAC;AAAA,QACF;AAEF,QAAAC,UAAS;AAAA,UACP,KAAK;AAAA,UACL;AAAA,QACF;AAEA,YAAI,IAAI;AAAA,UACN;AAAA,YACE,OACE,IAAI;AAAA,YAEN,OACE,OAAO;AAAA,YAET,QACE,OAAO;AAAA,UACX;AAAA,UAEA;AAAA,QACF;AAEA,cAAM,KAAK,MAAM;AAAA,MAEnB,SAAS,KAAK;AAEZ,cAAM,KAAK,GAAG,EAAE,KAAK;AAAA,UAEnB,OACG,IAAc;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;ACvWA,IAAMC,WAAU;AAAA,EACd,MAAM;AAAA,EACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,EACxC,UAAU,CAAC,OAAO;AACpB;AAEO,SAAS,oBACdC,MACAC,UACM;AAGN,EAAAD,KAAI,IASD,oBAAoB;AAAA,IACrB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAW;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YAAM,SAAS;AAAA,YACrD,aAAa;AAAA,UAAkC;AAAA,UAC5D,QAAW;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YACtC,aAAa;AAAA,UAAwC;AAAA,UAClE,WAAW;AAAA,YAAE,MAAM;AAAA,YAAU,WAAW;AAAA,YAC3B,aAAa;AAAA,UAA4B;AAAA,UACtD,UAAW;AAAA,YAAE,MAAM;AAAA,YAAU,MAAM,CAAC,WAAW,QAAQ,KAAK;AAAA,YAC/C,aAAa;AAAA,UAA8C;AAAA,UACxE,MAAW;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UAC5E,IAAW;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,QAC9E;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,0BAA0B,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACvF,KAAK,EAAE,aAAa,4BAA4B,GAAGD,SAAQ;AAAA,QAC3D,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,KAAK,UAAuC;AACpD,UAAM,EAAE,OAAO,QAAQ,SAAS,WAAW,UAAU,MAAM,GAAG,IAAI,IAAI;AACtE,UAAM,cAAc,SAAS,OAAO,SAAS,EAAE,GAAG,EAAE;AACpD,UAAM,qBAAqB,aAAa,QAAQ,SAAY;AAC5D,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,oBAAoB,aAAa;AAAA,QACxD,WAAW,aAAa;AAAA,QACxB,UAAW;AAAA,QACX,WAAW,QAAQ;AAAA,QACnB,SAAW,MAAQ;AAAA,MACrB,CAAC,CAAC;AAAA,IACJ,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAyC,iCAAiC;AAAA,IAC5E,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,WAAW,GAAG,WAAW,IAAI,EAAE;AAAA,QAC5E,UAAU,CAAC,aAAa;AAAA,MAC1B;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,yBAAyB,MAAM,SAAS;AAAA,QAC5D,KAAK,EAAE,aAAa,2BAA2B,GAAGD,SAAQ;AAAA,QAC1D,KAAKA;AAAA,QACL,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OACD,KACA,UACkB;AAClB,QAAI;AACF,YAAM,WAAW,MAAME,SAAQ,gBAAgB,IAAI,OAAO,WAAW;AACrE,UAAI,CAAC,UAAU;AACb,cAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC;AACpD;AAAA,MACF;AACA,YAAM,KAAK,QAAQ;AAAA,IACrB,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAMD,mBAAmB;AAAA,IACpB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,aAAa;AAAA,QACX,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAO;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UACxE,IAAO;AAAA,YAAE,MAAM;AAAA,YAAU,QAAQ;AAAA,YACxB,aAAa;AAAA,UAAkD;AAAA,UACxE,OAAO;AAAA,YAAE,MAAM;AAAA,YAAW,SAAS;AAAA,YAAG,SAAS;AAAA,YAAM,SAAS;AAAA,YACrD,aAAa;AAAA,UAAkC;AAAA,QAC1D;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,0BAA0B,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACvF,KAAK,EAAE,aAAa,4BAA4B,GAAGD,SAAQ;AAAA,QAC3D,KAAKA;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,MAAsB,UAAuC;AACrE,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,qBAAqB,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAI,gBAAgB;AAAA,IACtB,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aACE;AAAA,MAEF,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,8BAA8B,MAAM,SAAS;AAAA,QACjE,KAAKD;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OAAO,MAAsB,UAAuC;AACrE,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,SAAS,CAAC;AAAA,IACrC,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,EAAAD,KAAI,IAAyC,qCAAqC;AAAA,IAChF,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,OAAO;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,QAAQ,OAAO,EAAE;AAAA,QAC9D,UAAU,CAAC,aAAa;AAAA,MAC1B;AAAA,MACA,UAAU;AAAA,QACR,KAAK,EAAE,aAAa,wBAAwB,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,QACrF,KAAKD;AAAA,MACP;AAAA,IACF;AAAA,EACF,GAAG,OACD,KACA,UACkB;AAClB,QAAI;AACF,YAAM,KAAK,MAAME,SAAQ,4BAA4B,IAAI,OAAO,WAAW,CAAC;AAAA,IAC9E,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AACH;;;AHvLA,IAAMC,WAAU;AAAA,EACd,MAAM;AAAA,EACN,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,EACxC,UAAU,CAAC,OAAO;AACpB;AAEA,IAAM,oBAAoB;AAAA,EACxB,GAAGA;AAAA,EACH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,MAAM,CAAC,iBAAiB,EAAE,EAAE;AACrE;AAIA,SAAS,eAA+B;AACtC,MAAI;AAAE,IAAAC,oBAAmB;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAS;AACrE;AAEA,SAAS,kBAAyC;AAChD,MAAI,QAAQ,IAAI,oBAAqB,QAAO;AAC5C,MAAI,WAAW,+BAA+B,EAAG,QAAO;AACxD,SAAO;AACT;AAEA,eAAe,aAAa,IAAyE;AACnG,MAAI,CAAC,GAAI,QAAO;AAChB,MAAI;AAAE,UAAM,GAAG,KAAK;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAe;AACtE;AAuCO,SAAS,eACdC,MACA,MACM;AACN,QAAM,EAAE,QAAAC,SAAQ,UAAAC,WAAU,iBAAAC,kBAAiB,SAAAC,SAAQ,IAAI;AAIvD,EAAAJ,KAAI,IAAI,WAAW;AAAA,IACjB,QAAQ,EAAE,WAAW,EAAE,KAAK,KAAK,YAAY,WAAW,EAAE;AAAA,IAC1D,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,QACR,KAAK;AAAA,UACH,aAAa;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,YACV,QAAW,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,UAAU,EAAE;AAAA,YACtD,SAAW,EAAE,MAAM,SAAS;AAAA,YAC5B,WAAW,EAAE,MAAM,UAAU,QAAQ,YAAY;AAAA,YACjD,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,YAAY;AAAA,gBACV,kBAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,OAAO,EAAE;AAAA,gBAC1D,aAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,cAAc,EAAE;AAAA,gBACjE,UAAkB,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,eAAe,cAAc,EAAE;AAAA,cAClF;AAAA,cACA,UAAU,CAAC,oBAAoB,eAAe,UAAU;AAAA,YAC1D;AAAA,UACF;AAAA,UACA,UAAU,CAAC,UAAU,WAAW,aAAa,QAAQ;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,YAAY;AACb,UAAM,SAAS;AAAA,MACb,kBAAkB,aAAa;AAAA,MAC/B,aAAkB,gBAAgB;AAAA,MAClC,UAAkB,MAAM,aAAaI,QAAO;AAAA,IAC9C;AACA,UAAM,WAAW,OAAO,OAAO,MAAM,EAAE,KAAK,OAAK,MAAM,WAAW,MAAM,aAAa;AACrF,WAAO;AAAA,MACL,QAAW,WAAW,aAAsB;AAAA,MAC5C,SAAW;AAAA,MACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAC;AAID,uBAAqBJ,MAAK,EAAE,QAAAC,SAAQ,UAAAC,WAAU,SAAAE,SAAQ,CAAC;AAIvD,sBAAoBJ,MAAK,EAAE,UAAAE,WAAU,iBAAAC,kBAAiB,SAAAC,SAAQ,CAAC;AAI/D,MAAIA,UAAS;AACX,wBAAoBJ,MAAKI,QAAO;AAAA,EAClC;AAIA,QAAM,OAAO,OAAO,MAAsB,UAAuC;AAC/E,UAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,EACnD;AAEA,EAAAJ,KAAI,IAAI,qBAAqB;AAAA,IAC3B,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,IAAI,yBAAyB;AAAA,IAC/B,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,SAAS;AAAA,MAChB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,KAAK,aAAa;AAAA,IACpB,WAAW;AAAA,IACX,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,WAAW;AAAA,MAClB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AAEP,EAAAA,KAAI,KAAK,aAAa;AAAA,IACpB,WAAW;AAAA,IACX,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,YAAY,WAAW,EAAE;AAAA,IACzD,QAAQ;AAAA,MACN,MAAM,CAAC,WAAW;AAAA,MAClB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MAC7B,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB,UAAU,EAAE,KAAK,EAAE,aAAa,uBAAuB,GAAG,kBAAkB,EAAE;AAAA,IAChF;AAAA,EACF,GAAG,IAAI;AACT;;;AHhMA,SAAS,eAAe;;;AONjB,SAAS,sBAAsBK,UAAkB;AACtD,SAAO,eAAe,WACpB,KACA,OACe;AACf,IAAAA,SAAQ,gBAAgB;AAAA,MACtB,QAAiB,IAAI;AAAA,MACrB,MAAiB,IAAI;AAAA,MACrB,aAAiB,MAAM;AAAA,MACvB,kBAAkB,OAAO,SAAS,MAAM,WAAW,IAC/C,KAAK,MAAM,MAAM,WAAW,IAC5B;AAAA,MACJ,YAAY,IAAI;AAAA,MAChB,YAAY,IAAI,QAAQ,YAAY;AAAA,IACtC,CAAC;AAED,QAAI,MAAM,eAAe,KAAK;AAC5B,MAAAA,SAAQ,oBAAoB;AAAA,QAC1B,YAAY;AAAA,QACZ,UAAY;AAAA,QACZ,YAAY,IAAI;AAAA,QAChB,MAAY,IAAI;AAAA,QAChB,QAAY,IAAI;AAAA,QAChB,YAAY,IAAI,QAAQ,YAAY;AAAA,QACpC,SAAY,EAAE,aAAa,IAAI;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;APCO,SAAS,eAA+B;AAC7C,QAAMC,OAAM,QAAQ;AAAA,IAClB,WAAW;AAAA;AAAA,IACX,QAAQ;AAAA,MACN,OAAO,QAAQ,IAAI,cAAc,QAAQ,IAAI,aAAa,eAAe,SAAS;AAAA,MAClF,QAAQ;AAAA,QACN,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,MACA,aAAa;AAAA,QACX,IAAI,KAAK;AACP,gBAAM,MAAM,IAAI,QAAQ,iBAAiB;AACzC,iBAAO;AAAA,YACL,QAAQ,IAAI;AAAA,YACZ,KAAK,IAAI;AAAA,YACT,OAAO,IAAI;AAAA,YACX,gBAAgB,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,QAAQ,IAAI,QAAQ;AAAA,UACpE;AAAA,QACF;AAAA,QACA,IAAI,KAAK;AACP,iBAAO;AAAA,YACL,YAAY,IAAI;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,CAAC,QACR,IAAI,QAAQ,cAAc,KAA4B,WAAW;AAAA,EACtE,CAAC;AAED,QAAM,gBAAgB,QAAQ,IAAI;AAClC,QAAM,aACJ,kBAAkB,MAAM,OACxB,gBAAwB,cAAc,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC,IAC1C,CAAC,yBAAyB,uBAAuB;AAE3E,EAAAA,KAAI,SAAS,MAAM;AAAA,IACjB,QAAgB;AAAA,IAChB,SAAgB,CAAC,OAAO,MAAM;AAAA,IAC9B,gBAAgB,CAAC,gBAAgB,iBAAiB,cAAc;AAAA,IAChE,gBAAgB,CAAC,gBAAgB,qBAAqB,yBAAyB,mBAAmB;AAAA,IAClG,aAAgB;AAAA,IAChB,QAAgB;AAAA,EAClB,CAAC;AAED,EAAAA,KAAI,SAAS,QAAQ;AAAA,IACnB,uBAAuB;AAAA,MACrB,YAAY;AAAA,QACV,YAAY,CAAC,QAAQ;AAAA,QACrB,gBAAgB,CAAC,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA,IAC3B,2BAA2B,EAAE,QAAQ,eAAe;AAAA,IACpD,oBAAoB,EAAE,OAAO,MAAM;AAAA,IACnC,YAAY,EAAE,QAAQ,OAAO;AAAA,IAC7B,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,SAAS;AAAA,IACX;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA,IACT,gBAAgB,EAAE,QAAQ,cAAc;AAAA,IACxC,WAAW;AAAA,EACb,CAAC;AAED,QAAMC,WAAU,QAAQ,IAAI,qBACxB,IAAI,QAAQ,QAAQ,IAAI,kBAAkB,IAC1C;AAEJ,MAAIA,UAAS;AACX,IAAAA,SAAQ,QAAQ,EAAE;AAAA,MAAM,CAAC,QACvBD,KAAI,IAAI,MAAM,EAAE,IAAI,GAAG,uEAAkE;AAAA,IAC3F;AACA,IAAAA,KAAI,QAAQ,cAAc,sBAAsBC,QAAO,CAAC;AAAA,EAC1D;AAEA,EAAAD,KAAI,QAAQ,UAAU,OAAO,KAAK,UAAU;AAC1C,UAAM,OAAO,gBAAgB,IAAI,EAAE;AAAA,EACrC,CAAC;AAED,EAAAA,KAAI,QAAQ,UAAU,OAAO,MAAM,UAAU;AAC3C,UAAM,aAAa,cAAc;AAAA,EACnC,CAAC;AAED,EAAAA,KAAI,QAAQ,cAAc,QAAQ;AAGlC,QAAM,aAAa,QAAQ,IAAI,kBAC3B,WAAW,QAAQ,EAAE,OAAO,QAAQ,IAAI,eAAe,EAAE,OAAO,KAAK,IACrE;AAEJ,EAAAA,KAAI,SAAS,WAAW;AAAA,IACtB,aAAa,KAAK;AAChB,UAAI,WAAY,QAAO;AACvB,YAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,YAAM,eAAe,MAAM,QAAQ,SAAS,IAAI,UAAU,CAAC,IAAI;AAC/D,YAAM,cAAc,cAAc,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AACtD,YAAM,SAAS,IAAI,QAAQ,WAAW;AACtC,YAAM,YAAY,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AACtD,aAAO,eAAe,aAAa,IAAI;AAAA,IACzC;AAAA,IACA,qBAAqB,MAAM,SAAS;AAClC,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ;AAAA,QACf,WAAW;AAAA,QACX,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,KAAK,KAAK,QAAQ,MAAM,GAAI;AAAA,MACrE;AAAA,IACF;AAAA,EACF,CAAC;AAED,iBAAeA,MAAK,EAAE,QAAQ,UAAU,iBAAiB,SAAAC,SAAQ,CAAC;AAElE,SAAO,EAAE,KAAAD,MAAK,SAAAC,SAAQ;AACxB;;;AQrJA,IAAM,OAAO,SAAS,QAAQ,IAAI,QAAQ,QAAQ,EAAE;AACpD,IAAM,OAAO,QAAQ,IAAI,QAAQ;AAEjC,IAAM,EAAE,KAAK,QAAQ,IAAI,aAAa;AAEtC,eAAe,SAAS,QAA+B;AACrD,MAAI,IAAI,KAAK,6BAA6B,MAAM,sBAAsB;AAEtE,QAAM,kBAAkB,WAAW,MAAM;AACvC,QAAI,IAAI,MAAM,2CAA2C;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB,GAAG,GAAK;AAER,kBAAgB,MAAM;AAEtB,MAAI;AACF,UAAM,IAAI,MAAM;AAEhB,QAAI,SAAS;AACX,YAAM,QAAQ,WAAW;AAAA,IAC3B;AAEA,iBAAa,eAAe;AAE5B,QAAI,IAAI,KAAK,uBAAuB;AAEpC,YAAQ,KAAK,CAAC;AAAA,EAEhB,SAAS,KAAK;AACZ,QAAI,IAAI,MAAM,EAAE,IAAI,GAAG,uBAAuB;AAE9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,QAAQ,GAAG,WAAW,MAAM;AAC1B,OAAK,SAAS,SAAS;AACzB,CAAC;AAED,QAAQ,GAAG,UAAU,MAAM;AACzB,OAAK,SAAS,QAAQ;AACxB,CAAC;AAED,eAAsB,cAA6B;AACjD,MAAI;AACF,UAAM,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC;AAE/B,QAAI,IAAI,KAAK,8BAA8B,IAAI,IAAI,IAAI,EAAE;AAEzD,QAAI,SAAS;AACX,UAAI,IAAI,KAAK,oBAAoB;AAAA,IACnC,OAAO;AACL,UAAI,IAAI,KAAK,yBAAyB;AAAA,IACxC;AAEA,UAAM,SAAkD;AAAA,MACtD,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAEA,QAAI,IAAI,KAAK,OAAO,gBAAgB,CAAC;AAAA,EAEvC,SAAS,KAAK;AACZ,QAAI,IAAI,MAAM,GAAG;AAEjB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":["getRuntimeManifest","app","signer","verifier","auditDb","S_ERROR","S_RATE_LIMIT_ERROR","app","verifier","runtimeManifest","auditDb","S_ERROR","app","auditDb","S_ERROR","getRuntimeManifest","app","signer","verifier","runtimeManifest","auditDb","auditDb","app","auditDb"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parmanasystems/server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Fastify REST API server for parmanasystems governance runtime.",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"@fastify/cors": "^11.2.0",
|
|
25
25
|
"@fastify/helmet": "^13.0.2",
|
|
26
26
|
"@fastify/rate-limit": "^10.3.0",
|
|
27
|
-
"@parmanasystems/audit-db": "^1.
|
|
28
|
-
"@parmanasystems/crypto": "^1.
|
|
29
|
-
"@parmanasystems/execution": "^1.
|
|
30
|
-
"@parmanasystems/verifier": "^1.
|
|
27
|
+
"@parmanasystems/audit-db": "^1.18.0",
|
|
28
|
+
"@parmanasystems/crypto": "^1.18.0",
|
|
29
|
+
"@parmanasystems/execution": "^1.18.0",
|
|
30
|
+
"@parmanasystems/verifier": "^1.18.0",
|
|
31
31
|
"fastify": "^5.8.5"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|