@creatornader/agent-bridge 0.2.0 → 0.3.1

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 (115) hide show
  1. package/CHANGELOG.md +86 -4
  2. package/README.md +567 -55
  3. package/ROADMAP.md +114 -0
  4. package/SECURITY.md +90 -0
  5. package/SKILL.md +68 -2
  6. package/bin/agent-bridge +2 -2
  7. package/clients/claude-desktop.json +3 -1
  8. package/dist/archive.d.ts +163 -0
  9. package/dist/archive.js +50 -0
  10. package/dist/archive.js.map +1 -0
  11. package/dist/bridge-domain-CBX3IVqC.d.ts +153 -0
  12. package/dist/{bridge-service-CfqMcMAn.d.ts → bridge-service-hX1ZQp4W.d.ts} +15 -5
  13. package/dist/bridge-store-DPVSCwfs.d.ts +102 -0
  14. package/dist/bridge.d.ts +76 -17
  15. package/dist/bridge.js +52 -24
  16. package/dist/chunk-2DFNOLMO.js +618 -0
  17. package/dist/chunk-2DFNOLMO.js.map +1 -0
  18. package/dist/{chunk-KVR4JBRF.js → chunk-2EVLG3YA.js} +2 -2
  19. package/dist/{chunk-KVR4JBRF.js.map → chunk-2EVLG3YA.js.map} +1 -1
  20. package/dist/chunk-45BZGB77.js +709 -0
  21. package/dist/chunk-45BZGB77.js.map +1 -0
  22. package/dist/chunk-4VB44KJU.js +230 -0
  23. package/dist/chunk-4VB44KJU.js.map +1 -0
  24. package/dist/chunk-5GMB3A77.js +1013 -0
  25. package/dist/chunk-5GMB3A77.js.map +1 -0
  26. package/dist/chunk-A6W4QALF.js +1258 -0
  27. package/dist/chunk-A6W4QALF.js.map +1 -0
  28. package/dist/chunk-BZLMF5O5.js +328 -0
  29. package/dist/chunk-BZLMF5O5.js.map +1 -0
  30. package/dist/{chunk-AXL2I7FH.js → chunk-CEXBMOI5.js} +240 -79
  31. package/dist/chunk-CEXBMOI5.js.map +1 -0
  32. package/dist/chunk-GADH244D.js +527 -0
  33. package/dist/chunk-GADH244D.js.map +1 -0
  34. package/dist/chunk-MBPZXTJA.js +2428 -0
  35. package/dist/chunk-MBPZXTJA.js.map +1 -0
  36. package/dist/chunk-NCO7RLBM.js +146 -0
  37. package/dist/chunk-NCO7RLBM.js.map +1 -0
  38. package/dist/chunk-Q6PPMXJC.js +1050 -0
  39. package/dist/chunk-Q6PPMXJC.js.map +1 -0
  40. package/dist/{chunk-4KAOBC5X.js → chunk-SPSMZOCJ.js} +190 -165
  41. package/dist/chunk-SPSMZOCJ.js.map +1 -0
  42. package/dist/chunk-UAHMP6GC.js +54 -0
  43. package/dist/chunk-UAHMP6GC.js.map +1 -0
  44. package/dist/{chunk-YD6YJATN.js → chunk-VOQIDTCJ.js} +4 -2
  45. package/dist/chunk-VOQIDTCJ.js.map +1 -0
  46. package/dist/chunk-WAI2IYIQ.js +554 -0
  47. package/dist/chunk-WAI2IYIQ.js.map +1 -0
  48. package/dist/cli.d.ts +2 -1
  49. package/dist/cli.js +3555 -214
  50. package/dist/cli.js.map +1 -1
  51. package/dist/client-config.d.ts +1 -1
  52. package/dist/client-config.js +1 -1
  53. package/dist/client-runtime.d.ts +10 -6
  54. package/dist/client-runtime.js +9 -6
  55. package/dist/contracts/generate.d.ts +2 -0
  56. package/dist/contracts/generate.js +247 -0
  57. package/dist/contracts/generate.js.map +1 -0
  58. package/dist/dr.d.ts +324 -0
  59. package/dist/dr.js +124 -0
  60. package/dist/dr.js.map +1 -0
  61. package/dist/gateway-CggQ8vTC.d.ts +78 -0
  62. package/dist/gateway-main.js +190 -8
  63. package/dist/gateway-main.js.map +1 -1
  64. package/dist/gateway.d.ts +4 -3
  65. package/dist/gateway.js +4 -3
  66. package/dist/index.js +11 -8
  67. package/dist/index.js.map +1 -1
  68. package/dist/postgres-bridge-store-Bfd3hRId.d.ts +49 -0
  69. package/dist/server.d.ts +3 -2
  70. package/dist/server.js +13 -8
  71. package/dist/sqlite.d.ts +94 -12
  72. package/dist/sqlite.js +7 -4
  73. package/docs/architecture-v2.md +394 -0
  74. package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +85 -0
  75. package/docs/decisions/0002-canonical-operation-contract-registry.md +46 -0
  76. package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
  77. package/docs/ecosystem.md +86 -0
  78. package/docs/postmortems/2026-07-08-wrapper-source-drift.md +82 -0
  79. package/docs/troubleshooting.md +89 -0
  80. package/llms.txt +107 -6
  81. package/openapi/agent-bridge-v2.openapi.json +9610 -0
  82. package/package.json +24 -4
  83. package/schemas/agent-bridge-v2.capabilities.json +1829 -0
  84. package/schemas/agent-bridge-v2.mcp.json +2074 -0
  85. package/schemas/agent-bridge-v2.schema.json +4560 -0
  86. package/sql/migrations/008_message_projects.sql +36 -0
  87. package/sql/migrations/009_mailbox_query_indexes.sql +28 -0
  88. package/sql/migrations/010_publisher_delivery_policy.sql +210 -0
  89. package/sql/migrations/011_credential_security.sql +875 -0
  90. package/sql/migrations/012_request_authority.sql +177 -0
  91. package/sql/migrations/013_row_isolation.sql +495 -0
  92. package/sql/migrations/014_owner_control_plane.sql +1641 -0
  93. package/sql/migrations/015_portable_archives.sql +1813 -0
  94. package/sql/migrations/016_native_dr_fence.sql +1005 -0
  95. package/bin/CLAUDE.md +0 -11
  96. package/dist/bridge-domain-BcnBeHOn.d.ts +0 -97
  97. package/dist/bridge-store-BuGjxTn4.d.ts +0 -61
  98. package/dist/chunk-4KAOBC5X.js.map +0 -1
  99. package/dist/chunk-6MAZ6YLZ.js +0 -146
  100. package/dist/chunk-6MAZ6YLZ.js.map +0 -1
  101. package/dist/chunk-AXL2I7FH.js.map +0 -1
  102. package/dist/chunk-BV6W4AJK.js +0 -211
  103. package/dist/chunk-BV6W4AJK.js.map +0 -1
  104. package/dist/chunk-CKSKUBDQ.js +0 -153
  105. package/dist/chunk-CKSKUBDQ.js.map +0 -1
  106. package/dist/chunk-JOUBDRYX.js +0 -272
  107. package/dist/chunk-JOUBDRYX.js.map +0 -1
  108. package/dist/chunk-JTC5YURG.js +0 -49
  109. package/dist/chunk-JTC5YURG.js.map +0 -1
  110. package/dist/chunk-O26W5QHS.js +0 -409
  111. package/dist/chunk-O26W5QHS.js.map +0 -1
  112. package/dist/chunk-WEULPMUY.js +0 -988
  113. package/dist/chunk-WEULPMUY.js.map +0 -1
  114. package/dist/chunk-YD6YJATN.js.map +0 -1
  115. package/dist/gateway-BULozv3K.d.ts +0 -54
