@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.
- package/CHANGELOG.md +86 -4
- package/README.md +567 -55
- package/ROADMAP.md +114 -0
- package/SECURITY.md +90 -0
- package/SKILL.md +68 -2
- package/bin/agent-bridge +2 -2
- package/clients/claude-desktop.json +3 -1
- package/dist/archive.d.ts +163 -0
- package/dist/archive.js +50 -0
- package/dist/archive.js.map +1 -0
- package/dist/bridge-domain-CBX3IVqC.d.ts +153 -0
- package/dist/{bridge-service-CfqMcMAn.d.ts → bridge-service-hX1ZQp4W.d.ts} +15 -5
- package/dist/bridge-store-DPVSCwfs.d.ts +102 -0
- package/dist/bridge.d.ts +76 -17
- package/dist/bridge.js +52 -24
- package/dist/chunk-2DFNOLMO.js +618 -0
- package/dist/chunk-2DFNOLMO.js.map +1 -0
- package/dist/{chunk-KVR4JBRF.js → chunk-2EVLG3YA.js} +2 -2
- package/dist/{chunk-KVR4JBRF.js.map → chunk-2EVLG3YA.js.map} +1 -1
- package/dist/chunk-45BZGB77.js +709 -0
- package/dist/chunk-45BZGB77.js.map +1 -0
- package/dist/chunk-4VB44KJU.js +230 -0
- package/dist/chunk-4VB44KJU.js.map +1 -0
- package/dist/chunk-5GMB3A77.js +1013 -0
- package/dist/chunk-5GMB3A77.js.map +1 -0
- package/dist/chunk-A6W4QALF.js +1258 -0
- package/dist/chunk-A6W4QALF.js.map +1 -0
- package/dist/chunk-BZLMF5O5.js +328 -0
- package/dist/chunk-BZLMF5O5.js.map +1 -0
- package/dist/{chunk-AXL2I7FH.js → chunk-CEXBMOI5.js} +240 -79
- package/dist/chunk-CEXBMOI5.js.map +1 -0
- package/dist/chunk-GADH244D.js +527 -0
- package/dist/chunk-GADH244D.js.map +1 -0
- package/dist/chunk-MBPZXTJA.js +2428 -0
- package/dist/chunk-MBPZXTJA.js.map +1 -0
- package/dist/chunk-NCO7RLBM.js +146 -0
- package/dist/chunk-NCO7RLBM.js.map +1 -0
- package/dist/chunk-Q6PPMXJC.js +1050 -0
- package/dist/chunk-Q6PPMXJC.js.map +1 -0
- package/dist/{chunk-4KAOBC5X.js → chunk-SPSMZOCJ.js} +190 -165
- package/dist/chunk-SPSMZOCJ.js.map +1 -0
- package/dist/chunk-UAHMP6GC.js +54 -0
- package/dist/chunk-UAHMP6GC.js.map +1 -0
- package/dist/{chunk-YD6YJATN.js → chunk-VOQIDTCJ.js} +4 -2
- package/dist/chunk-VOQIDTCJ.js.map +1 -0
- package/dist/chunk-WAI2IYIQ.js +554 -0
- package/dist/chunk-WAI2IYIQ.js.map +1 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +3555 -214
- package/dist/cli.js.map +1 -1
- package/dist/client-config.d.ts +1 -1
- package/dist/client-config.js +1 -1
- package/dist/client-runtime.d.ts +10 -6
- package/dist/client-runtime.js +9 -6
- package/dist/contracts/generate.d.ts +2 -0
- package/dist/contracts/generate.js +247 -0
- package/dist/contracts/generate.js.map +1 -0
- package/dist/dr.d.ts +324 -0
- package/dist/dr.js +124 -0
- package/dist/dr.js.map +1 -0
- package/dist/gateway-CggQ8vTC.d.ts +78 -0
- package/dist/gateway-main.js +190 -8
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +4 -3
- package/dist/gateway.js +4 -3
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/dist/postgres-bridge-store-Bfd3hRId.d.ts +49 -0
- package/dist/server.d.ts +3 -2
- package/dist/server.js +13 -8
- package/dist/sqlite.d.ts +94 -12
- package/dist/sqlite.js +7 -4
- package/docs/architecture-v2.md +394 -0
- package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +85 -0
- package/docs/decisions/0002-canonical-operation-contract-registry.md +46 -0
- package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
- package/docs/ecosystem.md +86 -0
- package/docs/postmortems/2026-07-08-wrapper-source-drift.md +82 -0
- package/docs/troubleshooting.md +89 -0
- package/llms.txt +107 -6
- package/openapi/agent-bridge-v2.openapi.json +9610 -0
- package/package.json +24 -4
- package/schemas/agent-bridge-v2.capabilities.json +1829 -0
- package/schemas/agent-bridge-v2.mcp.json +2074 -0
- package/schemas/agent-bridge-v2.schema.json +4560 -0
- package/sql/migrations/008_message_projects.sql +36 -0
- package/sql/migrations/009_mailbox_query_indexes.sql +28 -0
- package/sql/migrations/010_publisher_delivery_policy.sql +210 -0
- package/sql/migrations/011_credential_security.sql +875 -0
- package/sql/migrations/012_request_authority.sql +177 -0
- package/sql/migrations/013_row_isolation.sql +495 -0
- package/sql/migrations/014_owner_control_plane.sql +1641 -0
- package/sql/migrations/015_portable_archives.sql +1813 -0
- package/sql/migrations/016_native_dr_fence.sql +1005 -0
- package/bin/CLAUDE.md +0 -11
- package/dist/bridge-domain-BcnBeHOn.d.ts +0 -97
- package/dist/bridge-store-BuGjxTn4.d.ts +0 -61
- package/dist/chunk-4KAOBC5X.js.map +0 -1
- package/dist/chunk-6MAZ6YLZ.js +0 -146
- package/dist/chunk-6MAZ6YLZ.js.map +0 -1
- package/dist/chunk-AXL2I7FH.js.map +0 -1
- package/dist/chunk-BV6W4AJK.js +0 -211
- package/dist/chunk-BV6W4AJK.js.map +0 -1
- package/dist/chunk-CKSKUBDQ.js +0 -153
- package/dist/chunk-CKSKUBDQ.js.map +0 -1
- package/dist/chunk-JOUBDRYX.js +0 -272
- package/dist/chunk-JOUBDRYX.js.map +0 -1
- package/dist/chunk-JTC5YURG.js +0 -49
- package/dist/chunk-JTC5YURG.js.map +0 -1
- package/dist/chunk-O26W5QHS.js +0 -409
- package/dist/chunk-O26W5QHS.js.map +0 -1
- package/dist/chunk-WEULPMUY.js +0 -988
- package/dist/chunk-WEULPMUY.js.map +0 -1
- package/dist/chunk-YD6YJATN.js.map +0 -1
- 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.
|
|
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
|
-
|
|
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(
|
|
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": "
|
|
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 };
|
package/dist/archive.js
ADDED
|
@@ -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":[]}
|