@creatornader/agent-bridge 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +174 -5
  2. package/README.md +341 -33
  3. package/ROADMAP.md +78 -16
  4. package/SECURITY.md +68 -1
  5. package/SKILL.md +104 -1
  6. package/dist/archive.d.ts +2 -2
  7. package/dist/archive.js +2 -2
  8. package/dist/{bridge-service-hX1ZQp4W.d.ts → bridge-service-YTjGr91A.d.ts} +1 -1
  9. package/dist/{bridge-store-DPVSCwfs.d.ts → bridge-store-Boaj-ZbO.d.ts} +2 -0
  10. package/dist/bridge.d.ts +17 -7
  11. package/dist/bridge.js +15 -7
  12. package/dist/{chunk-WAI2IYIQ.js → chunk-3YHVUPU2.js} +48 -5
  13. package/dist/chunk-3YHVUPU2.js.map +1 -0
  14. package/dist/{chunk-45BZGB77.js → chunk-6BTJE6D4.js} +168 -7
  15. package/dist/chunk-6BTJE6D4.js.map +1 -0
  16. package/dist/{chunk-5GMB3A77.js → chunk-DQOZJJZ2.js} +22 -10
  17. package/dist/chunk-DQOZJJZ2.js.map +1 -0
  18. package/dist/{chunk-NCO7RLBM.js → chunk-GTK4KOED.js} +108 -8
  19. package/dist/chunk-GTK4KOED.js.map +1 -0
  20. package/dist/{chunk-GADH244D.js → chunk-IHZFI7TH.js} +12 -4
  21. package/dist/chunk-IHZFI7TH.js.map +1 -0
  22. package/dist/{chunk-CEXBMOI5.js → chunk-LAHNQZDN.js} +2 -2
  23. package/dist/{chunk-UAHMP6GC.js → chunk-MCKKVNCE.js} +9 -6
  24. package/dist/chunk-MCKKVNCE.js.map +1 -0
  25. package/dist/{chunk-MBPZXTJA.js → chunk-PDIHDBP3.js} +173 -20
  26. package/dist/chunk-PDIHDBP3.js.map +1 -0
  27. package/dist/{chunk-Q6PPMXJC.js → chunk-SV3SVBYS.js} +377 -21
  28. package/dist/chunk-SV3SVBYS.js.map +1 -0
  29. package/dist/{chunk-SPSMZOCJ.js → chunk-SYGONYMM.js} +4 -4
  30. package/dist/{chunk-A6W4QALF.js → chunk-TC6A7GMF.js} +2 -2
  31. package/dist/cli.js +5856 -413
  32. package/dist/cli.js.map +1 -1
  33. package/dist/client-runtime.d.ts +4 -2
  34. package/dist/client-runtime.js +6 -6
  35. package/dist/contracts/generate.js +1 -1
  36. package/dist/dr.d.ts +9 -2
  37. package/dist/dr.js +6 -4
  38. package/dist/{gateway-CggQ8vTC.d.ts → gateway-BQHpV-MZ.d.ts} +27 -3
  39. package/dist/gateway-main.js +69 -5
  40. package/dist/gateway-main.js.map +1 -1
  41. package/dist/gateway.d.ts +3 -3
  42. package/dist/gateway.js +2 -2
  43. package/dist/index.js +7 -7
  44. package/dist/{postgres-bridge-store-Bfd3hRId.d.ts → postgres-bridge-store-WASumj26.d.ts} +1 -1
  45. package/dist/server.js +7 -7
  46. package/dist/sqlite-edge-store-Bc15DvpX.d.ts +148 -0
  47. package/dist/sqlite.d.ts +19 -80
  48. package/dist/sqlite.js +11 -3
  49. package/docs/architecture-v2.md +278 -13
  50. package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +2 -2
  51. package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
  52. package/docs/decisions/0004-client-lifecycle-and-endpoint-migration.md +204 -0
  53. package/docs/deployment.md +205 -0
  54. package/docs/ecosystem.md +35 -3
  55. package/docs/troubleshooting.md +23 -0
  56. package/llms.txt +79 -3
  57. package/openapi/agent-bridge-v2.openapi.json +1023 -0
  58. package/package.json +6 -2
  59. package/schemas/agent-bridge-v2.capabilities.json +24 -0
  60. package/schemas/agent-bridge-v2.mcp.json +6 -0
  61. package/schemas/agent-bridge-v2.schema.json +163 -0
  62. package/sql/migrations/017_gateway_authority_binding.sql +99 -0
  63. package/sql/migrations/018_endpoint_migration_challenges.sql +1028 -0
  64. package/sql/migrations/019_endpoint_migration_same_successor.sql +324 -0
  65. package/dist/chunk-45BZGB77.js.map +0 -1
  66. package/dist/chunk-5GMB3A77.js.map +0 -1
  67. package/dist/chunk-GADH244D.js.map +0 -1
  68. package/dist/chunk-MBPZXTJA.js.map +0 -1
  69. package/dist/chunk-NCO7RLBM.js.map +0 -1
  70. package/dist/chunk-Q6PPMXJC.js.map +0 -1
  71. package/dist/chunk-UAHMP6GC.js.map +0 -1
  72. package/dist/chunk-WAI2IYIQ.js.map +0 -1
  73. /package/dist/{chunk-CEXBMOI5.js.map → chunk-LAHNQZDN.js.map} +0 -0
  74. /package/dist/{chunk-SPSMZOCJ.js.map → chunk-SYGONYMM.js.map} +0 -0
  75. /package/dist/{chunk-A6W4QALF.js.map → chunk-TC6A7GMF.js.map} +0 -0
