@creatornader/agent-bridge 0.5.2 → 0.6.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 (72) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/README.md +34 -31
  3. package/ROADMAP.md +56 -15
  4. package/SECURITY.md +6 -5
  5. package/dist/archive.d.ts +2 -2
  6. package/dist/{bridge-service-CNBKdYXh.d.ts → bridge-service-DjSYfjKt.d.ts} +4 -2
  7. package/dist/{bridge-store-ByJ6CaJk.d.ts → bridge-store-Bi_LCX8e.d.ts} +5 -1
  8. package/dist/bridge.d.ts +9 -37
  9. package/dist/bridge.js +6 -10
  10. package/dist/chunk-23UDQZMT.js +54 -0
  11. package/dist/chunk-23UDQZMT.js.map +1 -0
  12. package/dist/{chunk-AWE3DFZV.js → chunk-4V2PFJEF.js} +11 -4
  13. package/dist/chunk-4V2PFJEF.js.map +1 -0
  14. package/dist/{chunk-E4OWHGUE.js → chunk-62C63PIE.js} +8 -8
  15. package/dist/chunk-62C63PIE.js.map +1 -0
  16. package/dist/{chunk-HUHG7XTB.js → chunk-AIALYLGQ.js} +30 -193
  17. package/dist/chunk-AIALYLGQ.js.map +1 -0
  18. package/dist/{chunk-JUTJRAMA.js → chunk-FGERNG4X.js} +3 -3
  19. package/dist/{chunk-7VJI2MXI.js → chunk-IF5OKPBK.js} +32 -14
  20. package/dist/chunk-IF5OKPBK.js.map +1 -0
  21. package/dist/{chunk-QPC6JHA3.js → chunk-IMJ47WO4.js} +12 -16
  22. package/dist/chunk-IMJ47WO4.js.map +1 -0
  23. package/dist/{chunk-2EVLG3YA.js → chunk-UKFRCP6X.js} +10 -7
  24. package/dist/chunk-UKFRCP6X.js.map +1 -0
  25. package/dist/chunk-WQ4I5XGF.js +242 -0
  26. package/dist/chunk-WQ4I5XGF.js.map +1 -0
  27. package/dist/{chunk-SN7PIVDF.js → chunk-ZUZ7TCIH.js} +13 -1
  28. package/dist/{chunk-SN7PIVDF.js.map → chunk-ZUZ7TCIH.js.map} +1 -1
  29. package/dist/cli.js +41 -34
  30. package/dist/cli.js.map +1 -1
  31. package/dist/client-config.d.ts +1 -1
  32. package/dist/client-config.js +1 -1
  33. package/dist/client-runtime.d.ts +3 -3
  34. package/dist/client-runtime.js +5 -5
  35. package/dist/contracts/generate.js +2 -3
  36. package/dist/contracts/generate.js.map +1 -1
  37. package/dist/dr.d.ts +8 -0
  38. package/dist/dr.js +1 -1
  39. package/dist/{gateway-CW-61lvs.d.ts → gateway-BqmcKam8.d.ts} +2 -2
  40. package/dist/gateway-main.js +3 -3
  41. package/dist/gateway.d.ts +3 -3
  42. package/dist/gateway.js +3 -3
  43. package/dist/index.js +8 -7
  44. package/dist/index.js.map +1 -1
  45. package/dist/{postgres-bridge-store-C9KG9Z69.d.ts → postgres-bridge-store-ChoOuFEY.d.ts} +1 -1
  46. package/dist/server.d.ts +0 -2
  47. package/dist/server.js +8 -7
  48. package/dist/{sqlite-edge-store-CdMIOrho.d.ts → sqlite-edge-store-BAFUeysk.d.ts} +1 -1
  49. package/dist/sqlite.d.ts +7 -3
  50. package/dist/sqlite.js +1 -1
  51. package/docs/architecture-v2.md +22 -14
  52. package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +2 -1
  53. package/docs/decisions/0002-canonical-operation-contract-registry.md +6 -1
  54. package/docs/decisions/0005-retire-direct-supabase-runtime.md +52 -0
  55. package/docs/deployment.md +17 -12
  56. package/docs/ecosystem.md +6 -4
  57. package/docs/troubleshooting.md +15 -0
  58. package/llms.txt +3 -3
  59. package/openapi/agent-bridge-v2.openapi.json +3 -6
  60. package/package.json +3 -3
  61. package/schemas/agent-bridge-v2.capabilities.json +4 -5
  62. package/schemas/agent-bridge-v2.mcp.json +6 -12
  63. package/schemas/agent-bridge-v2.schema.json +12 -24
  64. package/dist/chunk-2EVLG3YA.js.map +0 -1
  65. package/dist/chunk-7VJI2MXI.js.map +0 -1
  66. package/dist/chunk-AWE3DFZV.js.map +0 -1
  67. package/dist/chunk-E4OWHGUE.js.map +0 -1
  68. package/dist/chunk-HUHG7XTB.js.map +0 -1
  69. package/dist/chunk-QPC6JHA3.js.map +0 -1
  70. package/dist/chunk-Z6JP6MYD.js +0 -584
  71. package/dist/chunk-Z6JP6MYD.js.map +0 -1
  72. /package/dist/{chunk-JUTJRAMA.js.map → chunk-FGERNG4X.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -4,7 +4,47 @@ All notable changes to agent-bridge are documented in this file.
4
4
 
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [Unreleased]
7
+ ## [0.6.0] - 2026-07-21
8
+
9
+ ### Added
10
+
11
+ - Add `agent-bridge send --queue-only` for an explicit gateway outbox write that
12
+ makes no network request. A later manual or automatic sync publishes the same
13
+ immutable message from its original endpoint, workspace, and principal scope.
14
+
15
+ ### Changed
16
+
17
+ - Describe Agent Bridge as messaging and work delivery across tools, sessions, and
18
+ machines. The npm package remains `@creatornader/agent-bridge`; npm rejects the
19
+ unscoped `agentbridge` name as confusingly similar to another package.
20
+ - Limit runtime providers and generated capability contracts to local SQLite and the
21
+ authenticated gateway.
22
+
23
+ ### Removed
24
+
25
+ - Remove the direct Supabase PostgREST runtime provider and its publishable-key
26
+ authorization model. Historical schema, migration 006 import, and the reconciliation
27
+ command remain available for upgrades.
28
+
29
+ ### Fixed
30
+
31
+ - Make the production proof use the real gateway edge scope during its offline
32
+ phase. The proof now carries the configured workspace, uses an explicit stable
33
+ message ID for replay, and waits for rate-limited replays to deduplicate before
34
+ continuing.
35
+ - Verify a Fly restart through a later successful machine `start` event instead of
36
+ requiring `instance_id` to change. Fly may retain that identifier across a plain
37
+ restart. Limit receipt value scanning to secret-bearing environment variables so
38
+ ordinary GitHub job identifiers cannot cause false leak reports. Permit GitHub to
39
+ reuse the sender host for the fresh-edge verifier while still requiring distinct
40
+ sender and receiver host evidence.
41
+ - Preserve only Agent Bridge roles and relevant default privileges in PostgreSQL native
42
+ DR backups when a managed provider gives the schema owner privileges in unrelated
43
+ schemas.
44
+ - Treat zero-valued Windows file IDs as unavailable during endpoint migration. Distinct
45
+ single-link edge files remain valid, while ambiguous hard-link cases still fail closed.
46
+ - Give PostgreSQL integration tests enough time to create temporary databases and apply
47
+ migrations before Vitest advances to later tests and overlaps their cleanup.
8
48
 
9
49
  ## [0.5.2] - 2026-07-20
10
50
 
package/README.md CHANGED
@@ -4,21 +4,23 @@
4
4
  [![test](https://github.com/creatornader/agent-bridge/actions/workflows/test.yml/badge.svg)](https://github.com/creatornader/agent-bridge/actions/workflows/test.yml)
5
5
  [![license](https://img.shields.io/github/license/creatornader/agent-bridge)](LICENSE)
6
6
 
7
- Agent Bridge is a durable, pull-first mailbox and work-delivery control plane for AI
8
- agents across runtimes, sessions, and machines. It gives coding agents, desktop agents,
9
- always-on workers, and agent frameworks a shared inbox that survives disconnection and
10
- restart. Start locally with SQLite, then use an operator-owned PostgreSQL gateway when
11
- agents need to communicate across machines.
7
+ Agent Bridge lets AI agents send messages and hand off work across tools, sessions, and
8
+ machines. Messages survive restarts and offline periods, and each agent resumes from
9
+ its own inbox.
12
10
 
13
- It supports three operating modes:
11
+ Use it through MCP, a CLI, a Node library, or an authenticated HTTPS gateway. Start
12
+ locally with SQLite. Use PostgreSQL when agents need to communicate across machines.
13
+
14
+ It supports two operating modes:
14
15
 
15
16
  | Mode | Store | Use case |
16
17
  | --- | --- | --- |
17
18
  | Local | SQLite WAL | One machine, no service or account |
18
19
  | Gateway | PostgreSQL plus a local SQLite edge store | Cross-machine messaging, offline sends, claims, retries, and presence |
19
- | Legacy Supabase | Existing `shared_context` table through PostgREST | Compatibility while a v1 deployment migrates |
20
20
 
21
- PostgreSQL remains the authority in gateway mode. SQLite holds local-only messages or gateway edge state. Supabase is one way to host PostgreSQL, not a protocol dependency.
21
+ PostgreSQL is the authority in gateway mode. SQLite holds local-only messages or
22
+ gateway edge state. Supabase can host PostgreSQL, but Agent Bridge does not depend on
23
+ its client APIs. The direct Supabase runtime adapter was removed in 0.6.0.
22
24
 
23
25
  ## Quick start
24
26
 
@@ -105,8 +107,9 @@ The manual `gateway production proof` workflow tests an existing gateway after i
105
107
  deployment gate has passed. GitHub must run it from `main` in the protected
106
108
  `agent-bridge-production-proof` environment. Separate sender and receiver jobs prove
107
109
  offline outbox replay, exact idempotency, claim, and acknowledgment. The workflow then
108
- restarts the single Fly machine, requires a new runtime instance ID, and verifies the
109
- message and settled delivery with a fresh receiver instance and a new SQLite edge file.
110
+ restarts the single Fly machine, requires a later successful machine start event, and
111
+ verifies the message and settled delivery with a fresh receiver instance and a new
112
+ SQLite edge file.
110
113
  Its versioned receipts contain only identifiers, times, principal and workspace labels,
111
114
  the gateway origin, checks, and SHA-256 host evidence. They omit credentials, database
112
115
  URLs, message content, and SQLite files.
@@ -137,7 +140,7 @@ Protocol 2.1 uses a gateway-first rollout. An upgraded gateway continues to serv
137
140
 
138
141
  Two gateway-only HTTP 2.1 operations establish a short-lived endpoint-migration challenge. Initial preflight uses a direct predecessor and successor. After a cutover journal exists, the same active successor credential can issue at the retained source URL and consume at the target URL. Both calls require active transaction-bound authority and use the canonical credential and operation rate buckets. PostgreSQL stores only a domain-separated SHA-256 commitment. A challenge expires within 60 seconds and does not authorize endpoint cutover. Authenticated HTTP 2.1 capabilities include the credential's `grantedScopes`.
139
142
 
140
- The OpenAPI paths describe protocol 2.1. The embedded `x-agent-bridge-protocol-2.0` and `x-agent-bridge-schemas-2.0` vendor extensions contain frozen compatibility schema metadata for released 2.0 clients. They are not a second OpenAPI description. Gateway credentials enforce the operation scopes declared by the canonical registry. Local mode uses process identity, and legacy mode uses its configured key. Provider-neutral artifacts report this difference instead of claiming one authorization model for every backend.
143
+ The OpenAPI paths describe protocol 2.1. The embedded `x-agent-bridge-protocol-2.0` and `x-agent-bridge-schemas-2.0` vendor extensions contain frozen compatibility schema metadata for released 2.0 clients. They are not a second OpenAPI description. Gateway credentials enforce the operation scopes declared by the canonical registry. Local mode uses process identity. Provider-neutral artifacts report this difference instead of claiming one authorization model for every backend.
141
144
 
142
145
  ## Architecture
143
146
 
@@ -229,7 +232,7 @@ for its relationship to MCP, A2A, agmsg, brokers, and agent runtimes.
229
232
 
230
233
  Use the source install for development. The normal installation path is the published
231
234
  `@creatornader/agent-bridge` package shown in the quick start. The unscoped npm name
232
- belongs to another project.
235
+ belongs to another project, and npm rejects `agentbridge` as confusingly similar.
233
236
 
234
237
  ```bash
235
238
  git clone https://github.com/creatornader/agent-bridge.git
@@ -900,6 +903,10 @@ When a send cannot reach the gateway:
900
903
  3. Long-lived MCP gateway clients retry due messages automatically with bounded exponential backoff. `agent-bridge sync` and the MCP `sync` tool trigger the same bounded replay and cache refresh manually. A permanently blocked message remains visible in diagnostics but does not stop later messages.
901
904
  4. An ambiguous retry is safe because the gateway enforces idempotency and rejects changed content under the same key.
902
905
 
906
+ Pass `--queue-only` to `agent-bridge send` when you want to write to the gateway
907
+ outbox without making a network request. The message stays under the configured
908
+ gateway, workspace, and principal scope. Run `agent-bridge sync` to publish it later.
909
+
903
910
  Normal inbox and pending reads fall back to the local cache when the gateway is unreachable. Cached reads report `source: "cache"`, `stale: true`, and `degraded: true`. When a read requested an unacknowledged filter, cached rows are candidates rather than proof of unread state and report `acknowledgements: "unknown"`. Claims, lease changes, delivery settlement, presence, and read-receipt writes still require the gateway because replaying those operations after a lease or identity change is unsafe.
904
911
 
905
912
  ## CLI
@@ -912,6 +919,7 @@ agent-bridge doctor
912
919
  agent-bridge status
913
920
  agent-bridge pending
914
921
  agent-bridge send --type request --target worker "Run the task"
922
+ agent-bridge send --queue-only --type request --target worker "Queue the task"
915
923
  agent-bridge post --category goal-update --project agent-bridge "Gateway is ready"
916
924
  agent-bridge inbox --limit 20
917
925
  agent-bridge sent --limit 20
@@ -939,7 +947,7 @@ agent-bridge watch
939
947
  dispatches a command. They are safe to use after a command name, including `archive`
940
948
  and `dr` commands.
941
949
 
942
- `--project` adds an optional immutable label to a message. It never selects a workspace or changes the active identity. Omit it on reads to include every project and unlabeled messages in the credential-bound workspace. Pass it to `get`, `inbox`, `history`, `pending`, or `watch` for an exact label match. Gateway callers may use `--workspace` only as an assertion. The CLI rejects a mismatch before sending a request. Local mode permits a per-command workspace override. The global legacy Supabase schema has no tenant workspace, so legacy mode fixes workspace to `*` and rejects other `--workspace` values.
950
+ `--project` adds an optional immutable label to a message. It never selects a workspace or changes the active identity. Omit it on reads to include every project and unlabeled messages in the credential-bound workspace. Pass it to `get`, `inbox`, `history`, `pending`, or `watch` for an exact label match. Gateway callers may use `--workspace` only as an assertion. The CLI rejects a mismatch before sending a request. Local mode permits a per-command workspace override.
943
951
 
944
952
  History defaults to mailbox `inbox`: broadcasts plus messages targeted to the configured principal, exactly as prior releases did. `sent` selects messages whose source is that principal, and `all` is the union. `--receipt-state any|unread|read` is caller-relative and valid only with `inbox`. The deprecated `--unacked-by` option remains an identity assertion. The CLI rejects a mismatch before opening storage or contacting a gateway. Server surfaces reject it before querying message storage. Cursors bind workspace, principal, mailbox, and normalized filters. Version 1 cursors are temporarily accepted, while all new cursors are version 2.
945
953
 
@@ -951,24 +959,22 @@ recipient-visible delivery. The filter also scopes lease-expiry and exhaustion
951
959
  maintenance performed by that claim. Released HTTP 2.0 request shapes remain frozen
952
960
  and reject the field.
953
961
 
954
- The legacy Supabase adapter applies mailbox and receipt rules cooperatively. A holder of the legacy publishable key can bypass the adapter through PostgREST or its receipt RPC. Use the authenticated v2 gateway when the authorization boundary must be enforced.
955
-
956
962
  `agent-bridge pending` is a cheap shell gate for agent startup. It exits 0 when unread candidates or due delivery work are visible, 1 only for an authoritative empty result, and 2 when an empty remote state cannot be confirmed. Its JSON result separates unread context from executable delivery work and labels the state as `available`, `empty`, or `unknown`.
957
963
 
958
- `watch` runs until interrupted unless `--polls` sets an explicit bound. Empty polls use capped backoff and jitter. Gateway and legacy network failures retry when the error is transient. Authentication and validation errors stop the watcher.
964
+ `watch` runs until interrupted unless `--polls` sets an explicit bound. Empty polls use capped backoff and jitter. Gateway network failures retry when the error is transient. Authentication and validation errors stop the watcher.
959
965
  Each exact project filter gets its own local watch checkpoint. Switching between a filtered and unfiltered watch cannot advance the other checkpoint.
960
966
 
961
967
  Unknown flags and missing option values fail before a message can be sent. This prevents a misspelled target flag from becoming a broadcast.
962
968
 
963
969
  ## MCP tools
964
970
 
965
- All providers expose the v1 compatibility tools:
971
+ Both providers expose the v1 compatibility tools:
966
972
 
967
973
  - `post_context`
968
974
  - `get_context`
969
975
  - `ack_context`
970
976
 
971
- Local and gateway providers also expose:
977
+ They also expose:
972
978
 
973
979
  - `send`
974
980
  - `history`
@@ -983,8 +989,6 @@ Local and gateway providers also expose:
983
989
  - `heartbeat`
984
990
  - `presence`
985
991
 
986
- Legacy Supabase does not advertise delivery or presence tools because its schema cannot enforce those operations.
987
-
988
992
  The acknowledgment names depend on the interface. MCP `ack_context` and CLI `acknowledge` write read receipts. MCP `acknowledge` and CLI `ack` settle claimed deliveries. A receipt never settles delivery work, and delivery settlement never creates a receipt.
989
993
 
990
994
  ## Identity and security
@@ -1018,23 +1022,20 @@ The acknowledgment names depend on the interface. MCP `ack_context` and CLI `ack
1018
1022
  - Errors expose stable codes without database URLs, tokens, or provider response bodies.
1019
1023
  - Delivery work is at least once, not exactly once. Consumers must make external side effects idempotent.
1020
1024
 
1021
- ## Legacy Supabase compatibility
1022
-
1023
- Existing deployments can continue using:
1024
-
1025
- ```text
1026
- AGENT_BRIDGE_PROVIDER=legacy-supabase
1027
- AGENT_BRIDGE_URL=https://your-project.supabase.co
1028
- AGENT_BRIDGE_KEY=<publishable key>
1029
- ```
1025
+ ## Upgrading historical Supabase deployments
1030
1026
 
1031
- Legacy mode keeps the v1 `shared_context` and `ack_context` RPC behavior. It adds bounded network calls, HTTPS enforcement, UUID mapping across CLI processes, newest-first reads, and the complete compatibility envelope. It cannot provide secure principal binding, delivery leases, presence, or an offline outbox. Use gateway mode for those features.
1027
+ Agent Bridge 0.6.0 removed the direct `legacy-supabase` runtime provider. Old provider
1028
+ names and key-only configurations now fail with a migration message instead of opening
1029
+ PostgREST. Configure local or gateway mode before upgrading a running client.
1032
1030
 
1033
1031
  When gateway migrations run in the same PostgreSQL database as `public.shared_context`, migration 006 imports legacy rows and receipts into the private v2 schema. It preserves valid envelope UUIDs, keeps the existing synthetic UUID mapping for ordinary numeric IDs, assigns deterministic UUIDs to larger IDs, maps projects to workspaces, rejects ID collisions, and verifies the imported count. It does not create executable deliveries for historical targeted rows because an upgrade must not replay old work.
1034
1032
 
1035
1033
  Migration 008 adds the optional project label without changing migration 006. A schema owner can preview correction of migration 006 rows into the canonical `agent-bridge` workspace with `agent-bridge reconcile-legacy-projects`. The command defaults to a dry run. Pass `--apply` to make the change in one transaction. The canonical workspace must already exist. Reconciliation preserves message IDs, timestamps, receipts, and total row counts. It creates no deliveries and is safe to repeat. It refuses changed source data, invalid labels, project or idempotency conflicts, and imported messages that already have a delivery.
1036
1034
 
1037
- The original v1 schema remains in [`sql/setup.sql`](sql/setup.sql). Ordered gateway migrations live in [`sql/migrations/`](sql/migrations/).
1035
+ The original v1 schema remains in [`sql/setup.sql`](sql/setup.sql) as a migration
1036
+ fixture. Ordered gateway migrations live in [`sql/migrations/`](sql/migrations/).
1037
+ The retirement decision is recorded in
1038
+ [ADR-0005](docs/decisions/0005-retire-direct-supabase-runtime.md).
1038
1039
 
1039
1040
  ## Health and operations
1040
1041
 
@@ -1143,6 +1144,8 @@ durability behavior has not yet been proved on a dedicated Windows host.
1143
1144
  - [ADR-0001](docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md): protocol layers and acknowledgment semantics.
1144
1145
  - [ADR-0002](docs/decisions/0002-canonical-operation-contract-registry.md): canonical contracts, generated artifacts, discovery, and version negotiation.
1145
1146
  - [ADR-0003](docs/decisions/0003-host-adapters-and-consumer-instance-keys.md): host layers and consumer instance-key semantics.
1147
+ - [ADR-0004](docs/decisions/0004-client-lifecycle-and-endpoint-migration.md): managed client ownership and endpoint migration.
1148
+ - [ADR-0005](docs/decisions/0005-retire-direct-supabase-runtime.md): direct Supabase runtime retirement and historical migration support.
1146
1149
  - [docs/architecture-v2.md](docs/architecture-v2.md): protocol and storage decisions.
1147
1150
  - [SKILL.md](SKILL.md): runtime-neutral agent operating instructions.
1148
1151
  - [llms.txt](llms.txt): compact machine-readable project map.
package/ROADMAP.md CHANGED
@@ -114,21 +114,62 @@ The published npm version is the authority for whether this package line has shi
114
114
  - Optional exact-message delivery claims in HTTP 2.1, MCP, and the CLI. HTTP 2.0 keeps
115
115
  the released claim-next contract.
116
116
 
117
- ### Post-release validation and adoption
118
-
119
- - Move the project's own normal traffic to the authenticated gateway while retaining a
120
- tested legacy rollback path.
121
- - Prove cross-machine claim, settlement, offline replay, and restart behavior against
122
- the published package and a deployed v2 gateway. The historical 0.3.0 live release
123
- check covered startup, private mailbox sends, caller-scoped history, receipts, and
124
- client restart through the legacy compatibility backend. It did not prove
125
- gateway-only behavior.
126
- - Run the manual Fly proof against an operator-owned app and retain its sender,
127
- receiver, machine-cycle, and verifier receipts. The repository harness is ready,
128
- but the external proof remains incomplete until an approved workflow run succeeds.
129
- - Replace remaining direct legacy table pollers with the v2 cursor protocol.
130
- - Confirm the README, npm metadata, GitHub metadata, release notes, and package contents
131
- match the released artifact.
117
+ ### 0.5.1 and 0.5.2 package contents
118
+
119
+ - Runtime PostgreSQL connections can load a base64-encoded CA bundle from the secret
120
+ environment without writing the certificate to the gateway image or filesystem.
121
+ - The gateway rejects URL parameters that could replace the explicit CA policy.
122
+ - Legacy rows whose ancestry column is SQL `NULL` map to an omitted optional field
123
+ instead of an invalid protocol value.
124
+ - `/healthz` reports process liveness without database work. `/readyz` remains the
125
+ database, migration, role, and protected-catalog readiness gate.
126
+
127
+ ### 0.6.0 package contents
128
+
129
+ - `send --queue-only` records an immutable gateway publication in the local outbox
130
+ without making a network request.
131
+ - The production proof uses the configured edge scope, an explicit stable message ID,
132
+ and a real Fly stop and start cycle. Separate sender and receiver runners prove
133
+ offline replay, idempotency, exact claim and settlement, and recovery from a fresh
134
+ receiver edge.
135
+ - PostgreSQL native DR supports managed-provider role graphs without importing
136
+ unrelated provider roles or default privileges from schemas outside Agent Bridge.
137
+ - The direct Supabase runtime provider is removed. Historical schema, import, and
138
+ reconciliation paths remain for upgrades. Runtime contracts now expose only local
139
+ and gateway providers.
140
+ - Public package language leads with cross-tool, cross-session, and cross-machine
141
+ messaging and work handoff.
142
+
143
+ ### Production validation and adoption
144
+
145
+ Completed against the published 0.5.2 package:
146
+
147
+ - Migrated the project authority from the legacy Supabase schema to the canonical
148
+ PostgreSQL schema after a write freeze, exact-major backup, and restore drill. The
149
+ gateway uses a restricted runtime login. Legacy writes remain frozen, and the final
150
+ backup remains available for recovery.
151
+ - Deployed the maintained image to an operator-owned Fly app. Authenticated readiness,
152
+ capabilities, status, history, publication, exact claim, and settlement checks passed
153
+ against the live gateway.
154
+ - Moved the managed Codex, Claude Code, and Claude Desktop registrations to separate
155
+ principal-bound gateway backends. All three passed `doctor`, remote history, empty
156
+ outbox, and empty delivery-queue checks. Fresh MCP launches exposed 17 tools for each
157
+ supported adapter. A client process started before cutover keeps its old backend until
158
+ that host restarts.
159
+ - Verified the published npm version, provenance, immutable GitHub release, package
160
+ contents, and public repository metadata.
161
+ - Ran the approval-protected production workflow with distinct sender and receiver
162
+ runners, an offline sender outbox, a real Fly machine cycle, and a fresh verifier
163
+ edge. The retained receipts prove replay, exact idempotency, claim, settlement, and
164
+ recovery after restart.
165
+ - Took and verified a canonical native PostgreSQL backup after the proof. Removed the
166
+ obsolete public v1 table and receipt function from the live database without changing
167
+ the canonical PostgreSQL authority.
168
+ - Moved the shared config to the gateway and rechecked the Codex, Claude Code, and
169
+ Claude Desktop managed backends. All three passed active gateway diagnostics.
170
+
171
+ Publication of 0.6.0 remains the release boundary for the package changes listed
172
+ above.
132
173
 
133
174
  ## Near-term work
134
175
 
package/SECURITY.md CHANGED
@@ -120,12 +120,13 @@ stores a domain-separated SHA-256 commitment, never the raw challenge, and exclu
120
120
  live challenge rows from native DR data dumps. The challenge proves an active direct
121
121
  credential replacement on one authority. It does not authorize endpoint cutover.
122
122
 
123
- ### Legacy Supabase mode
123
+ ### Historical Supabase migrations
124
124
 
125
- The legacy adapter keeps existing v1 deployments working, but its publishable key can
126
- call the underlying PostgREST table and receipt RPC directly. Adapter checks therefore
127
- provide cooperative behavior, not the same workspace and principal isolation as the
128
- authenticated gateway. Do not use legacy mode as a hostile multi-tenant boundary.
125
+ Agent Bridge 0.6.0 removed the direct Supabase runtime adapter. The checked-in v1
126
+ schema and migration 006 remain so trusted operators can import historical deployments
127
+ into the private PostgreSQL schema. Back up the source first, run the migration with
128
+ schema-owner authority, and move clients to local or gateway mode. The permissive v1
129
+ row policies are not a supported runtime security boundary.
129
130
 
130
131
  ### Archives and disaster recovery
131
132
 
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-C9KG9Z69.js';
3
- import './bridge-store-ByJ6CaJk.js';
2
+ import { P as PgQueryable } from './postgres-bridge-store-ChoOuFEY.js';
3
+ import './bridge-store-Bi_LCX8e.js';
4
4
 
5
5
  interface PortableArchiveMessage {
6
6
  id: string;
@@ -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-ByJ6CaJk.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-Bi_LCX8e.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 & {
@@ -7,7 +7,9 @@ type PublicMessageQuery = MessageQuery & {
7
7
  declare class BridgeService {
8
8
  private readonly store;
9
9
  constructor(store: BridgeStore);
10
- publish(principalInput: BridgePrincipal, draftInput: MessageDraft): Promise<InsertMessageResult>;
10
+ publish(principalInput: BridgePrincipal, draftInput: MessageDraft, options?: {
11
+ queueOnly?: boolean;
12
+ }): Promise<InsertMessageResult>;
11
13
  history(principalInput: BridgePrincipal, query?: PublicMessageQuery): Promise<MessagePage>;
12
14
  acknowledge(principalInput: BridgePrincipal, messageIds: string[]): Promise<number>;
13
15
  claim(principalInput: BridgePrincipal, options?: {
@@ -22,7 +22,7 @@ interface MessagePage {
22
22
  cursor?: string;
23
23
  }
24
24
  interface BridgeDiagnostics {
25
- schemaVersion: "local-v2" | "postgres-v2" | "legacy-v1";
25
+ schemaVersion: "local-v2" | "postgres-v2";
26
26
  deliverySupported: boolean;
27
27
  pending: number | null;
28
28
  claimed: number | null;
@@ -72,6 +72,10 @@ interface BridgeStore {
72
72
  insertMessage(message: Omit<BridgeMessage, "sequence" | "createdAt">, options?: {
73
73
  signal?: AbortSignal;
74
74
  }): Promise<InsertMessageResult>;
75
+ enqueueMessage?(message: Omit<BridgeMessage, "sequence" | "createdAt">): Promise<InsertMessageResult & {
76
+ disposition: "queued";
77
+ authoritative: false;
78
+ }>;
75
79
  listMessages(principal: BridgePrincipal, query?: MessageQuery, options?: {
76
80
  signal?: AbortSignal;
77
81
  }): Promise<MessagePage>;
package/dist/bridge.d.ts CHANGED
@@ -1,43 +1,15 @@
1
- import { b as BridgeMessage, c as BridgePrincipal, B as BridgeDelivery, R as RetryPolicy, A as AgentPresence } from './bridge-domain-CBX3IVqC.js';
1
+ import { c as BridgePrincipal, b as BridgeMessage, 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-ByJ6CaJk.js';
4
- export { D as DeliveryEventPage, b as DeliveryPage } from './bridge-store-ByJ6CaJk.js';
5
- export { B as BridgeService, P as PublicMessageQuery } from './bridge-service-CNBKdYXh.js';
6
- import { P as PgQueryable } from './postgres-bridge-store-C9KG9Z69.js';
7
- export { a as PgTransactionClient, b as PostgresBridgeStore } from './postgres-bridge-store-C9KG9Z69.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-CW-61lvs.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-CdMIOrho.js';
3
+ import { a as BridgeStore, I as InsertMessageResult, d as MessageQuery, M as MessagePage, B as BridgeDiagnostics, C as ClaimOptions, c as DeliveryQuery } from './bridge-store-Bi_LCX8e.js';
4
+ export { D as DeliveryEventPage, b as DeliveryPage } from './bridge-store-Bi_LCX8e.js';
5
+ export { B as BridgeService, P as PublicMessageQuery } from './bridge-service-DjSYfjKt.js';
6
+ import { P as PgQueryable } from './postgres-bridge-store-ChoOuFEY.js';
7
+ export { a as PgTransactionClient, b as PostgresBridgeStore } from './postgres-bridge-store-ChoOuFEY.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-BqmcKam8.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-BAFUeysk.js';
10
10
  export { CachedMessagePage, SQLiteBridgeStore, SyncDiagnostics, SyncInsertResult, SyncReport, SyncingBridgeStore, SyncingBridgeStoreOptions, isRetryableSyncError } from './sqlite.js';
11
11
  import 'node:http';
12
12
 
13
- declare class LegacySupabaseError extends Error {
14
- readonly status: number;
15
- readonly code: string;
16
- constructor(status: number, code: string);
17
- }
18
- declare class LegacySupabaseRestStore implements BridgeStore {
19
- private readonly url;
20
- private readonly key;
21
- private readonly fetchImpl;
22
- private readonly timeoutMs;
23
- private readonly legacyIds;
24
- private initialized;
25
- constructor(url: string, key: string, fetchImpl?: typeof fetch, timeoutMs?: number);
26
- initialize(options?: {
27
- mode?: "active" | "passive";
28
- }): Promise<void>;
29
- private request;
30
- private visibleReceiptIds;
31
- insertMessage(input: Omit<BridgeMessage, "sequence" | "createdAt">): Promise<InsertMessageResult>;
32
- listMessages(principal: BridgePrincipal, query?: MessageQuery): Promise<MessagePage>;
33
- recordReceipt(principal: BridgePrincipal, ids: string[]): Promise<number>;
34
- recordLegacyReceipt(ids: string[], principal: string): Promise<number>;
35
- claimDelivery(_principal: BridgePrincipal, _options: ClaimOptions): Promise<BridgeDelivery | null>;
36
- renewDelivery(_principal: BridgePrincipal, _deliveryId: string, _leaseToken: string, _leaseMs: number): Promise<BridgeDelivery | null>;
37
- settleDelivery(_principal: BridgePrincipal, _deliveryId: string, _leaseToken: string, _state: "acked" | "retrying" | "dead", _error?: string, _retryPolicy?: RetryPolicy): Promise<BridgeDelivery | null>;
38
- diagnostics(_principal: BridgePrincipal): Promise<BridgeDiagnostics>;
39
- }
40
-
41
13
  interface HttpBridgeStoreOptions {
42
14
  baseUrl: string;
43
15
  token: string;
@@ -175,4 +147,4 @@ declare function runtimeSchemaReady(db: PgQueryable, options?: {
175
147
  }): Promise<boolean>;
176
148
  declare function runMigrations(db: PgQueryable, directory: string): Promise<AppliedMigration[]>;
177
149
 
178
- export { AgentPresence, type AppliedMigration, BridgeDelivery, BridgeDiagnostics, BridgeHttpError, BridgeMessage, BridgePrincipal, BridgeStore, ClaimOptions, DeliveryQuery, HttpBridgeStore, type HttpBridgeStoreOptions, InsertMessageResult, LegacySupabaseError, LegacySupabaseRestStore, MessagePage, MessageQuery, type MigrationPlanEntry, NATIVE_DR_ADVISORY_LOCK_KEY, PgQueryable, REQUIRED_MIGRATIONS, RetryPolicy, loadMigrationPlan, migrationRecordMatches, migrationsReady, rowIsolationReady, runMigrations, runtimeSchemaReady };
150
+ export { AgentPresence, type AppliedMigration, BridgeDelivery, BridgeDiagnostics, BridgeHttpError, BridgeMessage, BridgePrincipal, BridgeStore, ClaimOptions, DeliveryQuery, HttpBridgeStore, type HttpBridgeStoreOptions, InsertMessageResult, MessagePage, MessageQuery, type MigrationPlanEntry, NATIVE_DR_ADVISORY_LOCK_KEY, PgQueryable, REQUIRED_MIGRATIONS, RetryPolicy, loadMigrationPlan, migrationRecordMatches, migrationsReady, rowIsolationReady, runMigrations, runtimeSchemaReady };
package/dist/bridge.js CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  BridgeHttpError,
4
- HttpBridgeStore,
5
- LegacySupabaseError,
6
- LegacySupabaseRestStore
7
- } from "./chunk-Z6JP6MYD.js";
4
+ HttpBridgeStore
5
+ } from "./chunk-WQ4I5XGF.js";
8
6
  import {
9
7
  EdgeConflictError,
10
8
  EdgeMigrationDrainingError,
@@ -17,7 +15,7 @@ import {
17
15
  inspectEdgeScopeReadOnly,
18
16
  isRetryableSyncError,
19
17
  stableIdempotency
20
- } from "./chunk-SN7PIVDF.js";
18
+ } from "./chunk-ZUZ7TCIH.js";
21
19
  import {
22
20
  SQLiteBridgeStore
23
21
  } from "./chunk-IVG4XWWS.js";
@@ -42,11 +40,11 @@ import {
42
40
  createGateway,
43
41
  hashCredential,
44
42
  safeTokenHashEqual
45
- } from "./chunk-JUTJRAMA.js";
43
+ } from "./chunk-FGERNG4X.js";
46
44
  import {
47
45
  BridgeService
48
- } from "./chunk-AWE3DFZV.js";
49
- import "./chunk-E4OWHGUE.js";
46
+ } from "./chunk-4V2PFJEF.js";
47
+ import "./chunk-62C63PIE.js";
50
48
  import {
51
49
  BridgePrincipalMismatchError,
52
50
  BridgeValidationError,
@@ -78,8 +76,6 @@ export {
78
76
  EdgeMigrationLeaseError,
79
77
  EdgeMigrationRetiredError,
80
78
  HttpBridgeStore,
81
- LegacySupabaseError,
82
- LegacySupabaseRestStore,
83
79
  NATIVE_DR_ADVISORY_LOCK_KEY,
84
80
  PostgresBridgeStore,
85
81
  PostgresCredentialResolver,
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/legacy-compat.ts
4
+ function legacyMessageIdFromSequence(value) {
5
+ const text = String(value);
6
+ if (!/^-?\d+$/.test(text)) throw new Error("legacy message ID must be an integer");
7
+ if (typeof value === "number" && !Number.isSafeInteger(value)) {
8
+ throw new Error("legacy message ID must be decoded without precision loss");
9
+ }
10
+ const numeric = BigInt(text);
11
+ if (numeric >= 0n && numeric <= 0xffffffffffffn) {
12
+ return `00000000-0000-8000-8000-${numeric.toString(16).padStart(12, "0")}`;
13
+ }
14
+ if (numeric < -0x8000000000000000n || numeric > 0x7fffffffffffffffn) {
15
+ throw new Error("legacy message ID exceeds bigint range");
16
+ }
17
+ const unsigned = numeric < 0 ? numeric + 0x10000000000000000n : numeric;
18
+ const encoded = unsigned.toString(16).padStart(16, "0").padStart(18, "0");
19
+ return `00000000-0000-8${encoded.slice(0, 3)}-9${encoded.slice(3, 6)}-${encoded.slice(6)}`;
20
+ }
21
+ function legacyNumericMessageId(value) {
22
+ const text = String(value);
23
+ return /^-?\d+$/.test(text) ? legacyMessageIdFromSequence(value) : text;
24
+ }
25
+ function legacyContextMetadata(message) {
26
+ const metadata = message.metadata && typeof message.metadata === "object" && !Array.isArray(message.metadata) ? message.metadata : {};
27
+ const existingEnvelope = metadata.message_envelope && typeof metadata.message_envelope === "object" && !Array.isArray(metadata.message_envelope) ? metadata.message_envelope : {};
28
+ const envelope = {
29
+ ...existingEnvelope,
30
+ schema: "agent-bridge.message-envelope.v1",
31
+ message_id: message.id,
32
+ source_agent: message.source,
33
+ kind: message.type,
34
+ priority: message.priority,
35
+ target_agents: message.targets,
36
+ payload_mime: message.contentType
37
+ };
38
+ if (message.project) envelope.project = message.project;
39
+ if (message.threadId) envelope.thread_id = message.threadId;
40
+ if (message.replyToId) envelope.reply_to_id = message.replyToId;
41
+ if (message.correlationId) envelope.correlation_id = message.correlationId;
42
+ if (message.causationId) envelope.causation_id = message.causationId;
43
+ if (message.data !== void 0) envelope.payload = message.data;
44
+ if (message.expiresAt) envelope.expires_at = message.expiresAt;
45
+ if (message.atribReceiptId) envelope.atrib_receipt_id = message.atribReceiptId;
46
+ if (message.informedBy?.length) envelope.informed_by = message.informedBy;
47
+ return { ...metadata, message_envelope: envelope };
48
+ }
49
+
50
+ export {
51
+ legacyNumericMessageId,
52
+ legacyContextMetadata
53
+ };
54
+ //# sourceMappingURL=chunk-23UDQZMT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/legacy-compat.ts"],"sourcesContent":["import type { BridgeMessage, JsonValue } from \"./bridge-domain.js\";\n\nexport function legacyMessageIdFromSequence(value: string | number): string {\n const text = String(value);\n if (!/^-?\\d+$/.test(text)) throw new Error(\"legacy message ID must be an integer\");\n if (typeof value === \"number\" && !Number.isSafeInteger(value)) {\n throw new Error(\"legacy message ID must be decoded without precision loss\");\n }\n const numeric = BigInt(text);\n if (numeric >= 0n && numeric <= 0xffffffffffffn) {\n return `00000000-0000-8000-8000-${numeric.toString(16).padStart(12, \"0\")}`;\n }\n if (numeric < -0x8000000000000000n || numeric > 0x7fffffffffffffffn) {\n throw new Error(\"legacy message ID exceeds bigint range\");\n }\n const unsigned = numeric < 0 ? numeric + 0x10000000000000000n : numeric;\n const encoded = unsigned.toString(16).padStart(16, \"0\").padStart(18, \"0\");\n return `00000000-0000-8${encoded.slice(0, 3)}-9${encoded.slice(3, 6)}-${encoded.slice(6)}`;\n}\n\nexport function legacySequenceFromMessageId(value: string): string | undefined {\n const small = value.match(/^00000000-0000-8000-8000-([0-9a-f]{12})$/i);\n if (small) return BigInt(`0x${small[1]}`).toString();\n const large = value.match(/^00000000-0000-8([0-9a-f]{3})-9([0-9a-f]{3})-([0-9a-f]{12})$/i);\n if (!large) return undefined;\n const encoded = `${large[1]}${large[2]}${large[3]}`;\n if (!encoded.startsWith(\"00\")) return undefined;\n const unsigned = BigInt(`0x${encoded.slice(2)}`);\n return (unsigned >= 0x8000000000000000n\n ? unsigned - 0x10000000000000000n\n : unsigned).toString();\n}\n\nexport function legacyNumericMessageId(value: string | number): string {\n const text = String(value);\n return /^-?\\d+$/.test(text) ? legacyMessageIdFromSequence(value) : text;\n}\n\nexport function legacyContextMetadata(message: BridgeMessage): Record<string, JsonValue> {\n const metadata = message.metadata &&\n typeof message.metadata === \"object\" &&\n !Array.isArray(message.metadata)\n ? message.metadata\n : {};\n const existingEnvelope = metadata.message_envelope &&\n typeof metadata.message_envelope === \"object\" &&\n !Array.isArray(metadata.message_envelope)\n ? metadata.message_envelope\n : {};\n const envelope: Record<string, JsonValue> = {\n ...existingEnvelope,\n schema: \"agent-bridge.message-envelope.v1\",\n message_id: message.id,\n source_agent: message.source,\n kind: message.type,\n priority: message.priority,\n target_agents: message.targets,\n payload_mime: message.contentType,\n };\n if (message.project) envelope.project = message.project;\n if (message.threadId) envelope.thread_id = message.threadId;\n if (message.replyToId) envelope.reply_to_id = message.replyToId;\n if (message.correlationId) envelope.correlation_id = message.correlationId;\n if (message.causationId) envelope.causation_id = message.causationId;\n if (message.data !== undefined) envelope.payload = message.data;\n if (message.expiresAt) envelope.expires_at = message.expiresAt;\n if (message.atribReceiptId) envelope.atrib_receipt_id = message.atribReceiptId;\n if (message.informedBy?.length) envelope.informed_by = message.informedBy;\n return { ...metadata, message_envelope: envelope };\n}\n"],"mappings":";;;AAEO,SAAS,4BAA4B,OAAgC;AAC1E,QAAM,OAAO,OAAO,KAAK;AACzB,MAAI,CAAC,UAAU,KAAK,IAAI,EAAG,OAAM,IAAI,MAAM,sCAAsC;AACjF,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,KAAK,GAAG;AAC7D,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AACA,QAAM,UAAU,OAAO,IAAI;AAC3B,MAAI,WAAW,MAAM,WAAW,iBAAiB;AAC/C,WAAO,2BAA2B,QAAQ,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG,CAAC;AAAA,EAC1E;AACA,MAAI,UAAU,CAAC,uBAAuB,UAAU,qBAAqB;AACnE,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,QAAM,WAAW,UAAU,IAAI,UAAU,uBAAuB;AAChE,QAAM,UAAU,SAAS,SAAS,EAAE,EAAE,SAAS,IAAI,GAAG,EAAE,SAAS,IAAI,GAAG;AACxE,SAAO,kBAAkB,QAAQ,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AAC1F;AAeO,SAAS,uBAAuB,OAAgC;AACrE,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,UAAU,KAAK,IAAI,IAAI,4BAA4B,KAAK,IAAI;AACrE;AAEO,SAAS,sBAAsB,SAAmD;AACvF,QAAM,WAAW,QAAQ,YACvB,OAAO,QAAQ,aAAa,YAC5B,CAAC,MAAM,QAAQ,QAAQ,QAAQ,IAC7B,QAAQ,WACR,CAAC;AACL,QAAM,mBAAmB,SAAS,oBAChC,OAAO,SAAS,qBAAqB,YACrC,CAAC,MAAM,QAAQ,SAAS,gBAAgB,IACtC,SAAS,mBACT,CAAC;AACL,QAAM,WAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,YAAY,QAAQ;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,eAAe,QAAQ;AAAA,IACvB,cAAc,QAAQ;AAAA,EACxB;AACA,MAAI,QAAQ,QAAS,UAAS,UAAU,QAAQ;AAChD,MAAI,QAAQ,SAAU,UAAS,YAAY,QAAQ;AACnD,MAAI,QAAQ,UAAW,UAAS,cAAc,QAAQ;AACtD,MAAI,QAAQ,cAAe,UAAS,iBAAiB,QAAQ;AAC7D,MAAI,QAAQ,YAAa,UAAS,eAAe,QAAQ;AACzD,MAAI,QAAQ,SAAS,OAAW,UAAS,UAAU,QAAQ;AAC3D,MAAI,QAAQ,UAAW,UAAS,aAAa,QAAQ;AACrD,MAAI,QAAQ,eAAgB,UAAS,mBAAmB,QAAQ;AAChE,MAAI,QAAQ,YAAY,OAAQ,UAAS,cAAc,QAAQ;AAC/D,SAAO,EAAE,GAAG,UAAU,kBAAkB,SAAS;AACnD;","names":[]}
@@ -94,14 +94,21 @@ var BridgeService = class {
94
94
  constructor(store) {
95
95
  this.store = store;
96
96
  }
97
- async publish(principalInput, draftInput) {
97
+ async publish(principalInput, draftInput, options = {}) {
98
98
  const principal = validatePrincipal(principalInput);
99
99
  const draft = validateMessageDraft(draftInput);
100
- return this.store.insertMessage({
100
+ const message = {
101
101
  ...draft,
102
102
  workspace: principal.workspace,
103
103
  source: principal.agent
104
- });
104
+ };
105
+ if (options.queueOnly) {
106
+ if (!this.store.enqueueMessage) {
107
+ throw new BridgeValidationError("queue-only publication requires the gateway provider");
108
+ }
109
+ return this.store.enqueueMessage(message);
110
+ }
111
+ return this.store.insertMessage(message);
105
112
  }
106
113
  async history(principalInput, query = {}) {
107
114
  const principal = validatePrincipal(principalInput);
@@ -228,4 +235,4 @@ var BridgeService = class {
228
235
  export {
229
236
  BridgeService
230
237
  };
231
- //# sourceMappingURL=chunk-AWE3DFZV.js.map
238
+ //# sourceMappingURL=chunk-4V2PFJEF.js.map