package/ROADMAP.md ADDED
@@ -0,0 +1,114 @@
1
+ # Agent Bridge roadmap
2
+
3
+ Agent Bridge is working toward one specific role: durable messaging and work delivery
4
+ between agent runtimes that do not share a process, vendor, session, or machine.
5
+
6
+ This roadmap separates released behavior from code that has not reached a public
7
+ release. A merged implementation is not considered shipped until the package is
8
+ published and the supported clients pass a fresh end-to-end check.
9
+
10
+ ## Status
11
+
12
+ ### Released by 0.3.0
13
+
14
+ - Local SQLite and shared PostgreSQL storage behind provider-neutral interfaces.
15
+ - An authenticated HTTPS gateway and a named legacy Supabase adapter.
16
+ - Immutable messages, caller receipts, delivery leases, retries, dead letters, and
17
+ presence.
18
+ - Durable SQLite edge outbox and inbox cache for gateway clients.
19
+ - CLI, MCP, HTTPS, and Node library access surfaces.
20
+ - Automated host adapters for Codex, Claude Code, and Claude Desktop. The Codex
21
+ adapter configures the profile shared by the Codex CLI and the Codex surface in the
22
+ ChatGPT desktop app.
23
+ - Caller-bound inbox, sent, and combined history with scope-bound cursors.
24
+ - Publisher-owned delivery policy, priority claims, cancel, requeue, and delivery event
25
+ inspection.
26
+ - Canonical TypeBox operation definitions that generate JSON Schema, OpenAPI, MCP, and
27
+ capability artifacts.
28
+ - Credential scopes, rate policy, transaction-bound PostgreSQL request authority, and
29
+ forced row isolation.
30
+ - Offline owner commands for credential provisioning, inventory, rotation, and
31
+ revocation.
32
+ - Claude Desktop registration with absolute launcher paths that do not depend on the
33
+ application's inherited shell `PATH`.
34
+ - Portable workspace archives across canonical SQLite and PostgreSQL stores.
35
+ - Native SQLite and PostgreSQL backup, verification, and restore.
36
+
37
+ ### Post-release validation and adoption
38
+
39
+ - Move the project's own normal traffic to the authenticated gateway while retaining a
40
+ tested legacy rollback path.
41
+ - Prove cross-machine claim, settlement, offline replay, and restart behavior against
42
+ the published package and a deployed v2 gateway. The 0.3.0 live release check covered
43
+ startup, private mailbox sends, caller-scoped history, receipts, and client restart
44
+ through the legacy compatibility backend; it could not prove gateway-only behavior.
45
+ - Replace remaining direct legacy table pollers with the v2 cursor protocol.
46
+ - Confirm the README, npm metadata, GitHub metadata, release notes, and package contents
47
+ match the released artifact.
48
+
49
+ ## Near-term work
50
+
51
+ ### Installation and operations
52
+
53
+ - Add client repair, update, uninstall, and registration diagnostics.
54
+ - Provide a Compose-based development deployment and a production deployment guide.
55
+ - Add endpoint migration tooling that does not strand an existing SQLite outbox.
56
+ - Publish a maintained client compatibility matrix.
57
+
58
+ ### Storage lifecycle and observability
59
+
60
+ - Define retention separately from logical message immutability.
61
+ - Add audited archive and purge operations for expired data.
62
+ - Bound edge caches and resolve abandoned outbox state.
63
+ - Add workspace quotas, principal limits, queue-depth diagnostics, and capacity alerts.
64
+ - Maintain credential use and administrative audit records without logging secrets.
65
+
66
+ ### Presence and wakeups
67
+
68
+ - Separate the stable consumer instance key from a live process identity. Supported
69
+ installers generate one key per installed client, while direct clients may supply
70
+ their own. Processes that share a key also share presence in 0.3.
71
+ - Add per-process presence and session correlation only through an additive protocol
72
+ change with migration and conformance coverage.
73
+ - Maintain heartbeat and expiry automatically for supported long-lived clients.
74
+ - Add wake adapters only where they reduce latency. Lost wakeups must never lose data.
75
+ - Keep cursored pull as the authoritative recovery path.
76
+
77
+ ### Failure and performance evidence
78
+
79
+ - Measure install-to-first-message time and local and gateway latency.
80
+ - Test concurrent claims, SQLite lock contention, queue growth, duplicate suppression,
81
+ lease expiry, and crash recovery.
82
+ - Exercise gateway restarts, database outages, network partitions, clock skew, cache
83
+ corruption, and interrupted migrations.
84
+ - Publish the test setup and results instead of making unsupported throughput claims.
85
+
86
+ ## Ecosystem work
87
+
88
+ - Build an agmsg adapter for send, inbox, history, claim, and settlement operations.
89
+ - Carry A2A envelopes without implementing a competing task state machine.
90
+ - Publish conformance fixtures and an adapter template.
91
+ - Add client libraries where real integrations need them.
92
+ - Rename the compatibility `runtime` manifest key to an explicit host-adapter key in a
93
+ versioned manifest contract.
94
+ - Expand host installers after each product has a stable configuration contract.
95
+ Hermes, Pi, and similar harnesses can use a generic access surface when their host
96
+ supports one, but they do not have a dedicated adapter or conformance claim.
97
+
98
+ See [docs/ecosystem.md](docs/ecosystem.md) for the product boundary.
99
+
100
+ ## Project and community work
101
+
102
+ - Add contribution and support policies, issue templates, and a reviewable governance
103
+ path.
104
+ - Publish a local two-agent demo and a cross-machine recovery demo.
105
+ - Track completed cross-runtime deliveries and successful second-principal activation.
106
+ Any product telemetry must be opt-in.
107
+ - Review compatibility on every release and revisit interoperability choices each
108
+ quarter.
109
+
110
+ ## Deferred
111
+
112
+ JetStream or another required broker, a large dashboard, Kubernetes packaging, and
113
+ end-to-end payload encryption remain deferred until measurements or users justify the
114
+ extra operational and security work.
package/SECURITY.md ADDED
@@ -0,0 +1,90 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ | Version | Security updates |
6
+ | --- | --- |
7
+ | 0.3.x | Supported |
8
+ | 0.2.x | Not supported |
9
+ | 0.1.x | Not supported |
10
+ | Unreleased development code | No public support guarantee |
11
+
12
+ Upgrade to the latest published package before reporting a defect that may already be
13
+ fixed. The npm package and GitHub release page are the public version authorities.
14
+
15
+ ## Release integrity
16
+
17
+ GitHub immutable releases are enabled, and GitHub reports release `v0.3.0` as
18
+ immutable. A repository ruleset also blocks updates and deletion for every `v*` tag
19
+ without a bypass actor. The `v0.3.0` 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 `v0.3.0`
24
+ [recovery run](https://github.com/creatornader/agent-bridge/actions/runs/29461308262)
25
+ checked out package commit `95eb861`, while its attestation names recovery commit
26
+ `c23d9df` as the workflow identity. GitHub Actions logs expire, so the
27
+ [release notes](https://github.com/creatornader/agent-bridge/releases/tag/v0.3.0)
28
+ also record this boundary. Future recovery dispatches must run at the release tag, and
29
+ the workflow enforces that match before packaging.
30
+
31
+ ## Report a vulnerability
32
+
33
+ Use [GitHub private vulnerability reporting](https://github.com/creatornader/agent-bridge/security/advisories/new).
34
+ Do not open a public issue for a suspected vulnerability.
35
+
36
+ Include the affected version, provider mode, operating system, reproduction steps, and
37
+ the security boundary that failed. Remove bearer tokens, raw credential files, database
38
+ URLs, message content, archive data, and disaster-recovery bundles. The maintainer will
39
+ coordinate disclosure and remediation through the private advisory.
40
+
41
+ ## Security boundaries
42
+
43
+ ### Local mode
44
+
45
+ Local mode relies on operating-system account isolation and private file permissions.
46
+ Anyone who can act as the same operating-system user can generally read or replace that
47
+ user's Agent Bridge state. Local mode is not a hostile multi-user boundary.
48
+
49
+ ### Gateway mode
50
+
51
+ Gateway credentials bind one workspace and principal. The gateway derives remote
52
+ identity from the credential, applies operation scopes and rate policy, and uses
53
+ transaction-bound PostgreSQL request authority. Production runtime roles must not be
54
+ superusers or hold `BYPASSRLS`. Put every non-loopback gateway behind TLS.
55
+
56
+ Keep the schema-owner, runtime, operator, archive, backup, and restore database
57
+ authorities separate. Do not copy one client's token or backend file into another
58
+ client's configuration.
59
+
60
+ ### Legacy Supabase mode
61
+
62
+ The legacy adapter keeps existing v1 deployments working, but its publishable key can
63
+ call the underlying PostgREST table and receipt RPC directly. Adapter checks therefore
64
+ provide cooperative behavior, not the same workspace and principal isolation as the
65
+ authenticated gateway. Do not use legacy mode as a hostile multi-tenant boundary.
66
+
67
+ ### Archives and disaster recovery
68
+
69
+ Portable archives and native DR bundles may contain message content, routing metadata,
70
+ credentials, or database state. Their hashes detect changed bytes. They do not encrypt
71
+ the files or authenticate their source. Store them as private data and transfer them
72
+ through a separately trusted channel.
73
+
74
+ PostgreSQL restore executes SQL from the source dump. Use
75
+ `--accept-source-sql-risk` only for a bundle from a trusted source. Never activate the
76
+ source and restored target as authorities at the same time.
77
+
78
+ ### Optional integrations
79
+
80
+ Agent Bridge does not require atrib or another provenance system. A signed wrapper is a
81
+ separate security and availability boundary. Keep a direct Agent Bridge path available
82
+ when wrapper health is uncertain.
83
+
84
+ ## Secret handling
85
+
86
+ - Pass gateway tokens through private enrollment or backend files, not shell arguments.
87
+ - Keep database URLs in the documented environment variables. Do not put them in CLI
88
+ arguments, logs, issues, or examples.
89
+ - Treat client backend files, enrollment files, archives, and DR bundles as secrets.
90
+ - Sanitize `doctor` output and logs before sharing them publicly.
package/SKILL.md CHANGED
@@ -5,10 +5,23 @@ description: Share context and reliable work between agents across runtimes and
5
5
 
6
6
  # Agent Bridge
7
7
 
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
+
8
10
  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.
9
11
 
12
+ If the MCP server is unavailable or disconnects, report the outage instead of implying
13
+ that a post, read, or acknowledgment succeeded. Run `agent-bridge doctor --json` from a
14
+ shell and follow [docs/troubleshooting.md](docs/troubleshooting.md). Reinstall the client
15
+ registration if its executable or environment is stale.
16
+
17
+ History defaults to `inbox` (broadcasts and messages targeted to your configured identity). Use `sent` for messages you published or `mailbox: all` for the union. Receipt state is caller-relative; use `unread` or `read` only with inbox. Deprecated `unacked_by` and `--unacked-by` values must equal your configured identity.
18
+
10
19
  At session start, call `get_context` with a small limit. Summarize relevant unacknowledged entries, then call `ack_context` with the IDs you handled.
11
20
 
21
+ In gateway mode, long-lived MCP clients sync automatically. Call the MCP `sync` tool to trigger bounded outbox replay and inbox cache refresh manually.
22
+
23
+ Use `agent-bridge status` for a passive operational snapshot. Do not use it as a connectivity probe. Unprobed remote reachability is unknown, not healthy. Use `agent-bridge doctor` for active checks. Doctor exits 0 when ok, 2 when degraded, and 1 when checks fail. Treat blocked outbox rows as intervention-required even if a later send or pull succeeded. Distinguish due, scheduled, and leased work.
24
+
12
25
  Post context as events happen when another agent would need the information later:
13
26
 
14
27
  - `goal-update`: material progress, decisions, or completed research
@@ -17,8 +30,61 @@ Post context as events happen when another agent would need the information late
17
30
  - `operational`: runtime and repository handoffs
18
31
  - `bridge-meta`: limitations or proposed improvements to Agent Bridge
19
32
 
20
- Use v2 delivery tools for executable work. A read receipt does not claim work. Claim a delivery before acting, renew long leases, acknowledge success, and negatively acknowledge retryable or dead work with a bounded error.
33
+ Use v2 delivery tools for executable work. MCP `ack_context` and CLI `acknowledge` write read receipts. MCP `acknowledge` and CLI `ack` settle claimed deliveries. A read receipt does not claim or settle work, and delivery settlement does not create a receipt.
34
+
35
+ Publish executable work with `deliveryPolicy`; consumers never select retry limits or backoff. Leased policy accepts `maxAttempts`, `retryBaseDelayMs`, `retryMaxDelayMs`, `retryJitterRatio`, and optional `notBefore`. Untargeted messages default to mailbox mode and targeted messages to leased mode. Only publishers cancel or requeue. Publishers and recipients can inspect delivery history. Requeue starts a new cycle without resetting lifetime attempts. Consumer `maxAttempts` on claim and `retryPolicy` on nack are validated but ignored for one compatibility release. External task completion stays outside Agent Bridge.
21
36
 
22
- Use `agent-bridge pending` as a cheap process gate before starting an agent. Exit 0 means unread context or due delivery work exists. Exit 1 means neither exists. Treat network errors as unknown state, not as an empty queue.
37
+ Claim a delivery before acting. Renew a long lease only to retain ownership. A lease extension does not report progress or success. Record external task completion through the application or A2A protocol, then settle the Agent Bridge delivery separately.
38
+
39
+ Use `agent-bridge pending` as a cheap process gate before starting an agent. Exit 0 means unread candidates or due delivery work are visible. Exit 1 means the authoritative state is empty. Exit 2 means the remote state is unknown. During a gateway outage, cached unacknowledged results are degraded candidates with unknown acknowledgement state.
23
40
 
24
41
  Keep side effects idempotent. Agent Bridge provides at-least-once delivery and idempotent message insertion, not exactly-once execution.
42
+
43
+ Owner administration is an offline operator task. Use `agent-bridge owner provision`,
44
+ `inventory`, `rotate`, or `revoke` with
45
+ `AGENT_BRIDGE_OPERATOR_DATABASE_URL`. Do not route these commands through MCP or
46
+ HTTP. Provision and rotation produce a private enrollment file. Pass that file to
47
+ `agent-bridge clients install <runtime> --enrollment-file <path>`; never copy its raw
48
+ token into an argument or another client's environment. If the owner process stops,
49
+ resume from the same file instead of generating a new token or request UUID.
50
+ If a crash leaves the adjacent enrollment lock, wait at least 60 seconds and pass
51
+ `--recover-lock` with the resume or install command. Recovery must prove that the
52
+ same-host process recorded in the lock has stopped. Never remove the lock manually.
53
+
54
+ Portable archive work is an offline operator task, not normal MCP traffic. Use
55
+ `agent-bridge archive export --provider local|postgres --workspace <workspace>
56
+ --output <file>` to create an archive, then run `agent-bridge archive verify --file
57
+ <file>` before moving or importing it. Archive files and their directories must satisfy
58
+ the current user's private-path policy. Import replays three bounded passes through one
59
+ open descriptor. It is a dry run unless `--apply` is explicit; `--dry-run` and
60
+ `--apply` cannot be combined. Provide `--workspace` on import when the destination must
61
+ match an expected tenant. PostgreSQL archive commands accept only
62
+ `AGENT_BRIDGE_ARCHIVE_DATABASE_URL`.
63
+ Portable v1 requires current-domain records, lowercase UUIDs, and six-digit UTC
64
+ timestamps. It does not repair legacy or direct database rows. Use native database
65
+ recovery for rows that fail export validation.
66
+ Set and retain `--request-id` for export. The archive header records it as
67
+ `exportRequestId`; verification and import return that provenance. An import
68
+ `--request-id` identifies the destination operation and is independent. Retry an
69
+ export ID only with the same private output file. The CLI verifies completed exports
70
+ and reconciles matching started exports without streaming a new snapshot. Temporary
71
+ and backup files have deterministic adjacent names derived from the export ID. Follow
72
+ returned recovery paths and audit status exactly when replacement, cleanup, or audit
73
+ completion is uncertain.
74
+ Do not treat the archive digest as encryption or authentication. Archives contain
75
+ messages and read receipts but exclude deliveries, events, presence, credentials,
76
+ control records, and security state.
77
+
78
+ Native DR is also an offline operator task. Use `agent-bridge dr backup|verify|restore`
79
+ for one complete SQLite or PostgreSQL authority. Local DR accepts the SQLite authority,
80
+ not the gateway edge store. PostgreSQL backup and restore authority come only from
81
+ `AGENT_BRIDGE_DR_SOURCE_DATABASE_URL` and
82
+ `AGENT_BRIDGE_DR_TARGET_DATABASE_URL`. PostgreSQL restore needs a fresh same-name,
83
+ same-major database, a superuser, an explicit request ID, and
84
+ `--accept-source-sql-risk`. Never activate the source and restored target together.
85
+ Treat the bundle as private database material; its hashes do not encrypt or authenticate
86
+ the source.
87
+
88
+ 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
+
90
+ 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/bin/agent-bridge CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { runCli } from "../dist/cli.js";
2
+ import { formatCliError, runCli } from "../dist/cli.js";
3
3
 
4
4
  runCli().catch((error) => {
5
- process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
5
+ process.stderr.write(formatCliError(error));
6
6
  process.exitCode = 1;
7
7
  });
@@ -2,7 +2,8 @@
2
2
  "schema": "agent-bridge.runtime-manifest.v1",
3
3
  "runtime": "claude-desktop",
4
4
  "transport": "stdio",
5
- "command": "agent-bridge-mcp",
5
+ "command": "{{absoluteNodeExecutable}}",
6
+ "args": ["{{absoluteServerEntry}}"],
6
7
  "identity": { "source": "env", "variable": "AGENT_BRIDGE_AGENT", "required": true },
7
8
  "instance": { "source": "env", "variable": "AGENT_BRIDGE_INSTANCE", "required": true },
8
9
  "backendConfig": { "source": "env", "variable": "AGENT_BRIDGE_CONFIG", "perClient": true },
@@ -13,6 +14,7 @@
13
14
  "identityValue": "operator-selected",
14
15
  "instanceValue": "installer-generated",
15
16
  "backendConfigValue": "installer-generated",
17
+ "launchValue": "installer-resolved-absolute",
16
18
  "restartRequired": true
17
19
  },
18
20
  "wakeModes": ["poll"],
@@ -0,0 +1,163 @@
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';
4
+
5
+ interface PortableArchiveMessage {
6
+ id: string;
7
+ project: string | null;
8
+ source: string;
9
+ type: string;
10
+ content: string;
11
+ contentType: string;
12
+ data: JsonValue | null;
13
+ targets: string[];
14
+ threadId: string | null;
15
+ replyToId: string | null;
16
+ correlationId: string | null;
17
+ causationId: string | null;
18
+ priority: MessagePriority;
19
+ expiresAt: string | null;
20
+ idempotencyKey: string | null;
21
+ atribReceiptId: string | null;
22
+ informedBy: string[];
23
+ metadata: JsonValue | null;
24
+ deliveryPolicy: DeliveryPolicy;
25
+ createdAt: string;
26
+ }
27
+ interface PortableArchiveReceipt {
28
+ messageId: string;
29
+ principal: string;
30
+ readAt: string;
31
+ }
32
+ /** In-memory helper used by format tests and small programmatic archives. Stores do not use it. */
33
+ interface PortableArchiveContents {
34
+ exportRequestId: string;
35
+ workspace: string;
36
+ messages: PortableArchiveMessage[];
37
+ receipts: PortableArchiveReceipt[];
38
+ digest?: string;
39
+ }
40
+ interface PortableArchiveMetadata {
41
+ exportRequestId: string;
42
+ workspace: string;
43
+ digest: string;
44
+ messageCount: number;
45
+ receiptCount: number;
46
+ }
47
+ type PortableArchiveAbandonCode = "stream_failed" | "snapshot_failed" | "publication_failed" | "audit_failed" | "not_published";
48
+ interface PortableArchiveExportSession {
49
+ messages(): AsyncIterable<PortableArchiveMessage>;
50
+ receipts(): AsyncIterable<PortableArchiveReceipt>;
51
+ complete(result: PortableArchiveMetadata & {
52
+ publishedAt: string;
53
+ }): Promise<void>;
54
+ reconcile(result: PortableArchiveMetadata & {
55
+ publishedAt: string;
56
+ }): Promise<void>;
57
+ abandon(reason: PortableArchiveAbandonCode): Promise<void>;
58
+ close(): Promise<void> | void;
59
+ }
60
+ type PortableArchiveExportStart = {
61
+ status: "active";
62
+ session: PortableArchiveExportSession;
63
+ replayed: boolean;
64
+ } | {
65
+ status: "completed";
66
+ metadata: PortableArchiveMetadata & {
67
+ publishedAt: string;
68
+ };
69
+ };
70
+ interface PortableArchiveImportPasses {
71
+ messageBatches(): AsyncIterable<readonly PortableArchiveMessage[]>;
72
+ receiptBatches(): AsyncIterable<readonly PortableArchiveReceipt[]>;
73
+ }
74
+ interface PortableArchiveResult {
75
+ requestId: string;
76
+ workspace: string;
77
+ digest: string;
78
+ apply: boolean;
79
+ messages: {
80
+ created: number;
81
+ replayed: number;
82
+ };
83
+ receipts: {
84
+ created: number;
85
+ replayed: number;
86
+ };
87
+ }
88
+ interface PortableArchiveStore {
89
+ beginExport(requestId: string, workspace: string): Promise<PortableArchiveExportStart>;
90
+ importWorkspace(requestId: string, metadata: PortableArchiveMetadata, passes: PortableArchiveImportPasses, options: {
91
+ apply: boolean;
92
+ }): Promise<PortableArchiveResult>;
93
+ close?(): Promise<void> | void;
94
+ }
95
+
96
+ declare const PORTABLE_ARCHIVE_FORMAT = "agent-bridge.portable-archive";
97
+ declare const PORTABLE_ARCHIVE_VERSION = 1;
98
+ declare const PORTABLE_ARCHIVE_MAX_LINE_BYTES: number;
99
+ declare const PORTABLE_ARCHIVE_MAX_BYTES: number;
100
+ declare const PORTABLE_ARCHIVE_BATCH_BYTES: number;
101
+ declare const PORTABLE_ARCHIVE_BATCH_ROWS = 1000;
102
+ declare class PortableArchiveError extends Error {
103
+ readonly code = "invalid_portable_archive";
104
+ constructor(message: string);
105
+ }
106
+ declare function canonicalJson(value: unknown): string;
107
+ declare function normalizeArchiveTimestamp(value: unknown, field: string): string;
108
+ declare function validateArchiveWorkspace(value: unknown): string;
109
+ declare function validatePortableArchiveRequestId(value: unknown): string;
110
+ declare function parsePortableArchiveMessage(value: unknown): PortableArchiveMessage;
111
+ declare function parsePortableArchiveReceipt(value: unknown): PortableArchiveReceipt;
112
+ declare function encodePortableArchive(contents: PortableArchiveContents): Buffer;
113
+ declare function decodePortableArchive(input: Uint8Array): PortableArchiveContents & {
114
+ digest: string;
115
+ };
116
+
117
+ declare class PortableArchiveFile implements PortableArchiveImportPasses {
118
+ readonly path: string;
119
+ private readonly descriptor;
120
+ private readonly identity;
121
+ private closed;
122
+ private verified?;
123
+ constructor(path: string);
124
+ private assertIdentity;
125
+ private lines;
126
+ private validatedRecords;
127
+ verify(): PortableArchiveMetadata;
128
+ proveDurable(): void;
129
+ messageBatches(): AsyncIterable<readonly PortableArchiveMessage[]>;
130
+ receiptBatches(): AsyncIterable<readonly PortableArchiveReceipt[]>;
131
+ close(): void;
132
+ }
133
+
134
+ declare function streamPortableArchive(session: PortableArchiveExportSession, workspaceValue: string, exportRequestIdValue: string, write: (bytes: Buffer) => void | Promise<void>): Promise<PortableArchiveMetadata>;
135
+ /** Small in-memory compatibility helper. It abandons the durable export audit. */
136
+ declare function exportPortableArchive(store: PortableArchiveStore, workspace: string, exportRequestIdValue: string): Promise<Buffer>;
137
+ /** Small in-memory compatibility helper. CLI imports use PortableArchiveFile instead. */
138
+ declare function importPortableArchive(store: PortableArchiveStore, bytes: Uint8Array, options: {
139
+ requestId: string;
140
+ apply?: boolean;
141
+ }): Promise<PortableArchiveResult>;
142
+
143
+ declare class SQLitePortableArchiveStore implements PortableArchiveStore {
144
+ private readonly path;
145
+ private readonly db;
146
+ constructor(path: string);
147
+ beginExport(requestIdValue: string, workspaceValue: string): Promise<PortableArchiveExportStart>;
148
+ importWorkspace(requestId: string, archive: PortableArchiveMetadata, passes: PortableArchiveImportPasses, options: {
149
+ apply: boolean;
150
+ }): Promise<PortableArchiveResult>;
151
+ close(): void;
152
+ }
153
+
154
+ declare class PostgresPortableArchiveStore implements PortableArchiveStore {
155
+ private readonly db;
156
+ constructor(db: PgQueryable);
157
+ beginExport(requestId: string, workspace: string): Promise<PortableArchiveExportStart>;
158
+ importWorkspace(requestId: string, metadata: PortableArchiveMetadata, passes: PortableArchiveImportPasses, options: {
159
+ apply: boolean;
160
+ }): Promise<PortableArchiveResult>;
161
+ }
162
+
163
+ export { PORTABLE_ARCHIVE_BATCH_BYTES, PORTABLE_ARCHIVE_BATCH_ROWS, PORTABLE_ARCHIVE_FORMAT, PORTABLE_ARCHIVE_MAX_BYTES, PORTABLE_ARCHIVE_MAX_LINE_BYTES, PORTABLE_ARCHIVE_VERSION, type PortableArchiveAbandonCode, type PortableArchiveContents, PortableArchiveError, type PortableArchiveExportSession, type PortableArchiveExportStart, PortableArchiveFile, type PortableArchiveImportPasses, type PortableArchiveMessage, type PortableArchiveMetadata, type PortableArchiveReceipt, type PortableArchiveResult, type PortableArchiveStore, PostgresPortableArchiveStore, SQLitePortableArchiveStore, canonicalJson, decodePortableArchive, encodePortableArchive, exportPortableArchive, importPortableArchive, normalizeArchiveTimestamp, parsePortableArchiveMessage, parsePortableArchiveReceipt, streamPortableArchive, validateArchiveWorkspace, validatePortableArchiveRequestId };
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ PORTABLE_ARCHIVE_BATCH_BYTES,
4
+ PORTABLE_ARCHIVE_BATCH_ROWS,
5
+ PORTABLE_ARCHIVE_FORMAT,
6
+ PORTABLE_ARCHIVE_MAX_BYTES,
7
+ PORTABLE_ARCHIVE_MAX_LINE_BYTES,
8
+ PORTABLE_ARCHIVE_VERSION,
9
+ PortableArchiveError,
10
+ PortableArchiveFile,
11
+ PostgresPortableArchiveStore,
12
+ SQLitePortableArchiveStore,
13
+ canonicalJson,
14
+ decodePortableArchive,
15
+ encodePortableArchive,
16
+ exportPortableArchive,
17
+ importPortableArchive,
18
+ normalizeArchiveTimestamp,
19
+ parsePortableArchiveMessage,
20
+ parsePortableArchiveReceipt,
21
+ streamPortableArchive,
22
+ validateArchiveWorkspace,
23
+ validatePortableArchiveRequestId
24
+ } from "./chunk-A6W4QALF.js";
25
+ import "./chunk-NCO7RLBM.js";
26
+ import "./chunk-BZLMF5O5.js";
27
+ export {
28
+ PORTABLE_ARCHIVE_BATCH_BYTES,
29
+ PORTABLE_ARCHIVE_BATCH_ROWS,
30
+ PORTABLE_ARCHIVE_FORMAT,
31
+ PORTABLE_ARCHIVE_MAX_BYTES,
32
+ PORTABLE_ARCHIVE_MAX_LINE_BYTES,
33
+ PORTABLE_ARCHIVE_VERSION,
34
+ PortableArchiveError,
35
+ PortableArchiveFile,
36
+ PostgresPortableArchiveStore,
37
+ SQLitePortableArchiveStore,
38
+ canonicalJson,
39
+ decodePortableArchive,
40
+ encodePortableArchive,
41
+ exportPortableArchive,
42
+ importPortableArchive,
43
+ normalizeArchiveTimestamp,
44
+ parsePortableArchiveMessage,
45
+ parsePortableArchiveReceipt,
46
+ streamPortableArchive,
47
+ validateArchiveWorkspace,
48
+ validatePortableArchiveRequestId
49
+ };
50
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}