@creatornader/agent-bridge 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +222 -1
- package/README.md +312 -12
- package/ROADMAP.md +88 -7
- package/SECURITY.md +78 -5
- package/SKILL.md +108 -1
- package/dist/archive.d.ts +2 -2
- package/dist/archive.js +2 -2
- package/dist/{bridge-service-hX1ZQp4W.d.ts → bridge-service-CNBKdYXh.d.ts} +2 -1
- package/dist/{bridge-store-DPVSCwfs.d.ts → bridge-store-ByJ6CaJk.d.ts} +3 -0
- package/dist/bridge.d.ts +25 -8
- package/dist/bridge.js +19 -9
- package/dist/{chunk-MBPZXTJA.js → chunk-7VJI2MXI.js} +285 -42
- package/dist/chunk-7VJI2MXI.js.map +1 -0
- package/dist/{chunk-4VB44KJU.js → chunk-AWE3DFZV.js} +3 -2
- package/dist/chunk-AWE3DFZV.js.map +1 -0
- package/dist/{chunk-GADH244D.js → chunk-E4OWHGUE.js} +16 -5
- package/dist/chunk-E4OWHGUE.js.map +1 -0
- package/dist/{chunk-NCO7RLBM.js → chunk-GTK4KOED.js} +108 -8
- package/dist/chunk-GTK4KOED.js.map +1 -0
- package/dist/{chunk-SPSMZOCJ.js → chunk-HUHG7XTB.js} +6 -5
- package/dist/chunk-HUHG7XTB.js.map +1 -0
- package/dist/{chunk-5GMB3A77.js → chunk-IVG4XWWS.js} +26 -14
- package/dist/chunk-IVG4XWWS.js.map +1 -0
- package/dist/{chunk-WAI2IYIQ.js → chunk-P635FAN4.js} +50 -7
- package/dist/chunk-P635FAN4.js.map +1 -0
- package/dist/{chunk-45BZGB77.js → chunk-QNXHDOJ5.js} +218 -24
- package/dist/chunk-QNXHDOJ5.js.map +1 -0
- package/dist/{chunk-UAHMP6GC.js → chunk-QPC6JHA3.js} +10 -7
- package/dist/chunk-QPC6JHA3.js.map +1 -0
- package/dist/{chunk-Q6PPMXJC.js → chunk-SN7PIVDF.js} +377 -21
- package/dist/chunk-SN7PIVDF.js.map +1 -0
- package/dist/{chunk-A6W4QALF.js → chunk-TC6A7GMF.js} +2 -2
- package/dist/{chunk-2DFNOLMO.js → chunk-XDNT6ZNZ.js} +9 -6
- package/dist/chunk-XDNT6ZNZ.js.map +1 -0
- package/dist/{chunk-CEXBMOI5.js → chunk-Z6JP6MYD.js} +2 -2
- package/dist/cli.js +5867 -438
- package/dist/cli.js.map +1 -1
- package/dist/client-runtime.d.ts +4 -2
- package/dist/client-runtime.js +7 -7
- package/dist/contracts/generate.js +1 -1
- package/dist/dr.d.ts +9 -2
- package/dist/dr.js +6 -4
- package/dist/{gateway-CggQ8vTC.d.ts → gateway-CW-61lvs.d.ts} +27 -3
- package/dist/gateway-main.js +71 -7
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +3 -3
- package/dist/index.js +8 -8
- package/dist/{postgres-bridge-store-Bfd3hRId.d.ts → postgres-bridge-store-C9KG9Z69.d.ts} +1 -1
- package/dist/postgres-production-preflight.d.ts +32 -0
- package/dist/postgres-production-preflight.js +249 -0
- package/dist/postgres-production-preflight.js.map +1 -0
- package/dist/server.js +8 -8
- package/dist/sqlite-edge-store-CdMIOrho.d.ts +148 -0
- package/dist/sqlite.d.ts +19 -80
- package/dist/sqlite.js +11 -3
- package/docs/architecture-v2.md +292 -15
- package/docs/decisions/0004-client-lifecycle-and-endpoint-migration.md +204 -0
- package/docs/deployment.md +349 -0
- package/docs/troubleshooting.md +23 -0
- package/llms.txt +69 -1
- package/openapi/agent-bridge-v2.openapi.json +1151 -124
- package/package.json +10 -2
- package/schemas/agent-bridge-v2.capabilities.json +26 -1
- package/schemas/agent-bridge-v2.mcp.json +11 -1
- package/schemas/agent-bridge-v2.schema.json +167 -0
- package/sql/migrations/007_runtime_role.sql +8 -4
- package/sql/migrations/013_row_isolation.sql +71 -8
- package/sql/migrations/014_owner_control_plane.sql +124 -31
- package/sql/migrations/015_portable_archives.sql +143 -41
- package/sql/migrations/016_native_dr_fence.sql +102 -35
- package/sql/migrations/017_gateway_authority_binding.sql +99 -0
- package/sql/migrations/018_endpoint_migration_challenges.sql +1054 -0
- package/sql/migrations/019_endpoint_migration_same_successor.sql +348 -0
- package/sql/migrations/020_managed_authority_compat.sql +698 -0
- package/sql/migrations/021_native_backup_reader.sql +421 -0
- package/sql/setup.sql +1 -3
- package/dist/chunk-2DFNOLMO.js.map +0 -1
- package/dist/chunk-45BZGB77.js.map +0 -1
- package/dist/chunk-4VB44KJU.js.map +0 -1
- package/dist/chunk-5GMB3A77.js.map +0 -1
- package/dist/chunk-GADH244D.js.map +0 -1
- package/dist/chunk-MBPZXTJA.js.map +0 -1
- package/dist/chunk-NCO7RLBM.js.map +0 -1
- package/dist/chunk-Q6PPMXJC.js.map +0 -1
- package/dist/chunk-SPSMZOCJ.js.map +0 -1
- package/dist/chunk-UAHMP6GC.js.map +0 -1
- package/dist/chunk-WAI2IYIQ.js.map +0 -1
- /package/dist/{chunk-A6W4QALF.js.map → chunk-TC6A7GMF.js.map} +0 -0
- /package/dist/{chunk-CEXBMOI5.js.map → chunk-Z6JP6MYD.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
BridgeService
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AWE3DFZV.js";
|
|
5
5
|
import {
|
|
6
6
|
ContractResponseError,
|
|
7
7
|
ContractValidationError,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
parseResponse,
|
|
17
17
|
validateRequest,
|
|
18
18
|
validateRequestForProtocol
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-E4OWHGUE.js";
|
|
20
20
|
import {
|
|
21
21
|
BridgePrincipalMismatchError,
|
|
22
22
|
BridgeValidationError
|
|
@@ -385,7 +385,16 @@ function createGateway(options) {
|
|
|
385
385
|
rowIsolation = false;
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
|
-
sendOperation(response, 200, "capabilities",
|
|
388
|
+
sendOperation(response, 200, "capabilities", {
|
|
389
|
+
...capabilityDocument({
|
|
390
|
+
surface: "http",
|
|
391
|
+
provider: "gateway",
|
|
392
|
+
selectedProtocolVersion: String(response.getHeader(PROTOCOL_HEADER)),
|
|
393
|
+
requestAuthority: Boolean(options.requestAuthority),
|
|
394
|
+
rowIsolation
|
|
395
|
+
}),
|
|
396
|
+
grantedScopes: [...credential.scopes]
|
|
397
|
+
}, requestId);
|
|
389
398
|
return;
|
|
390
399
|
}
|
|
391
400
|
if (req.method === "GET" && url.pathname === "/v2/status") {
|
|
@@ -393,13 +402,47 @@ function createGateway(options) {
|
|
|
393
402
|
closedQuery(url, "status", []);
|
|
394
403
|
validateRequest("status", {});
|
|
395
404
|
const activeStore = authority?.store ?? options.store;
|
|
405
|
+
const authorityBinding = authority && response.getHeader(PROTOCOL_HEADER) === PROTOCOL_VERSION ? {
|
|
406
|
+
gatewayAuthorityId: authority.gatewayAuthorityId,
|
|
407
|
+
credentialId: authority.credential.id
|
|
408
|
+
} : {};
|
|
396
409
|
if (!activeStore.diagnostics) {
|
|
397
|
-
sendOperation(response, 200, "status", { schemaVersion: "postgres-v2", deliverySupported: false, pending: null, claimed: null, retrying: null, dead: null, principal: credential.principal }, requestId);
|
|
410
|
+
sendOperation(response, 200, "status", { schemaVersion: "postgres-v2", deliverySupported: false, pending: null, claimed: null, retrying: null, dead: null, ...authorityBinding, principal: credential.principal }, requestId);
|
|
398
411
|
} else {
|
|
399
|
-
sendOperation(response, 200, "status", { ...await activeStore.diagnostics(principal), principal: credential.principal }, requestId);
|
|
412
|
+
sendOperation(response, 200, "status", { ...await activeStore.diagnostics(principal), ...authorityBinding, principal: credential.principal }, requestId);
|
|
400
413
|
}
|
|
401
414
|
return;
|
|
402
415
|
}
|
|
416
|
+
if (req.method === "POST" && url.pathname === "/v2/endpoint-migration-challenges") {
|
|
417
|
+
requireCurrentProtocol(response);
|
|
418
|
+
await authorize("issue_endpoint_migration_challenge");
|
|
419
|
+
const input = validateRequestForProtocol("issue_endpoint_migration_challenge", await requestBody(), selectedProtocol(response));
|
|
420
|
+
if (!authority?.endpointMigrationChallenges) throw Object.assign(new Error("endpoint migration challenges require request authority"), { status: 503, code: "security_unavailable" });
|
|
421
|
+
active(abort.signal);
|
|
422
|
+
await authority.beginDomainWork();
|
|
423
|
+
mutationStarted = true;
|
|
424
|
+
sendOperation(response, 200, "issue_endpoint_migration_challenge", await authority.endpointMigrationChallenges.issue({
|
|
425
|
+
challenge: String(input.challenge),
|
|
426
|
+
expectedGatewayAuthorityId: String(input.expectedGatewayAuthorityId),
|
|
427
|
+
verifierCredentialId: String(input.verifierCredentialId)
|
|
428
|
+
}), requestId);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (req.method === "POST" && url.pathname === "/v2/endpoint-migration-challenges/consume") {
|
|
432
|
+
requireCurrentProtocol(response);
|
|
433
|
+
await authorize("consume_endpoint_migration_challenge");
|
|
434
|
+
const input = validateRequestForProtocol("consume_endpoint_migration_challenge", await requestBody(), selectedProtocol(response));
|
|
435
|
+
if (!authority?.endpointMigrationChallenges) throw Object.assign(new Error("endpoint migration challenges require request authority"), { status: 503, code: "security_unavailable" });
|
|
436
|
+
active(abort.signal);
|
|
437
|
+
await authority.beginDomainWork();
|
|
438
|
+
mutationStarted = true;
|
|
439
|
+
sendOperation(response, 200, "consume_endpoint_migration_challenge", await authority.endpointMigrationChallenges.consume({
|
|
440
|
+
challenge: String(input.challenge),
|
|
441
|
+
expectedGatewayAuthorityId: String(input.expectedGatewayAuthorityId),
|
|
442
|
+
issuerCredentialId: String(input.issuerCredentialId)
|
|
443
|
+
}), requestId);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
403
446
|
if (req.method === "POST" && url.pathname === "/v2/messages") {
|
|
404
447
|
await authorize("publish_message");
|
|
405
448
|
const input = validateRequestForProtocol("publish_message", await requestBody(), String(response.getHeader(PROTOCOL_HEADER)));
|
|
@@ -445,7 +488,7 @@ function createGateway(options) {
|
|
|
445
488
|
}
|
|
446
489
|
if (req.method === "POST" && url.pathname === "/v2/deliveries/claim") {
|
|
447
490
|
await authorize("claim_delivery");
|
|
448
|
-
const input =
|
|
491
|
+
const input = validateRequestForProtocol("claim_delivery", await requestBody(), selectedProtocol(response));
|
|
449
492
|
active(abort.signal);
|
|
450
493
|
await authority?.beginDomainWork();
|
|
451
494
|
mutationStarted = true;
|
|
@@ -551,4 +594,4 @@ export {
|
|
|
551
594
|
safeTokenHashEqual,
|
|
552
595
|
createGateway
|
|
553
596
|
};
|
|
554
|
-
//# sourceMappingURL=chunk-
|
|
597
|
+
//# sourceMappingURL=chunk-P635FAN4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gateway.ts","../src/gateway-auth.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { BridgePrincipalMismatchError, BridgeValidationError, type MessageDraft } from \"./bridge-domain.js\";\nimport { BridgeService } from \"./bridge-service.js\";\nimport type { BridgeStore } from \"./bridge-store.js\";\nimport { bearerToken, hashCredential, type CredentialResolver } from \"./gateway-auth.js\";\nimport type { GatewaySecurity } from \"./gateway-security.js\";\nimport type { RequestAuthority, RequestAuthorityContext } from \"./postgres-request-authority.js\";\nimport {\n capabilityDocument,\n ContractResponseError,\n ContractValidationError,\n LEGACY_PROTOCOL_VERSION,\n negotiateProtocolVersion,\n operationContract,\n parseResponse,\n PROTOCOL_HEADER,\n PROTOCOL_VERSION,\n SUPPORTED_PROTOCOL_HEADER,\n SUPPORTED_PROTOCOL_VERSIONS,\n type OperationId,\n validateRequest,\n validateRequestForProtocol,\n} from \"./contracts/registry.js\";\n\nexport interface GatewayOptions {\n store: BridgeStore;\n credentials: CredentialResolver;\n security: GatewaySecurity;\n allowedOrigins?: string[];\n bodyLimitBytes?: number;\n requestDeadlineMs?: number;\n ready?: () => Promise<boolean>;\n /** Reports whether the configured database has verified row isolation. */\n rowIsolationReady?: () => Promise<boolean>;\n /** Production PostgreSQL request authority. Other providers omit this. */\n requestAuthority?: RequestAuthority;\n}\n\ntype Metrics = { requests: number; errors: number; timeouts: number; authFailures: number };\nconst jsonHeaders = { \"content-type\": \"application/json; charset=utf-8\", \"cache-control\": \"no-store\" };\n\ninterface ResponseWriter {\n readonly writableEnded: boolean;\n getHeader(name: string): string | number | readonly string[] | undefined;\n setHeader(name: string, value: string | number | readonly string[]): unknown;\n writeHead(status: number, headers?: any): unknown;\n end(chunk?: any): unknown;\n}\n\nclass BufferedResponse implements ResponseWriter {\n private readonly headers = new Map<string, string | number | readonly string[]>();\n private status: number | undefined;\n private headHeaders: any;\n private body: any;\n\n constructor(private readonly target: ServerResponse) {}\n get writableEnded(): boolean { return this.body !== undefined; }\n getHeader(name: string) { return this.headers.get(name.toLowerCase()) ?? this.target.getHeader(name); }\n setHeader(name: string, value: string | number | readonly string[]) { this.headers.set(name.toLowerCase(), value); return this; }\n writeHead(status: number, headers?: any) {\n this.status = status;\n this.headHeaders = headers;\n return this;\n }\n end(chunk?: any) { this.body = chunk ?? null; return this; }\n flush(): void {\n if (this.target.writableEnded) return;\n for (const [name, value] of this.headers) this.target.setHeader(name, value);\n if (this.status !== undefined) this.target.writeHead(this.status, this.headHeaders);\n if (this.body !== undefined) this.target.end(this.body);\n }\n}\n\nfunction send(res: ResponseWriter, status: number, value: unknown, requestId: string): void {\n if (res.writableEnded) return;\n res.writeHead(status, {\n ...jsonHeaders,\n \"x-request-id\": requestId,\n });\n res.end(JSON.stringify(value));\n}\n\nfunction sendOperation(res: ResponseWriter, status: number, operation: string, value: unknown, requestId: string): void {\n const canonical = parseResponse(operation, value) as Record<string, unknown>;\n const protocolVersion = String(res.getHeader(PROTOCOL_HEADER) ?? PROTOCOL_VERSION);\n if (protocolVersion !== LEGACY_PROTOCOL_VERSION) {\n send(res, status, canonical, requestId);\n return;\n }\n if (operation === \"claim_delivery\") {\n send(res, status, canonical.delivery === null ? null : canonical, requestId);\n return;\n }\n if ([\"cancel_delivery\", \"requeue_delivery\", \"extend_delivery\", \"acknowledge_delivery\", \"negative_acknowledge_delivery\"].includes(operation)) {\n send(res, status, canonical.delivery, requestId);\n return;\n }\n send(res, status, canonical, requestId);\n}\n\nfunction failure(\n res: ResponseWriter,\n status: number,\n code: string,\n requestId: string,\n details: Record<string, unknown> = {},\n): void {\n send(res, status, { error: { code, requestId, ...details } }, requestId);\n}\n\nasync function body(\n req: IncomingMessage,\n limit: number,\n signal: AbortSignal,\n): Promise<Record<string, any>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n const cleanup = () => {\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n signal.removeEventListener(\"abort\", onAbort);\n };\n const finish = (callback: () => void) => {\n cleanup();\n callback();\n };\n const onData = (chunk: Buffer | string) => {\n const buffer = Buffer.from(chunk);\n size += buffer.length;\n if (size > limit) {\n finish(() => reject(Object.assign(new Error(\"body too large\"), {\n status: 413,\n code: \"body_too_large\",\n })));\n req.resume();\n return;\n }\n chunks.push(buffer);\n };\n const onEnd = () => finish(() => {\n if (!size) {\n resolve({});\n return;\n }\n try {\n const parsed = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n if (!parsed || Array.isArray(parsed) || typeof parsed !== \"object\") throw new Error();\n resolve(parsed);\n } catch {\n reject(Object.assign(new Error(\"invalid JSON\"), { status: 400, code: \"malformed_json\" }));\n }\n });\n const onError = (error: Error) => finish(() => reject(error));\n const onAbort = () => {\n finish(() => reject(signal.reason));\n req.resume();\n };\n req.on(\"data\", onData);\n req.on(\"end\", onEnd);\n req.on(\"error\", onError);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n if (signal.aborted) onAbort();\n });\n}\n\nasync function jsonBody(\n req: IncomingMessage,\n limit: number,\n signal: AbortSignal,\n): Promise<Record<string, any>> {\n if (hasRequestBody(req) && req.headers[\"content-type\"]?.split(\";\", 1)[0] !== \"application/json\") {\n throw Object.assign(new Error(\"unsupported media type\"), {\n status: 415,\n code: \"unsupported_media_type\",\n });\n }\n return body(req, limit, signal);\n}\n\nfunction numberParam(value: string | null, name: string): number | undefined {\n if (value === null) return undefined;\n const result = Number(value);\n if (!Number.isSafeInteger(result)) throw new BridgeValidationError(`${name} is invalid`);\n return result;\n}\n\nfunction booleanParam(value: string | null, name: string): boolean | undefined {\n if (value === null) return undefined;\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw new BridgeValidationError(`${name} must be true or false`);\n}\n\nfunction hasRequestBody(req: IncomingMessage): boolean {\n const length = req.headers[\"content-length\"];\n return req.headers[\"transfer-encoding\"] !== undefined || (length !== undefined && length !== \"0\");\n}\n\nfunction pathBoundInput(\n operation: string,\n deliveryId: string,\n rawInput: Record<string, unknown>,\n protocolVersion?: string,\n): Record<string, unknown> {\n if (Object.prototype.hasOwnProperty.call(rawInput, \"deliveryId\")) {\n throw new ContractValidationError(operation, [{ path: \"/deliveryId\", message: \"deliveryId is supplied by the request path\" }]);\n }\n const value = { ...rawInput, deliveryId };\n return protocolVersion\n ? validateRequestForProtocol(operation, value, protocolVersion)\n : validateRequest(operation, value);\n}\n\nfunction active(signal: AbortSignal): void {\n if (signal.aborted) throw signal.reason;\n}\n\nfunction closedQuery(url: URL, operation: string, allowed: readonly string[]): void {\n const unknown = [...url.searchParams.keys()].find((key) => !allowed.includes(key));\n if (unknown) throw new ContractValidationError(operation, [{ path: `/${unknown}`, message: \"Unexpected query parameter\" }]);\n}\n\nfunction selectedProtocol(res: ResponseWriter): string {\n return String(res.getHeader(PROTOCOL_HEADER) ?? PROTOCOL_VERSION);\n}\n\nfunction requireCurrentProtocol(res: ResponseWriter): void {\n if (selectedProtocol(res) === LEGACY_PROTOCOL_VERSION) {\n const error = new Error(\"Operation is not available in protocol 2.0\") as Error & { status: number; code: string };\n error.status = 404;\n error.code = \"not_found\";\n throw error;\n }\n}\n\nexport function createGateway(options: GatewayOptions) {\n const metrics: Metrics = { requests: 0, errors: 0, timeouts: 0, authFailures: 0 };\n const limit = options.bodyLimitBytes ?? 128 * 1024;\n const deadline = options.requestDeadlineMs ?? 10_000;\n const origins = new Set(options.allowedOrigins ?? []);\n\n return createServer((req, res) => {\n const requestId = randomUUID();\n const abort = new AbortController();\n let mutationStarted = false;\n metrics.requests += 1;\n const requestedProtocol = req.headers[PROTOCOL_HEADER];\n const rawRequestedProtocol = Array.isArray(requestedProtocol) ? requestedProtocol[0] : requestedProtocol;\n const initialProtocol = rawRequestedProtocol === undefined || rawRequestedProtocol.trim() === \"\"\n ? LEGACY_PROTOCOL_VERSION\n : (SUPPORTED_PROTOCOL_VERSIONS as readonly string[]).includes(rawRequestedProtocol.trim())\n ? rawRequestedProtocol.trim()\n : PROTOCOL_VERSION;\n res.setHeader(PROTOCOL_HEADER, initialProtocol);\n res.setHeader(SUPPORTED_PROTOCOL_HEADER, SUPPORTED_PROTOCOL_VERSIONS.join(\",\"));\n const timer = setTimeout(() => {\n abort.abort(new Error(\"request deadline exceeded\"));\n metrics.timeouts += 1; metrics.errors += 1;\n res.once(\"finish\", () => {\n if (!req.complete) req.destroy();\n });\n failure(\n res,\n 504,\n mutationStarted ? \"mutation_outcome_unknown\" : \"request_timeout\",\n requestId,\n );\n }, deadline);\n let parsedBody: Promise<Record<string, any>> | undefined;\n const requestBody = () => parsedBody ??= jsonBody(req, limit, abort.signal);\n\n const dispatch = async (authority?: RequestAuthorityContext, response: ResponseWriter = res): Promise<void> => {\n const url = new URL(req.url ?? \"/\", \"http://gateway.invalid\");\n if (req.method === \"GET\" && url.pathname === \"/readyz\") {\n let ready = false;\n try {\n ready = await (options.ready?.() ?? options.store.initialize().then(() => true));\n } catch {\n ready = false;\n }\n send(response, ready ? 200 : 503, { status: ready ? \"ready\" : \"not_ready\" }, requestId);\n return;\n }\n const origin = req.headers.origin;\n if (origin && !origins.has(origin)) {\n failure(response, 403, \"origin_forbidden\", requestId); return;\n }\n const token = bearerToken(req.headers.authorization);\n if (options.requestAuthority && !authority) {\n if (!token) {\n metrics.authFailures += 1;\n failure(response, 401, \"unauthorized\", requestId); return;\n }\n const preflight = await options.credentials.resolve(token, abort.signal);\n active(abort.signal);\n if (!preflight) {\n metrics.authFailures += 1;\n failure(response, 401, \"unauthorized\", requestId); return;\n }\n if (hasRequestBody(req)) await requestBody();\n active(abort.signal);\n const buffered = new BufferedResponse(res);\n await options.requestAuthority!.run(\n preflight.id,\n hashCredential(token),\n requestId,\n abort.signal,\n (context) => dispatch(context, buffered),\n );\n active(abort.signal);\n buffered.flush();\n return;\n }\n const credential = authority?.credential ?? (token ? await options.credentials.resolve(token, abort.signal) : null);\n active(abort.signal);\n if (!credential) {\n metrics.authFailures += 1;\n failure(response, 401, \"unauthorized\", requestId); return;\n }\n if (!Array.isArray(credential.scopes)) {\n failure(response, 503, \"security_unavailable\", requestId); return;\n }\n const service = new BridgeService(authority?.store ?? options.store);\n const security = authority?.security ?? options.security;\n if (url.pathname.startsWith(\"/v2/\") || url.pathname === \"/metrics\") {\n response.setHeader(PROTOCOL_HEADER, negotiateProtocolVersion(req.headers[PROTOCOL_HEADER]));\n }\n const authorize = async (operationId: OperationId): Promise<void> => {\n const requiredScopes = operationContract(operationId).scopes;\n if (requiredScopes.some((scope) => !credential.scopes.includes(scope))) {\n try {\n await security.recordScopeDenial(credential.id, operationId, requestId, abort.signal);\n } catch {\n throw Object.assign(new Error(\"Scope denial could not be audited\"), {\n status: 503,\n code: \"security_unavailable\",\n });\n }\n throw Object.assign(new Error(\"Credential lacks a required scope\"), {\n status: 403, code: \"insufficient_scope\", requiredScopes,\n });\n }\n let decision;\n try {\n decision = await security.consume(credential.id, operationId, requestId, abort.signal);\n } catch {\n throw Object.assign(new Error(\"Rate limit state is unavailable\"), {\n status: 503,\n code: \"security_unavailable\",\n });\n }\n if (!decision.allowed) {\n const retryAfter = Math.max(1, Math.ceil(decision.retryAfterSeconds));\n response.setHeader(\"retry-after\", String(retryAfter));\n throw Object.assign(new Error(\"Credential rate limit exceeded\"), {\n status: 429, code: \"rate_limited\", retryAfterSeconds: retryAfter,\n });\n }\n };\n if (req.method === \"GET\" && url.pathname === \"/metrics\") {\n await authorize(\"gateway_metrics\");\n validateRequest(\"gateway_metrics\", {});\n const result = Object.entries(metrics).map(([key, value]) => `agent_bridge_gateway_${key}_total ${value}`).join(\"\\n\") + \"\\n\";\n parseResponse(\"gateway_metrics\", result);\n response.writeHead(200, {\n ...jsonHeaders,\n \"content-type\": \"text/plain; version=0.0.4\",\n \"x-request-id\": requestId,\n });\n response.end(result);\n return;\n }\n const instanceHeader = req.headers[\"x-agent-bridge-instance\"];\n const principal = {\n ...credential.principal,\n instance: Array.isArray(instanceHeader) ? instanceHeader[0] : instanceHeader,\n };\n\n if (req.method === \"GET\" && url.pathname === \"/v2/capabilities\") {\n requireCurrentProtocol(response);\n await authorize(\"capabilities\");\n closedQuery(url, \"capabilities\", []);\n validateRequest(\"capabilities\", {});\n let rowIsolation = false;\n if (options.requestAuthority && options.rowIsolationReady) {\n try {\n rowIsolation = await options.rowIsolationReady();\n } catch {\n rowIsolation = false;\n }\n }\n sendOperation(response, 200, \"capabilities\", {\n ...capabilityDocument({\n surface: \"http\",\n provider: \"gateway\",\n selectedProtocolVersion: String(response.getHeader(PROTOCOL_HEADER)),\n requestAuthority: Boolean(options.requestAuthority),\n rowIsolation,\n }),\n grantedScopes: [...credential.scopes],\n }, requestId); return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v2/status\") {\n await authorize(\"status\");\n closedQuery(url, \"status\", []);\n validateRequest(\"status\", {});\n const activeStore = authority?.store ?? options.store;\n const authorityBinding = authority && response.getHeader(PROTOCOL_HEADER) === PROTOCOL_VERSION ? {\n gatewayAuthorityId: authority.gatewayAuthorityId,\n credentialId: authority.credential.id,\n } : {};\n if (!activeStore.diagnostics) {\n sendOperation(response, 200, \"status\", { schemaVersion: \"postgres-v2\", deliverySupported: false, pending: null, claimed: null, retrying: null, dead: null, ...authorityBinding, principal: credential.principal }, requestId);\n } else {\n sendOperation(response, 200, \"status\", { ...await activeStore.diagnostics(principal), ...authorityBinding, principal: credential.principal }, requestId);\n }\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v2/endpoint-migration-challenges\") {\n requireCurrentProtocol(response);\n await authorize(\"issue_endpoint_migration_challenge\");\n const input = validateRequestForProtocol(\"issue_endpoint_migration_challenge\", await requestBody(), selectedProtocol(response));\n if (!authority?.endpointMigrationChallenges) throw Object.assign(new Error(\"endpoint migration challenges require request authority\"), { status: 503, code: \"security_unavailable\" });\n active(abort.signal);\n await authority.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 200, \"issue_endpoint_migration_challenge\", await authority.endpointMigrationChallenges.issue({\n challenge: String(input.challenge),\n expectedGatewayAuthorityId: String(input.expectedGatewayAuthorityId),\n verifierCredentialId: String(input.verifierCredentialId),\n }), requestId); return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v2/endpoint-migration-challenges/consume\") {\n requireCurrentProtocol(response);\n await authorize(\"consume_endpoint_migration_challenge\");\n const input = validateRequestForProtocol(\"consume_endpoint_migration_challenge\", await requestBody(), selectedProtocol(response));\n if (!authority?.endpointMigrationChallenges) throw Object.assign(new Error(\"endpoint migration challenges require request authority\"), { status: 503, code: \"security_unavailable\" });\n active(abort.signal);\n await authority.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 200, \"consume_endpoint_migration_challenge\", await authority.endpointMigrationChallenges.consume({\n challenge: String(input.challenge),\n expectedGatewayAuthorityId: String(input.expectedGatewayAuthorityId),\n issuerCredentialId: String(input.issuerCredentialId),\n }), requestId); return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v2/messages\") {\n await authorize(\"publish_message\");\n const input = validateRequestForProtocol(\"publish_message\", await requestBody(), String(response.getHeader(PROTOCOL_HEADER)));\n if (input.source !== undefined && input.source !== principal.agent) {\n throw new BridgePrincipalMismatchError(\"source must match the authenticated principal\");\n }\n const { source: _source, ...draft } = input;\n active(abort.signal);\n await authority?.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 201, \"publish_message\", await service.publish(principal, draft as unknown as MessageDraft), requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v2/history\") {\n await authorize(\"history\");\n closedQuery(url, \"history\", [\"cursor\", \"mailbox\", \"receiptState\", \"limit\", \"type\", \"includeExpired\", \"source\", \"project\", \"since\", \"unacknowledgedBy\", \"unacked_by\", \"threadId\", \"latest\"]);\n const types = url.searchParams.getAll(\"type\");\n const input = validateRequestForProtocol(\"history\", {\n cursor: url.searchParams.get(\"cursor\") ?? undefined,\n mailbox: url.searchParams.get(\"mailbox\") ?? undefined as any,\n receiptState: url.searchParams.get(\"receiptState\") ?? undefined as any,\n limit: numberParam(url.searchParams.get(\"limit\"), \"limit\"),\n types: types.length ? types : undefined,\n includeExpired: booleanParam(url.searchParams.get(\"includeExpired\"), \"includeExpired\"),\n source: url.searchParams.get(\"source\") ?? undefined,\n project: url.searchParams.get(\"project\") ?? undefined,\n since: url.searchParams.get(\"since\") ?? undefined,\n unacknowledgedBy: url.searchParams.get(\"unacknowledgedBy\") ?? url.searchParams.get(\"unacked_by\") ?? undefined,\n threadId: url.searchParams.get(\"threadId\") ?? undefined,\n latest: booleanParam(url.searchParams.get(\"latest\"), \"latest\"),\n }, String(response.getHeader(PROTOCOL_HEADER)));\n sendOperation(response, 200, \"history\", await service.history(principal, input), requestId); return;\n }\n if (req.method === \"POST\" && url.pathname === \"/v2/receipts\") {\n await authorize(\"record_receipt\");\n const input = validateRequest(\"record_receipt\", await requestBody());\n active(abort.signal);\n await authority?.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 200, \"record_receipt\", { recorded: await service.acknowledge(principal, input.messageIds as string[]) }, requestId); return;\n }\n if (req.method === \"POST\" && url.pathname === \"/v2/deliveries/claim\") {\n await authorize(\"claim_delivery\");\n const input = validateRequestForProtocol(\"claim_delivery\", await requestBody(), selectedProtocol(response));\n active(abort.signal);\n await authority?.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 200, \"claim_delivery\", await service.claim(principal, input) ?? { delivery: null }, requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v2/deliveries\") {\n requireCurrentProtocol(response);\n await authorize(\"list_deliveries\");\n closedQuery(url, \"list_deliveries\", [\"cursor\", \"limit\", \"role\", \"messageId\", \"recipient\", \"state\"]);\n const input = validateRequest(\"list_deliveries\", {cursor:url.searchParams.get(\"cursor\")??undefined,limit:numberParam(url.searchParams.get(\"limit\"),\"limit\"),role:url.searchParams.get(\"role\")??undefined,messageId:url.searchParams.get(\"messageId\")??undefined,recipient:url.searchParams.get(\"recipient\")??undefined,states:url.searchParams.getAll(\"state\")});\n sendOperation(response,200,\"list_deliveries\",await service.deliveries(principal,input as any),requestId);return;\n }\n const eventsMatch=url.pathname.match(/^\\/v2\\/deliveries\\/([^/]+)\\/events$/);\n if(req.method===\"GET\"&&eventsMatch){requireCurrentProtocol(response);await authorize(\"list_delivery_events\");closedQuery(url,\"list_delivery_events\",[\"cursor\",\"limit\"]);const input=validateRequest(\"list_delivery_events\",{deliveryId:eventsMatch[1],cursor:url.searchParams.get(\"cursor\")??undefined,limit:numberParam(url.searchParams.get(\"limit\"),\"limit\")});sendOperation(response,200,\"list_delivery_events\",await service.deliveryEvents(principal,eventsMatch[1]!,input as any),requestId);return;}\n const controlMatch=url.pathname.match(/^\\/v2\\/deliveries\\/([^/]+)\\/(cancel|requeue)$/);\n if(req.method===\"POST\"&&controlMatch){requireCurrentProtocol(response);const operation=controlMatch[2]===\"cancel\"?\"cancel_delivery\":\"requeue_delivery\";await authorize(operation);pathBoundInput(operation,controlMatch[1]!,await requestBody());await authority?.beginDomainWork();mutationStarted=true;const result=controlMatch[2]===\"cancel\"?await service.cancel(principal,controlMatch[1]!):await service.requeue(principal,controlMatch[1]!);if(!result)failure(response,404,\"not_found\",requestId);else sendOperation(response,200,operation,{delivery:result},requestId);return;}\n if (req.method === \"POST\" && url.pathname === \"/v2/presence/heartbeat\") {\n await authorize(\"heartbeat\");\n const input = validateRequest(\"heartbeat\", await requestBody());\n active(abort.signal);\n await authority?.beginDomainWork(); mutationStarted = true;\n sendOperation(response, 200, \"heartbeat\", await service.heartbeat(principal, input), requestId); return;\n }\n if (req.method === \"GET\" && url.pathname === \"/v2/presence\") {\n await authorize(\"presence\");\n closedQuery(url, \"presence\", []);\n validateRequest(\"presence\", {});\n sendOperation(response, 200, \"presence\", { agents: await service.presence(principal) }, requestId); return;\n }\n const match = url.pathname.match(/^\\/v2\\/deliveries\\/([^/]+)\\/(extend|ack|nack)$/);\n if (req.method === \"POST\" && match) {\n const operationId = match[2] === \"extend\" ? \"extend_delivery\" : match[2] === \"ack\" ? \"acknowledge_delivery\" : \"negative_acknowledge_delivery\";\n await authorize(operationId);\n const rawInput = await requestBody();\n const protocolVersion = String(response.getHeader(PROTOCOL_HEADER) ?? PROTOCOL_VERSION);\n const input = pathBoundInput(operationId, match[1]!, rawInput, protocolVersion);\n active(abort.signal);\n await authority?.beginDomainWork(); mutationStarted = true;\n const [, id, action] = match;\n const result = action === \"extend\"\n ? await service.extend(principal, id, input.leaseToken as string, input.leaseMs as number)\n : action === \"ack\"\n ? await service.ack(principal, id, input.leaseToken as string)\n : await service.nack(\n principal,\n id,\n input.leaseToken as string,\n (input.error as string | undefined) ?? \"negative acknowledgment\",\n (input.disposition ?? input.dead ?? \"retry\") as \"retry\" | \"dead\" | boolean,\n input.retryPolicy,\n );\n if (!result) failure(response, 409, \"lease_conflict\", requestId);\n else sendOperation(response, 200, operationId, { delivery: result }, requestId);\n return;\n }\n failure(response, 404, \"not_found\", requestId);\n };\n void dispatch().catch((error: any) => {\n if (res.writableEnded) return;\n metrics.errors += 1;\n if (error instanceof ContractValidationError || error instanceof ContractResponseError) {\n failure(res, error.status, error.code, requestId, { operation: error.operation, issues: error.issues });\n } else if (error?.status === 426) {\n failure(res, 426, error.code, requestId, { supportedProtocolVersions: [...SUPPORTED_PROTOCOL_VERSIONS] });\n } else if (error?.code === \"insufficient_scope\") {\n failure(res, 403, error.code, requestId, { details: { requiredScopes: [...error.requiredScopes] } });\n } else if (error?.code === \"rate_limited\") {\n res.setHeader(\"retry-after\", String(error.retryAfterSeconds));\n failure(res, 429, error.code, requestId, { details: { retryAfterSeconds: error.retryAfterSeconds } });\n } else if (error instanceof BridgeValidationError || error instanceof BridgePrincipalMismatchError) {\n failure(res, \"status\" in error ? error.status : 400, error.code, requestId, { message: error.message });\n } else {\n failure(res, error?.status ?? 500, error?.code ?? \"internal_error\", requestId);\n }\n }).finally(() => clearTimeout(timer));\n });\n}\n","import { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { BridgePrincipal } from \"./bridge-domain.js\";\nimport type { AuthorizationScope } from \"./contracts/registry.js\";\nimport type { PgQueryable } from \"./postgres-bridge-store.js\";\n\nexport interface AuthenticatedCredential {\n id: string;\n principal: BridgePrincipal;\n /** Canonical authorization scopes granted to this credential. */\n scopes: readonly AuthorizationScope[];\n}\n\nexport interface CredentialResolver {\n resolve(token: string, signal?: AbortSignal): Promise<AuthenticatedCredential | null>;\n}\n\nexport function hashCredential(token: string): string {\n return createHash(\"sha256\").update(token, \"utf8\").digest(\"hex\");\n}\n\nexport class PostgresCredentialResolver implements CredentialResolver {\n constructor(private readonly db: PgQueryable) {}\n\n async resolve(token: string, signal?: AbortSignal): Promise<AuthenticatedCredential | null> {\n if (signal?.aborted) throw signal.reason;\n const result = await this.db.query<{\n credential_id: string; workspace_id: string; principal: string; scopes: AuthorizationScope[];\n }>(\n `SELECT credential_id,workspace_id,principal,scopes\n FROM agent_bridge.resolve_credential_hash($1::text)`,\n [hashCredential(token)],\n );\n const row = result.rows[0];\n if (signal?.aborted) throw signal.reason;\n return row ? {\n id: row.credential_id,\n principal: { workspace: row.workspace_id, agent: row.principal },\n scopes: row.scopes,\n } : null;\n }\n}\n\nexport function bearerToken(value: string | undefined): string | null {\n if (!value?.startsWith(\"Bearer \")) return null;\n const token = value.slice(7);\n if (!token || token.length > 4096 || /\\s/.test(token)) return null;\n return token;\n}\n\nexport function safeTokenHashEqual(token: string, expectedHash: string): boolean {\n const actual = Buffer.from(hashCredential(token));\n const expected = Buffer.from(expectedHash);\n return actual.length === expected.length && timingSafeEqual(actual, expected);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -56,6 +56,25 @@ var REQUIRED_COLUMNS = /* @__PURE__ */ new Map([
|
|
|
56
56
|
["request_authorities.principal", "text"],
|
|
57
57
|
["request_authorities.scopes", "_text"],
|
|
58
58
|
["request_authorities.opened_session_user", "name"],
|
|
59
|
+
["request_authorities.authorized_endpoint_migration_operation", "text"],
|
|
60
|
+
["gateway_authority.singleton", "bool"],
|
|
61
|
+
["gateway_authority.authority_id", "uuid"],
|
|
62
|
+
["endpoint_migration_challenges.challenge_hash", "bpchar"],
|
|
63
|
+
["endpoint_migration_challenges.authority_id", "uuid"],
|
|
64
|
+
["endpoint_migration_challenges.workspace_id", "text"],
|
|
65
|
+
["endpoint_migration_challenges.principal", "text"],
|
|
66
|
+
["endpoint_migration_challenges.issuer_credential_id", "uuid"],
|
|
67
|
+
["endpoint_migration_challenges.verifier_credential_id", "uuid"],
|
|
68
|
+
["endpoint_migration_challenges.issued_at", "timestamptz"],
|
|
69
|
+
["endpoint_migration_challenges.expires_at", "timestamptz"],
|
|
70
|
+
["endpoint_migration_challenges.consumed_at", "timestamptz"],
|
|
71
|
+
["endpoint_migration_challenge_events.sequence", "int8"],
|
|
72
|
+
["endpoint_migration_challenge_events.event_id", "uuid"],
|
|
73
|
+
["endpoint_migration_challenge_events.request_id", "uuid"],
|
|
74
|
+
["endpoint_migration_challenge_events.event_type", "text"],
|
|
75
|
+
["endpoint_migration_challenge_events.created_at", "timestamptz"],
|
|
76
|
+
["endpoint_migration_challenge_attestations.name", "text"],
|
|
77
|
+
["endpoint_migration_challenge_attestations.catalog_definition", "text"],
|
|
59
78
|
["row_isolation_attestations.name", "text"],
|
|
60
79
|
["row_isolation_attestations.catalog_definition", "text"],
|
|
61
80
|
["row_isolation_attestations.attested_at", "timestamptz"],
|
|
@@ -180,6 +199,20 @@ var REQUIRED_COLUMNS = /* @__PURE__ */ new Map([
|
|
|
180
199
|
["agent_instances.instance", "text"],
|
|
181
200
|
["agent_instances.capabilities", "jsonb"]
|
|
182
201
|
]);
|
|
202
|
+
var RELEASED_MIGRATION_CHECKSUMS = /* @__PURE__ */ new Map([
|
|
203
|
+
["7_runtime_role", /* @__PURE__ */ new Set(["70cca251f736c5e5a9835d5b80645e8816131767127a11a5daa9281bd38004fc"])],
|
|
204
|
+
["13_row_isolation", /* @__PURE__ */ new Set(["52ed880fe6df145181f102421be8a757731713a561acfcc98acdbbca12dcf8e4"])],
|
|
205
|
+
["14_owner_control_plane", /* @__PURE__ */ new Set(["7249901ab5db665fa36d6854202c9db4339f6b989a7c5b8c46b3819c5ab54353"])],
|
|
206
|
+
["15_portable_archives", /* @__PURE__ */ new Set(["b019bbd9b6cfbdc0501d2cb78541de04001cde47c55fd7e011e1f88bd072460d"])],
|
|
207
|
+
["16_native_dr_fence", /* @__PURE__ */ new Set(["801edad796813320bfd5d194abf35c108ab51380027af4f160b7a14a4fc79e11"])],
|
|
208
|
+
["18_endpoint_migration_challenges", /* @__PURE__ */ new Set(["353285c04d8c4287dea75b30779c26f0e38e8572618403c4ed8f8a346eed0c97"])],
|
|
209
|
+
["19_endpoint_migration_same_successor", /* @__PURE__ */ new Set(["feb805b9ba00f82e303a294ec26e3a7ae0f587438e5138f3ead6ad84f54bee5f"])]
|
|
210
|
+
]);
|
|
211
|
+
function migrationRecordMatches(recorded, required) {
|
|
212
|
+
if (recorded.version !== required.version || recorded.name !== required.name) return false;
|
|
213
|
+
if (recorded.checksum === required.checksum) return true;
|
|
214
|
+
return RELEASED_MIGRATION_CHECKSUMS.get(`${required.version}_${required.name}`)?.has(recorded.checksum) === true;
|
|
215
|
+
}
|
|
183
216
|
var REQUIRED_MIGRATIONS = [
|
|
184
217
|
{ version: 1, name: "schema_state" },
|
|
185
218
|
{ version: 2, name: "workspaces_agents_credentials" },
|
|
@@ -196,7 +229,12 @@ var REQUIRED_MIGRATIONS = [
|
|
|
196
229
|
{ version: 13, name: "row_isolation" },
|
|
197
230
|
{ version: 14, name: "owner_control_plane" },
|
|
198
231
|
{ version: 15, name: "portable_archives" },
|
|
199
|
-
{ version: 16, name: "native_dr_fence" }
|
|
232
|
+
{ version: 16, name: "native_dr_fence" },
|
|
233
|
+
{ version: 17, name: "gateway_authority_binding" },
|
|
234
|
+
{ version: 18, name: "endpoint_migration_challenges" },
|
|
235
|
+
{ version: 19, name: "endpoint_migration_same_successor" },
|
|
236
|
+
{ version: 20, name: "managed_authority_compat" },
|
|
237
|
+
{ version: 21, name: "native_backup_reader" }
|
|
200
238
|
];
|
|
201
239
|
function withNativeDrSharedLock(source) {
|
|
202
240
|
if (!/^begin;\s/i.test(source)) {
|
|
@@ -245,7 +283,7 @@ async function loadMigrationPlan(directory) {
|
|
|
245
283
|
async function migrationsReady(db, expected) {
|
|
246
284
|
const applied = await recordedMigrations(db);
|
|
247
285
|
return expected.every(
|
|
248
|
-
(required, index) => applied[index]
|
|
286
|
+
(required, index) => applied[index] !== void 0 && migrationRecordMatches(applied[index], required)
|
|
249
287
|
) && applied.length === expected.length;
|
|
250
288
|
}
|
|
251
289
|
async function rowIsolationReady(db, allowPrivilegedCaller) {
|
|
@@ -254,7 +292,8 @@ async function rowIsolationReady(db, allowPrivilegedCaller) {
|
|
|
254
292
|
('agent_bridge_runtime_' || substr(md5(current_database()),1,16))::name AS runtime_role,
|
|
255
293
|
('agent_bridge_data_owner_' || substr(md5(current_database()),1,16))::name AS data_owner,
|
|
256
294
|
('agent_bridge_context_reader_' || substr(md5(current_database()),1,16))::name AS context_reader,
|
|
257
|
-
('agent_bridge_event_writer_' || substr(md5(current_database()),1,16))::name AS event_writer
|
|
295
|
+
('agent_bridge_event_writer_' || substr(md5(current_database()),1,16))::name AS event_writer,
|
|
296
|
+
(SELECT nspowner FROM pg_namespace WHERE nspname='agent_bridge') AS schema_owner
|
|
258
297
|
), required_roles(role_name) AS (
|
|
259
298
|
SELECT runtime_role FROM names UNION ALL SELECT data_owner FROM names
|
|
260
299
|
UNION ALL SELECT context_reader FROM names UNION ALL SELECT event_writer FROM names
|
|
@@ -262,6 +301,18 @@ async function rowIsolationReady(db, allowPrivilegedCaller) {
|
|
|
262
301
|
VALUES ('messages'),('receipts'),('deliveries'),('delivery_events'),('agent_instances')
|
|
263
302
|
), caller_role AS (
|
|
264
303
|
SELECT * FROM pg_roles WHERE rolname=current_user
|
|
304
|
+
), runtime_membership AS (
|
|
305
|
+
SELECT count(*)=1 AND bool_and(
|
|
306
|
+
NOT membership.admin_option
|
|
307
|
+
AND coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
308
|
+
AND coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
309
|
+
AND membership.grantor=(SELECT schema_owner FROM names)
|
|
310
|
+
) AS ready
|
|
311
|
+
FROM pg_auth_members membership
|
|
312
|
+
JOIN pg_roles granted ON granted.oid=membership.roleid
|
|
313
|
+
JOIN pg_roles member ON member.oid=membership.member
|
|
314
|
+
WHERE member.rolname=current_user
|
|
315
|
+
AND granted.rolname=(SELECT runtime_role::text FROM names)
|
|
265
316
|
), expected_policies(table_name,policy_name,command_name,role_name,needs_workspace,needs_principal) AS (
|
|
266
317
|
SELECT 'messages','messages_owner_all','*',data_owner::text,false,false FROM names UNION ALL
|
|
267
318
|
SELECT 'messages','messages_runtime_select','r',runtime_role::text,true,true FROM names UNION ALL
|
|
@@ -305,7 +356,7 @@ async function rowIsolationReady(db, allowPrivilegedCaller) {
|
|
|
305
356
|
(SELECT rolcanlogin AND rolinherit AND NOT rolsuper AND NOT rolcreatedb
|
|
306
357
|
AND NOT rolcreaterole AND NOT rolreplication AND NOT rolbypassrls
|
|
307
358
|
FROM caller_role)
|
|
308
|
-
AND
|
|
359
|
+
AND (SELECT ready FROM runtime_membership)
|
|
309
360
|
AND NOT EXISTS (
|
|
310
361
|
SELECT 1 FROM pg_roles unexpected
|
|
311
362
|
WHERE unexpected.oid<>(SELECT oid FROM caller_role)
|
|
@@ -525,7 +576,7 @@ async function rowIsolationReady(db, allowPrivilegedCaller) {
|
|
|
525
576
|
row?.rolesReady && callerReady && row.ownershipReady && row.policiesReady && row.functionsReady && row.constraintsReady && row.triggersReady && row.grantsReady && row.catalogReady
|
|
526
577
|
);
|
|
527
578
|
}
|
|
528
|
-
async function
|
|
579
|
+
async function inspectRuntimeSchemaReady(db, options = {}) {
|
|
529
580
|
const columns = await db.query(
|
|
530
581
|
`SELECT relation.relname AS table_name, attribute.attname AS column_name,
|
|
531
582
|
type.typname AS udt_name
|
|
@@ -584,11 +635,70 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
584
635
|
to_regprocedure('agent_bridge.consume_rate_limit(uuid,text,uuid)') IS NOT NULL AS "rateConsume",
|
|
585
636
|
to_regprocedure('agent_bridge.security_schema_ready()') IS NOT NULL AS "securityReady",
|
|
586
637
|
to_regclass('agent_bridge.request_authorities') IS NOT NULL AS "requestAuthorities",
|
|
638
|
+
to_regclass('agent_bridge.gateway_authority') IS NOT NULL AS "gatewayAuthority",
|
|
639
|
+
(
|
|
640
|
+
(SELECT attribute.attnotnull
|
|
641
|
+
FROM pg_attribute attribute
|
|
642
|
+
WHERE attribute.attrelid=to_regclass('agent_bridge.gateway_authority')
|
|
643
|
+
AND attribute.attname='singleton' AND attribute.attnum>0 AND NOT attribute.attisdropped)
|
|
644
|
+
AND (SELECT attribute.attnotnull
|
|
645
|
+
FROM pg_attribute attribute
|
|
646
|
+
WHERE attribute.attrelid=to_regclass('agent_bridge.gateway_authority')
|
|
647
|
+
AND attribute.attname='authority_id' AND attribute.attnum>0 AND NOT attribute.attisdropped)
|
|
648
|
+
AND EXISTS (
|
|
649
|
+
SELECT 1 FROM pg_constraint table_constraint
|
|
650
|
+
WHERE table_constraint.conrelid=to_regclass('agent_bridge.gateway_authority')
|
|
651
|
+
AND table_constraint.conname='gateway_authority_singleton'
|
|
652
|
+
AND table_constraint.contype='p'
|
|
653
|
+
AND table_constraint.conkey::smallint[]=ARRAY[(SELECT attribute.attnum FROM pg_attribute attribute
|
|
654
|
+
WHERE attribute.attrelid=to_regclass('agent_bridge.gateway_authority')
|
|
655
|
+
AND attribute.attname='singleton' AND attribute.attnum>0 AND NOT attribute.attisdropped)]
|
|
656
|
+
)
|
|
657
|
+
AND EXISTS (
|
|
658
|
+
SELECT 1 FROM pg_constraint table_constraint
|
|
659
|
+
WHERE table_constraint.conrelid=to_regclass('agent_bridge.gateway_authority')
|
|
660
|
+
AND table_constraint.conname='gateway_authority_singleton_true'
|
|
661
|
+
AND table_constraint.contype='c'
|
|
662
|
+
AND regexp_replace(
|
|
663
|
+
pg_get_expr(table_constraint.conbin,table_constraint.conrelid),'[[:space:]()]','','g'
|
|
664
|
+
)='singleton'
|
|
665
|
+
)
|
|
666
|
+
AND EXISTS (
|
|
667
|
+
SELECT 1 FROM pg_constraint table_constraint
|
|
668
|
+
WHERE table_constraint.conrelid=to_regclass('agent_bridge.gateway_authority')
|
|
669
|
+
AND table_constraint.conname='gateway_authority_id_unique'
|
|
670
|
+
AND table_constraint.contype='u'
|
|
671
|
+
AND table_constraint.conkey::smallint[]=ARRAY[(SELECT attribute.attnum FROM pg_attribute attribute
|
|
672
|
+
WHERE attribute.attrelid=to_regclass('agent_bridge.gateway_authority')
|
|
673
|
+
AND attribute.attname='authority_id' AND attribute.attnum>0 AND NOT attribute.attisdropped)]
|
|
674
|
+
)
|
|
675
|
+
) AS "gatewayAuthorityShape",
|
|
676
|
+
EXISTS (
|
|
677
|
+
SELECT 1
|
|
678
|
+
FROM pg_trigger trigger
|
|
679
|
+
JOIN pg_proc trigger_function ON trigger_function.oid=trigger.tgfoid
|
|
680
|
+
JOIN pg_namespace trigger_namespace ON trigger_namespace.oid=trigger_function.pronamespace
|
|
681
|
+
WHERE trigger.tgrelid=to_regclass('agent_bridge.gateway_authority')
|
|
682
|
+
AND trigger.tgname='gateway_authority_immutable'
|
|
683
|
+
AND NOT trigger.tgisinternal AND trigger.tgenabled='O'
|
|
684
|
+
AND (trigger.tgtype::integer & 1)=0
|
|
685
|
+
AND (trigger.tgtype::integer & 2)=2
|
|
686
|
+
AND (trigger.tgtype::integer & 56)=56
|
|
687
|
+
AND trigger_function.proname='reject_gateway_authority_mutation'
|
|
688
|
+
AND trigger_namespace.nspname='agent_bridge'
|
|
689
|
+
AND trigger_function.proowner=(SELECT nspowner FROM pg_namespace WHERE nspname='agent_bridge')
|
|
690
|
+
AND NOT trigger_function.prosecdef
|
|
691
|
+
AND coalesce(trigger_function.proconfig @> ARRAY['search_path=""'],false)
|
|
692
|
+
) AS "gatewayAuthorityImmutable",
|
|
587
693
|
to_regprocedure('agent_bridge.open_request_authority(uuid,text,uuid)') IS NOT NULL
|
|
588
694
|
AND to_regprocedure('agent_bridge.resolve_credential_hash(text)') IS NOT NULL AS "authorityOpen",
|
|
695
|
+
to_regprocedure('agent_bridge.open_request_authority_bound(uuid,text,uuid)') IS NOT NULL AS "authorityBoundOpen",
|
|
589
696
|
to_regprocedure('agent_bridge.close_request_authority()') IS NOT NULL AS "authorityClose",
|
|
697
|
+
to_regprocedure('agent_bridge.gateway_authority_ready()') IS NOT NULL AS "authorityReady",
|
|
590
698
|
NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.credentials','SELECT') AS "credentialDigestHidden",
|
|
591
699
|
NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.request_authorities','SELECT') AS "authorityRowsHidden",
|
|
700
|
+
(NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.gateway_authority','SELECT')
|
|
701
|
+
AND NOT has_table_privilege('public','agent_bridge.gateway_authority','SELECT')) AS "gatewayAuthorityRowsHidden",
|
|
592
702
|
(NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.agents','SELECT')
|
|
593
703
|
AND NOT has_table_privilege((SELECT runtime_role FROM names),'agent_bridge.workspaces','SELECT')) AS "principalTablesHidden",
|
|
594
704
|
(
|
|
@@ -596,7 +706,8 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
596
706
|
SELECT 1
|
|
597
707
|
FROM unnest(ARRAY[
|
|
598
708
|
'agent_bridge.credentials','agent_bridge.agents',
|
|
599
|
-
'agent_bridge.workspaces','agent_bridge.request_authorities'
|
|
709
|
+
'agent_bridge.workspaces','agent_bridge.request_authorities',
|
|
710
|
+
'agent_bridge.gateway_authority'
|
|
600
711
|
]) protected_table(value)
|
|
601
712
|
CROSS JOIN unnest(ARRAY[
|
|
602
713
|
'SELECT','INSERT','UPDATE','DELETE','TRUNCATE','REFERENCES','TRIGGER'
|
|
@@ -609,7 +720,8 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
609
720
|
SELECT 1
|
|
610
721
|
FROM unnest(ARRAY[
|
|
611
722
|
'agent_bridge.credentials','agent_bridge.agents',
|
|
612
|
-
'agent_bridge.workspaces','agent_bridge.request_authorities'
|
|
723
|
+
'agent_bridge.workspaces','agent_bridge.request_authorities',
|
|
724
|
+
'agent_bridge.gateway_authority'
|
|
613
725
|
]) protected_table(value)
|
|
614
726
|
CROSS JOIN unnest(ARRAY['SELECT','INSERT','UPDATE','REFERENCES']) requested_privilege(value)
|
|
615
727
|
WHERE has_any_column_privilege(
|
|
@@ -617,10 +729,26 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
617
729
|
)
|
|
618
730
|
)
|
|
619
731
|
) AS "authorityTablesLocked",
|
|
732
|
+
NOT EXISTS (
|
|
733
|
+
SELECT 1
|
|
734
|
+
FROM unnest(ARRAY[
|
|
735
|
+
'SELECT','INSERT','UPDATE','DELETE','TRUNCATE','REFERENCES','TRIGGER'
|
|
736
|
+
]) requested_privilege(value)
|
|
737
|
+
WHERE has_table_privilege('public','agent_bridge.gateway_authority',requested_privilege.value)
|
|
738
|
+
)
|
|
739
|
+
AND NOT EXISTS (
|
|
740
|
+
SELECT 1
|
|
741
|
+
FROM unnest(ARRAY['SELECT','INSERT','UPDATE','REFERENCES']) requested_privilege(value)
|
|
742
|
+
WHERE has_any_column_privilege(
|
|
743
|
+
'public','agent_bridge.gateway_authority',requested_privilege.value
|
|
744
|
+
)
|
|
745
|
+
) AS "gatewayAuthorityPublicLocked",
|
|
620
746
|
(
|
|
621
747
|
has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.resolve_credential_hash(text)','EXECUTE')
|
|
622
748
|
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.open_request_authority(uuid,text,uuid)','EXECUTE')
|
|
749
|
+
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.open_request_authority_bound(uuid,text,uuid)','EXECUTE')
|
|
623
750
|
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.close_request_authority()','EXECUTE')
|
|
751
|
+
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.gateway_authority_ready()','EXECUTE')
|
|
624
752
|
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.record_scope_denial(uuid,text,uuid)','EXECUTE')
|
|
625
753
|
AND has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.consume_rate_limit(uuid,text,uuid)','EXECUTE')
|
|
626
754
|
AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.active_request_authority()','EXECUTE')
|
|
@@ -629,7 +757,9 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
629
757
|
AND NOT has_function_privilege((SELECT runtime_role FROM names),'agent_bridge.consume_rate_limit_unbound_011(uuid,text,uuid)','EXECUTE')
|
|
630
758
|
AND NOT has_function_privilege('public','agent_bridge.resolve_credential_hash(text)','EXECUTE')
|
|
631
759
|
AND NOT has_function_privilege('public','agent_bridge.open_request_authority(uuid,text,uuid)','EXECUTE')
|
|
760
|
+
AND NOT has_function_privilege('public','agent_bridge.open_request_authority_bound(uuid,text,uuid)','EXECUTE')
|
|
632
761
|
AND NOT has_function_privilege('public','agent_bridge.close_request_authority()','EXECUTE')
|
|
762
|
+
AND NOT has_function_privilege('public','agent_bridge.gateway_authority_ready()','EXECUTE')
|
|
633
763
|
AND NOT has_function_privilege('public','agent_bridge.record_scope_denial(uuid,text,uuid)','EXECUTE')
|
|
634
764
|
AND NOT has_function_privilege('public','agent_bridge.consume_rate_limit(uuid,text,uuid)','EXECUTE')
|
|
635
765
|
AND NOT has_function_privilege('public','agent_bridge.record_scope_denial_unbound_011(uuid,text,uuid)','EXECUTE')
|
|
@@ -639,7 +769,8 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
639
769
|
JOIN pg_namespace namespace ON namespace.oid=procedure.pronamespace
|
|
640
770
|
WHERE namespace.nspname='agent_bridge'
|
|
641
771
|
AND procedure.proname IN (
|
|
642
|
-
'resolve_credential_hash','open_request_authority','
|
|
772
|
+
'resolve_credential_hash','open_request_authority','open_request_authority_bound',
|
|
773
|
+
'gateway_authority_ready','active_request_authority',
|
|
643
774
|
'assert_active_request_credential','close_request_authority','record_scope_denial',
|
|
644
775
|
'consume_rate_limit','record_scope_denial_unbound_011','consume_rate_limit_unbound_011'
|
|
645
776
|
)
|
|
@@ -653,22 +784,84 @@ async function runtimeSchemaReady(db, options = {}) {
|
|
|
653
784
|
);
|
|
654
785
|
const row = objects.rows[0];
|
|
655
786
|
if (!Boolean(
|
|
656
|
-
row?.immutable && row.deliveryAudit && row.idempotency && row.claim && row.publisher && row.terminal && row.source && row.thread && row.created && row.presence && row.project && row.targets && row.scopeSets && row.securityEvents && row.ratePolicies && row.rateBuckets && row.replacement && row.rateCleanup && row.credentialSecurity && row.eventAppendOnly && row.scopeAudit && row.rateConsume && row.securityReady && row.requestAuthorities && row.authorityOpen && row.authorityClose && row.credentialDigestHidden && row.authorityRowsHidden && row.principalTablesHidden && row.authorityTablesLocked && row.authorityCatalog
|
|
787
|
+
row?.immutable && row.deliveryAudit && row.idempotency && row.claim && row.publisher && row.terminal && row.source && row.thread && row.created && row.presence && row.project && row.targets && row.scopeSets && row.securityEvents && row.ratePolicies && row.rateBuckets && row.replacement && row.rateCleanup && row.credentialSecurity && row.eventAppendOnly && row.scopeAudit && row.rateConsume && row.securityReady && row.requestAuthorities && row.gatewayAuthority && row.gatewayAuthorityShape && row.gatewayAuthorityImmutable && row.authorityOpen && row.authorityBoundOpen && row.authorityClose && row.authorityReady && row.credentialDigestHidden && row.authorityRowsHidden && row.gatewayAuthorityRowsHidden && row.principalTablesHidden && row.authorityTablesLocked && row.gatewayAuthorityPublicLocked && row.authorityCatalog
|
|
657
788
|
)) return false;
|
|
789
|
+
const endpointChallenge = await db.query(`
|
|
790
|
+
WITH names AS (
|
|
791
|
+
SELECT ('agent_bridge_runtime_' || substr(md5(current_database()),1,16))::name AS runtime_role
|
|
792
|
+
) SELECT
|
|
793
|
+
to_regclass('agent_bridge.endpoint_migration_challenges') IS NOT NULL
|
|
794
|
+
AND to_regclass('agent_bridge.endpoint_migration_challenge_events') IS NOT NULL
|
|
795
|
+
AND to_regclass('agent_bridge.endpoint_migration_challenge_attestations') IS NOT NULL AS tables,
|
|
796
|
+
to_regprocedure('agent_bridge.issue_endpoint_migration_challenge(uuid,uuid,text)') IS NOT NULL
|
|
797
|
+
AND to_regprocedure('agent_bridge.consume_endpoint_migration_challenge(uuid,uuid,text)') IS NOT NULL
|
|
798
|
+
AND to_regprocedure('agent_bridge.endpoint_migration_challenge_ready()') IS NOT NULL AS functions,
|
|
799
|
+
NOT EXISTS (
|
|
800
|
+
SELECT 1
|
|
801
|
+
FROM unnest(ARRAY[
|
|
802
|
+
'agent_bridge.endpoint_migration_challenges',
|
|
803
|
+
'agent_bridge.endpoint_migration_challenge_events',
|
|
804
|
+
'agent_bridge.endpoint_migration_challenge_attestations'
|
|
805
|
+
]) relation_name
|
|
806
|
+
CROSS JOIN unnest(ARRAY['SELECT','INSERT','UPDATE','DELETE','TRUNCATE','REFERENCES','TRIGGER']) privilege
|
|
807
|
+
WHERE has_table_privilege((SELECT runtime_role FROM names),relation_name,privilege)
|
|
808
|
+
OR has_table_privilege('public',relation_name,privilege)
|
|
809
|
+
)
|
|
810
|
+
AND has_function_privilege((SELECT runtime_role FROM names),
|
|
811
|
+
'agent_bridge.issue_endpoint_migration_challenge(uuid,uuid,text)','EXECUTE')
|
|
812
|
+
AND has_function_privilege((SELECT runtime_role FROM names),
|
|
813
|
+
'agent_bridge.consume_endpoint_migration_challenge(uuid,uuid,text)','EXECUTE')
|
|
814
|
+
AND NOT has_function_privilege('public',
|
|
815
|
+
'agent_bridge.issue_endpoint_migration_challenge(uuid,uuid,text)','EXECUTE')
|
|
816
|
+
AND NOT has_function_privilege('public',
|
|
817
|
+
'agent_bridge.consume_endpoint_migration_challenge(uuid,uuid,text)','EXECUTE')
|
|
818
|
+
AND NOT EXISTS (
|
|
819
|
+
SELECT 1
|
|
820
|
+
FROM pg_catalog.pg_proc procedure
|
|
821
|
+
JOIN pg_catalog.pg_namespace namespace ON namespace.oid=procedure.pronamespace
|
|
822
|
+
WHERE namespace.nspname='agent_bridge'
|
|
823
|
+
AND procedure.proname IN (
|
|
824
|
+
'guard_endpoint_migration_challenge',
|
|
825
|
+
'reject_endpoint_migration_challenge_truncate',
|
|
826
|
+
'reject_endpoint_migration_challenge_event_mutation',
|
|
827
|
+
'reject_endpoint_migration_challenge_attestation_mutation',
|
|
828
|
+
'cleanup_endpoint_migration_challenges',
|
|
829
|
+
'endpoint_migration_challenge_active_credential',
|
|
830
|
+
'endpoint_migration_challenge_direct_lineage',
|
|
831
|
+
'endpoint_migration_challenge_catalog_definition',
|
|
832
|
+
'endpoint_migration_challenge_ready'
|
|
833
|
+
)
|
|
834
|
+
AND has_function_privilege((SELECT runtime_role FROM names),procedure.oid,'EXECUTE')
|
|
835
|
+
) AS grants,
|
|
836
|
+
EXISTS (
|
|
837
|
+
SELECT 1 FROM pg_catalog.pg_attribute
|
|
838
|
+
WHERE attrelid='agent_bridge.request_authorities'::regclass
|
|
839
|
+
AND attname='authorized_endpoint_migration_operation'
|
|
840
|
+
AND NOT attnotnull
|
|
841
|
+
) AS marker
|
|
842
|
+
`);
|
|
843
|
+
const endpoint = endpointChallenge.rows[0];
|
|
844
|
+
if (!endpoint?.tables || !endpoint.functions || !endpoint.grants || !endpoint.marker) return false;
|
|
845
|
+
const security = await db.query(
|
|
846
|
+
"SELECT agent_bridge.security_schema_ready() AS ready"
|
|
847
|
+
);
|
|
848
|
+
const ownerControl = await db.query(
|
|
849
|
+
"SELECT agent_bridge.owner_control_plane_ready() AS ready"
|
|
850
|
+
);
|
|
851
|
+
const portableArchive = await db.query(
|
|
852
|
+
"SELECT agent_bridge.portable_archive_ready() AS ready"
|
|
853
|
+
);
|
|
854
|
+
const gatewayAuthority = await db.query(
|
|
855
|
+
"SELECT agent_bridge.gateway_authority_ready() AS ready"
|
|
856
|
+
);
|
|
857
|
+
return security.rows[0]?.ready === true && ownerControl.rows[0]?.ready === true && portableArchive.rows[0]?.ready === true && gatewayAuthority.rows[0]?.ready === true && await rowIsolationReady(
|
|
858
|
+
db,
|
|
859
|
+
options.allowPrivilegedCaller === true
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
async function runtimeSchemaReady(db, options = {}) {
|
|
658
863
|
try {
|
|
659
|
-
|
|
660
|
-
"SELECT agent_bridge.security_schema_ready() AS ready"
|
|
661
|
-
);
|
|
662
|
-
const ownerControl = await db.query(
|
|
663
|
-
"SELECT agent_bridge.owner_control_plane_ready() AS ready"
|
|
664
|
-
);
|
|
665
|
-
const portableArchive = await db.query(
|
|
666
|
-
"SELECT agent_bridge.portable_archive_ready() AS ready"
|
|
667
|
-
);
|
|
668
|
-
return security.rows[0]?.ready === true && ownerControl.rows[0]?.ready === true && portableArchive.rows[0]?.ready === true && await rowIsolationReady(
|
|
669
|
-
db,
|
|
670
|
-
options.allowPrivilegedCaller === true
|
|
671
|
-
);
|
|
864
|
+
return await inspectRuntimeSchemaReady(db, options);
|
|
672
865
|
} catch {
|
|
673
866
|
return false;
|
|
674
867
|
}
|
|
@@ -679,7 +872,7 @@ async function runMigrations(db, directory) {
|
|
|
679
872
|
const applied = await recordedMigrations(db);
|
|
680
873
|
const recorded = applied.find((entry) => entry.version === migration.version);
|
|
681
874
|
if (recorded) {
|
|
682
|
-
if (recorded
|
|
875
|
+
if (!migrationRecordMatches(recorded, migration)) {
|
|
683
876
|
throw new Error(`migration ${migration.version}_${migration.name} conflicts with schema state`);
|
|
684
877
|
}
|
|
685
878
|
continue;
|
|
@@ -699,6 +892,7 @@ async function runMigrations(db, directory) {
|
|
|
699
892
|
|
|
700
893
|
export {
|
|
701
894
|
NATIVE_DR_ADVISORY_LOCK_KEY,
|
|
895
|
+
migrationRecordMatches,
|
|
702
896
|
REQUIRED_MIGRATIONS,
|
|
703
897
|
loadMigrationPlan,
|
|
704
898
|
migrationsReady,
|
|
@@ -706,4 +900,4 @@ export {
|
|
|
706
900
|
runtimeSchemaReady,
|
|
707
901
|
runMigrations
|
|
708
902
|
};
|
|
709
|
-
//# sourceMappingURL=chunk-
|
|
903
|
+
//# sourceMappingURL=chunk-QNXHDOJ5.js.map
|