package/SECURITY.md CHANGED
@@ -4,13 +4,35 @@
4
4
 
5
5
  | Version | Security updates |
6
6
  | --- | --- |
7
- | 0.2.x | Supported until its successor is released |
7
+ | 0.3.x | Supported |
8
+ | 0.2.x | Not supported |
8
9
  | 0.1.x | Not supported |
9
10
  | Unreleased development code | No public support guarantee |
10
11
 
11
12
  Upgrade to the latest published package before reporting a defect that may already be
12
13
  fixed. The npm package and GitHub release page are the public version authorities.
13
14
 
15
+ ## Release integrity
16
+
17
+ GitHub immutable releases are enabled, and GitHub reports release `v0.3.1` as
18
+ immutable. A repository ruleset also blocks updates and deletion for every `v*` tag
19
+ without a bypass actor. The `v0.3.1` tag is unsigned.
20
+
21
+ npm publication uses a protected GitHub environment, an OIDC trusted-publisher
22
+ binding, and provenance for the package artifact. Verify the package digest and
23
+ attestation before treating provenance as source identity. The
24
+ [`v0.3.1` release run](https://github.com/creatornader/agent-bridge/actions/runs/29465467036)
25
+ used package commit `d17ba544d31beaa33b4955e41c3b3d4e3f141900`.
26
+
27
+ The historical `v0.3.0`
28
+ [recovery run](https://github.com/creatornader/agent-bridge/actions/runs/29461308262)
29
+ checked out package commit `95eb861`, while its attestation names recovery commit
30
+ `c23d9df` as the workflow identity. GitHub Actions logs expire, so the
31
+ [release notes](https://github.com/creatornader/agent-bridge/releases/tag/v0.3.0)
32
+ also record this boundary. Recovery dispatches must run at the release tag. The
33
+ workflow also requires a successful `test.yml` run from `main` for the exact package
34
+ commit before packaging.
35
+
14
36
  ## Report a vulnerability
15
37
 
16
38
  Use [GitHub private vulnerability reporting](https://github.com/creatornader/agent-bridge/security/advisories/new).
@@ -29,6 +51,13 @@ Local mode relies on operating-system account isolation and private file permiss
29
51
  Anyone who can act as the same operating-system user can generally read or replace that
30
52
  user's Agent Bridge state. Local mode is not a hostile multi-user boundary.
31
53
 
54
+ Managed-client mutations may cache a successful native Windows ACL check while one
55
+ operation lock remains held. The cache is bound to the verified directory identity and is
56
+ discarded with the lock. New locks, resumed operations, and passive inspection check
57
+ the ACL again. POSIX permission checks are not cached. A same-user process can still
58
+ change an ACL on an unchanged object or replace a directory with one that reuses the
59
+ same filesystem identity. Both actions are within the local-mode trust boundary.
60
+
32
61
  ### Gateway mode
33
62
 
34
63
  Gateway credentials bind one workspace and principal. The gateway derives remote
@@ -36,10 +65,31 @@ identity from the credential, applies operation scopes and rate policy, and uses
36
65
  transaction-bound PostgreSQL request authority. Production runtime roles must not be
37
66
  superusers or hold `BYPASSRLS`. Put every non-loopback gateway behind TLS.
38
67
 
68
+ Do not publish PostgreSQL on a public interface. Put it on a private network reachable
69
+ only by the migration, runtime bootstrap, gateway, backup, and recovery jobs that need
70
+ it. The checked-in Compose file binds both published ports to loopback and serves plain
71
+ HTTP for local development. It is not a public deployment template.
72
+
39
73
  Keep the schema-owner, runtime, operator, archive, backup, and restore database
40
74
  authorities separate. Do not copy one client's token or backend file into another
41
75
  client's configuration.
42
76
 
77
+ Run migrations as a one-shot schema-owner job before starting a new gateway image.
78
+ Take and verify a native DR backup first. Gateway readiness checks the exact migration
79
+ plan and protected catalog state. Once a migration changes the database, starting an
80
+ older image is not a safe rollback. Apply a forward fix or restore the backup into a
81
+ fresh target and switch authority only after verification.
82
+
83
+ Drain old gateway instances before migrations 017 and 018. An old image reports `/readyz` as
84
+ not ready after the new migration is visible, but a process that was already running
85
+ can still serve ordinary requests until traffic is removed or it exits. Start the new
86
+ gateway only after the migration and runtime bootstrap finish.
87
+
88
+ Migration 018 accepts raw endpoint-migration challenges only as SQL function input. It
89
+ stores a domain-separated SHA-256 commitment, never the raw challenge, and excludes
90
+ live challenge rows from native DR data dumps. The challenge proves an active direct
91
+ credential replacement on one authority. It does not authorize endpoint cutover.
92
+
43
93
  ### Legacy Supabase mode
44
94
 
45
95
  The legacy adapter keeps existing v1 deployments working, but its publishable key can
@@ -57,6 +107,9 @@ through a separately trusted channel.
57
107
  PostgreSQL restore executes SQL from the source dump. Use
58
108
  `--accept-source-sql-risk` only for a bundle from a trusted source. Never activate the
59
109
  source and restored target as authorities at the same time.
110
+ The restored gateway authority UUID identifies the same logical authority. It does not
111
+ prevent an operator from activating a live clone, so the deployment cutover remains an
112
+ operator-controlled safety boundary.
60
113
 
61
114
  ### Optional integrations
62
115
 
@@ -69,5 +122,19 @@ when wrapper health is uncertain.
69
122
  - Pass gateway tokens through private enrollment or backend files, not shell arguments.
70
123
  - Keep database URLs in the documented environment variables. Do not put them in CLI
71
124
  arguments, logs, issues, or examples.
125
+ - Store Compose password files outside version control with owner-only permissions.
126
+ Use the deployment platform's secret manager in production. Do not bake passwords or
127
+ tokens into images, Compose environment blocks, or image layers.
128
+ - File-backed Compose secrets retain host ownership on native Linux. The development
129
+ stack starts a small Node entrypoint as root with `DAC_OVERRIDE`, `SETUID`, and
130
+ `SETGID`, reads one granted secret, then drops supplementary groups and UID/GID to
131
+ 1000 before it imports the gateway. The final process has no effective capabilities
132
+ and cannot regain them under `no-new-privileges`. The fixed runtime-bootstrap job
133
+ keeps `DAC_OVERRIDE`, `SETUID`, and `SETGID` while it reads its two secrets, then runs
134
+ `psql` as the PostgreSQL account. It rejects runtime passwords shorter than 32
135
+ characters.
72
136
  - Treat client backend files, enrollment files, archives, and DR bundles as secrets.
73
137
  - Sanitize `doctor` output and logs before sharing them publicly.
138
+
139
+ A Docker volume provides persistence, not backup. Keep verified native DR bundles on a
140
+ separate failure domain with retention and restore drills appropriate to the deployment.
package/SKILL.md CHANGED
@@ -7,6 +7,11 @@ description: Share context and reliable work between agents across runtimes and
7
7
 
8
8
  Discover the active v2 operation contract with MCP `capabilities`, CLI `agent-bridge capabilities`, or authenticated `GET /v2/capabilities`. Released 2.0 clients continue to work after the gateway is upgraded. A new 2.1 client must receive complete, consistent negotiation headers that select and advertise 2.1 before it mutates remote state. If the probe is headerless, selects 2.0, or returns partial or contradictory headers, do not mutate. Upgrade the gateway first instead of downgrading the client.
9
9
 
10
+ An authenticated PostgreSQL gateway status response can include `gatewayAuthorityId`
11
+ and `credentialId`. They are additive in HTTP 2.1. `clients migrate cutover`
12
+ requires and validates both fields before it switches a managed gateway endpoint.
13
+ Do not switch an endpoint by editing its backend file.
14
+
10
15
  Use the Agent Bridge MCP tools for normal traffic. Let the active runtime supply its own identity. Do not pass a literal source unless a standalone CLI process has no configured identity.
11
16
 
12
17
  If the MCP server is unavailable or disconnects, report the outage instead of implying
@@ -51,6 +56,104 @@ If a crash leaves the adjacent enrollment lock, wait at least 60 seconds and pas
51
56
  `--recover-lock` with the resume or install command. Recovery must prove that the
52
57
  same-host process recorded in the lock has stopped. Never remove the lock manually.
53
58
 
59
+ Before Agent Bridge takes lifecycle ownership of an existing Codex, Claude Code, or
60
+ Claude Desktop registration, run `agent-bridge clients inspect <runtime>` with its
61
+ exact `--identity`, stable `--instance`, and absolute `--backend-config` path. Supply
62
+ the installed command and Claude Code scope when they differ from defaults. Treat
63
+ `drifted` as a stop condition. `agent-bridge clients adopt` returns a plan by default;
64
+ only add `--apply` after reviewing an exact `unmanaged` result. Adoption writes
65
+ credential-free owner-private metadata only. It does not rewrite the MCP registration
66
+ or backend file, and inspection never returns backend values or contacts the gateway.
67
+ Desktop adoption records the normalized config path. Codex adoption records the active
68
+ profile config. Run Claude Code local or project adoption from the directory that
69
+ later lifecycle operations should use; the native CLI exposes no stronger target.
70
+ The backend and its immediate parent must already pass the owner-only no-link policy.
71
+ Treat registration state separately from connectivity health; applied adoption
72
+ re-inspects the registration before it reports success. Enrollment-based first-time
73
+ provisioning continues to refuse registration and backend-file collisions.
74
+ Use `agent-bridge clients operations` or append an operation UUID to inspect local
75
+ crash-safe operation state. Artifact contents remain confined to owner-private files;
76
+ inspection reports resumable, classification-required, blocked, or complete and names
77
+ the exact pending step only. Begin is lock-covered, resume is same-host only, and
78
+ ordered steps use no-replace before and verified after artifacts. Treat corrupt,
79
+ cross-host, or ambiguous state as a stop condition. Cleanup is restartable per artifact
80
+ and `committed` means verified writes plus removed artifacts. The terminal manifest
81
+ keeps a credential-free completion record but no request, step, digest, locator, or
82
+ artifact metadata.
83
+
84
+ For a managed registration, use `clients repair <runtime> --identity <name> --instance
85
+ <key>` to preview its recorded launch contract and backend privacy repair. Add `--apply`
86
+ only after reviewing the plan. Use `clients update` with the same metadata-selected
87
+ runtime and instance to validate a replacement launch contract. The same identity must
88
+ match the stored metadata and the immutable request. Native commands are one executable
89
+ contract. Do not pass arguments, URLs, or credential selectors in `--command`. Repair, update, and uninstall reject
90
+ `--backend-config`, `--scope`, and `--config-path`; `--identity` is an assertion, not a
91
+ locator. A no-op exact registration creates no journal. Native updates remove, prove
92
+ absence, add, and prove the target before metadata changes. Desktop updates replace only
93
+ the Agent Bridge entry and retain unrelated JSON values in memory. It publishes through
94
+ a private operation-scoped temporary file. A concurrent same-user Desktop writer can
95
+ still race this advisory single-file update because Node cannot provide an OS transaction.
96
+
97
+ Use `clients uninstall <runtime> --identity <name> --instance <key>` to preview a
98
+ forward-only removal. With `--apply`, it proves and removes the managed registration,
99
+ deletes the already private backend file, then deletes metadata. It refuses a backend
100
+ that needs privacy repair and never recreates an earlier target after a later failure.
101
+ Desktop removes only its Agent Bridge entry. Backend content never enters the journal.
102
+
103
+ Use `clients rollback <update-operation-id> --identity <name>` to inspect an explicit
104
+ reverse plan for a committed same-host v4 update. Add `--apply` only after reviewing
105
+ that plan. The source record retains only prior nonsecret managed metadata, its exact
106
+ registration contract, and forward-state digests. Rollback verifies those digests
107
+ against the current registration, then creates a separate reverse journal. Native
108
+ rollback removes the forward entry, adds the prior entry, and writes prior metadata
109
+ last. Claude Desktop replaces only its Agent Bridge entry and preserves unrelated JSON.
110
+ Repair has no rollback. Uninstall remains forward-only, so recovery is re-enrollment.
111
+
112
+ Use `clients migrate stage <runtime> --identity <name> --instance <key>
113
+ --enrollment-file <path>` to review a gateway successor prepared from a non-immediate
114
+ rotation enrollment. Add `--apply` only after reviewing the plan. Staging writes a
115
+ private successor backend and a credential-free operation record. It leaves the active
116
+ registration and active backend unchanged. It initializes the source edge gate but
117
+ leaves that gate active. It does not drain, cut over, or prove that two gateway URLs
118
+ reach the same database authority. The source backend must use an absolute, normalized
119
+ edge database path, not `:memory:`. Resume an interrupted stage with `clients resume
120
+ <operation-id> [--recover-lock]`. Use lock
121
+ recovery only after the recorded same-host process has stopped. Never remove a lock
122
+ manually.
123
+
124
+ Use `clients migrate cutover <stage-operation-id> --exclusive-edge` to inspect the
125
+ host switch. Add `--apply` only after checking the plan. The applied command requires
126
+ an active source edge and an active empty target edge. It verifies both HTTP 2.1
127
+ gateways against the recorded workspace, principal, credential IDs, and authority ID.
128
+ It also requires the successor `status:read` and `messages:write` grants, then completes
129
+ a direct predecessor-to-successor route challenge. Once its journal exists, it uses the
130
+ retained normalized source URL with the successor credential for route proofs and
131
+ source-edge replay through the target gateway. It leases and drains the source edge to
132
+ exact zero outbox work before changing a host registration. Native clients remove the
133
+ source and add the target. Claude Desktop replaces its one Agent Bridge entry. Managed
134
+ metadata changes last. The command rechecks gateway authority and the source lease
135
+ before each host write.
136
+
137
+ Every phase needs `--exclusive-edge`. Agent Bridge verifies the managed registrations
138
+ that share the edge file, including hardlink aliases. It cannot enumerate unmanaged
139
+ publishers, so the operator must assert that cohort is exclusive. `clients migrate
140
+ finalize <cutover-operation-id> --exclusive-edge --apply` works after
141
+ grace expires and retires the source edge. To return to a previous endpoint, rotate a
142
+ new owner credential and cut forward to it as a new successor. Resume any interrupted
143
+ v6 phase with `clients resume <operation-id> [--recover-lock]`. A new worker must wait
144
+ for the held drain lease to expire. Dry planning never contacts a gateway or writes
145
+ SQLite. It refuses an edge with live WAL sidecars rather than read stale outbox state.
146
+
147
+ Resume an action-specific operation with the same action, runtime, instance, and
148
+ identity: `--apply --resume <uuid>`. The stored request controls resume. Do not supply
149
+ a new command unless it exactly matches the recorded update request. Use
150
+ `clients resume <uuid> [--recover-lock]` to resume from a recorded v3, supported v4,
151
+ v5 migration-stage, or v6 endpoint-migration request alone. It does not accept
152
+ replacement client authority. Use the generic form after uninstall has
153
+ deleted metadata. `--recover-lock` on an action-specific command also requires
154
+ `--apply`; it only recovers a stale same-host lock after process-death proof. Never
155
+ remove operation locks by hand.
156
+
54
157
  Portable archive work is an offline operator task, not normal MCP traffic. Use
55
158
  `agent-bridge archive export --provider local|postgres --workspace <workspace>
56
159
  --output <file>` to create an archive, then run `agent-bridge archive verify --file
@@ -87,4 +190,4 @@ the source.
87
190
 
88
191
  Use `project` only as an optional message label. Workspace remains the tenant and credential boundary. Omit a project filter to read labeled and unlabeled messages, or provide one for an exact match. Reusing a workspace/source idempotency key with a different project is a conflict.
89
192
 
90
- For gateway mode, treat the credential-bound workspace and principal returned by the server as authoritative. Instance identifies one runtime of that same principal; it cannot select a workspace, agent, or scopes. A production gateway reports row isolation only when transaction-bound request authority and every database readiness check pass. RLS isolates workspace and principal rows. The service still enforces lease transitions and target-to-delivery membership.
193
+ For gateway mode, treat the credential-bound workspace and principal returned by the server as authoritative. Instance is an optional caller-supplied stable consumer key; it cannot select a workspace, agent, or scopes. Supported installers generate and persist it. Direct clients may do so when they need separate consumer state or presence. The gateway does not bind the key to an installer registration. Unless `AGENT_BRIDGE_CURSOR` is explicit, processes that share one key also share its cursor path. They also share delivery lease ownership and instance-keyed presence. Without a key or explicit cursor path, cursor storage uses `default`. Leases use the principal, and presence is unavailable. Instance is not a PID, unique live process, session, or thread. A production gateway reports row isolation only when transaction-bound request authority and every database readiness check pass. RLS isolates workspace and principal rows. The service still enforces lease transitions and target-to-delivery membership.
package/dist/archive.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { J as JsonValue, i as MessagePriority, f as DeliveryPolicy } from './bridge-domain-CBX3IVqC.js';
2
- import { P as PgQueryable } from './postgres-bridge-store-Bfd3hRId.js';
3
- import './bridge-store-DPVSCwfs.js';
2
+ import { P as PgQueryable } from './postgres-bridge-store-WASumj26.js';
3
+ import './bridge-store-Boaj-ZbO.js';
4
4
 
5
5
  interface PortableArchiveMessage {
6
6
  id: string;
package/dist/archive.js CHANGED
@@ -21,8 +21,8 @@ import {
21
21
  streamPortableArchive,
22
22
  validateArchiveWorkspace,
23
23
  validatePortableArchiveRequestId
24
- } from "./chunk-A6W4QALF.js";
25
- import "./chunk-NCO7RLBM.js";
24
+ } from "./chunk-TC6A7GMF.js";
25
+ import "./chunk-GTK4KOED.js";
26
26
  import "./chunk-BZLMF5O5.js";
27
27
  export {
28
28
  PORTABLE_ARCHIVE_BATCH_BYTES,
@@ -1,4 +1,4 @@
1
- import { a as BridgeStore, I as InsertMessageResult, d as MessageQuery, M as MessagePage, c as DeliveryQuery, b as DeliveryPage, D as DeliveryEventPage } from './bridge-store-DPVSCwfs.js';
1
+ import { a as BridgeStore, I as InsertMessageResult, d as MessageQuery, M as MessagePage, c as DeliveryQuery, b as DeliveryPage, D as DeliveryEventPage } from './bridge-store-Boaj-ZbO.js';
2
2
  import { c as BridgePrincipal, M as MessageDraft, B as BridgeDelivery, A as AgentPresence } from './bridge-domain-CBX3IVqC.js';
3
3
 
4
4
  type PublicMessageQuery = MessageQuery & {
@@ -35,6 +35,8 @@ interface BridgeDiagnostics {
35
35
  expiredLeases?: number | null;
36
36
  oldestDueAt?: string;
37
37
  queueLagMs?: number | null;
38
+ gatewayAuthorityId?: string;
39
+ credentialId?: string;
38
40
  principal?: {
39
41
  workspace: string;
40
42
  agent: string;
package/dist/bridge.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { b as BridgeMessage, c as BridgePrincipal, B as BridgeDelivery, R as RetryPolicy, A as AgentPresence } from './bridge-domain-CBX3IVqC.js';
2
2
  export { a as BridgeDeliveryEvent, d as BridgePrincipalMismatchError, e as BridgeValidationError, D as DeliveryAction, f as DeliveryPolicy, g as DeliveryState, h as DeliveryStateConflictError, J as JsonValue, L as LeasedDeliveryPolicy, M as MessageDraft, i as MessagePriority, j as cursorScope, k as decodeCursor, l as decodeScopedCursor, m as encodeCursor, n as encodeScopedCursor, s as scopedCursorScope, u as uuidv7, v as validateDeliveryCursorPosition, o as validateDeliveryPolicy, p as validateEventCursorPosition, q as validateLeasedDeliveryPolicy, r as validateMessageDraft, t as validatePrincipal, w as validateProject, x as validateUuid } from './bridge-domain-CBX3IVqC.js';
3
- import { a as BridgeStore, I as InsertMessageResult, d as MessageQuery, M as MessagePage, C as ClaimOptions, B as BridgeDiagnostics, c as DeliveryQuery } from './bridge-store-DPVSCwfs.js';
4
- export { D as DeliveryEventPage, b as DeliveryPage } from './bridge-store-DPVSCwfs.js';
5
- export { B as BridgeService, P as PublicMessageQuery } from './bridge-service-hX1ZQp4W.js';
6
- import { P as PgQueryable } from './postgres-bridge-store-Bfd3hRId.js';
7
- export { a as PgTransactionClient, b as PostgresBridgeStore } from './postgres-bridge-store-Bfd3hRId.js';
8
- export { A as AuthenticatedCredential, C as CredentialResolver, G as GatewayOptions, P as PostgresCredentialResolver, b as bearerToken, c as createGateway, h as hashCredential, s as safeTokenHashEqual } from './gateway-CggQ8vTC.js';
9
- export { CachedMessagePage, EdgeConflictError, EdgeEnqueueResult, EdgeOutboxRecord, EdgeScope, EdgeStats, PendingMessage, SQLiteBridgeStore, SQLiteEdgeStore, SyncDiagnostics, SyncInsertResult, SyncReport, SyncingBridgeStore, SyncingBridgeStoreOptions, edgeMessageFingerprint, edgeScopeKey, isRetryableSyncError, stableIdempotency } from './sqlite.js';
3
+ import { a as BridgeStore, I as InsertMessageResult, d as MessageQuery, M as MessagePage, C as ClaimOptions, B as BridgeDiagnostics, c as DeliveryQuery } from './bridge-store-Boaj-ZbO.js';
4
+ export { D as DeliveryEventPage, b as DeliveryPage } from './bridge-store-Boaj-ZbO.js';
5
+ export { B as BridgeService, P as PublicMessageQuery } from './bridge-service-YTjGr91A.js';
6
+ import { P as PgQueryable } from './postgres-bridge-store-WASumj26.js';
7
+ export { a as PgTransactionClient, b as PostgresBridgeStore } from './postgres-bridge-store-WASumj26.js';
8
+ export { A as AuthenticatedCredential, C as CredentialResolver, G as GatewayOptions, P as PostgresCredentialResolver, b as bearerToken, c as createGateway, h as hashCredential, s as safeTokenHashEqual } from './gateway-BQHpV-MZ.js';
9
+ export { E as EdgeConflictError, a as EdgeDrainLease, b as EdgeEnqueueResult, c as EdgeMigrationDrainingError, d as EdgeMigrationGate, e as EdgeMigrationGateState, f as EdgeMigrationLeaseError, g as EdgeMigrationRetiredError, h as EdgeOutboxRecord, i as EdgeReadOnlyInspection, j as EdgeScope, k as EdgeStats, P as PendingMessage, S as SQLiteEdgeStore, l as edgeMessageFingerprint, m as edgeScopeKey, n as inspectEdgeScopeReadOnly, s as stableIdempotency } from './sqlite-edge-store-Bc15DvpX.js';
10
+ export { CachedMessagePage, SQLiteBridgeStore, SyncDiagnostics, SyncInsertResult, SyncReport, SyncingBridgeStore, SyncingBridgeStoreOptions, isRetryableSyncError } from './sqlite.js';
10
11
  import 'node:http';
11
12
 
12
13
  declare class LegacySupabaseError extends Error {
@@ -149,6 +150,15 @@ declare const REQUIRED_MIGRATIONS: readonly [{
149
150
  }, {
150
151
  readonly version: 16;
151
152
  readonly name: "native_dr_fence";
153
+ }, {
154
+ readonly version: 17;
155
+ readonly name: "gateway_authority_binding";
156
+ }, {
157
+ readonly version: 18;
158
+ readonly name: "endpoint_migration_challenges";
159
+ }, {
160
+ readonly version: 19;
161
+ readonly name: "endpoint_migration_same_successor";
152
162
  }];
153
163
  declare function loadMigrationPlan(directory: string): Promise<MigrationPlanEntry[]>;
154
164
  declare function migrationsReady(db: PgQueryable, expected: ReadonlyArray<Pick<MigrationPlanEntry, "version" | "name" | "checksum">>): Promise<boolean>;
package/dist/bridge.js CHANGED
@@ -4,20 +4,24 @@ import {
4
4
  HttpBridgeStore,
5
5
  LegacySupabaseError,
6
6
  LegacySupabaseRestStore
7
- } from "./chunk-CEXBMOI5.js";
7
+ } from "./chunk-LAHNQZDN.js";
8
8
  import {
9
9
  EdgeConflictError,
10
+ EdgeMigrationDrainingError,
11
+ EdgeMigrationLeaseError,
12
+ EdgeMigrationRetiredError,
10
13
  SQLiteEdgeStore,
11
14
  SyncingBridgeStore,
12
15
  edgeMessageFingerprint,
13
16
  edgeScopeKey,
17
+ inspectEdgeScopeReadOnly,
14
18
  isRetryableSyncError,
15
19
  stableIdempotency
16
- } from "./chunk-Q6PPMXJC.js";
20
+ } from "./chunk-SV3SVBYS.js";
17
21
  import {
18
22
  SQLiteBridgeStore
19
- } from "./chunk-5GMB3A77.js";
20
- import "./chunk-NCO7RLBM.js";
23
+ } from "./chunk-DQOZJJZ2.js";
24
+ import "./chunk-GTK4KOED.js";
21
25
  import {
22
26
  PostgresBridgeStore
23
27
  } from "./chunk-2DFNOLMO.js";
@@ -29,7 +33,7 @@ import {
29
33
  rowIsolationReady,
30
34
  runMigrations,
31
35
  runtimeSchemaReady
32
- } from "./chunk-45BZGB77.js";
36
+ } from "./chunk-6BTJE6D4.js";
33
37
  import "./chunk-VOQIDTCJ.js";
34
38
  import {
35
39
  PostgresCredentialResolver,
@@ -37,11 +41,11 @@ import {
37
41
  createGateway,
38
42
  hashCredential,
39
43
  safeTokenHashEqual
40
- } from "./chunk-WAI2IYIQ.js";
44
+ } from "./chunk-3YHVUPU2.js";
41
45
  import {
42
46
  BridgeService
43
47
  } from "./chunk-4VB44KJU.js";
44
- import "./chunk-GADH244D.js";
48
+ import "./chunk-IHZFI7TH.js";
45
49
  import {
46
50
  BridgePrincipalMismatchError,
47
51
  BridgeValidationError,
@@ -69,6 +73,9 @@ export {
69
73
  BridgeValidationError,
70
74
  DeliveryStateConflictError,
71
75
  EdgeConflictError,
76
+ EdgeMigrationDrainingError,
77
+ EdgeMigrationLeaseError,
78
+ EdgeMigrationRetiredError,
72
79
  HttpBridgeStore,
73
80
  LegacySupabaseError,
74
81
  LegacySupabaseRestStore,
@@ -89,6 +96,7 @@ export {
89
96
  encodeCursor,
90
97
  encodeScopedCursor,
91
98
  hashCredential,
99
+ inspectEdgeScopeReadOnly,
92
100
  isRetryableSyncError,
93
101
  loadMigrationPlan,
94
102
  migrationsReady,
@@ -16,7 +16,7 @@ import {
16
16
  parseResponse,
17
17
  validateRequest,
18
18
  validateRequestForProtocol
19
- } from "./chunk-GADH244D.js";
19
+ } from "./chunk-IHZFI7TH.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", capabilityDocument({ surface: "http", provider: "gateway", selectedProtocolVersion: String(response.getHeader(PROTOCOL_HEADER)), requestAuthority: Boolean(options.requestAuthority), rowIsolation }), requestId);
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)));
@@ -551,4 +594,4 @@ export {
551
594
  safeTokenHashEqual,
552
595
  createGateway
553
596
  };
554
- //# sourceMappingURL=chunk-WAI2IYIQ.js.map
597
+ //# sourceMappingURL=chunk-3YHVUPU2.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 = validateRequest(\"claim_delivery\", await requestBody());\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":[]}