@substrat-run/control-plane-api 0.163.0 → 0.164.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.
@@ -1 +1 @@
1
- {"version":3,"file":"platform-entry.generated.d.ts","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,gCAAgC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,EAAE,MAAqilD,CAAC;AAE1klD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,4DAA4D,CAAC;AACnG,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB,EAAE,MAAuqW,CAAC"}
1
+ {"version":3,"file":"platform-entry.generated.d.ts","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,gCAAgC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,EAAE,MAAs8lD,CAAC;AAE3+lD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,4DAA4D,CAAC;AACnG,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB,EAAE,MAAuqW,CAAC"}
@@ -9,8 +9,8 @@
9
9
  export const PLATFORM_ENTRY_MODULE = 'substrat-platform-entry.js';
10
10
  /** The import specifier the uploader replaces with `./<the bundle's entry>`. */
11
11
  export const PLATFORM_ENTRY_PLACEHOLDER = '__SUBSTRAT_VERTICAL_ENTRY__';
12
- /** The entry itself — 49661 bytes of ESM. */
13
- export const PLATFORM_ENTRY_SOURCE = "// substrat-platform-entry.ts\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// packages/contracts/dist/auth-diagnostics.js\nvar AUTH_CHECK_STAGES = [\"bearer\", \"session\", \"mcp-audience\", \"mcp-caller\"];\nvar AUTH_CHECK_OUTCOMES = [\"accepted\", \"refused\", \"absent\", \"error\"];\nvar AUTH_CHECK_REASONS = [\n \"verified\",\n \"session-invalid\",\n \"credential-missing\",\n \"discovery-failed\",\n \"key-resolution-failed\",\n \"token-expired\",\n \"token-not-active\",\n \"issuer-invalid\",\n \"audience-invalid\",\n \"claims-invalid\",\n \"signature-invalid\",\n \"token-invalid\",\n \"verification-failed\",\n \"subject-missing\",\n \"assertion-not-access-token\",\n \"delegation-refused\",\n \"token-not-for-app\",\n \"resource-mismatch\",\n \"caller-resolved\",\n \"caller-refused\",\n \"caller-error\"\n];\nvar AUTH_CHECK_CAP = 16;\nvar AUTH_DIAGNOSTICS_KEY = /* @__PURE__ */ Symbol.for(\"substrat.auth-diagnostics\");\nfunction authCheckOf(value) {\n if (!value || typeof value !== \"object\")\n return void 0;\n const v = value;\n if (!AUTH_CHECK_STAGES.includes(v.stage) || !AUTH_CHECK_OUTCOMES.includes(v.outcome) || !AUTH_CHECK_REASONS.includes(v.reason))\n return void 0;\n return { stage: v.stage, outcome: v.outcome, reason: v.reason };\n}\nfunction tallyAuthCheck(record2, value) {\n const check = authCheckOf(value);\n if (!check)\n return;\n const checks = record2.authChecks ??= [];\n if (checks.length < AUTH_CHECK_CAP)\n checks.push(check);\n else\n record2.authChecksDropped = (record2.authChecksDropped ?? 0) + 1;\n}\n\n// packages/contracts/dist/invocation-record.js\nvar INVOCATION_RECORD_HEADER = \"x-substrat-invocation-record\";\nvar REQUEST_ID_HEADER = \"x-substrat-request-id\";\nvar PARENT_REQUEST_ID_HEADER = \"x-substrat-parent-request-id\";\nvar REQUEST_ID_SHAPE = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nfunction parentRequestIdOf(value) {\n return typeof value === \"string\" && REQUEST_ID_SHAPE.test(value) ? value : void 0;\n}\nvar INVOCATION_RECORD_FIELD_MAX = 128;\nvar FIELDS = [\"operation\", \"problemCode\", \"principalKind\"];\nfunction encodeInvocationRecord(record2) {\n const params = new URLSearchParams();\n for (const key of FIELDS) {\n const v = record2[key];\n if (typeof v === \"string\" && v !== \"\")\n params.set(key, v.slice(0, INVOCATION_RECORD_FIELD_MAX));\n }\n const value = params.toString();\n return value === \"\" ? null : value;\n}\nvar FIELD_COVERAGE_HEADER = \"x-substrat-field-coverage\";\nfunction invocationLevelOf(status, threw, problemCode) {\n if (threw || status === null || status >= 500)\n return \"error\";\n if (status >= 400)\n return \"warn\";\n if (problemCode)\n return \"warn\";\n return \"info\";\n}\n\n// packages/contracts/dist/trace-sink.js\nvar TRACE_SINK_KEY = /* @__PURE__ */ Symbol.for(\"substrat.trace-sink\");\nvar STARTS_KEY = /* @__PURE__ */ Symbol.for(\"substrat.trace-starts\");\nfunction starts() {\n const slots = globalThis;\n return slots[STARTS_KEY] ??= /* @__PURE__ */ new Map();\n}\nfunction markTraceStart(invocationId, at = performance.now()) {\n const map = starts();\n if (!map.has(invocationId))\n map.set(invocationId, at);\n}\nfunction forgetTraceStart(invocationId) {\n starts().delete(invocationId);\n}\nfunction installedTraceSink() {\n return globalThis[TRACE_SINK_KEY];\n}\n\n// packages/kernel/dist/invocation-line.js\nfunction invocationLine(f) {\n const emitted = f.emitted;\n return {\n substrat: \"invocation\",\n ...f.kind ? { kind: f.kind } : {},\n tenantId: f.tenantId,\n scopeId: f.scopeId,\n vertical: f.vertical ?? null,\n surface: f.surface ?? null,\n method: f.method ?? null,\n path: f.path ?? null,\n status: f.status ?? null,\n threw: f.threw,\n durationMs: f.durationMs,\n invocationId: f.invocationId,\n level: f.level,\n operation: f.operation ?? null,\n problemCode: f.problemCode ?? null,\n principalKind: f.principalKind ?? null,\n eventCount: emitted ? emitted.total : null,\n eventTypes: emitted ? distinct(emitted.events.map((e) => e.type)) : [],\n entities: emitted && f.withEntities !== false ? distinct(emitted.events.map((e) => e.entity)) : [],\n versionId: f.versionId ?? null,\n ...f.outputFields ? { outputFields: f.outputFields, ...f.fieldCoverageId ? { fieldCoverageId: f.fieldCoverageId } : {} } : {},\n ...f.storeCalls && f.storeCalls.length > 0 ? { storeCalls: f.storeCalls } : {},\n ...f.storeCallsDropped ? { storeCallsDropped: f.storeCallsDropped } : {},\n ...f.outboundCalls && f.outboundCalls.length > 0 ? { outboundCalls: f.outboundCalls } : {},\n ...f.outboundCallsDropped ? { outboundCallsDropped: f.outboundCallsDropped } : {},\n ...f.authChecks?.length ? { authChecks: f.authChecks } : {},\n ...f.authChecksDropped ? { authChecksDropped: f.authChecksDropped } : {},\n ...f.parentInvocationId ? { parentInvocationId: f.parentInvocationId, ...f.parentScopeId ? { parentScopeId: f.parentScopeId } : {} } : {},\n ...f.async ?? {}\n };\n}\nvar STORE_CALL_LOG_CAP = 16;\nfunction tallyStoreCall(tally, call) {\n const calls = tally.storeCalls ?? (tally.storeCalls = []);\n if (calls.length < STORE_CALL_LOG_CAP) {\n calls.push({ binding: call.binding, operation: call.operation, outcome: call.outcome, durationMs: call.durationMs });\n } else {\n tally.storeCallsDropped = (tally.storeCallsDropped ?? 0) + 1;\n }\n}\nvar OUTBOUND_CALL_LOG_CAP = 16;\nfunction tallyOutboundCall(tally, call) {\n const calls = tally.outboundCalls ?? (tally.outboundCalls = []);\n if (calls.length < OUTBOUND_CALL_LOG_CAP) {\n calls.push({\n host: call.host,\n path: call.path,\n method: call.method,\n status: call.status,\n outcome: call.outcome,\n durationMs: call.durationMs,\n atMs: call.atMs,\n ...call.reason !== void 0 ? { reason: call.reason } : {}\n });\n } else {\n tally.outboundCallsDropped = (tally.outboundCallsDropped ?? 0) + 1;\n }\n}\nvar STORE_CALL_SINK_KEY = \"substrat.store-call-sink\";\nfunction distinct(values) {\n return [...new Set(values)];\n}\n\n// packages/kernel/dist/ulid.js\nvar B32 = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\nvar MAX_ULID_TIME = 2 ** 48 - 1;\nvar ULID_SHAPE = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar unencodable = (t) => `not an encodable ULID instant: ${t} (want 0..${MAX_ULID_TIME})`;\nfunction encodeTime(time) {\n let ts = \"\";\n let t = time;\n for (let i = 0; i < 10; i++) {\n ts = B32[t % 32] + ts;\n t = Math.floor(t / 32);\n }\n return ts;\n}\nfunction createUlid() {\n let lastTime = -1;\n const lastRand = new Array(16).fill(0);\n function freshRandom() {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n for (let i = 0; i < 16; i++)\n lastRand[i] = bytes[i] % 32;\n }\n function incrementRandom() {\n for (let i = 15; i >= 0; i--) {\n if (lastRand[i] < 31) {\n lastRand[i]++;\n return true;\n }\n lastRand[i] = 0;\n }\n return false;\n }\n const mint = ((now = Date.now()) => {\n if (!Number.isSafeInteger(now))\n throw new RangeError(unencodable(now));\n let time = now;\n if (time <= lastTime) {\n time = lastTime;\n if (!incrementRandom()) {\n time = lastTime + 1;\n freshRandom();\n }\n } else {\n freshRandom();\n }\n if (time < 0 || time > MAX_ULID_TIME)\n throw new RangeError(unencodable(time));\n lastTime = time;\n let r = \"\";\n for (const d of lastRand)\n r += B32[d];\n return encodeTime(time) + r;\n });\n mint.seedFrom = (id) => {\n const time = ulidTime(id);\n if (time < lastTime)\n return;\n const rand = [];\n for (const ch of id.slice(10))\n rand.push(B32.indexOf(ch));\n if (time === lastTime) {\n let ahead = false;\n for (let i = 0; i < 16; i++) {\n if (rand[i] !== lastRand[i]) {\n ahead = rand[i] > lastRand[i];\n break;\n }\n }\n if (!ahead)\n return;\n }\n lastTime = time;\n for (let i = 0; i < 16; i++)\n lastRand[i] = rand[i];\n };\n return mint;\n}\nvar processUlid = createUlid();\nfunction ulid(now = Date.now()) {\n return processUlid(now);\n}\nfunction ulidTime(id) {\n if (!ULID_SHAPE.test(id))\n throw new Error(`not a ULID: ${id}`);\n let t = 0;\n for (const ch of id.slice(0, 10))\n t = t * 32 + B32.indexOf(ch);\n if (t > MAX_ULID_TIME)\n throw new Error(`not a ULID: ${id}`);\n return t;\n}\n\n// packages/vertical-host/src/outbound-calls.ts\nvar EGRESS_REFUSAL_HEADER = \"x-substrat-egress\";\nvar STORE_CALL_HOST = \"store.substrat.internal\";\nvar REDACTED = \"[redacted]\";\nvar PATH_MAX = 200;\nvar WORDS = /^[a-z]{1,16}(?:[-_][a-z]{1,16}){0,3}$/;\nvar WORDS_WITH_EXTENSION = /^[a-z]{1,16}(?:[-_][a-z]{1,16}){0,3}\\.[a-z][a-z0-9]{0,4}$/;\nvar SEGMENT_MAX = 40;\nvar SMALL_INTEGER = /^[0-9]{1,10}$/;\nvar VERSION = /^v[0-9]{1,3}(?:\\.[0-9]{1,3}){0,2}$/;\nfunction keepsSegment(segment) {\n if (segment.length > SEGMENT_MAX) return false;\n return segment === \"\" || WORDS.test(segment) || WORDS_WITH_EXTENSION.test(segment) || SMALL_INTEGER.test(segment) || VERSION.test(segment);\n}\nfunction redactOutboundPath(pathname) {\n const path = pathname.split(\"/\").map((segment) => keepsSegment(segment) ? segment : REDACTED).join(\"/\");\n return path.length > PATH_MAX ? `${path.slice(0, PATH_MAX)}…` : path;\n}\nvar ERROR_CLASS = /^[A-Z][A-Za-z]{0,30}(?:Error|Exception)$/;\nfunction errorName(e) {\n const name = e?.name;\n return typeof name === \"string\" && ERROR_CLASS.test(name) ? name : \"Error\";\n}\nfunction answeredOutcome(response) {\n if (response.status === 403 && response.headers?.get?.(EGRESS_REFUSAL_HEADER) === \"refused\") return \"refused\";\n return response.status >= 400 ? \"http-error\" : \"ok\";\n}\nfunction rejectedOutcome(e) {\n const name = errorName(e);\n if (name === \"TimeoutError\") return { outcome: \"timeout\" };\n if (name === \"AbortError\") return { outcome: \"aborted\" };\n return { outcome: \"failed\", reason: name };\n}\nvar SINCE = /* @__PURE__ */ Symbol.for(\"substrat.outbound-since\");\nfunction sinceMap() {\n const g = globalThis;\n return g[SINCE] ??= /* @__PURE__ */ new WeakMap();\n}\nfunction markRequestStart(recording, started) {\n try {\n sinceMap().set(recording, started);\n } catch {\n }\n}\nfunction destinationOf(input, init) {\n const fromRequest = typeof input === \"object\" && input !== null && !(input instanceof URL);\n const raw = fromRequest ? input.url : input;\n let url;\n try {\n url = new URL(String(raw));\n } catch {\n return null;\n }\n const initMethod = init?.method;\n const requestMethod = fromRequest ? input.method : void 0;\n const method = typeof initMethod === \"string\" ? initMethod : typeof requestMethod === \"string\" ? requestMethod : \"GET\";\n return { url, method: method.toUpperCase().slice(0, 16) };\n}\nfunction record(recording, destination, startedAt, end) {\n try {\n const call = {\n host: destination.url.host.toLowerCase(),\n path: redactOutboundPath(destination.url.pathname),\n method: destination.method,\n status: end.status,\n outcome: end.outcome,\n durationMs: Math.max(0, Date.now() - startedAt),\n atMs: Math.max(0, startedAt - (sinceMap().get(recording) ?? startedAt)),\n ...end.reason !== void 0 ? { reason: end.reason } : {}\n };\n tallyOutboundCall(recording, call);\n } catch {\n }\n}\nvar WRAPPED = /* @__PURE__ */ Symbol.for(\"substrat.outbound-fetch\");\nvar IN_CALL = /* @__PURE__ */ Symbol.for(\"substrat.outbound-fetch.in-call\");\nfunction recordingFetch(original, current) {\n const wrapped = function fetch(input, init) {\n const g = globalThis;\n if (g[IN_CALL] === true) return original.call(globalThis, input, init);\n let recording;\n let destination = null;\n try {\n recording = current();\n if (recording) destination = destinationOf(input, init);\n } catch {\n recording = void 0;\n }\n if (!recording || !destination || destination.url.hostname.toLowerCase() === STORE_CALL_HOST) {\n return original.call(globalThis, input, init);\n }\n const rec = recording;\n const dest = destination;\n const startedAt = Date.now();\n let pending;\n g[IN_CALL] = true;\n try {\n pending = original.call(globalThis, input, init);\n } finally {\n g[IN_CALL] = false;\n }\n return pending.then(\n (response) => {\n let status = null;\n let outcome = \"failed\";\n try {\n status = response.status;\n outcome = answeredOutcome(response);\n } catch {\n }\n record(rec, dest, startedAt, { status, outcome });\n return response;\n },\n (e) => {\n let end = { outcome: \"failed\", reason: \"Error\" };\n try {\n end = rejectedOutcome(e);\n } catch {\n }\n record(rec, dest, startedAt, { status: null, ...end });\n throw e;\n }\n );\n };\n Object.defineProperty(wrapped, WRAPPED, { value: true });\n return wrapped;\n}\nfunction installOutboundRecorder(current) {\n try {\n const g = globalThis;\n const existing = g.fetch;\n if (typeof existing !== \"function\" || existing[WRAPPED]) return;\n g.fetch = recordingFetch(existing, current);\n } catch {\n }\n}\n\n// packages/contracts/dist/wire-headers.js\nvar PLATFORM_SECRET_HEADER = \"x-substrat-platform\";\nvar CONNECTOR_ATTACHMENT_META_MAX_BYTES = 8 * 1024;\n\n// packages/contracts/dist/wire-auth.js\nvar PlatformCallError = class extends Error {\n};\nfunction secretMatches(presented, expected) {\n const given = presented ?? \"\";\n let diff = given.length ^ expected.length | (given.length === 0 ? 1 : 0);\n for (let i = 0; i < expected.length; i++) {\n diff |= (i < given.length ? given.charCodeAt(i) : 0) ^ expected.charCodeAt(i);\n }\n return diff === 0;\n}\nfunction assertPlatformCall(headers, options = {}) {\n const { expectedSecret } = options;\n if (!expectedSecret) {\n throw new PlatformCallError(\"platform calls are not configured on this deployment\");\n }\n if (!secretMatches(headers.get(PLATFORM_SECRET_HEADER), expectedSecret)) {\n throw new PlatformCallError(\"not a platform call\");\n }\n}\n\n// packages/vertical-host/src/routed-node.ts\nvar ROUTED_ID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar RouterAssertionError = class extends Error {\n};\nfunction readRoutedNode(headers, options = {}) {\n const rawTenant = headers.get(\"x-substrat-tenant\");\n const rawScope = headers.get(\"x-substrat-scope\");\n if (!rawTenant && !rawScope) return null;\n const { expectedSecret, allowUnsigned: allowUnsigned2 = false } = options;\n if (expectedSecret) {\n if (!secretMatches(headers.get(\"x-substrat-router\"), expectedSecret)) {\n throw new RouterAssertionError(\"router assertion is not signed by a known router\");\n }\n } else if (!allowUnsigned2) {\n throw new RouterAssertionError(\n \"router assertion cannot be verified: this worker has no ROUTER_SECRET configured\"\n );\n }\n if (!rawTenant || !rawScope) {\n throw new RouterAssertionError(\"router assertion is incomplete\");\n }\n if (!ROUTED_ID.test(rawTenant) || !ROUTED_ID.test(rawScope)) {\n throw new RouterAssertionError(\"router assertion carries a malformed id\");\n }\n return {\n tenantId: rawTenant,\n scopeId: rawScope,\n surface: headers.get(\"x-substrat-surface\") ?? \"app\",\n verticalSlug: headers.get(\"x-substrat-vertical\")\n };\n}\n\n// packages/vertical-host/src/invocation-log.ts\nfunction builtinAsyncLocalStorage() {\n try {\n const proc = globalThis.process;\n const mod = proc?.getBuiltinModule?.(\"node:async_hooks\");\n return typeof mod?.AsyncLocalStorage === \"function\" ? mod.AsyncLocalStorage : void 0;\n } catch {\n return void 0;\n }\n}\nfunction storeCallSlot(provided) {\n try {\n const g = globalThis;\n const key = Symbol.for(STORE_CALL_SINK_KEY);\n const existing = g[key];\n if (typeof existing?.run === \"function\" && typeof existing.current === \"function\") return existing;\n const Als = provided ?? builtinAsyncLocalStorage();\n if (!Als) return void 0;\n const storage = new Als();\n const slot2 = {\n current() {\n const tally = storage.getStore()?.tally;\n return tally ? (call) => tallyStoreCall(tally, call) : void 0;\n },\n invocationId: () => storage.getStore()?.invocationId,\n run: (tally, fn, invocationId) => storage.run({ tally, invocationId }, fn),\n recording: () => storage.getStore()?.tally\n };\n g[key] = slot2;\n return slot2;\n } catch {\n return void 0;\n }\n}\nfunction currentRecording() {\n const slot2 = globalThis[Symbol.for(STORE_CALL_SINK_KEY)];\n return typeof slot2?.recording === \"function\" ? slot2.recording() : void 0;\n}\nfunction runRecording(stamp, started, provided, fn) {\n const slot2 = storeCallSlot(provided);\n if (!slot2) return fn();\n try {\n const authSink = {\n record(check) {\n const record2 = currentRecording();\n if (record2) tallyAuthCheck(record2, check);\n }\n };\n globalThis[AUTH_DIAGNOSTICS_KEY] = authSink;\n } catch {\n }\n markRequestStart(stamp.record, started);\n installOutboundRecorder(currentRecording);\n return slot2.run(stamp.record, fn, stamp.invocationId);\n}\nfunction versionIdOf(env) {\n const v = env?.SUBSTRAT_VERSION_ID;\n return typeof v === \"string\" && v.length > 0 ? v : null;\n}\nvar UPLOAD_LINK_LOG_SECRET_PREFIX = \"sbup_\";\nvar UPLOAD_LINK_SECRET_SEGMENT = /^(\\/api\\/attachment-uploads\\/[^/]+\\/[^/]+\\/)[^/]+/;\nvar SECRET_SHAPED_SEGMENT = new RegExp(`(^|/)${UPLOAD_LINK_LOG_SECRET_PREFIX}[^/]*`, \"g\");\nvar redactUploadLinkSecret = (pathname) => pathname.replace(UPLOAD_LINK_SECRET_SEGMENT, \"$1[redacted]\").replace(SECRET_SHAPED_SEGMENT, \"$1[redacted]\");\nfunction pathOf(url) {\n try {\n return redactUploadLinkSecret(new URL(url).pathname);\n } catch {\n return \"/\";\n }\n}\nvar STAMPS = /* @__PURE__ */ Symbol.for(\"substrat.invocation-stamp\");\nfunction stamps() {\n const g = globalThis;\n return g[STAMPS] ??= /* @__PURE__ */ new WeakMap();\n}\nfunction invocationStampOf(request) {\n return stamps().get(request);\n}\nfunction withRequestId(response, id) {\n const headers = response?.headers;\n try {\n headers?.set?.(REQUEST_ID_HEADER, id);\n return response;\n } catch {\n }\n try {\n const r = response;\n if (r.status === 101) return response;\n const copy = new Response(r.body, r);\n copy.headers.set(REQUEST_ID_HEADER, id);\n return copy;\n } catch {\n return response;\n }\n}\nfunction beginStamp(request, env, options) {\n const stamp = { invocationId: ulid(), record: {} };\n if (installedTraceSink()) markTraceStart(stamp.invocationId);\n const fieldCoverageId = armedFieldCoverageId(request.headers, env, options);\n if (fieldCoverageId) stamp.fieldCoverageId = fieldCoverageId;\n stamps().set(request, stamp);\n return stamp;\n}\nfunction armedFieldCoverageId(headers, env, options) {\n let id;\n try {\n id = headers.get(FIELD_COVERAGE_HEADER);\n } catch {\n return void 0;\n }\n if (id === null || !ROUTED_ID.test(id)) return void 0;\n return routedNodeOrNull(headers, env, options) !== null ? id : void 0;\n}\nfunction writeInvocationLine(stamp, done, options) {\n traceRequest(stamp, done);\n try {\n writeLineOrThrow(stamp, done, options);\n } catch (e) {\n try {\n console.log(JSON.stringify({ substrat: \"invocation-log-fault\", detail: String(e) }));\n } catch {\n }\n }\n}\nfunction traceRequest(stamp, done) {\n const sink = installedTraceSink();\n if (!sink) return;\n try {\n const { record: record2, invocationId } = stamp;\n const durationMs = Date.now() - done.started;\n const line = invocationLine({\n tenantId: \"\",\n scopeId: null,\n vertical: null,\n surface: null,\n method: done.request.method,\n path: pathOf(done.request.url),\n status: done.status,\n threw: done.threw,\n durationMs,\n invocationId,\n level: invocationLevelOf(done.status, done.threw, record2.problemCode),\n operation: record2.operation,\n problemCode: record2.problemCode,\n principalKind: record2.principalKind,\n ...record2.emitted ? { emitted: record2.emitted } : {},\n versionId: versionIdOf(done.env)\n });\n sink.head(invocationId, {\n startedAt: new Date(done.started).toISOString(),\n method: line.method,\n path: line.path,\n status: line.status,\n threw: line.threw,\n durationMs: line.durationMs,\n level: line.level,\n operation: line.operation,\n problemCode: line.problemCode,\n principalKind: line.principalKind,\n eventCount: line.eventCount,\n eventTypes: line.eventTypes,\n entities: line.entities,\n versionId: line.versionId,\n // Calls the record kept no room for: a truncated list must read as truncated.\n ...record2.outboundCallsDropped ? { stepsDropped: record2.outboundCallsDropped } : {}\n });\n for (const call of record2.outboundCalls ?? []) {\n sink.step(invocationId, {\n type: \"outbound\",\n atMs: call.atMs,\n durationMs: call.durationMs,\n host: call.host,\n path: call.path,\n method: call.method,\n status: call.status,\n outcome: call.outcome,\n ...call.reason ? { reason: call.reason } : {}\n });\n }\n for (const check of record2.authChecks ?? []) {\n sink.step(invocationId, { type: \"log\", atMs: durationMs, level: check.outcome === \"refused\" || check.outcome === \"error\" ? \"warn\" : \"info\", message: `auth ${check.stage}: ${check.outcome} (${check.reason})` });\n }\n if (record2.authChecksDropped) sink.head(invocationId, { stepsDropped: record2.authChecksDropped });\n sink.end(invocationId);\n forgetTraceStart(invocationId);\n } catch {\n }\n}\nfunction writeLineOrThrow(stamp, done, options) {\n const node = routedNodeOrNull(done.request.headers, done.env, options);\n if (!node) return;\n const { record: record2, invocationId } = stamp;\n const line = invocationLine({\n tenantId: node.tenantId,\n scopeId: node.scopeId,\n vertical: node.verticalSlug,\n surface: node.surface,\n method: done.request.method,\n path: pathOf(done.request.url),\n status: done.status,\n threw: done.threw,\n durationMs: Date.now() - done.started,\n invocationId,\n level: invocationLevelOf(done.status, done.threw, record2.problemCode),\n operation: record2.operation,\n problemCode: record2.problemCode,\n principalKind: record2.principalKind,\n ...record2.emitted ? { emitted: record2.emitted } : {},\n versionId: versionIdOf(done.env),\n ...record2.outputFields ? { outputFields: record2.outputFields } : {},\n ...stamp.fieldCoverageId ? { fieldCoverageId: stamp.fieldCoverageId } : {},\n ...record2.storeCalls && record2.storeCalls.length > 0 ? { storeCalls: record2.storeCalls } : {},\n ...record2.storeCallsDropped ? { storeCallsDropped: record2.storeCallsDropped } : {},\n ...record2.outboundCalls && record2.outboundCalls.length > 0 ? { outboundCalls: record2.outboundCalls } : {},\n ...record2.outboundCallsDropped ? { outboundCallsDropped: record2.outboundCallsDropped } : {},\n ...record2.authChecks?.length ? { authChecks: record2.authChecks } : {},\n ...record2.authChecksDropped ? { authChecksDropped: record2.authChecksDropped } : {}\n });\n console.log(JSON.stringify(line));\n}\nvar OTHER_HANDLERS = [\"scheduled\", \"queue\", \"email\", \"tail\", \"trace\", \"alarm\", \"test\"];\nfunction withInvocationLog(worker, options = {}) {\n const inner = worker?.fetch;\n if (typeof inner !== \"function\") return worker;\n const wrapped = {\n async fetch(request, env, ctx) {\n if (invocationStampOf(request)) return inner.call(worker, request, env, ctx);\n const started = Date.now();\n const stamp = beginStamp(request, env, options);\n let status = null;\n let threw = false;\n try {\n const response = withRequestId(\n await runRecording(stamp, started, options.asyncLocalStorage, () => inner.call(worker, request, env, ctx)),\n stamp.invocationId\n );\n status = response.status;\n handRecordToRouter(response, stamp.record, request, env, options);\n return response;\n } catch (e) {\n threw = true;\n throw e;\n } finally {\n writeInvocationLine(stamp, { request, env, status, threw, started }, options);\n }\n }\n };\n for (const name of OTHER_HANDLERS) {\n const h = worker[name];\n if (typeof h === \"function\") wrapped[name] = h.bind(worker);\n }\n return wrapped;\n}\nfunction handRecordToRouter(response, record2, request, env, options) {\n try {\n const value = encodeInvocationRecord(record2);\n if (value === null || !routedNodeOrNull(request.headers, env, options)) return;\n response.headers?.set?.(\n INVOCATION_RECORD_HEADER,\n value\n );\n } catch {\n }\n}\nfunction routedNodeOrNull(headers, env, options) {\n try {\n return readRoutedNode(headers, {\n expectedSecret: options.routerSecret?.(env),\n allowUnsigned: options.allowUnsigned?.(env) ?? false\n });\n } catch (e) {\n if (!(e instanceof RouterAssertionError)) console.log(JSON.stringify({ substrat: \"invocation-log-fault\", detail: String(e) }));\n return null;\n }\n}\n\n// packages/contracts/dist/scope-store-envelope.js\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem2 = scopeStorePublicKeyProblem(key);\n if (problem2)\n throw new Error(PUBLIC_KEY_PROBLEM[problem2]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\n\n// packages/contracts/dist/wire-signing.js\nvar WIRE_ENVELOPE_VERSION = 1;\nvar WIRE_ENVELOPE_TAG = `substrat-wire/${WIRE_ENVELOPE_VERSION}`;\nvar WIRE_ENVELOPE_HEADER = \"x-substrat-wire-envelope\";\nvar WIRE_SIGNATURE_HEADER = \"x-substrat-wire-signature\";\nvar WIRE_ENVELOPE_MAX_LIFETIME_SECONDS = 120;\nvar WIRE_CLOCK_SKEW_SECONDS = 30;\nvar SHAPES = {\n router: {\n // An end user's request the router resolved: always a tenant, a scope and a surface. The\n // body is a stream the router does not buffer, so a route binds none.\n route: { scope: \"required\", surface: \"required\", vertical: \"optional\", body: \"absent\" },\n // An internal call the router makes itself, such as a peer invocation.\n call: { scope: \"optional\", surface: \"absent\", vertical: \"optional\", body: \"required\" }\n },\n platform: {\n call: { scope: \"optional\", surface: \"absent\", vertical: \"absent\", body: \"required\" }\n }\n};\nfunction wireEnvelopeShape(iss, kind) {\n const byKind = Object.hasOwn(SHAPES, iss) ? SHAPES[iss] : void 0;\n return byKind && Object.hasOwn(byKind, kind) ? byKind[kind] : void 0;\n}\nvar LINES = 15;\nvar ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar METHOD = /^[!#$%&'*+.^_`|~0-9A-Z-]{1,32}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar SECONDS = /^(0|[1-9]\\d{0,14})$/;\nvar CONTROL = /[\\u0000-\\u001f\\u007f]/;\nvar LONE_SURROGATE = /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/;\nvar MAX_TEXT = 255;\nvar isText = (value) => value.length <= MAX_TEXT && !CONTROL.test(value) && !LONE_SURROGATE.test(value);\nvar isWireAudience = (value) => value !== \"\" && isText(value);\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nfunction admits(presence, value, valid) {\n if (value === \"\")\n return presence !== \"required\";\n return presence !== \"absent\" && valid(value);\n}\nfunction parseWireEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== LINES)\n return void 0;\n const [tag, iss, kind, kid, aud, tenantId, scopeId, surface, vertical2, method, targetDigest, bodyDigest, iat, exp, nonce] = lines;\n if (tag !== WIRE_ENVELOPE_TAG)\n return void 0;\n const shape = wireEnvelopeShape(iss, kind);\n if (!shape)\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n if (!isWireAudience(aud))\n return void 0;\n if (tenantId === \"\" !== (scopeId === \"\"))\n return void 0;\n if (!admits(shape.scope, tenantId, (id) => ULID.test(id)) || !admits(shape.scope, scopeId, (id) => ULID.test(id)))\n return void 0;\n if (!admits(shape.surface, surface, isText) || !admits(shape.vertical, vertical2, isText))\n return void 0;\n if (!METHOD.test(method) || !DIGEST.test(targetDigest) || !admits(shape.body, bodyDigest, (d) => DIGEST.test(d)))\n return void 0;\n if (!SECONDS.test(iat) || !SECONDS.test(exp))\n return void 0;\n const orNull = (value) => value === \"\" ? null : value;\n return {\n v: 1,\n iss,\n kind,\n kid,\n aud,\n tenantId: orNull(tenantId),\n scopeId: orNull(scopeId),\n surface: orNull(surface),\n vertical: orNull(vertical2),\n method,\n targetDigest,\n bodyDigest: orNull(bodyDigest),\n iat: Number(iat),\n exp: Number(exp),\n nonce\n };\n}\nfunction decodeWireEnvelope(header) {\n const bytes = base64UrlToBytes(header);\n if (!bytes)\n return void 0;\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return void 0;\n }\n const claims = parseWireEnvelope(canonical);\n return claims ? { canonical, claims } : void 0;\n}\nfunction bytesOf(data) {\n if (typeof data === \"string\")\n return new TextEncoder().encode(data);\n const view = ArrayBuffer.isView(data) ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) : new Uint8Array(data);\n return view.buffer instanceof ArrayBuffer ? view : view.slice();\n}\nasync function wireDigest(data) {\n const hash = await crypto.subtle.digest(\"SHA-256\", bytesOf(data));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction wireRequestBinding(request) {\n const url = new URL(request.url);\n return { method: request.method.toUpperCase(), target: `${url.pathname}${url.search}` };\n}\nfunction lifetimeAdmitted(iat, exp) {\n return exp > iat && exp - iat <= WIRE_ENVELOPE_MAX_LIFETIME_SECONDS;\n}\nvar PREPARED = /* @__PURE__ */ new WeakMap();\nasync function wireVerificationKeys(config) {\n const listed = (text) => text?.trim() ? parseScopeStorePublicKeys(text) : [];\n const router = listed(config.router);\n const platform = listed(config.platform);\n if (router.some((key) => platform.includes(key)))\n throw new Error(\"a wire public key is listed for both issuers\");\n const byKid = async (keys2) => new Map(await Promise.all(keys2.map(async (key) => [await scopeStoreKeyId(key), key])));\n const own = Object.freeze({ router: await byKid(router), platform: await byKid(platform) });\n const keys = Object.freeze({ router: new Map(own.router), platform: new Map(own.platform) });\n PREPARED.set(keys, own);\n return keys;\n}\nvar WIRE_REFUSED = Object.freeze({ ok: false });\nasync function verifyWireEnvelope(input) {\n const refuse = (reason) => {\n try {\n void Promise.resolve(input.onRefusal?.(reason)).catch(() => {\n });\n } catch {\n }\n return WIRE_REFUSED;\n };\n const { expected, keys, nowSeconds } = input;\n const own = PREPARED.get(keys);\n if (!own)\n throw new TypeError(\"verifyWireEnvelope takes the key set wireVerificationKeys built\");\n const replay = expected.kind === \"call\" ? expected.replay : \"none\";\n if (replay !== \"none\" && typeof replay?.claim !== \"function\") {\n throw new TypeError(\"a call's expectation states its replay policy: 'none' or a nonce cache\");\n }\n if (replay !== \"none\" && expected.scopeId == null) {\n throw new TypeError(\"a call that keeps nonces pins the scope whose object holds them\");\n }\n if (replay !== \"none\" && typeof input.clockSeconds !== \"function\") {\n throw new TypeError(\"a call that keeps nonces takes a clockSeconds function to time its claim\");\n }\n const header = input.headers.get(WIRE_ENVELOPE_HEADER);\n const signature = input.headers.get(WIRE_SIGNATURE_HEADER);\n if (!header || !signature)\n return refuse(\"missing\");\n const decoded = decodeWireEnvelope(header);\n if (!decoded)\n return refuse(\"malformed\");\n const { canonical, claims } = decoded;\n if (claims.iss !== expected.iss)\n return refuse(\"issuer\");\n if (claims.kind !== expected.kind)\n return refuse(\"kind\");\n const publicKey = own[claims.iss].get(claims.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, signature))\n return refuse(\"signature\");\n if (claims.aud !== expected.aud)\n return refuse(\"audience\");\n if (!lifetimeAdmitted(claims.iat, claims.exp))\n return refuse(\"lifetime\");\n if (!(nowSeconds >= claims.iat - WIRE_CLOCK_SKEW_SECONDS))\n return refuse(\"not-yet-valid\");\n if (!(nowSeconds <= claims.exp + WIRE_CLOCK_SKEW_SECONDS))\n return refuse(\"expired\");\n if (claims.method !== expected.method)\n return refuse(\"method\");\n if (claims.targetDigest !== await wireDigest(expected.target))\n return refuse(\"target\");\n if (expected.kind === \"call\") {\n const body = typeof expected.body === \"function\" ? await expected.body() : expected.body;\n if (body == null || claims.bodyDigest !== await wireDigest(body))\n return refuse(\"body\");\n }\n if (expected.tenantId !== void 0 && claims.tenantId !== expected.tenantId)\n return refuse(\"scope\");\n if (expected.scopeId !== void 0 && claims.scopeId !== expected.scopeId)\n return refuse(\"scope\");\n if (replay !== \"none\") {\n const until = claims.exp + WIRE_CLOCK_SKEW_SECONDS;\n const claimedAt = input.clockSeconds();\n if (!Number.isFinite(claimedAt) || claimedAt < 0) {\n throw new TypeError(\"clockSeconds read something other than a time in seconds\");\n }\n if (!(claimedAt <= until))\n return refuse(\"claim-after-until\");\n if (await replay.claim(claims.nonce, until) !== true)\n return refuse(\"replay\");\n }\n return { ok: true, claims };\n}\nvar WIRE_ROUTER_KEYS_VAR = \"SUBSTRAT_WIRE_ROUTER_KEYS\";\nvar WIRE_PLATFORM_KEYS_VAR = \"SUBSTRAT_WIRE_PLATFORM_KEYS\";\nvar WIRE_AUDIENCE_VAR = \"SUBSTRAT_WIRE_AUDIENCE\";\nvar WIRE_STATE_VAR = \"SUBSTRAT_WIRE_STATE\";\nfunction wireStateOf(config) {\n const listed = (value) => typeof value === \"string\" && value.trim() !== \"\";\n if (!listed(config.routerKeys) && !listed(config.platformKeys))\n return \"legacy-only\";\n return config.state === \"legacy-only\" || config.state === \"signed-only\" ? config.state : \"dual\";\n}\nvar ROUTE_ENDPOINT = Object.freeze({ kind: \"route\", issuers: Object.freeze([\"router\"]) });\nvar CALL_ENDPOINT = Object.freeze({ kind: \"call\", issuers: Object.freeze([\"platform\"]) });\nvar PEER_INVOKE_ENDPOINT = Object.freeze({ kind: \"call\", issuers: Object.freeze([\"platform\", \"router\"]) });\nfunction tryDecode(path, decoder) {\n try {\n return decoder(path);\n } catch {\n return path.replace(/(?:%[0-9A-Fa-f]{2})+/g, (run) => {\n try {\n return decoder(run);\n } catch {\n return run;\n }\n });\n }\n}\nfunction collapsed(path) {\n const segments = [];\n for (const segment of path.split(\"/\")) {\n if (segment === \"..\")\n segments.pop();\n else if (segment !== \"\" && segment !== \".\")\n segments.push(segment);\n }\n return `/${segments.join(\"/\")}`;\n}\nvar INTERNAL = /^\\/internal(?:\\/|$)/i;\nfunction wireEndpoint(pathname) {\n const routed = tryDecode(pathname.includes(\"%25\") ? pathname.replace(/%25/g, \"%2525\") : pathname, decodeURI);\n const forms = [pathname, routed, tryDecode(pathname, decodeURIComponent)];\n if (!forms.some((form) => INTERNAL.test(form) || INTERNAL.test(collapsed(form))))\n return ROUTE_ENDPOINT;\n return pathname === \"/internal/vertical-invoke\" ? PEER_INVOKE_ENDPOINT : CALL_ENDPOINT;\n}\nvar WIRE_REPLAY_FREE_CALLS = Object.freeze([\n \"/internal/query\",\n \"/internal/redrain-count\",\n \"/internal/lifecycle-flow\",\n \"/internal/operation-series\",\n \"/internal/connector-grants\"\n]);\nvar SAFE_METHODS = /* @__PURE__ */ new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\nfunction wireReplayOf(method, pathname) {\n return SAFE_METHODS.has(method.toUpperCase()) || WIRE_REPLAY_FREE_CALLS.includes(pathname) ? \"none\" : \"nonce\";\n}\nvar UNSIGNED = Object.freeze([\n [FIELD_COVERAGE_HEADER, \"route\", (value) => ULID.test(value)],\n [PARENT_REQUEST_ID_HEADER, \"call\", (value) => parentRequestIdOf(value) !== void 0]\n]);\nvar WIRE_UNSIGNED_HEADERS = Object.freeze(Object.fromEntries(UNSIGNED.map(([name, kind]) => [name, kind])));\nfunction wireUnsignedHeadersOf(kind, headers) {\n const kept = [];\n for (const [name, on, valid] of UNSIGNED) {\n const value = on === kind ? headers.get(name) : null;\n if (value !== null && valid(value))\n kept.push([name, value]);\n }\n return kept;\n}\n\n// packages/control-plane-api/platform-entry/wire-gate.ts\nvar WIRE_CLAIM_TIMEOUT_MS = 1e3;\nvar WIRE_REFUSAL_BODY = '{\"type\":\"about:blank\",\"title\":\"Unauthorized\",\"status\":401,\"detail\":\"unauthorized\",\"error\":\"unauthorized\"}';\nvar WIRE_FAULT_BODY = '{\"type\":\"about:blank\",\"title\":\"Service unavailable\",\"status\":503,\"detail\":\"this request could not be verified\",\"error\":\"this request could not be verified\"}';\nvar problem = (body, status) => new Response(body, { status, headers: { \"content-type\": \"application/problem+json\" } });\nvar ASSERTED_PREFIX = \"x-substrat-\";\nvar TENANT = \"x-substrat-tenant\";\nvar SCOPE = \"x-substrat-scope\";\nvar SURFACE = \"x-substrat-surface\";\nvar VERTICAL = \"x-substrat-vertical\";\nvar ROUTER_CREDENTIAL = \"x-substrat-router\";\nvar GateFault = class extends Error {\n constructor(fault) {\n super(fault);\n this.fault = fault;\n }\n fault;\n};\nfunction claimedThrough(reach, timeoutMs) {\n return {\n async claim(nonce, until) {\n let cache;\n try {\n cache = reach();\n } catch {\n throw new GateFault(\"nonce-store\");\n }\n if (cache == null) throw new GateFault(\"no-nonce-store\");\n let timer;\n try {\n return await Promise.race([\n cache.claim(nonce, until),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"the nonce store did not answer in time\")), timeoutMs);\n })\n ]);\n } catch {\n throw new GateFault(\"nonce-store\");\n } finally {\n clearTimeout(timer);\n }\n }\n };\n}\nvar builtKeys;\nfunction keysFor(router, platform) {\n const text = `${router}\n${platform}`;\n if (builtKeys?.text !== text) builtKeys = { text, keys: wireVerificationKeys({ router, platform }) };\n return builtKeys.keys;\n}\nvar textOf = (value) => typeof value === \"string\" ? value : \"\";\nfunction stateOf(env) {\n const e = env ?? {};\n return wireStateOf({ routerKeys: e[WIRE_ROUTER_KEYS_VAR], platformKeys: e[WIRE_PLATFORM_KEYS_VAR], state: e[WIRE_STATE_VAR] });\n}\nfunction legacyOf(request, call, env, options) {\n if (call) {\n let credential = request.headers.has(PLATFORM_SECRET_HEADER) ? \"invalid\" : \"absent\";\n try {\n assertPlatformCall(request.headers, { expectedSecret: options.platformSecret(env) });\n credential = \"valid\";\n } catch {\n }\n return { credential, identity: null };\n }\n try {\n const node = options.routedNode(request.headers, env);\n return node ? { credential: \"valid\", identity: node } : { credential: \"absent\", identity: null };\n } catch {\n return { credential: \"invalid\", identity: null };\n }\n}\nvar sameIdentity = (legacy, claims) => legacy.tenantId === claims.tenantId && legacy.scopeId === claims.scopeId && legacy.surface === claims.surface && legacy.verticalSlug === claims.vertical;\nvar servedAs = (who) => ({\n tenantId: who?.tenantId ?? null,\n scopeId: who?.scopeId ?? null\n});\nfunction withWireGate(worker, options) {\n const inner = worker?.fetch;\n if (typeof inner !== \"function\") return worker;\n const clock = options.clock ?? Date.now;\n const seconds = () => Math.floor(clock() / 1e3);\n const timeoutMs = options.claimTimeoutMs ?? WIRE_CLAIM_TIMEOUT_MS;\n const log = options.log ?? ((line) => console.log(line));\n const serve = (request, env, ctx) => inner.call(worker, request, env, ctx);\n async function judged(request, env, ctx, state) {\n const nowSeconds = seconds();\n const e = env;\n const aud = textOf(e[WIRE_AUDIENCE_VAR]);\n const { method, target } = wireRequestBinding(request);\n const pathname = new URL(request.url).pathname;\n const endpoint = wireEndpoint(pathname);\n const call = endpoint.kind === \"call\";\n const claimed = call ? decodeWireEnvelope(request.headers.get(WIRE_ENVELOPE_HEADER) ?? \"\")?.claims : void 0;\n const issuer = claimed && endpoint.issuers.includes(claimed.iss) ? claimed.iss : endpoint.issuers[0];\n let claims;\n const line = (outcome, legacy2, extra = {}) => {\n const v = e[\"SUBSTRAT_VERSION_ID\"];\n const record2 = {\n substrat: \"wire\",\n state,\n issuer: claims?.iss ?? (endpoint.issuers.length === 1 ? endpoint.issuers[0] : null),\n kind: endpoint.kind,\n outcome,\n reason: null,\n fault: null,\n legacy: legacy2,\n tenantId: null,\n scopeId: null,\n versionId: typeof v === \"string\" && v.length > 0 ? v : null,\n ...extra\n };\n try {\n log(JSON.stringify(record2));\n } catch {\n }\n };\n const faulted = (fault, legacy2) => {\n line(\"fault\", legacy2, { fault });\n return problem(WIRE_FAULT_BODY, 503);\n };\n const legacy = legacyOf(request, call, env, options);\n let downstream = request;\n const staticFault = (fault, extra = {}) => {\n if (state !== \"dual\") return faulted(fault, legacy.credential);\n line(\"fault\", legacy.credential, { fault, ...extra });\n return serve(downstream, env, ctx);\n };\n let keys;\n try {\n keys = await keysFor(textOf(e[WIRE_ROUTER_KEYS_VAR]), textOf(e[WIRE_PLATFORM_KEYS_VAR]));\n } catch {\n return staticFault(\"keys\", servedAs(legacy.identity));\n }\n const readBody = async () => {\n if (request.body === null) return \"\";\n let body;\n try {\n body = await request.arrayBuffer();\n } catch {\n return null;\n }\n downstream = new Request(request, { body });\n return body;\n };\n const keepsNonces = call && wireReplayOf(method, pathname) === \"nonce\";\n const pinned = keepsNonces ? claimed?.scopeId ?? void 0 : void 0;\n const reach = options.nonceCache;\n const store = pinned !== void 0 && reach ? claimedThrough(() => reach(env, pinned, claimed?.tenantId ?? null), timeoutMs) : void 0;\n const expected = call ? {\n iss: issuer,\n kind: \"call\",\n aud,\n method,\n target,\n body: readBody,\n replay: store ?? \"none\",\n scopeId: store ? pinned : void 0\n } : { iss: \"router\", kind: \"route\", aud, method, target };\n let reason = null;\n let noStore = !store;\n try {\n const verdict = await verifyWireEnvelope({\n headers: request.headers,\n keys,\n expected,\n nowSeconds,\n clockSeconds: seconds,\n onRefusal: (why) => {\n reason = why;\n }\n });\n if (verdict.ok) claims = verdict.claims;\n } catch (error) {\n if (error instanceof GateFault && error.fault === \"no-nonce-store\") {\n claims = claimed;\n noStore = true;\n } else {\n return faulted(error instanceof GateFault ? error.fault : \"verifier\", legacy.credential);\n }\n }\n if (claims && keepsNonces && noStore) {\n return staticFault(claims.scopeId == null ? \"unscoped\" : \"no-nonce-store\", servedAs(legacy.identity ?? claims));\n }\n const mismatched = !!claims && !!legacy.identity && !sameIdentity(legacy.identity, claims);\n if (state === \"dual\" && legacy.credential === \"valid\") {\n const outcome = !claims ? \"legacy-accepted\" : mismatched ? \"dual-mismatch\" : \"signed-accepted\";\n line(outcome, \"valid\", { reason, ...servedAs(legacy.identity ?? claims ?? null) });\n return serve(downstream, env, ctx);\n }\n if (!claims) {\n line(\"refused\", legacy.credential, { reason });\n if (state === \"dual\") return serve(downstream, env, ctx);\n return problem(WIRE_REFUSAL_BODY, 401);\n }\n let proven;\n try {\n proven = provenAs(downstream, claims, env, options);\n } catch {\n return faulted(\"verifier\", legacy.credential);\n }\n line(mismatched ? \"dual-mismatch\" : \"signed-accepted\", legacy.credential, servedAs(claims));\n return serve(proven, env, ctx);\n }\n return {\n ...worker,\n fetch(request, env, ctx) {\n const state = stateOf(env);\n if (state === \"legacy-only\") return serve(request, env, ctx);\n return judged(request, env, ctx, state);\n }\n };\n}\nfunction provenAs(request, claims, env, options) {\n const headers = new Headers(request.headers);\n for (const name of [...headers.keys()]) if (name.startsWith(ASSERTED_PREFIX)) headers.delete(name);\n for (const [name, value] of wireUnsignedHeadersOf(claims.kind, request.headers)) headers.set(name, value);\n const put = (name, value) => {\n if (value) headers.set(name, value);\n };\n if (claims.kind === \"route\") {\n put(TENANT, claims.tenantId);\n put(SCOPE, claims.scopeId);\n put(SURFACE, claims.surface);\n put(VERTICAL, claims.vertical);\n put(ROUTER_CREDENTIAL, options.routerSecret(env));\n } else {\n put(VERTICAL, claims.vertical);\n put(PLATFORM_SECRET_HEADER, options.platformSecret(env));\n }\n return new Request(request, { headers });\n}\n\n// packages/control-plane-api/platform-entry/nonce-store.ts\nfunction nonceStoreOf(registered) {\n return (env, scopeId, tenantId) => {\n const hostFor = registered();\n if (!hostFor) return void 0;\n const store = hostFor(env);\n if (typeof store?.claimWireNonceLocal !== \"function\" || tenantId === null) return void 0;\n const claim = store.claimWireNonceLocal.bind(store);\n return { claim: (nonce, until) => claim(tenantId, scopeId, nonce, until) };\n };\n}\n\n// packages/vertical-host/src/scope-sweep-host.ts\nvar SCOPE_SWEEP_HOST_KEY = \"substrat.scope-sweep-host\";\nfunction slot() {\n return globalThis;\n}\nfunction registeredScopeSweepHost() {\n return slot()[Symbol.for(SCOPE_SWEEP_HOST_KEY)];\n}\n\n// substrat-platform-entry.ts\nimport * as vertical from \"__SUBSTRAT_VERTICAL_ENTRY__\";\nexport * from \"__SUBSTRAT_VERTICAL_ENTRY__\";\nvar routerSecret = (env) => env.ROUTER_SECRET;\nvar allowUnsigned = (env) => env.ALLOW_DEV_NODE === \"true\";\nvar substrat_platform_entry_default = withWireGate(\n withInvocationLog(vertical.default, { routerSecret, allowUnsigned, asyncLocalStorage: AsyncLocalStorage }),\n {\n routedNode: (headers, env) => readRoutedNode(headers, { expectedSecret: routerSecret(env), allowUnsigned: allowUnsigned(env) }),\n routerSecret,\n platformSecret: (env) => env.PLATFORM_SECRET,\n nonceCache: nonceStoreOf(registeredScopeSweepHost)\n }\n);\nexport {\n substrat_platform_entry_default as default\n};\n";
12
+ /** The entry itself — 50067 bytes of ESM. */
13
+ export const PLATFORM_ENTRY_SOURCE = "// substrat-platform-entry.ts\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// packages/contracts/dist/auth-diagnostics.js\nvar AUTH_CHECK_STAGES = [\"bearer\", \"session\", \"mcp-audience\", \"mcp-caller\"];\nvar AUTH_CHECK_OUTCOMES = [\"accepted\", \"refused\", \"absent\", \"error\"];\nvar AUTH_CHECK_REASONS = [\n \"verified\",\n \"session-invalid\",\n \"credential-missing\",\n \"discovery-failed\",\n \"key-resolution-failed\",\n \"token-expired\",\n \"token-not-active\",\n \"issuer-invalid\",\n \"audience-invalid\",\n \"claims-invalid\",\n \"signature-invalid\",\n \"token-invalid\",\n \"verification-failed\",\n \"subject-missing\",\n \"assertion-not-access-token\",\n \"delegation-refused\",\n \"token-not-for-app\",\n \"resource-mismatch\",\n \"caller-resolved\",\n \"caller-refused\",\n \"caller-error\"\n];\nvar AUTH_CHECK_CAP = 16;\nvar AUTH_DIAGNOSTICS_KEY = /* @__PURE__ */ Symbol.for(\"substrat.auth-diagnostics\");\nfunction authCheckOf(value) {\n if (!value || typeof value !== \"object\")\n return void 0;\n const v = value;\n if (!AUTH_CHECK_STAGES.includes(v.stage) || !AUTH_CHECK_OUTCOMES.includes(v.outcome) || !AUTH_CHECK_REASONS.includes(v.reason))\n return void 0;\n return { stage: v.stage, outcome: v.outcome, reason: v.reason };\n}\nfunction tallyAuthCheck(record2, value) {\n const check = authCheckOf(value);\n if (!check)\n return;\n const checks = record2.authChecks ??= [];\n if (checks.length < AUTH_CHECK_CAP)\n checks.push(check);\n else\n record2.authChecksDropped = (record2.authChecksDropped ?? 0) + 1;\n}\n\n// packages/contracts/dist/invocation-record.js\nvar INVOCATION_RECORD_HEADER = \"x-substrat-invocation-record\";\nvar REQUEST_ID_HEADER = \"x-substrat-request-id\";\nvar PARENT_REQUEST_ID_HEADER = \"x-substrat-parent-request-id\";\nvar REQUEST_ID_SHAPE = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nfunction parentRequestIdOf(value) {\n return typeof value === \"string\" && REQUEST_ID_SHAPE.test(value) ? value : void 0;\n}\nvar INVOCATION_RECORD_FIELD_MAX = 128;\nvar FIELDS = [\"operation\", \"problemCode\", \"principalKind\"];\nfunction encodeInvocationRecord(record2) {\n const params = new URLSearchParams();\n for (const key of FIELDS) {\n const v = record2[key];\n if (typeof v === \"string\" && v !== \"\")\n params.set(key, v.slice(0, INVOCATION_RECORD_FIELD_MAX));\n }\n const value = params.toString();\n return value === \"\" ? null : value;\n}\nvar FIELD_COVERAGE_HEADER = \"x-substrat-field-coverage\";\nfunction invocationLevelOf(status, threw, problemCode) {\n if (threw || status === null || status >= 500)\n return \"error\";\n if (status >= 400)\n return \"warn\";\n if (problemCode)\n return \"warn\";\n return \"info\";\n}\n\n// packages/contracts/dist/trace-sink.js\nvar TRACE_SINK_KEY = /* @__PURE__ */ Symbol.for(\"substrat.trace-sink\");\nvar STARTS_KEY = /* @__PURE__ */ Symbol.for(\"substrat.trace-starts\");\nfunction starts() {\n const slots = globalThis;\n return slots[STARTS_KEY] ??= /* @__PURE__ */ new Map();\n}\nfunction markTraceStart(invocationId, at = performance.now()) {\n const map = starts();\n if (!map.has(invocationId))\n map.set(invocationId, at);\n}\nfunction forgetTraceStart(invocationId) {\n starts().delete(invocationId);\n}\nfunction installedTraceSink() {\n return globalThis[TRACE_SINK_KEY];\n}\n\n// packages/kernel/dist/invocation-line.js\nfunction invocationLine(f) {\n const emitted = f.emitted;\n return {\n substrat: \"invocation\",\n ...f.kind ? { kind: f.kind } : {},\n tenantId: f.tenantId,\n scopeId: f.scopeId,\n vertical: f.vertical ?? null,\n surface: f.surface ?? null,\n method: f.method ?? null,\n path: f.path ?? null,\n status: f.status ?? null,\n threw: f.threw,\n durationMs: f.durationMs,\n invocationId: f.invocationId,\n level: f.level,\n operation: f.operation ?? null,\n problemCode: f.problemCode ?? null,\n principalKind: f.principalKind ?? null,\n eventCount: emitted ? emitted.total : null,\n eventTypes: emitted ? distinct(emitted.events.map((e) => e.type)) : [],\n entities: emitted && f.withEntities !== false ? distinct(emitted.events.map((e) => e.entity)) : [],\n versionId: f.versionId ?? null,\n ...f.outputFields ? { outputFields: f.outputFields, ...f.fieldCoverageId ? { fieldCoverageId: f.fieldCoverageId } : {} } : {},\n ...f.storeCalls && f.storeCalls.length > 0 ? { storeCalls: f.storeCalls } : {},\n ...f.storeCallsDropped ? { storeCallsDropped: f.storeCallsDropped } : {},\n ...f.outboundCalls && f.outboundCalls.length > 0 ? { outboundCalls: f.outboundCalls } : {},\n ...f.outboundCallsDropped ? { outboundCallsDropped: f.outboundCallsDropped } : {},\n ...f.authChecks?.length ? { authChecks: f.authChecks } : {},\n ...f.authChecksDropped ? { authChecksDropped: f.authChecksDropped } : {},\n ...f.parentInvocationId ? { parentInvocationId: f.parentInvocationId, ...f.parentScopeId ? { parentScopeId: f.parentScopeId } : {} } : {},\n ...f.async ?? {}\n };\n}\nvar STORE_CALL_LOG_CAP = 16;\nfunction tallyStoreCall(tally, call) {\n const calls = tally.storeCalls ?? (tally.storeCalls = []);\n if (calls.length < STORE_CALL_LOG_CAP) {\n calls.push({ binding: call.binding, operation: call.operation, outcome: call.outcome, durationMs: call.durationMs });\n } else {\n tally.storeCallsDropped = (tally.storeCallsDropped ?? 0) + 1;\n }\n}\nvar OUTBOUND_CALL_LOG_CAP = 16;\nfunction tallyOutboundCall(tally, call) {\n const calls = tally.outboundCalls ?? (tally.outboundCalls = []);\n if (calls.length < OUTBOUND_CALL_LOG_CAP) {\n calls.push({\n host: call.host,\n path: call.path,\n method: call.method,\n status: call.status,\n outcome: call.outcome,\n durationMs: call.durationMs,\n atMs: call.atMs,\n ...call.reason !== void 0 ? { reason: call.reason } : {}\n });\n } else {\n tally.outboundCallsDropped = (tally.outboundCallsDropped ?? 0) + 1;\n }\n}\nvar STORE_CALL_SINK_KEY = \"substrat.store-call-sink\";\nfunction distinct(values) {\n return [...new Set(values)];\n}\n\n// packages/kernel/dist/ulid.js\nvar B32 = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\nvar MAX_ULID_TIME = 2 ** 48 - 1;\nvar ULID_SHAPE = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar unencodable = (t) => `not an encodable ULID instant: ${t} (want 0..${MAX_ULID_TIME})`;\nfunction encodeTime(time) {\n let ts = \"\";\n let t = time;\n for (let i = 0; i < 10; i++) {\n ts = B32[t % 32] + ts;\n t = Math.floor(t / 32);\n }\n return ts;\n}\nfunction createUlid() {\n let lastTime = -1;\n const lastRand = new Array(16).fill(0);\n function freshRandom() {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n for (let i = 0; i < 16; i++)\n lastRand[i] = bytes[i] % 32;\n }\n function incrementRandom() {\n for (let i = 15; i >= 0; i--) {\n if (lastRand[i] < 31) {\n lastRand[i]++;\n return true;\n }\n lastRand[i] = 0;\n }\n return false;\n }\n const mint = ((now = Date.now()) => {\n if (!Number.isSafeInteger(now))\n throw new RangeError(unencodable(now));\n let time = now;\n if (time <= lastTime) {\n time = lastTime;\n if (!incrementRandom()) {\n time = lastTime + 1;\n freshRandom();\n }\n } else {\n freshRandom();\n }\n if (time < 0 || time > MAX_ULID_TIME)\n throw new RangeError(unencodable(time));\n lastTime = time;\n let r = \"\";\n for (const d of lastRand)\n r += B32[d];\n return encodeTime(time) + r;\n });\n mint.seedFrom = (id) => {\n const time = ulidTime(id);\n if (time < lastTime)\n return;\n const rand = [];\n for (const ch of id.slice(10))\n rand.push(B32.indexOf(ch));\n if (time === lastTime) {\n let ahead = false;\n for (let i = 0; i < 16; i++) {\n if (rand[i] !== lastRand[i]) {\n ahead = rand[i] > lastRand[i];\n break;\n }\n }\n if (!ahead)\n return;\n }\n lastTime = time;\n for (let i = 0; i < 16; i++)\n lastRand[i] = rand[i];\n };\n return mint;\n}\nvar processUlid = createUlid();\nfunction ulid(now = Date.now()) {\n return processUlid(now);\n}\nfunction ulidTime(id) {\n if (!ULID_SHAPE.test(id))\n throw new Error(`not a ULID: ${id}`);\n let t = 0;\n for (const ch of id.slice(0, 10))\n t = t * 32 + B32.indexOf(ch);\n if (t > MAX_ULID_TIME)\n throw new Error(`not a ULID: ${id}`);\n return t;\n}\n\n// packages/vertical-host/src/outbound-calls.ts\nvar EGRESS_REFUSAL_HEADER = \"x-substrat-egress\";\nvar STORE_CALL_HOST = \"store.substrat.internal\";\nvar REDACTED = \"[redacted]\";\nvar PATH_MAX = 200;\nvar WORDS = /^[a-z]{1,16}(?:[-_][a-z]{1,16}){0,3}$/;\nvar WORDS_WITH_EXTENSION = /^[a-z]{1,16}(?:[-_][a-z]{1,16}){0,3}\\.[a-z][a-z0-9]{0,4}$/;\nvar SEGMENT_MAX = 40;\nvar SMALL_INTEGER = /^[0-9]{1,10}$/;\nvar VERSION = /^v[0-9]{1,3}(?:\\.[0-9]{1,3}){0,2}$/;\nfunction keepsSegment(segment) {\n if (segment.length > SEGMENT_MAX) return false;\n return segment === \"\" || WORDS.test(segment) || WORDS_WITH_EXTENSION.test(segment) || SMALL_INTEGER.test(segment) || VERSION.test(segment);\n}\nfunction redactOutboundPath(pathname) {\n const path = pathname.split(\"/\").map((segment) => keepsSegment(segment) ? segment : REDACTED).join(\"/\");\n return path.length > PATH_MAX ? `${path.slice(0, PATH_MAX)}…` : path;\n}\nvar ERROR_CLASS = /^[A-Z][A-Za-z]{0,30}(?:Error|Exception)$/;\nfunction errorName(e) {\n const name = e?.name;\n return typeof name === \"string\" && ERROR_CLASS.test(name) ? name : \"Error\";\n}\nfunction answeredOutcome(response) {\n if (response.status === 403 && response.headers?.get?.(EGRESS_REFUSAL_HEADER) === \"refused\") return \"refused\";\n return response.status >= 400 ? \"http-error\" : \"ok\";\n}\nfunction rejectedOutcome(e) {\n const name = errorName(e);\n if (name === \"TimeoutError\") return { outcome: \"timeout\" };\n if (name === \"AbortError\") return { outcome: \"aborted\" };\n return { outcome: \"failed\", reason: name };\n}\nvar SINCE = /* @__PURE__ */ Symbol.for(\"substrat.outbound-since\");\nfunction sinceMap() {\n const g = globalThis;\n return g[SINCE] ??= /* @__PURE__ */ new WeakMap();\n}\nfunction markRequestStart(recording, started) {\n try {\n sinceMap().set(recording, started);\n } catch {\n }\n}\nfunction destinationOf(input, init) {\n const fromRequest = typeof input === \"object\" && input !== null && !(input instanceof URL);\n const raw = fromRequest ? input.url : input;\n let url;\n try {\n url = new URL(String(raw));\n } catch {\n return null;\n }\n const initMethod = init?.method;\n const requestMethod = fromRequest ? input.method : void 0;\n const method = typeof initMethod === \"string\" ? initMethod : typeof requestMethod === \"string\" ? requestMethod : \"GET\";\n return { url, method: method.toUpperCase().slice(0, 16) };\n}\nfunction record(recording, destination, startedAt, end) {\n try {\n const call = {\n host: destination.url.host.toLowerCase(),\n path: redactOutboundPath(destination.url.pathname),\n method: destination.method,\n status: end.status,\n outcome: end.outcome,\n durationMs: Math.max(0, Date.now() - startedAt),\n atMs: Math.max(0, startedAt - (sinceMap().get(recording) ?? startedAt)),\n ...end.reason !== void 0 ? { reason: end.reason } : {}\n };\n tallyOutboundCall(recording, call);\n } catch {\n }\n}\nvar WRAPPED = /* @__PURE__ */ Symbol.for(\"substrat.outbound-fetch\");\nvar IN_CALL = /* @__PURE__ */ Symbol.for(\"substrat.outbound-fetch.in-call\");\nfunction recordingFetch(original, current) {\n const wrapped = function fetch(input, init) {\n const g = globalThis;\n if (g[IN_CALL] === true) return original.call(globalThis, input, init);\n let recording;\n let destination = null;\n try {\n recording = current();\n if (recording) destination = destinationOf(input, init);\n } catch {\n recording = void 0;\n }\n if (!recording || !destination || destination.url.hostname.toLowerCase() === STORE_CALL_HOST) {\n return original.call(globalThis, input, init);\n }\n const rec = recording;\n const dest = destination;\n const startedAt = Date.now();\n let pending;\n g[IN_CALL] = true;\n try {\n pending = original.call(globalThis, input, init);\n } finally {\n g[IN_CALL] = false;\n }\n return pending.then(\n (response) => {\n let status = null;\n let outcome = \"failed\";\n try {\n status = response.status;\n outcome = answeredOutcome(response);\n } catch {\n }\n record(rec, dest, startedAt, { status, outcome });\n return response;\n },\n (e) => {\n let end = { outcome: \"failed\", reason: \"Error\" };\n try {\n end = rejectedOutcome(e);\n } catch {\n }\n record(rec, dest, startedAt, { status: null, ...end });\n throw e;\n }\n );\n };\n Object.defineProperty(wrapped, WRAPPED, { value: true });\n return wrapped;\n}\nfunction installOutboundRecorder(current) {\n try {\n const g = globalThis;\n const existing = g.fetch;\n if (typeof existing !== \"function\" || existing[WRAPPED]) return;\n g.fetch = recordingFetch(existing, current);\n } catch {\n }\n}\n\n// packages/contracts/dist/wire-headers.js\nvar PLATFORM_SECRET_HEADER = \"x-substrat-platform\";\nvar CONNECTOR_ATTACHMENT_META_MAX_BYTES = 8 * 1024;\n\n// packages/contracts/dist/wire-auth.js\nvar PlatformCallError = class extends Error {\n};\nfunction secretMatches(presented, expected) {\n const given = presented ?? \"\";\n let diff = given.length ^ expected.length | (given.length === 0 ? 1 : 0);\n for (let i = 0; i < expected.length; i++) {\n diff |= (i < given.length ? given.charCodeAt(i) : 0) ^ expected.charCodeAt(i);\n }\n return diff === 0;\n}\nfunction assertPlatformCall(headers, options = {}) {\n const { expectedSecret } = options;\n if (!expectedSecret) {\n throw new PlatformCallError(\"platform calls are not configured on this deployment\");\n }\n if (!secretMatches(headers.get(PLATFORM_SECRET_HEADER), expectedSecret)) {\n throw new PlatformCallError(\"not a platform call\");\n }\n}\n\n// packages/vertical-host/src/routed-node.ts\nvar ROUTED_ID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar RouterAssertionError = class extends Error {\n};\nfunction readRoutedNode(headers, options = {}) {\n const rawTenant = headers.get(\"x-substrat-tenant\");\n const rawScope = headers.get(\"x-substrat-scope\");\n if (!rawTenant && !rawScope) return null;\n const { expectedSecret, allowUnsigned: allowUnsigned2 = false } = options;\n if (expectedSecret) {\n if (!secretMatches(headers.get(\"x-substrat-router\"), expectedSecret)) {\n throw new RouterAssertionError(\"router assertion is not signed by a known router\");\n }\n } else if (!allowUnsigned2) {\n throw new RouterAssertionError(\n \"router assertion cannot be verified: this worker has no ROUTER_SECRET configured\"\n );\n }\n if (!rawTenant || !rawScope) {\n throw new RouterAssertionError(\"router assertion is incomplete\");\n }\n if (!ROUTED_ID.test(rawTenant) || !ROUTED_ID.test(rawScope)) {\n throw new RouterAssertionError(\"router assertion carries a malformed id\");\n }\n return {\n tenantId: rawTenant,\n scopeId: rawScope,\n surface: headers.get(\"x-substrat-surface\") ?? \"app\",\n verticalSlug: headers.get(\"x-substrat-vertical\")\n };\n}\n\n// packages/vertical-host/src/invocation-log.ts\nfunction builtinAsyncLocalStorage() {\n try {\n const proc = globalThis.process;\n const mod = proc?.getBuiltinModule?.(\"node:async_hooks\");\n return typeof mod?.AsyncLocalStorage === \"function\" ? mod.AsyncLocalStorage : void 0;\n } catch {\n return void 0;\n }\n}\nfunction storeCallSlot(provided) {\n try {\n const g = globalThis;\n const key = Symbol.for(STORE_CALL_SINK_KEY);\n const existing = g[key];\n if (typeof existing?.run === \"function\" && typeof existing.current === \"function\") return existing;\n const Als = provided ?? builtinAsyncLocalStorage();\n if (!Als) return void 0;\n const storage = new Als();\n const slot2 = {\n current() {\n const tally = storage.getStore()?.tally;\n return tally ? (call) => tallyStoreCall(tally, call) : void 0;\n },\n invocationId: () => storage.getStore()?.invocationId,\n run: (tally, fn, invocationId) => storage.run({ tally, invocationId }, fn),\n recording: () => storage.getStore()?.tally\n };\n g[key] = slot2;\n return slot2;\n } catch {\n return void 0;\n }\n}\nfunction currentRecording() {\n const slot2 = globalThis[Symbol.for(STORE_CALL_SINK_KEY)];\n return typeof slot2?.recording === \"function\" ? slot2.recording() : void 0;\n}\nfunction runRecording(stamp, started, provided, fn) {\n const slot2 = storeCallSlot(provided);\n if (!slot2) return fn();\n try {\n const authSink = {\n record(check) {\n const record2 = currentRecording();\n if (record2) tallyAuthCheck(record2, check);\n }\n };\n globalThis[AUTH_DIAGNOSTICS_KEY] = authSink;\n } catch {\n }\n markRequestStart(stamp.record, started);\n installOutboundRecorder(currentRecording);\n return slot2.run(stamp.record, fn, stamp.invocationId);\n}\nfunction versionIdOf(env) {\n const v = env?.SUBSTRAT_VERSION_ID;\n return typeof v === \"string\" && v.length > 0 ? v : null;\n}\nvar UPLOAD_LINK_LOG_SECRET_PREFIX = \"sbup_\";\nvar UPLOAD_LINK_SECRET_SEGMENT = /^(\\/api\\/attachment-uploads\\/[^/]+\\/[^/]+\\/)[^/]+/;\nvar SECRET_SHAPED_SEGMENT = new RegExp(`(^|/)${UPLOAD_LINK_LOG_SECRET_PREFIX}[^/]*`, \"g\");\nvar redactUploadLinkSecret = (pathname) => pathname.replace(UPLOAD_LINK_SECRET_SEGMENT, \"$1[redacted]\").replace(SECRET_SHAPED_SEGMENT, \"$1[redacted]\");\nfunction pathOf(url) {\n try {\n return redactUploadLinkSecret(new URL(url).pathname);\n } catch {\n return \"/\";\n }\n}\nvar STAMPS = /* @__PURE__ */ Symbol.for(\"substrat.invocation-stamp\");\nfunction stamps() {\n const g = globalThis;\n return g[STAMPS] ??= /* @__PURE__ */ new WeakMap();\n}\nfunction invocationStampOf(request) {\n return stamps().get(request);\n}\nfunction withRequestId(response, id) {\n const headers = response?.headers;\n try {\n headers?.set?.(REQUEST_ID_HEADER, id);\n return response;\n } catch {\n }\n try {\n const r = response;\n if (r.status === 101) return response;\n const copy = new Response(r.body, r);\n copy.headers.set(REQUEST_ID_HEADER, id);\n return copy;\n } catch {\n return response;\n }\n}\nfunction beginStamp(request, env, options) {\n const stamp = { invocationId: ulid(), record: {} };\n if (installedTraceSink()) markTraceStart(stamp.invocationId);\n const fieldCoverageId = armedFieldCoverageId(request.headers, env, options);\n if (fieldCoverageId) stamp.fieldCoverageId = fieldCoverageId;\n stamps().set(request, stamp);\n return stamp;\n}\nfunction armedFieldCoverageId(headers, env, options) {\n let id;\n try {\n id = headers.get(FIELD_COVERAGE_HEADER);\n } catch {\n return void 0;\n }\n if (id === null || !ROUTED_ID.test(id)) return void 0;\n return routedNodeOrNull(headers, env, options) !== null ? id : void 0;\n}\nfunction writeInvocationLine(stamp, done, options) {\n traceRequest(stamp, done);\n try {\n writeLineOrThrow(stamp, done, options);\n } catch (e) {\n try {\n console.log(JSON.stringify({ substrat: \"invocation-log-fault\", detail: String(e) }));\n } catch {\n }\n }\n}\nfunction traceRequest(stamp, done) {\n const sink = installedTraceSink();\n if (!sink) return;\n try {\n const { record: record2, invocationId } = stamp;\n const durationMs = Date.now() - done.started;\n const line = invocationLine({\n tenantId: \"\",\n scopeId: null,\n vertical: null,\n surface: null,\n method: done.request.method,\n path: pathOf(done.request.url),\n status: done.status,\n threw: done.threw,\n durationMs,\n invocationId,\n level: invocationLevelOf(done.status, done.threw, record2.problemCode),\n operation: record2.operation,\n problemCode: record2.problemCode,\n principalKind: record2.principalKind,\n ...record2.emitted ? { emitted: record2.emitted } : {},\n versionId: versionIdOf(done.env)\n });\n sink.head(invocationId, {\n startedAt: new Date(done.started).toISOString(),\n method: line.method,\n path: line.path,\n status: line.status,\n threw: line.threw,\n durationMs: line.durationMs,\n level: line.level,\n operation: line.operation,\n problemCode: line.problemCode,\n principalKind: line.principalKind,\n eventCount: line.eventCount,\n eventTypes: line.eventTypes,\n entities: line.entities,\n versionId: line.versionId,\n // Calls the record kept no room for: a truncated list must read as truncated.\n ...record2.outboundCallsDropped ? { stepsDropped: record2.outboundCallsDropped } : {}\n });\n for (const call of record2.outboundCalls ?? []) {\n sink.step(invocationId, {\n type: \"outbound\",\n atMs: call.atMs,\n durationMs: call.durationMs,\n host: call.host,\n path: call.path,\n method: call.method,\n status: call.status,\n outcome: call.outcome,\n ...call.reason ? { reason: call.reason } : {}\n });\n }\n for (const check of record2.authChecks ?? []) {\n sink.step(invocationId, { type: \"log\", atMs: durationMs, level: check.outcome === \"refused\" || check.outcome === \"error\" ? \"warn\" : \"info\", message: `auth ${check.stage}: ${check.outcome} (${check.reason})` });\n }\n if (record2.authChecksDropped) sink.head(invocationId, { stepsDropped: record2.authChecksDropped });\n sink.end(invocationId);\n forgetTraceStart(invocationId);\n } catch {\n }\n}\nfunction writeLineOrThrow(stamp, done, options) {\n const node = routedNodeOrNull(done.request.headers, done.env, options);\n if (!node) return;\n const { record: record2, invocationId } = stamp;\n const line = invocationLine({\n tenantId: node.tenantId,\n scopeId: node.scopeId,\n vertical: node.verticalSlug,\n surface: node.surface,\n method: done.request.method,\n path: pathOf(done.request.url),\n status: done.status,\n threw: done.threw,\n durationMs: Date.now() - done.started,\n invocationId,\n level: invocationLevelOf(done.status, done.threw, record2.problemCode),\n operation: record2.operation,\n problemCode: record2.problemCode,\n principalKind: record2.principalKind,\n ...record2.emitted ? { emitted: record2.emitted } : {},\n versionId: versionIdOf(done.env),\n ...record2.outputFields ? { outputFields: record2.outputFields } : {},\n ...stamp.fieldCoverageId ? { fieldCoverageId: stamp.fieldCoverageId } : {},\n ...record2.storeCalls && record2.storeCalls.length > 0 ? { storeCalls: record2.storeCalls } : {},\n ...record2.storeCallsDropped ? { storeCallsDropped: record2.storeCallsDropped } : {},\n ...record2.outboundCalls && record2.outboundCalls.length > 0 ? { outboundCalls: record2.outboundCalls } : {},\n ...record2.outboundCallsDropped ? { outboundCallsDropped: record2.outboundCallsDropped } : {},\n ...record2.authChecks?.length ? { authChecks: record2.authChecks } : {},\n ...record2.authChecksDropped ? { authChecksDropped: record2.authChecksDropped } : {}\n });\n console.log(JSON.stringify(line));\n}\nvar OTHER_HANDLERS = [\"scheduled\", \"queue\", \"email\", \"tail\", \"trace\", \"alarm\", \"test\"];\nfunction withInvocationLog(worker, options = {}) {\n const inner = worker?.fetch;\n if (typeof inner !== \"function\") return worker;\n const wrapped = {\n async fetch(request, env, ctx) {\n if (invocationStampOf(request)) return inner.call(worker, request, env, ctx);\n const started = Date.now();\n const stamp = beginStamp(request, env, options);\n let status = null;\n let threw = false;\n try {\n const response = withRequestId(\n await runRecording(stamp, started, options.asyncLocalStorage, () => inner.call(worker, request, env, ctx)),\n stamp.invocationId\n );\n status = response.status;\n handRecordToRouter(response, stamp.record, request, env, options);\n return response;\n } catch (e) {\n threw = true;\n throw e;\n } finally {\n writeInvocationLine(stamp, { request, env, status, threw, started }, options);\n }\n }\n };\n for (const name of OTHER_HANDLERS) {\n const h = worker[name];\n if (typeof h === \"function\") wrapped[name] = h.bind(worker);\n }\n return wrapped;\n}\nfunction handRecordToRouter(response, record2, request, env, options) {\n try {\n const value = encodeInvocationRecord(record2);\n if (value === null || !routedNodeOrNull(request.headers, env, options)) return;\n response.headers?.set?.(\n INVOCATION_RECORD_HEADER,\n value\n );\n } catch {\n }\n}\nfunction routedNodeOrNull(headers, env, options) {\n try {\n return readRoutedNode(headers, {\n expectedSecret: options.routerSecret?.(env),\n allowUnsigned: options.allowUnsigned?.(env) ?? false\n });\n } catch (e) {\n if (!(e instanceof RouterAssertionError)) console.log(JSON.stringify({ substrat: \"invocation-log-fault\", detail: String(e) }));\n return null;\n }\n}\n\n// packages/contracts/dist/scope-store-envelope.js\nfunction bytesToBase64Url(bytes) {\n let binary = \"\";\n for (const byte of bytes)\n binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\nfunction base64UrlToBytes(value) {\n if (!/^[A-Za-z0-9_-]+$/.test(value))\n return void 0;\n const padded = value.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\") + \"=\".repeat((4 - value.length % 4) % 4);\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return bytes;\n } catch {\n return void 0;\n }\n}\nfunction copyBytes(bytes) {\n const copy = new ArrayBuffer(bytes.byteLength);\n new Uint8Array(copy).set(bytes);\n return copy;\n}\nvar SMALL_ORDER_KEYS = [\n \"0000000000000000000000000000000000000000000000000000000000000000\",\n // y = 0, order 4\n \"0100000000000000000000000000000000000000000000000000000000000000\",\n // the identity, order 1\n \"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05\",\n // order 8\n \"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a\",\n // order 8\n \"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p - 1, order 2\n \"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\",\n // y = p, a non-canonical 0\n \"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f\"\n // y = p + 1, a non-canonical identity\n];\nfunction isSmallOrderKey(bytes) {\n const unsigned = Uint8Array.from(bytes);\n unsigned[31] = unsigned[31] & 127;\n const hex = [...unsigned].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return SMALL_ORDER_KEYS.includes(hex);\n}\nasync function scopeStoreKeyId(publicKey) {\n const bytes = base64UrlToBytes(publicKey);\n if (!bytes || bytes.length !== 32)\n throw new Error(\"a store public key is not 32 bytes of base64url\");\n if (isSmallOrderKey(bytes))\n throw new Error(\"a store public key is a small-order point\");\n const hash = await crypto.subtle.digest(\"SHA-256\", copyBytes(bytes));\n return bytesToBase64Url(new Uint8Array(hash).slice(0, 8));\n}\nfunction scopeStorePublicKeyProblem(key) {\n if (key.length === 0)\n return \"empty\";\n const bytes = base64UrlToBytes(key);\n if (bytes?.length !== 32)\n return \"length\";\n if (isSmallOrderKey(bytes))\n return \"small-order\";\n if (bytesToBase64Url(bytes) !== key)\n return \"non-canonical\";\n return void 0;\n}\nvar PUBLIC_KEY_PROBLEM = {\n empty: \"a store public key list is empty or has an empty entry\",\n length: \"a store public key is not 32 bytes of base64url\",\n \"small-order\": \"a store public key is a small-order point\",\n \"non-canonical\": \"a store public key is not canonical base64url\"\n};\nfunction parseScopeStorePublicKeys(text) {\n const keys = text.split(\",\").map((key) => key.trim());\n if (keys.some((key) => key.length === 0))\n throw new Error(PUBLIC_KEY_PROBLEM.empty);\n const seen = /* @__PURE__ */ new Set();\n for (const key of keys) {\n const problem2 = scopeStorePublicKeyProblem(key);\n if (problem2)\n throw new Error(PUBLIC_KEY_PROBLEM[problem2]);\n if (seen.has(key))\n throw new Error(\"a store public key is listed twice\");\n seen.add(key);\n }\n return keys;\n}\nasync function verifyScopeStoreEnvelope(publicKey, canonical, signature) {\n const keyBytes = base64UrlToBytes(publicKey);\n const sigBytes = base64UrlToBytes(signature);\n if (!keyBytes || !sigBytes || sigBytes.length !== 64)\n return false;\n try {\n const key = await crypto.subtle.importKey(\"raw\", copyBytes(keyBytes), { name: \"Ed25519\" }, false, [\"verify\"]);\n return await crypto.subtle.verify(\"Ed25519\", key, copyBytes(sigBytes), new TextEncoder().encode(canonical));\n } catch {\n return false;\n }\n}\n\n// packages/contracts/dist/wire-signing.js\nvar WIRE_ENVELOPE_VERSION = 1;\nvar WIRE_ENVELOPE_TAG = `substrat-wire/${WIRE_ENVELOPE_VERSION}`;\nvar WIRE_ENVELOPE_HEADER = \"x-substrat-wire-envelope\";\nvar WIRE_SIGNATURE_HEADER = \"x-substrat-wire-signature\";\nvar WIRE_ENVELOPE_MAX_LIFETIME_SECONDS = 120;\nvar WIRE_CLOCK_SKEW_SECONDS = 30;\nvar SHAPES = {\n router: {\n // An end user's request the router resolved: always a tenant, a scope and a surface. The\n // body is a stream the router does not buffer, so a route binds none.\n route: { scope: \"required\", surface: \"required\", vertical: \"optional\", body: \"absent\" },\n // An internal call the router makes itself, such as a peer invocation.\n call: { scope: \"optional\", surface: \"absent\", vertical: \"optional\", body: \"required\" }\n },\n platform: {\n call: { scope: \"optional\", surface: \"absent\", vertical: \"absent\", body: \"required\" }\n }\n};\nfunction wireEnvelopeShape(iss, kind) {\n const byKind = Object.hasOwn(SHAPES, iss) ? SHAPES[iss] : void 0;\n return byKind && Object.hasOwn(byKind, kind) ? byKind[kind] : void 0;\n}\nvar LINES = 15;\nvar ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nvar METHOD = /^[!#$%&'*+.^_`|~0-9A-Z-]{1,32}$/;\nvar DIGEST = /^[0-9a-f]{64}$/;\nvar SECONDS = /^(0|[1-9]\\d{0,14})$/;\nvar CONTROL = /[\\u0000-\\u001f\\u007f]/;\nvar LONE_SURROGATE = /[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/;\nvar MAX_TEXT = 255;\nvar isText = (value) => value.length <= MAX_TEXT && !CONTROL.test(value) && !LONE_SURROGATE.test(value);\nvar isWireAudience = (value) => value !== \"\" && isText(value);\nfunction isCanonicalBase64Url(text, length) {\n const bytes = base64UrlToBytes(text);\n return bytes?.length === length && bytesToBase64Url(bytes) === text;\n}\nfunction admits(presence, value, valid) {\n if (value === \"\")\n return presence !== \"required\";\n return presence !== \"absent\" && valid(value);\n}\nfunction parseWireEnvelope(canonical) {\n const lines = canonical.split(\"\\n\");\n if (lines.length !== LINES)\n return void 0;\n const [tag, iss, kind, kid, aud, tenantId, scopeId, surface, vertical2, method, targetDigest, bodyDigest, iat, exp, nonce] = lines;\n if (tag !== WIRE_ENVELOPE_TAG)\n return void 0;\n const shape = wireEnvelopeShape(iss, kind);\n if (!shape)\n return void 0;\n if (!isCanonicalBase64Url(kid, 8) || !isCanonicalBase64Url(nonce, 16))\n return void 0;\n if (!isWireAudience(aud))\n return void 0;\n if (tenantId === \"\" !== (scopeId === \"\"))\n return void 0;\n if (!admits(shape.scope, tenantId, (id) => ULID.test(id)) || !admits(shape.scope, scopeId, (id) => ULID.test(id)))\n return void 0;\n if (!admits(shape.surface, surface, isText) || !admits(shape.vertical, vertical2, isText))\n return void 0;\n if (!METHOD.test(method) || !DIGEST.test(targetDigest) || !admits(shape.body, bodyDigest, (d) => DIGEST.test(d)))\n return void 0;\n if (!SECONDS.test(iat) || !SECONDS.test(exp))\n return void 0;\n const orNull = (value) => value === \"\" ? null : value;\n return {\n v: 1,\n iss,\n kind,\n kid,\n aud,\n tenantId: orNull(tenantId),\n scopeId: orNull(scopeId),\n surface: orNull(surface),\n vertical: orNull(vertical2),\n method,\n targetDigest,\n bodyDigest: orNull(bodyDigest),\n iat: Number(iat),\n exp: Number(exp),\n nonce\n };\n}\nfunction decodeWireEnvelope(header) {\n const bytes = base64UrlToBytes(header);\n if (!bytes)\n return void 0;\n let canonical;\n try {\n canonical = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return void 0;\n }\n const claims = parseWireEnvelope(canonical);\n return claims ? { canonical, claims } : void 0;\n}\nfunction bytesOf(data) {\n if (typeof data === \"string\")\n return new TextEncoder().encode(data);\n const view = ArrayBuffer.isView(data) ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) : new Uint8Array(data);\n return view.buffer instanceof ArrayBuffer ? view : view.slice();\n}\nasync function wireDigest(data) {\n const hash = await crypto.subtle.digest(\"SHA-256\", bytesOf(data));\n return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nfunction wireRequestBinding(request) {\n const url = new URL(request.url);\n return { method: request.method.toUpperCase(), target: `${url.pathname}${url.search}` };\n}\nfunction lifetimeAdmitted(iat, exp) {\n return exp > iat && exp - iat <= WIRE_ENVELOPE_MAX_LIFETIME_SECONDS;\n}\nvar PREPARED = /* @__PURE__ */ new WeakMap();\nasync function wireVerificationKeys(config) {\n const listed = (text) => text?.trim() ? parseScopeStorePublicKeys(text) : [];\n const router = listed(config.router);\n const platform = listed(config.platform);\n if (router.some((key) => platform.includes(key)))\n throw new Error(\"a wire public key is listed for both issuers\");\n const byKid = async (keys2) => new Map(await Promise.all(keys2.map(async (key) => [await scopeStoreKeyId(key), key])));\n const own = Object.freeze({ router: await byKid(router), platform: await byKid(platform) });\n const keys = Object.freeze({ router: new Map(own.router), platform: new Map(own.platform) });\n PREPARED.set(keys, own);\n return keys;\n}\nvar WIRE_REFUSED = Object.freeze({ ok: false });\nasync function verifyWireEnvelope(input) {\n const refuse = (reason) => {\n try {\n void Promise.resolve(input.onRefusal?.(reason)).catch(() => {\n });\n } catch {\n }\n return WIRE_REFUSED;\n };\n const { expected, keys, nowSeconds } = input;\n const own = PREPARED.get(keys);\n if (!own)\n throw new TypeError(\"verifyWireEnvelope takes the key set wireVerificationKeys built\");\n const replay = expected.kind === \"call\" ? expected.replay : \"none\";\n if (replay !== \"none\" && typeof replay?.claim !== \"function\") {\n throw new TypeError(\"a call's expectation states its replay policy: 'none' or a nonce cache\");\n }\n if (replay !== \"none\" && expected.scopeId == null) {\n throw new TypeError(\"a call that keeps nonces pins the scope whose object holds them\");\n }\n if (replay !== \"none\" && typeof input.clockSeconds !== \"function\") {\n throw new TypeError(\"a call that keeps nonces takes a clockSeconds function to time its claim\");\n }\n const header = input.headers.get(WIRE_ENVELOPE_HEADER);\n const signature = input.headers.get(WIRE_SIGNATURE_HEADER);\n if (!header || !signature)\n return refuse(\"missing\");\n const decoded = decodeWireEnvelope(header);\n if (!decoded)\n return refuse(\"malformed\");\n const { canonical, claims } = decoded;\n if (claims.iss !== expected.iss)\n return refuse(\"issuer\");\n if (claims.kind !== expected.kind)\n return refuse(\"kind\");\n const publicKey = own[claims.iss].get(claims.kid);\n if (!publicKey)\n return refuse(\"kid\");\n if (!await verifyScopeStoreEnvelope(publicKey, canonical, signature))\n return refuse(\"signature\");\n if (claims.aud !== expected.aud)\n return refuse(\"audience\");\n if (!lifetimeAdmitted(claims.iat, claims.exp))\n return refuse(\"lifetime\");\n if (!(nowSeconds >= claims.iat - WIRE_CLOCK_SKEW_SECONDS))\n return refuse(\"not-yet-valid\");\n if (!(nowSeconds <= claims.exp + WIRE_CLOCK_SKEW_SECONDS))\n return refuse(\"expired\");\n if (claims.method !== expected.method)\n return refuse(\"method\");\n if (claims.targetDigest !== await wireDigest(expected.target))\n return refuse(\"target\");\n if (expected.kind === \"call\") {\n const body = typeof expected.body === \"function\" ? await expected.body() : expected.body;\n if (body == null || claims.bodyDigest !== await wireDigest(body))\n return refuse(\"body\");\n }\n if (expected.tenantId !== void 0 && claims.tenantId !== expected.tenantId)\n return refuse(\"scope\");\n if (expected.scopeId !== void 0 && claims.scopeId !== expected.scopeId)\n return refuse(\"scope\");\n if (replay !== \"none\") {\n const until = claims.exp + WIRE_CLOCK_SKEW_SECONDS;\n const claimedAt = input.clockSeconds();\n if (!Number.isFinite(claimedAt) || claimedAt < 0) {\n throw new TypeError(\"clockSeconds read something other than a time in seconds\");\n }\n if (!(claimedAt <= until))\n return refuse(\"claim-after-until\");\n if (await replay.claim(claims.nonce, until) !== true)\n return refuse(\"replay\");\n }\n return { ok: true, claims };\n}\nvar WIRE_ROUTER_KEYS_VAR = \"SUBSTRAT_WIRE_ROUTER_KEYS\";\nvar WIRE_PLATFORM_KEYS_VAR = \"SUBSTRAT_WIRE_PLATFORM_KEYS\";\nvar WIRE_AUDIENCE_VAR = \"SUBSTRAT_WIRE_AUDIENCE\";\nvar WIRE_STATE_VAR = \"SUBSTRAT_WIRE_STATE\";\nfunction wireStateOf(config) {\n const listed = (value) => typeof value === \"string\" && value.trim() !== \"\";\n if (!listed(config.routerKeys) && !listed(config.platformKeys))\n return \"legacy-only\";\n return config.state === \"legacy-only\" || config.state === \"signed-only\" ? config.state : \"dual\";\n}\nvar ROUTE_ENDPOINT = Object.freeze({ kind: \"route\", issuers: Object.freeze([\"router\"]) });\nvar CALL_ENDPOINT = Object.freeze({ kind: \"call\", issuers: Object.freeze([\"platform\"]) });\nvar PEER_INVOKE_ENDPOINT = Object.freeze({ kind: \"call\", issuers: Object.freeze([\"platform\", \"router\"]) });\nvar ROUTER_CALLS = Object.freeze([\"/internal/vertical-invoke\", \"/internal/connector-call\", \"/internal/connector-probe\"]);\nfunction tryDecode(path, decoder) {\n try {\n return decoder(path);\n } catch {\n return path.replace(/(?:%[0-9A-Fa-f]{2})+/g, (run) => {\n try {\n return decoder(run);\n } catch {\n return run;\n }\n });\n }\n}\nfunction collapsed(path) {\n const segments = [];\n for (const segment of path.split(\"/\")) {\n if (segment === \"..\")\n segments.pop();\n else if (segment !== \"\" && segment !== \".\")\n segments.push(segment);\n }\n return `/${segments.join(\"/\")}`;\n}\nvar INTERNAL = /^\\/internal(?:\\/|$)/i;\nfunction wireEndpoint(pathname) {\n const routed = tryDecode(pathname.includes(\"%25\") ? pathname.replace(/%25/g, \"%2525\") : pathname, decodeURI);\n const forms = [pathname, routed, tryDecode(pathname, decodeURIComponent)];\n if (!forms.some((form) => INTERNAL.test(form) || INTERNAL.test(collapsed(form))))\n return ROUTE_ENDPOINT;\n return ROUTER_CALLS.includes(pathname) ? PEER_INVOKE_ENDPOINT : CALL_ENDPOINT;\n}\nvar WIRE_REPLAY_FREE_CALLS = Object.freeze([\n \"/internal/query\",\n \"/internal/redrain-count\",\n \"/internal/lifecycle-flow\",\n \"/internal/operation-series\",\n \"/internal/connector-grants\",\n // A connector probe (vertical-connectors.md §6.3) reads no scope and writes nothing in the\n // vertical: any state it changes comes back in the response for the platform to apply. It names\n // no scope either, so there is no store a nonce could be kept in.\n \"/internal/connector-probe\"\n]);\nvar SAFE_METHODS = /* @__PURE__ */ new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\nfunction wireReplayOf(method, pathname) {\n return SAFE_METHODS.has(method.toUpperCase()) || WIRE_REPLAY_FREE_CALLS.includes(pathname) ? \"none\" : \"nonce\";\n}\nvar UNSIGNED = Object.freeze([\n [FIELD_COVERAGE_HEADER, \"route\", (value) => ULID.test(value)],\n [PARENT_REQUEST_ID_HEADER, \"call\", (value) => parentRequestIdOf(value) !== void 0]\n]);\nvar WIRE_UNSIGNED_HEADERS = Object.freeze(Object.fromEntries(UNSIGNED.map(([name, kind]) => [name, kind])));\nfunction wireUnsignedHeadersOf(kind, headers) {\n const kept = [];\n for (const [name, on, valid] of UNSIGNED) {\n const value = on === kind ? headers.get(name) : null;\n if (value !== null && valid(value))\n kept.push([name, value]);\n }\n return kept;\n}\n\n// packages/control-plane-api/platform-entry/wire-gate.ts\nvar WIRE_CLAIM_TIMEOUT_MS = 1e3;\nvar WIRE_REFUSAL_BODY = '{\"type\":\"about:blank\",\"title\":\"Unauthorized\",\"status\":401,\"detail\":\"unauthorized\",\"error\":\"unauthorized\"}';\nvar WIRE_FAULT_BODY = '{\"type\":\"about:blank\",\"title\":\"Service unavailable\",\"status\":503,\"detail\":\"this request could not be verified\",\"error\":\"this request could not be verified\"}';\nvar problem = (body, status) => new Response(body, { status, headers: { \"content-type\": \"application/problem+json\" } });\nvar ASSERTED_PREFIX = \"x-substrat-\";\nvar TENANT = \"x-substrat-tenant\";\nvar SCOPE = \"x-substrat-scope\";\nvar SURFACE = \"x-substrat-surface\";\nvar VERTICAL = \"x-substrat-vertical\";\nvar ROUTER_CREDENTIAL = \"x-substrat-router\";\nvar GateFault = class extends Error {\n constructor(fault) {\n super(fault);\n this.fault = fault;\n }\n fault;\n};\nfunction claimedThrough(reach, timeoutMs) {\n return {\n async claim(nonce, until) {\n let cache;\n try {\n cache = reach();\n } catch {\n throw new GateFault(\"nonce-store\");\n }\n if (cache == null) throw new GateFault(\"no-nonce-store\");\n let timer;\n try {\n return await Promise.race([\n cache.claim(nonce, until),\n new Promise((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"the nonce store did not answer in time\")), timeoutMs);\n })\n ]);\n } catch {\n throw new GateFault(\"nonce-store\");\n } finally {\n clearTimeout(timer);\n }\n }\n };\n}\nvar builtKeys;\nfunction keysFor(router, platform) {\n const text = `${router}\n${platform}`;\n if (builtKeys?.text !== text) builtKeys = { text, keys: wireVerificationKeys({ router, platform }) };\n return builtKeys.keys;\n}\nvar textOf = (value) => typeof value === \"string\" ? value : \"\";\nfunction stateOf(env) {\n const e = env ?? {};\n return wireStateOf({ routerKeys: e[WIRE_ROUTER_KEYS_VAR], platformKeys: e[WIRE_PLATFORM_KEYS_VAR], state: e[WIRE_STATE_VAR] });\n}\nfunction legacyOf(request, call, env, options) {\n if (call) {\n let credential = request.headers.has(PLATFORM_SECRET_HEADER) ? \"invalid\" : \"absent\";\n try {\n assertPlatformCall(request.headers, { expectedSecret: options.platformSecret(env) });\n credential = \"valid\";\n } catch {\n }\n return { credential, identity: null };\n }\n try {\n const node = options.routedNode(request.headers, env);\n return node ? { credential: \"valid\", identity: node } : { credential: \"absent\", identity: null };\n } catch {\n return { credential: \"invalid\", identity: null };\n }\n}\nvar sameIdentity = (legacy, claims) => legacy.tenantId === claims.tenantId && legacy.scopeId === claims.scopeId && legacy.surface === claims.surface && legacy.verticalSlug === claims.vertical;\nvar servedAs = (who) => ({\n tenantId: who?.tenantId ?? null,\n scopeId: who?.scopeId ?? null\n});\nfunction withWireGate(worker, options) {\n const inner = worker?.fetch;\n if (typeof inner !== \"function\") return worker;\n const clock = options.clock ?? Date.now;\n const seconds = () => Math.floor(clock() / 1e3);\n const timeoutMs = options.claimTimeoutMs ?? WIRE_CLAIM_TIMEOUT_MS;\n const log = options.log ?? ((line) => console.log(line));\n const serve = (request, env, ctx) => inner.call(worker, request, env, ctx);\n async function judged(request, env, ctx, state) {\n const nowSeconds = seconds();\n const e = env;\n const aud = textOf(e[WIRE_AUDIENCE_VAR]);\n const { method, target } = wireRequestBinding(request);\n const pathname = new URL(request.url).pathname;\n const endpoint = wireEndpoint(pathname);\n const call = endpoint.kind === \"call\";\n const claimed = call ? decodeWireEnvelope(request.headers.get(WIRE_ENVELOPE_HEADER) ?? \"\")?.claims : void 0;\n const issuer = claimed && endpoint.issuers.includes(claimed.iss) ? claimed.iss : endpoint.issuers[0];\n let claims;\n const line = (outcome, legacy2, extra = {}) => {\n const v = e[\"SUBSTRAT_VERSION_ID\"];\n const record2 = {\n substrat: \"wire\",\n state,\n issuer: claims?.iss ?? (endpoint.issuers.length === 1 ? endpoint.issuers[0] : null),\n kind: endpoint.kind,\n outcome,\n reason: null,\n fault: null,\n legacy: legacy2,\n tenantId: null,\n scopeId: null,\n versionId: typeof v === \"string\" && v.length > 0 ? v : null,\n ...extra\n };\n try {\n log(JSON.stringify(record2));\n } catch {\n }\n };\n const faulted = (fault, legacy2) => {\n line(\"fault\", legacy2, { fault });\n return problem(WIRE_FAULT_BODY, 503);\n };\n const legacy = legacyOf(request, call, env, options);\n let downstream = request;\n const staticFault = (fault, extra = {}) => {\n if (state !== \"dual\") return faulted(fault, legacy.credential);\n line(\"fault\", legacy.credential, { fault, ...extra });\n return serve(downstream, env, ctx);\n };\n let keys;\n try {\n keys = await keysFor(textOf(e[WIRE_ROUTER_KEYS_VAR]), textOf(e[WIRE_PLATFORM_KEYS_VAR]));\n } catch {\n return staticFault(\"keys\", servedAs(legacy.identity));\n }\n const readBody = async () => {\n if (request.body === null) return \"\";\n let body;\n try {\n body = await request.arrayBuffer();\n } catch {\n return null;\n }\n downstream = new Request(request, { body });\n return body;\n };\n const keepsNonces = call && wireReplayOf(method, pathname) === \"nonce\";\n const pinned = keepsNonces ? claimed?.scopeId ?? void 0 : void 0;\n const reach = options.nonceCache;\n const store = pinned !== void 0 && reach ? claimedThrough(() => reach(env, pinned, claimed?.tenantId ?? null), timeoutMs) : void 0;\n const expected = call ? {\n iss: issuer,\n kind: \"call\",\n aud,\n method,\n target,\n body: readBody,\n replay: store ?? \"none\",\n scopeId: store ? pinned : void 0\n } : { iss: \"router\", kind: \"route\", aud, method, target };\n let reason = null;\n let noStore = !store;\n try {\n const verdict = await verifyWireEnvelope({\n headers: request.headers,\n keys,\n expected,\n nowSeconds,\n clockSeconds: seconds,\n onRefusal: (why) => {\n reason = why;\n }\n });\n if (verdict.ok) claims = verdict.claims;\n } catch (error) {\n if (error instanceof GateFault && error.fault === \"no-nonce-store\") {\n claims = claimed;\n noStore = true;\n } else {\n return faulted(error instanceof GateFault ? error.fault : \"verifier\", legacy.credential);\n }\n }\n if (claims && keepsNonces && noStore) {\n return staticFault(claims.scopeId == null ? \"unscoped\" : \"no-nonce-store\", servedAs(legacy.identity ?? claims));\n }\n const mismatched = !!claims && !!legacy.identity && !sameIdentity(legacy.identity, claims);\n if (state === \"dual\" && legacy.credential === \"valid\") {\n const outcome = !claims ? \"legacy-accepted\" : mismatched ? \"dual-mismatch\" : \"signed-accepted\";\n line(outcome, \"valid\", { reason, ...servedAs(legacy.identity ?? claims ?? null) });\n return serve(downstream, env, ctx);\n }\n if (!claims) {\n line(\"refused\", legacy.credential, { reason });\n if (state === \"dual\") return serve(downstream, env, ctx);\n return problem(WIRE_REFUSAL_BODY, 401);\n }\n let proven;\n try {\n proven = provenAs(downstream, claims, env, options);\n } catch {\n return faulted(\"verifier\", legacy.credential);\n }\n line(mismatched ? \"dual-mismatch\" : \"signed-accepted\", legacy.credential, servedAs(claims));\n return serve(proven, env, ctx);\n }\n return {\n ...worker,\n fetch(request, env, ctx) {\n const state = stateOf(env);\n if (state === \"legacy-only\") return serve(request, env, ctx);\n return judged(request, env, ctx, state);\n }\n };\n}\nfunction provenAs(request, claims, env, options) {\n const headers = new Headers(request.headers);\n for (const name of [...headers.keys()]) if (name.startsWith(ASSERTED_PREFIX)) headers.delete(name);\n for (const [name, value] of wireUnsignedHeadersOf(claims.kind, request.headers)) headers.set(name, value);\n const put = (name, value) => {\n if (value) headers.set(name, value);\n };\n if (claims.kind === \"route\") {\n put(TENANT, claims.tenantId);\n put(SCOPE, claims.scopeId);\n put(SURFACE, claims.surface);\n put(VERTICAL, claims.vertical);\n put(ROUTER_CREDENTIAL, options.routerSecret(env));\n } else {\n put(VERTICAL, claims.vertical);\n put(PLATFORM_SECRET_HEADER, options.platformSecret(env));\n }\n return new Request(request, { headers });\n}\n\n// packages/control-plane-api/platform-entry/nonce-store.ts\nfunction nonceStoreOf(registered) {\n return (env, scopeId, tenantId) => {\n const hostFor = registered();\n if (!hostFor) return void 0;\n const store = hostFor(env);\n if (typeof store?.claimWireNonceLocal !== \"function\" || tenantId === null) return void 0;\n const claim = store.claimWireNonceLocal.bind(store);\n return { claim: (nonce, until) => claim(tenantId, scopeId, nonce, until) };\n };\n}\n\n// packages/vertical-host/src/scope-sweep-host.ts\nvar SCOPE_SWEEP_HOST_KEY = \"substrat.scope-sweep-host\";\nfunction slot() {\n return globalThis;\n}\nfunction registeredScopeSweepHost() {\n return slot()[Symbol.for(SCOPE_SWEEP_HOST_KEY)];\n}\n\n// substrat-platform-entry.ts\nimport * as vertical from \"__SUBSTRAT_VERTICAL_ENTRY__\";\nexport * from \"__SUBSTRAT_VERTICAL_ENTRY__\";\nvar routerSecret = (env) => env.ROUTER_SECRET;\nvar allowUnsigned = (env) => env.ALLOW_DEV_NODE === \"true\";\nvar substrat_platform_entry_default = withWireGate(\n withInvocationLog(vertical.default, { routerSecret, allowUnsigned, asyncLocalStorage: AsyncLocalStorage }),\n {\n routedNode: (headers, env) => readRoutedNode(headers, { expectedSecret: routerSecret(env), allowUnsigned: allowUnsigned(env) }),\n routerSecret,\n platformSecret: (env) => env.PLATFORM_SECRET,\n nonceCache: nonceStoreOf(registeredScopeSweepHost)\n }\n);\nexport {\n substrat_platform_entry_default as default\n};\n";
14
14
  /**
15
15
  * #2245: the entry's `node:async_hooks` import, as it appears in `PLATFORM_ENTRY_SOURCE`, and
16
16
  * the line the uploader puts in its place for a script that can have no `AsyncLocalStorage`
@@ -1 +1 @@
1
- {"version":3,"file":"platform-entry.generated.js","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAAA,sOAAsO;AACtO,sEAAsE;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,6BAA6B,CAAC;AAExE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAW,4hlDAA4hlD,CAAC;AAE1klD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yDAAyD,CAAC;AACnG,MAAM,CAAC,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,uBAAuB,GAAW,8pWAA8pW,CAAC"}
1
+ {"version":3,"file":"platform-entry.generated.js","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAAA,sOAAsO;AACtO,sEAAsE;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,6BAA6B,CAAC;AAExE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAW,67lDAA67lD,CAAC;AAE3+lD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yDAAyD,CAAC;AACnG,MAAM,CAAC,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,uBAAuB,GAAW,8pWAA8pW,CAAC"}
@@ -0,0 +1,102 @@
1
+ import { type Connection, type ConnectorCallRequest, type ManifestConnectors, type PlatformActorId, type Scope, type ScopeId, type TenantId, type VerticalConnectorDeclaration } from '@substrat-run/contracts';
2
+ import { type ConnectionBinder, type ConnectorSweeper, type ScopeHost, type ServingPointer } from '@substrat-run/kernel';
3
+ import type { ConnectionInspector } from './api.js';
4
+ import type { PlatformRequestHandler } from './platform-drain.js';
5
+ /**
6
+ * The platform side of a vertical-defined connector (docs/architecture/vertical-connectors.md §6):
7
+ * the sweeper, binder, inspector and dispatch handler the control plane falls back to for a
8
+ * `<namespace>.<name>` provider. Each keeps what the platform keeps for a first-party connector —
9
+ * the sealed credential, the bindings, the connector state, the connection's health — and runs the
10
+ * provider code by calling into the vertical's own deployment, one connection's worth per call.
11
+ *
12
+ * The transport is injected (`call`): the hosted control plane reaches the router's
13
+ * `ConnectorCalls` entrypoint, which dispatches with the target version's `outbound` policy.
14
+ */
15
+ /** Which deployment a call goes to, and the policy the router dispatches it under. */
16
+ export interface VerticalConnectorTarget {
17
+ deploymentRef: string;
18
+ slug: string;
19
+ tenantId: string;
20
+ scopeId: string | null;
21
+ hosts: string[];
22
+ }
23
+ export interface VerticalConnectorDeps {
24
+ host: ScopeHost;
25
+ /** The actor the dispatch handler reads its connection row as. */
26
+ actor: PlatformActorId;
27
+ /** The declaration and the deployment that runs it: the scope's own running version when scopeId is given, else the vertical's serving version. */
28
+ resolve(input: {
29
+ tenantId: TenantId;
30
+ vertical: string;
31
+ scopeId: ScopeId | null;
32
+ provider: string;
33
+ }): Promise<{
34
+ declaration: VerticalConnectorDeclaration;
35
+ target: VerticalConnectorTarget;
36
+ } | {
37
+ refused: string;
38
+ }>;
39
+ call(target: VerticalConnectorTarget, request: ConnectorCallRequest): Promise<{
40
+ status: number;
41
+ body: unknown;
42
+ }>;
43
+ now(): string;
44
+ }
45
+ /** The directory and registry reads {@link resolveVerticalConnectorTarget} decides from. */
46
+ export interface VerticalConnectorReads {
47
+ scope(tenantId: TenantId, scopeId: ScopeId): Promise<Pick<Scope, 'vertical' | 'kind' | 'forkedFrom' | 'verticalVersionId' | 'servingRef'> | null | undefined>;
48
+ /** What the vertical's stable serving script runs, or null before its first in-place serve. */
49
+ serving(vertical: string): Promise<ServingPointer | null>;
50
+ /** The version the vertical's `prod` channel points at, or null. */
51
+ prodVersionId(vertical: string): Promise<string | null>;
52
+ version(vertical: string, versionId: string): Promise<{
53
+ deploymentRef: string | null;
54
+ outbound?: string[] | null;
55
+ } | null | undefined>;
56
+ /** The connectors the version's STORED manifest declares (`connectorsOfManifestJson`). */
57
+ connectors(vertical: string, versionId: string): Promise<ManifestConnectors>;
58
+ }
59
+ /** {@link VerticalConnectorReads} over a host's directory and registry, read as `actor`. */
60
+ export declare function verticalConnectorReadsOf(host: Pick<ScopeHost, 'admin'> & {
61
+ versionConnectors(vertical: string, versionId: string): Promise<ManifestConnectors>;
62
+ }, actor: PlatformActorId): VerticalConnectorReads;
63
+ /**
64
+ * Which declaration a call runs and where it goes (§6.3, §6.4) — `VerticalConnectorDeps.resolve`.
65
+ * A scoped call runs the scope's RUNNING version (`runningVersionOf`) in the deployment that holds
66
+ * its data: its serving script, else that version's own. A connection-level call runs the
67
+ * vertical's serving version, else its prod channel's. The declaration is read off that version's
68
+ * stored manifest on every call, so a promote that drops a connector stops it at the next one; the
69
+ * hosts are that version's declared `outbound`.
70
+ */
71
+ export declare function resolveVerticalConnectorTarget(reads: VerticalConnectorReads, { tenantId, vertical, scopeId, provider }: Parameters<VerticalConnectorDeps['resolve']>[0]): ReturnType<VerticalConnectorDeps['resolve']>;
72
+ /**
73
+ * The poll floor for one vertical-defined connection: one call per bound scope, to that scope's own
74
+ * deployment, carrying that scope's state (§6.1). Built per connection, since the pass hands a
75
+ * sweeper only an id. Answers `{ found, failed, landed }`, which the pass reads
76
+ * (`connectorSweepAnswerOf`).
77
+ */
78
+ export declare function verticalConnectorSweeper(deps: VerticalConnectorDeps, connection: Connection): ConnectorSweeper;
79
+ /**
80
+ * The binder the landing pass binds a vertical-defined connection with (#2316). It lists each
81
+ * binding's DECLARED options, so the pass compares a declaration with what was declared, never with
82
+ * what the connector's `bind` hook normalised it to.
83
+ */
84
+ export declare function verticalConnectorBinder(deps: VerticalConnectorDeps): ConnectionBinder;
85
+ /**
86
+ * What the inspection routes and the relay's connect-time gate ask of a vertical-defined provider,
87
+ * for one (tenant, vertical). `activity`, `credential` and `certificate` are absent, so those
88
+ * routes keep answering 501 / 404 for such a connection.
89
+ */
90
+ export declare function verticalConnectorInspector(deps: VerticalConnectorDeps, provider: string, context: {
91
+ tenantId: TenantId;
92
+ vertical: string;
93
+ scopeId: ScopeId | null;
94
+ }): Required<Pick<ConnectionInspector, 'probe' | 'probeCandidate' | 'bindScope' | 'bindings'>>;
95
+ /**
96
+ * The `connector:<namespace>.<name>` handler: one routed event, dispatched into the drained scope's
97
+ * own deployment with that scope's binding (or none) and state. Expressed as
98
+ * `connectorDispatchHandler` expresses its outcomes: a refusal settles `failed`, anything retryable
99
+ * throws (the drain settles it `pending`), and a delivered event is `done`.
100
+ */
101
+ export declare function verticalConnectorDispatchHandler(deps: VerticalConnectorDeps): PlatformRequestHandler;
102
+ //# sourceMappingURL=vertical-connectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vertical-connectors.d.ts","sourceRoot":"","sources":["../src/vertical-connectors.ts"],"names":[],"mappings":"AAAA,OAAO,EAiBL,KAAK,UAAU,EAIf,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,QAAQ,EAEb,KAAK,4BAA4B,EAClC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAoC,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3J,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAElE;;;;;;;;;GASG;AAEH,sFAAsF;AACtF,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,kEAAkE;IAClE,KAAK,EAAE,eAAe,CAAC;IACvB,mJAAmJ;IACnJ,OAAO,CAAC,KAAK,EAAE;QACb,QAAQ,EAAE,QAAQ,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,4BAA4B,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClH,IAAI,CAAC,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACjH,GAAG,IAAI,MAAM,CAAC;CACf;AAED,4FAA4F;AAC5F,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,mBAAmB,GAAG,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9J,+FAA+F;IAC/F,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC1D,oEAAoE;IACpE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACvI,0FAA0F;IAC1F,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC9E;AAED,4FAA4F;AAC5F,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG;IAAE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;CAAE,EACxH,KAAK,EAAE,eAAe,GACrB,sBAAsB,CAWxB;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,sBAAsB,EAC7B,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GACzF,UAAU,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CA8B9C;AA0ID;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,qBAAqB,EAAE,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAiD9G;AAgDD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,gBAAgB,CAWrF;AA8BD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,qBAAqB,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GACzE,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,gBAAgB,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC,CAoC5F;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,qBAAqB,GAAG,sBAAsB,CA6CpG"}