@creatornader/agent-bridge 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +174 -5
- package/README.md +341 -33
- package/ROADMAP.md +78 -16
- package/SECURITY.md +68 -1
- package/SKILL.md +104 -1
- package/dist/archive.d.ts +2 -2
- package/dist/archive.js +2 -2
- package/dist/{bridge-service-hX1ZQp4W.d.ts → bridge-service-YTjGr91A.d.ts} +1 -1
- package/dist/{bridge-store-DPVSCwfs.d.ts → bridge-store-Boaj-ZbO.d.ts} +2 -0
- package/dist/bridge.d.ts +17 -7
- package/dist/bridge.js +15 -7
- package/dist/{chunk-WAI2IYIQ.js → chunk-3YHVUPU2.js} +48 -5
- package/dist/chunk-3YHVUPU2.js.map +1 -0
- package/dist/{chunk-45BZGB77.js → chunk-6BTJE6D4.js} +168 -7
- package/dist/chunk-6BTJE6D4.js.map +1 -0
- package/dist/{chunk-5GMB3A77.js → chunk-DQOZJJZ2.js} +22 -10
- package/dist/chunk-DQOZJJZ2.js.map +1 -0
- package/dist/{chunk-NCO7RLBM.js → chunk-GTK4KOED.js} +108 -8
- package/dist/chunk-GTK4KOED.js.map +1 -0
- package/dist/{chunk-GADH244D.js → chunk-IHZFI7TH.js} +12 -4
- package/dist/chunk-IHZFI7TH.js.map +1 -0
- package/dist/{chunk-CEXBMOI5.js → chunk-LAHNQZDN.js} +2 -2
- package/dist/{chunk-UAHMP6GC.js → chunk-MCKKVNCE.js} +9 -6
- package/dist/chunk-MCKKVNCE.js.map +1 -0
- package/dist/{chunk-MBPZXTJA.js → chunk-PDIHDBP3.js} +173 -20
- package/dist/chunk-PDIHDBP3.js.map +1 -0
- package/dist/{chunk-Q6PPMXJC.js → chunk-SV3SVBYS.js} +377 -21
- package/dist/chunk-SV3SVBYS.js.map +1 -0
- package/dist/{chunk-SPSMZOCJ.js → chunk-SYGONYMM.js} +4 -4
- package/dist/{chunk-A6W4QALF.js → chunk-TC6A7GMF.js} +2 -2
- package/dist/cli.js +5856 -413
- package/dist/cli.js.map +1 -1
- package/dist/client-runtime.d.ts +4 -2
- package/dist/client-runtime.js +6 -6
- package/dist/contracts/generate.js +1 -1
- package/dist/dr.d.ts +9 -2
- package/dist/dr.js +6 -4
- package/dist/{gateway-CggQ8vTC.d.ts → gateway-BQHpV-MZ.d.ts} +27 -3
- package/dist/gateway-main.js +69 -5
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +2 -2
- package/dist/index.js +7 -7
- package/dist/{postgres-bridge-store-Bfd3hRId.d.ts → postgres-bridge-store-WASumj26.d.ts} +1 -1
- package/dist/server.js +7 -7
- package/dist/sqlite-edge-store-Bc15DvpX.d.ts +148 -0
- package/dist/sqlite.d.ts +19 -80
- package/dist/sqlite.js +11 -3
- package/docs/architecture-v2.md +278 -13
- package/docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md +2 -2
- package/docs/decisions/0003-host-adapters-and-consumer-instance-keys.md +88 -0
- package/docs/decisions/0004-client-lifecycle-and-endpoint-migration.md +204 -0
- package/docs/deployment.md +205 -0
- package/docs/ecosystem.md +35 -3
- package/docs/troubleshooting.md +23 -0
- package/llms.txt +79 -3
- package/openapi/agent-bridge-v2.openapi.json +1023 -0
- package/package.json +6 -2
- package/schemas/agent-bridge-v2.capabilities.json +24 -0
- package/schemas/agent-bridge-v2.mcp.json +6 -0
- package/schemas/agent-bridge-v2.schema.json +163 -0
- package/sql/migrations/017_gateway_authority_binding.sql +99 -0
- package/sql/migrations/018_endpoint_migration_challenges.sql +1028 -0
- package/sql/migrations/019_endpoint_migration_same_successor.sql +324 -0
- package/dist/chunk-45BZGB77.js.map +0 -1
- package/dist/chunk-5GMB3A77.js.map +0 -1
- package/dist/chunk-GADH244D.js.map +0 -1
- package/dist/chunk-MBPZXTJA.js.map +0 -1
- package/dist/chunk-NCO7RLBM.js.map +0 -1
- package/dist/chunk-Q6PPMXJC.js.map +0 -1
- package/dist/chunk-UAHMP6GC.js.map +0 -1
- package/dist/chunk-WAI2IYIQ.js.map +0 -1
- /package/dist/{chunk-CEXBMOI5.js.map → chunk-LAHNQZDN.js.map} +0 -0
- /package/dist/{chunk-SPSMZOCJ.js.map → chunk-SYGONYMM.js.map} +0 -0
- /package/dist/{chunk-A6W4QALF.js.map → chunk-TC6A7GMF.js.map} +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ADR-0003: Separate host adapters from consumer instance keys
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-07-15
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Agent products often combine an agent harness with a host application. Codex runs in
|
|
14
|
+
the Codex CLI and in the Codex surface of the ChatGPT desktop app. Claude Code and
|
|
15
|
+
Claude Desktop are separate hosts. OpenClaw, Hermes, Pi, scripts, CI jobs, and services
|
|
16
|
+
have different host and access options.
|
|
17
|
+
|
|
18
|
+
The released protocol also uses `AGENT_BRIDGE_INSTANCE` in several places. Supported
|
|
19
|
+
installers generate one value for each installed client, but the gateway accepts the
|
|
20
|
+
value from the caller. Calling it a registered process identity would promise an
|
|
21
|
+
authority check that the server does not perform.
|
|
22
|
+
|
|
23
|
+
## Decision
|
|
24
|
+
|
|
25
|
+
The integration model separates these concepts:
|
|
26
|
+
|
|
27
|
+
- A harness runs an agent loop.
|
|
28
|
+
- A host is a CLI, desktop application, daemon, job, or service that contains a
|
|
29
|
+
harness or calls Agent Bridge.
|
|
30
|
+
- A host adapter configures a host to use Agent Bridge.
|
|
31
|
+
- MCP over stdio, the CLI, the HTTPS API, and the Node library are access surfaces.
|
|
32
|
+
- Scripts, CI jobs, and services may use an access surface directly without becoming
|
|
33
|
+
agent harnesses.
|
|
34
|
+
|
|
35
|
+
The `codex` adapter configures the profile shared by the Codex CLI and the Codex
|
|
36
|
+
surface in the ChatGPT desktop app. Claude Code and Claude Desktop have separate
|
|
37
|
+
adapters. Their supported installation flows create separate host registrations and
|
|
38
|
+
instance keys. OpenClaw and generic MCP manifests are operator-managed. Hermes, Pi,
|
|
39
|
+
and other harnesses have no dedicated compatibility or conformance claim until an
|
|
40
|
+
adapter is tested.
|
|
41
|
+
|
|
42
|
+
`AGENT_BRIDGE_INSTANCE` is an optional caller-supplied stable consumer key. Supported
|
|
43
|
+
installers generate and persist one for each installed client. Direct clients should
|
|
44
|
+
generate and persist a value when they need separate consumer state or presence. The
|
|
45
|
+
gateway does not bind the value to an installer registration.
|
|
46
|
+
|
|
47
|
+
Unless `AGENT_BRIDGE_CURSOR` sets an explicit path, a present instance key selects
|
|
48
|
+
cursor storage. The key also selects delivery lease ownership and presence. Processes
|
|
49
|
+
that share one key also share those resources. When the key and explicit cursor path
|
|
50
|
+
are both absent, cursor storage uses the `default` path component. Delivery ownership
|
|
51
|
+
falls back to the principal, and presence is unavailable. The key is not a PID,
|
|
52
|
+
live-process identity, session, or conversation. Per-process presence requires a
|
|
53
|
+
separate additive identity.
|
|
54
|
+
|
|
55
|
+
The v1 client manifest key named `runtime` remains a compatibility field for the host
|
|
56
|
+
installation target. A future manifest version may rename it without changing the
|
|
57
|
+
meaning of `AGENT_BRIDGE_INSTANCE`.
|
|
58
|
+
|
|
59
|
+
## Consequences
|
|
60
|
+
|
|
61
|
+
The architecture diagram and compatibility matrix can list desktop apps, CLIs,
|
|
62
|
+
daemons, and direct callers without presenting them as one category.
|
|
63
|
+
|
|
64
|
+
Installer-generated keys work without a new protocol field. Direct client authors who
|
|
65
|
+
use a key are responsible for stable storage and uniqueness within a principal. Reusing
|
|
66
|
+
a key intentionally creates one shared delivery consumer and presence identity.
|
|
67
|
+
|
|
68
|
+
The current gateway does not prevent two callers from choosing the same key. Clients
|
|
69
|
+
must not treat an instance value as proof of process identity or server registration.
|
|
70
|
+
|
|
71
|
+
## Alternatives considered
|
|
72
|
+
|
|
73
|
+
### Treat the adapter name as the harness identity
|
|
74
|
+
|
|
75
|
+
Rejected because one adapter may configure more than one host surface. The `codex`
|
|
76
|
+
adapter is the current example.
|
|
77
|
+
|
|
78
|
+
### Treat every live process as an instance
|
|
79
|
+
|
|
80
|
+
Rejected because the released instance key already selects cursor paths, lease
|
|
81
|
+
ownership, and presence. Changing it on every process start would alter consumer
|
|
82
|
+
ownership and strand existing state.
|
|
83
|
+
|
|
84
|
+
### Bind instance keys to server-side registrations now
|
|
85
|
+
|
|
86
|
+
Deferred. Binding could prevent accidental key collisions, but it needs a migration,
|
|
87
|
+
credential rules, and direct-client enrollment semantics. The current gateway accepts
|
|
88
|
+
the caller-supplied key and must be documented honestly.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# ADR 0004: Client lifecycle ownership and endpoint migration
|
|
2
|
+
|
|
3
|
+
Status: accepted
|
|
4
|
+
|
|
5
|
+
Date: 2026-07-18
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Agent Bridge can install Codex, Claude Code, and Claude Desktop registrations, but an
|
|
10
|
+
existing registration may have been created by an older package or by an operator.
|
|
11
|
+
Repair, update, uninstall, and endpoint migration must not silently take ownership of
|
|
12
|
+
such state. In particular, host configuration and per-client backend files may contain
|
|
13
|
+
credential-bearing references and queued gateway edge state.
|
|
14
|
+
|
|
15
|
+
Lifecycle unit 1 needs a safe ownership boundary before later mutating operations are
|
|
16
|
+
added. It must distinguish missing state, exact but unowned state, owned state, and
|
|
17
|
+
drift without probing a gateway or exposing backend configuration values.
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
The CLI provides two local lifecycle operations for the three automated adapters:
|
|
22
|
+
|
|
23
|
+
- `clients inspect` is read-only. The operator supplies the expected runtime,
|
|
24
|
+
identity, stable instance key, backend file path, launch command, and Claude Code
|
|
25
|
+
scope when applicable. Inspection reads only the host registration, backend path
|
|
26
|
+
existence, and managed metadata. It does not read backend values, contact the
|
|
27
|
+
gateway, interpret connectivity health, rewrite a host config, or create metadata.
|
|
28
|
+
- `clients adopt` uses the same exact contract. Without `--apply` it returns a plan.
|
|
29
|
+
With `--apply` it may create managed metadata only when inspection reports an exact
|
|
30
|
+
unmanaged registration. Adoption never rewrites the registration or backend file.
|
|
31
|
+
|
|
32
|
+
Inspection returns one of four states:
|
|
33
|
+
|
|
34
|
+
- `absent`: the requested registration, backend file, and managed metadata are all absent.
|
|
35
|
+
- `unmanaged`: the host registration, identity, instance, backend path, scope, and
|
|
36
|
+
launch contract are exact, the backend path and its immediate parent pass the
|
|
37
|
+
no-link owner-only private-path policy, and metadata is absent.
|
|
38
|
+
- `managed`: the exact registration and backend file are accompanied by exact managed
|
|
39
|
+
metadata.
|
|
40
|
+
- `drifted`: any other combination, including malformed or inexact registration,
|
|
41
|
+
missing, insecure, or linked backend residue without a registration, stale metadata,
|
|
42
|
+
or metadata that structurally differs from the requested contract.
|
|
43
|
+
|
|
44
|
+
Managed metadata uses schema `agent-bridge.client-management`, version 1, under the
|
|
45
|
+
owner-only `~/.agent-bridge/clients/` directory. It records only runtime, identity,
|
|
46
|
+
instance, absolute backend path, launch command and arguments, scope, and a nonsecret
|
|
47
|
+
registration locator. Claude Desktop records the normalized configuration path.
|
|
48
|
+
Codex records the active profile configuration path. Claude Code records scope and,
|
|
49
|
+
for local or project scope, the normalized invocation directory. Its native CLI does
|
|
50
|
+
not expose a stronger configuration locator. User scope has no directory context. A
|
|
51
|
+
later inspection from a different locator reports drift instead of guessing which
|
|
52
|
+
registration to mutate. Metadata never copies a token, backend setting, credential
|
|
53
|
+
identifier, URL, workspace, or backend file contents. Publication uses a private
|
|
54
|
+
same-directory temporary file, file fsync, atomic rename, private-path verification,
|
|
55
|
+
and directory fsync where supported.
|
|
56
|
+
|
|
57
|
+
Codex inspection compares the semantic registration fields in its real JSON MCP
|
|
58
|
+
description and ignores status, timeout, and transport diagnostic fields. JSON object
|
|
59
|
+
property order is not significant, while the environment must contain exactly the
|
|
60
|
+
three Agent Bridge keys. Claude Code inspection uses its native MCP description and
|
|
61
|
+
exact scope/removal contract but excludes connectivity status from registration
|
|
62
|
+
exactness. Claude Desktop inspection reads only the `agent-bridge` entry in its JSON
|
|
63
|
+
configuration and uses the installer's canonical resolver: an explicit executable is
|
|
64
|
+
validated, while the default is absolute Node plus the absolute server entry.
|
|
65
|
+
|
|
66
|
+
Identity, instance, backend, and command inputs are normalized before comparison and
|
|
67
|
+
metadata publication. Desktop configuration and Codex profile paths are normalized
|
|
68
|
+
before they become locators. Claude Code local and project adoption must run from the
|
|
69
|
+
directory that later lifecycle operations should use. After publication, adoption
|
|
70
|
+
re-inspects the live registration and fails if it changed. Inspection and plan-only
|
|
71
|
+
adoption preserve backend bytes, inode, and modification time. Applied adoption
|
|
72
|
+
writes only the management metadata described above; registration state and client
|
|
73
|
+
health remain separate authorities.
|
|
74
|
+
|
|
75
|
+
First-time `clients install` and enrollment behavior remains unchanged. A provision
|
|
76
|
+
enrollment still refuses an existing backend file or MCP registration, so adoption
|
|
77
|
+
cannot weaken first-install collision protection.
|
|
78
|
+
|
|
79
|
+
`clients repair`, `clients update`, and `clients uninstall` operate only on a strict
|
|
80
|
+
managed metadata record.
|
|
81
|
+
The runtime and stable instance locate that record. `--identity` must match the record
|
|
82
|
+
and the immutable request, but never locates it. These commands reject
|
|
83
|
+
backend path, scope, and config-path flags.
|
|
84
|
+
They plan without writing by default. A no-op exact registration creates no operation.
|
|
85
|
+
|
|
86
|
+
Repair restores the recorded launch. Update resolves a replacement launch before it
|
|
87
|
+
creates a journal. The update request records the identity, command, arguments, scope,
|
|
88
|
+
and fixed three Agent Bridge environment key names. It does not record their values.
|
|
89
|
+
Native launch arguments are empty. A native command is one executable contract. Bare
|
|
90
|
+
commands reject argument separators and URL-like surfaces. Absolute paths must resolve
|
|
91
|
+
to executable files before an update is journaled. Claude Desktop uses the installer's
|
|
92
|
+
absolute launch resolver. An action-specific resume uses that recorded request and
|
|
93
|
+
rejects another action, runtime, instance, identity, or replacement command.
|
|
94
|
+
|
|
95
|
+
Before a mutation starts, metadata load verifies the private management root, clients
|
|
96
|
+
directory, and metadata file. It rejects links, replacement, oversized files, unknown
|
|
97
|
+
keys, incorrect schema versions, malformed locators, and non-absolute backend paths.
|
|
98
|
+
The file is opened without following links and checked against its path identity before
|
|
99
|
+
the loader accepts it. The full record is loaded again after the client lock is acquired
|
|
100
|
+
and before every non-metadata mutation. Any difference blocks the operation.
|
|
101
|
+
|
|
102
|
+
Repair can tighten backend privacy only when that change removes access. Its journal
|
|
103
|
+
proofs contain the role, file identity, and private or repairable policy state. They
|
|
104
|
+
never contain backend bytes, credentials, URLs, workspace, or configuration values.
|
|
105
|
+
Links, disappearance, owner changes, replacement, and a permission change that would
|
|
106
|
+
grant new owner access fail closed. Windows accepts an already private backend path and
|
|
107
|
+
refuses a non-private one because the repair path cannot prove a monotonic ACL change.
|
|
108
|
+
|
|
109
|
+
Registration proofing records a bounded Agent Bridge observation and its full target
|
|
110
|
+
contract. Unknown environment keys, malformed values, unexpected scope, opaque fields,
|
|
111
|
+
or arguments outside the stored current or target launch stop before journal creation.
|
|
112
|
+
For Codex, get, remove, and add run with the recorded `CODEX_HOME` over the supplied
|
|
113
|
+
environment. Claude Code uses the recorded scope, invocation directory, and supplied
|
|
114
|
+
environment. Native changes remove, verify absence, add, verify the target, and write
|
|
115
|
+
changed metadata last. Claude Desktop reads the recorded JSON config without following
|
|
116
|
+
links or link ancestors, changes only `mcpServers.agent-bridge`, and publishes through
|
|
117
|
+
a private operation-scoped temporary file. It pins and rechecks the original file and
|
|
118
|
+
parent identities before rename, then verifies the final entry. Claude Desktop has no
|
|
119
|
+
cooperative transaction protocol. Node cannot guarantee a transaction against an
|
|
120
|
+
independent same-user writer.
|
|
121
|
+
|
|
122
|
+
The operation substrate remains internal with read-only inspection. Revisioned
|
|
123
|
+
manifests contain typed credential-agnostic requests, non-sensitive locators, and
|
|
124
|
+
unique no-replace before/after artifacts. Begin holds the runtime-plus-instance lock
|
|
125
|
+
while refusing another unfinished operation; a blocked journal fences new mutations and
|
|
126
|
+
resume. Resume is same-host only. Journal states
|
|
127
|
+
are prepared, snapshotted, in-progress, applied, cleaning, and committed. Inspection
|
|
128
|
+
separately reports resumable, classification-required, blocked, or complete.
|
|
129
|
+
|
|
130
|
+
Repair and uninstall journals use operation format version 3. New update journals use
|
|
131
|
+
v4 and carry a bounded credential-free inverse contract. Gateway migration staging
|
|
132
|
+
uses v5 and binds a managed identity, source and target endpoint digests, enrollment
|
|
133
|
+
credential IDs, a source edge database path and scope key, and a predecessor grace
|
|
134
|
+
cutoff. It contains no raw gateway URL or token. A version 2 journal keeps its released
|
|
135
|
+
request shape and remains inspectable. A non-terminal version 2 journal cannot resume
|
|
136
|
+
because it lacks an identity-bound request.
|
|
137
|
+
|
|
138
|
+
Endpoint cutover uses v6. Its journal retains the normalized source gateway URL without
|
|
139
|
+
a token so post-journal recovery can reconstruct the source edge route from the target
|
|
140
|
+
successor backend. Initial preflight uses the predecessor and direct successor. Every
|
|
141
|
+
later proof and source-edge replay uses the successor credential at both URLs. There is
|
|
142
|
+
no endpoint reverse operation. Returning to a prior endpoint requires a fresh owner
|
|
143
|
+
rotation and a new forward cutover.
|
|
144
|
+
|
|
145
|
+
Creation pins the operation root before it publishes state. Cleanup pins that root,
|
|
146
|
+
the operation directory, and the snapshots directory before it records intent or
|
|
147
|
+
unlinks anything. Cleanup records durable intent per artifact, verifies and unlinks the pinned file, and
|
|
148
|
+
records POSIX directory sync or explicit Windows unavailability. An absent artifact is
|
|
149
|
+
safe only when intent predates the cleanup attempt. Inspection recognizes a verified
|
|
150
|
+
after artifact for the current intent-recorded step, but rejects other missing or extra
|
|
151
|
+
files. Committed means verified writes and removed artifacts. It drops requests, steps,
|
|
152
|
+
locators, digests, and artifact metadata while retaining a bounded credential-free
|
|
153
|
+
completion record for audit. Public repair, update, and uninstall use this substrate.
|
|
154
|
+
|
|
155
|
+
Uninstall is forward-only. It removes the managed registration and proves absence,
|
|
156
|
+
deletes the already private backend file, then deletes metadata. It refuses a backend
|
|
157
|
+
that still needs privacy repair, so it cannot loosen that policy as a side effect of
|
|
158
|
+
deletion. A later failure does not restore a registration, backend, or metadata file.
|
|
159
|
+
The uninstall plan never stores backend bytes. File deletion confirms the file and
|
|
160
|
+
private parent identities before unlink. POSIX syncs the parent directory after a
|
|
161
|
+
verified absence. Windows records unavailable directory durability. Node's pathname
|
|
162
|
+
unlink cannot provide a transaction against a same-user writer, so this is an advisory
|
|
163
|
+
race boundary. Desktop removes only `mcpServers.agent-bridge`.
|
|
164
|
+
|
|
165
|
+
`clients rollback <source-operation-id> --identity <name>` is plan-first and accepts
|
|
166
|
+
only a committed same-host v4 update source. `--apply` creates a new v4 `rollback`
|
|
167
|
+
operation. It verifies the asserted identity, prior nonsecret metadata and exact
|
|
168
|
+
registration contract, and the current forward metadata and registration digests.
|
|
169
|
+
Native rollback removes the forward registration, proves absence, adds the prior
|
|
170
|
+
registration, proves it, then writes prior metadata. Desktop replaces only
|
|
171
|
+
`mcpServers.agent-bridge` and writes prior metadata last. The source journal remains
|
|
172
|
+
unchanged. Reverse resume derives authority from its recorded source UUID and inverse
|
|
173
|
+
contract. A changed current state, v2 or v3 source, repair, uninstall, unsafe inverse
|
|
174
|
+
fields, or a different host fails closed. A failed forward update never rolls back
|
|
175
|
+
automatically. Repair remains monotonic. Uninstall recovery is re-enrollment.
|
|
176
|
+
|
|
177
|
+
`clients migrate stage <runtime> --identity <name> --instance <key>
|
|
178
|
+
--enrollment-file <path>` is plan-first. With `--apply`, it creates a private staged
|
|
179
|
+
successor backend and a credential-free v5 record without changing the managed
|
|
180
|
+
registration or active backend. It initializes the source edge gate and leaves its
|
|
181
|
+
state active. It probes active and staged bearer credentials and requires a
|
|
182
|
+
non-immediate predecessor grace cutoff. It neither drains the outbox nor authorizes a
|
|
183
|
+
cutover. It requires an absolute, normalized source edge database path and rejects
|
|
184
|
+
in-memory edge state. The stage does not prove that source and target URLs reach the
|
|
185
|
+
same database authority.
|
|
186
|
+
|
|
187
|
+
`clients resume <operation-id> [--recover-lock]` resumes v3 repair, update, and
|
|
188
|
+
uninstall requests, supported v4 update and rollback requests, and v5 migration-stage
|
|
189
|
+
requests. It derives action, runtime, instance, identity, launch, and reverse source
|
|
190
|
+
from the record and accepts no replacement client authority. It cannot resume a version
|
|
191
|
+
2 operation. It also completes an uninstall interrupted after metadata deletion and a
|
|
192
|
+
rollback interrupted after any ordered step. A later endpoint cutover is limited to
|
|
193
|
+
alternate URLs and must dynamically attest one logical database authority. Physical
|
|
194
|
+
erasure is outside the contract.
|
|
195
|
+
|
|
196
|
+
## Consequences
|
|
197
|
+
|
|
198
|
+
Managed repair, update, and uninstall have a narrow authority boundary and can fail
|
|
199
|
+
closed on drift, metadata corruption, ambiguous crash state, and unsafe backend policy
|
|
200
|
+
changes. Existing exact registrations still require intentional, reviewable adoption.
|
|
201
|
+
Migration staging preserves active state while it prepares later work. Endpoint
|
|
202
|
+
cutover uses a separate v6 journal to drain the gateway edge outbox, attest shared live
|
|
203
|
+
route state, change the host registration, and retain enough credential-free authority
|
|
204
|
+
for crash recovery and post-grace source retirement.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Deploy Agent Bridge
|
|
2
|
+
|
|
3
|
+
The repository includes a Compose stack for local development and a production image
|
|
4
|
+
definition. The Compose file is intentionally bound to loopback. It is useful for
|
|
5
|
+
evaluation, integration work, and the repository acceptance test. It is not a public
|
|
6
|
+
TLS deployment.
|
|
7
|
+
|
|
8
|
+
## Development stack
|
|
9
|
+
|
|
10
|
+
Requirements:
|
|
11
|
+
|
|
12
|
+
- Docker Engine or Docker Desktop with Compose v2.
|
|
13
|
+
- Node.js 22.23.1 or newer to generate private development secrets and run operator
|
|
14
|
+
commands from the source checkout.
|
|
15
|
+
- Free loopback ports 8787 and 54329, or explicit replacement values.
|
|
16
|
+
|
|
17
|
+
Create two independent passwords. Keep the files out of version control.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
mkdir -m 700 .secrets
|
|
21
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" > .secrets/postgres_password
|
|
22
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" > .secrets/runtime_password
|
|
23
|
+
chmod 600 .secrets/*
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Build and start the stack:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
docker compose build --pull gateway
|
|
30
|
+
docker compose up --wait gateway
|
|
31
|
+
curl --fail http://127.0.0.1:8787/readyz
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The services start in this order:
|
|
35
|
+
|
|
36
|
+
1. PostgreSQL becomes healthy.
|
|
37
|
+
2. `migrate` applies the ordered schema with the schema-owner login and exits.
|
|
38
|
+
3. `bootstrap-runtime` creates or updates `agent_bridge_gateway`, grants the
|
|
39
|
+
database-derived runtime role, and exits.
|
|
40
|
+
4. `gateway` starts with the restricted login and must pass `/readyz`.
|
|
41
|
+
|
|
42
|
+
The stack stores PostgreSQL data in the `postgres_data` named volume. `docker compose
|
|
43
|
+
down` removes containers and keeps the volume. `docker compose down --volumes` deletes
|
|
44
|
+
the development database. Inspect the project name and volume before using the second
|
|
45
|
+
command.
|
|
46
|
+
|
|
47
|
+
The default bindings are `127.0.0.1:8787` for the gateway and `127.0.0.1:54329` for
|
|
48
|
+
PostgreSQL. Override them without editing the file:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
AGENT_BRIDGE_PORT=18787 \
|
|
52
|
+
AGENT_BRIDGE_POSTGRES_PORT=15432 \
|
|
53
|
+
docker compose up --wait gateway
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use the [owner enrollment workflow](../README.md#gateway-setup) to
|
|
57
|
+
create principal-bound credentials. Do not put a gateway token in the shared backend
|
|
58
|
+
config. Each installed client receives its own private backend file.
|
|
59
|
+
|
|
60
|
+
Run the same disposable proof as CI after building the TypeScript artifacts:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm ci
|
|
64
|
+
npm run build
|
|
65
|
+
./scripts/compose-smoke.sh
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The script creates a unique Compose project name that callers cannot override. It also
|
|
69
|
+
creates temporary database passwords, a temporary operator, and two principal
|
|
70
|
+
credentials. It proves source and workspace binding, targeted delivery, lease
|
|
71
|
+
settlement, short-password rejection, denied runtime access to credential hashes, and
|
|
72
|
+
message persistence through a full stack restart with a fresh edge cache. Its exit trap
|
|
73
|
+
removes the project volume, image tag, credentials, and temporary files.
|
|
74
|
+
|
|
75
|
+
## Production requirements
|
|
76
|
+
|
|
77
|
+
Use the image stages and service boundaries as inputs to the deployment platform. Do
|
|
78
|
+
not expose the checked-in Compose stack unchanged.
|
|
79
|
+
|
|
80
|
+
### Network and TLS
|
|
81
|
+
|
|
82
|
+
- Keep PostgreSQL on a private network. Do not publish port 5432 to the internet.
|
|
83
|
+
- Put every non-loopback gateway behind a TLS terminator. Forward only from the trusted
|
|
84
|
+
proxy or ingress layer to the gateway's HTTP port.
|
|
85
|
+
- Restrict administrative database access to migration, owner-control, archive,
|
|
86
|
+
backup, and restore jobs. Clients use the HTTPS gateway, not PostgreSQL.
|
|
87
|
+
- Apply request size, connection, and upstream timeouts at the proxy without retrying
|
|
88
|
+
ambiguous mutations. Agent Bridge uses idempotency keys for safe publication replay.
|
|
89
|
+
|
|
90
|
+
### Images and process policy
|
|
91
|
+
|
|
92
|
+
- Build from the pinned Node base image and deploy an immutable image digest.
|
|
93
|
+
- Run the gateway with a read-only root filesystem, a small writable temporary
|
|
94
|
+
filesystem, and `no-new-privileges`. The final gateway process must run as the
|
|
95
|
+
non-root image user with no effective Linux capabilities.
|
|
96
|
+
- Compose file secrets retain host ownership on native Linux. The migration and gateway
|
|
97
|
+
services therefore start a small Node entrypoint as root with `DAC_OVERRIDE`,
|
|
98
|
+
`SETUID`, and `SETGID`. It reads the one granted secret, drops supplementary groups
|
|
99
|
+
and UID/GID to 1000, then imports the requested module. The final process has no
|
|
100
|
+
effective capabilities. The one-shot runtime bootstrap keeps `DAC_OVERRIDE`,
|
|
101
|
+
`SETUID`, and `SETGID` while it reads the two secret files, then `gosu` runs its fixed
|
|
102
|
+
SQL script as the PostgreSQL account. A production
|
|
103
|
+
secret injector may mount the secret directly for the runtime UID and omit this
|
|
104
|
+
handoff.
|
|
105
|
+
- Allow at least 30 seconds for graceful shutdown. Stop accepting traffic before
|
|
106
|
+
terminating the process.
|
|
107
|
+
- Gate traffic on `/readyz`. Liveness alone does not prove migration, row-isolation,
|
|
108
|
+
role, or protected-catalog readiness.
|
|
109
|
+
|
|
110
|
+
### Secrets and database roles
|
|
111
|
+
|
|
112
|
+
Keep these authorities separate:
|
|
113
|
+
|
|
114
|
+
| Authority | Purpose | Long-lived gateway access |
|
|
115
|
+
| --- | --- | --- |
|
|
116
|
+
| Schema owner | Ordered migrations and trusted role registration | Never |
|
|
117
|
+
| Runtime login | Gateway requests and readiness | Required |
|
|
118
|
+
| Control operator | Credential provision, inventory, rotation, and revocation | Never |
|
|
119
|
+
| Archive operator | Portable PostgreSQL archive operations | Never |
|
|
120
|
+
| Backup and restore | Native DR backup or restore | Never |
|
|
121
|
+
|
|
122
|
+
Use the platform's secret manager or private mounted secret files. Do not put raw
|
|
123
|
+
passwords, tokens, or complete database URLs in image layers, source control, command
|
|
124
|
+
arguments, deployment logs, or shared client config. Rotate each authority on its own
|
|
125
|
+
schedule and after any suspected exposure.
|
|
126
|
+
|
|
127
|
+
The runtime database password must contain at least 32 characters. The bootstrap job
|
|
128
|
+
fails before role creation or alteration when the mounted value is shorter.
|
|
129
|
+
|
|
130
|
+
### Persistent data and backup
|
|
131
|
+
|
|
132
|
+
A database volume or managed PostgreSQL disk keeps runtime state. It does not protect
|
|
133
|
+
against operator error, catalog drift, account loss, or regional failure.
|
|
134
|
+
|
|
135
|
+
- Schedule native PostgreSQL DR backups with the exact PostgreSQL major tools.
|
|
136
|
+
- Store verified bundles on a separate failure domain.
|
|
137
|
+
- Record retention and deletion policy separately from message immutability.
|
|
138
|
+
- Run restore drills into a fresh database with the same name and PostgreSQL major.
|
|
139
|
+
- Never activate the source and restored target as authorities at the same time.
|
|
140
|
+
|
|
141
|
+
Portable archives complement native DR when an operator needs one workspace's messages
|
|
142
|
+
and eligible read receipts. They do not contain credentials, delivery state,
|
|
143
|
+
owner-control state, or security events.
|
|
144
|
+
|
|
145
|
+
## Upgrade procedure
|
|
146
|
+
|
|
147
|
+
1. Confirm the target image supports the deployed PostgreSQL major and current protocol
|
|
148
|
+
clients.
|
|
149
|
+
2. Drain or preserve each gateway client's SQLite outbox. Do not discard an edge store
|
|
150
|
+
with queued publications.
|
|
151
|
+
3. Drain old gateway instances or remove them from traffic before migration 017, then
|
|
152
|
+
keep them out of traffic before migration 018. An old process can serve ordinary
|
|
153
|
+
requests until it exits even though its `/readyz` probe
|
|
154
|
+
fails after the newer migration is applied.
|
|
155
|
+
4. Create and verify a native DR backup.
|
|
156
|
+
5. Stop schema-changing jobs other than the selected migration job.
|
|
157
|
+
6. Run the new image's migration command once with schema-owner authority.
|
|
158
|
+
7. Run the runtime bootstrap with separate runtime-login credentials.
|
|
159
|
+
8. Start the new gateway and require `/readyz`, an authenticated capability probe, and
|
|
160
|
+
an authenticated status probe.
|
|
161
|
+
9. Send, read, claim, and settle a disposable targeted delivery.
|
|
162
|
+
10. Roll clients forward only after the gateway proof passes.
|
|
163
|
+
11. Keep the previous authority available but inactive until the observation window
|
|
164
|
+
closes.
|
|
165
|
+
|
|
166
|
+
Run one migration job at a time. The migration ledger makes ordered application
|
|
167
|
+
idempotent, but it does not make concurrent deployment orchestration desirable.
|
|
168
|
+
|
|
169
|
+
## Rollback boundaries
|
|
170
|
+
|
|
171
|
+
| Failure point | Safe response |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| Before schema migration | Stop the new gateway and return to the prior image and configuration. |
|
|
174
|
+
| After migration, before client rollout | Keep clients on the old authority. Apply a forward fix, or restore the verified backup into a fresh target. |
|
|
175
|
+
| After clients have published through the new gateway | Stop further cutover. Preserve every edge database and credential until queued outboxes are zero. Reconcile authoritative messages before switching back. |
|
|
176
|
+
| Database corruption or unrecoverable catalog drift | Restore native DR into a fresh target, verify readiness, then switch authority once. |
|
|
177
|
+
|
|
178
|
+
An older gateway may refuse a database with a newer migration plan. Starting the old
|
|
179
|
+
image is therefore not a general schema rollback. A volume snapshot is also not enough
|
|
180
|
+
unless its consistency and restore procedure have been proved for the database setup.
|
|
181
|
+
Migration 017 makes this readiness failure explicit for an old compiled migration
|
|
182
|
+
plan. It does not terminate an already-running old gateway. Drain it before applying
|
|
183
|
+
the migration.
|
|
184
|
+
|
|
185
|
+
## Operational checks
|
|
186
|
+
|
|
187
|
+
- `/healthz` proves the HTTP process is alive.
|
|
188
|
+
- `/readyz` proves the gateway can use the restricted database and that required
|
|
189
|
+
security attestations still match.
|
|
190
|
+
- `agent-bridge doctor --json` probes a configured client's remote path.
|
|
191
|
+
- `agent-bridge status` is passive and reports remote reachability as unknown until a
|
|
192
|
+
probe occurs.
|
|
193
|
+
- Gateway metrics require a credential with `gateway:metrics`.
|
|
194
|
+
|
|
195
|
+
Alert on readiness failure, repeated authorization denial, rate-limit pressure,
|
|
196
|
+
database connection exhaustion, due or blocked outbox rows, dead-letter growth, backup
|
|
197
|
+
failure, and restore-test failure. Keep tokens, database URLs, message content, and DR
|
|
198
|
+
bundle paths out of telemetry.
|
|
199
|
+
|
|
200
|
+
Related references:
|
|
201
|
+
|
|
202
|
+
- [Architecture](architecture-v2.md)
|
|
203
|
+
- [Security policy](../SECURITY.md)
|
|
204
|
+
- [Troubleshooting](troubleshooting.md)
|
|
205
|
+
- [Portable archives and native DR](../README.md#portable-archives)
|
package/docs/ecosystem.md
CHANGED
|
@@ -9,16 +9,48 @@ full agent stack.
|
|
|
9
9
|
|
|
10
10
|
| Layer | Examples | Relationship to Agent Bridge |
|
|
11
11
|
| --- | --- | --- |
|
|
12
|
-
| Tool and context access | MCP | Agent Bridge
|
|
12
|
+
| Tool and context access | MCP, CLI, HTTPS, Node library | These surfaces expose Agent Bridge operations. They do not define its stored message or delivery protocol. |
|
|
13
13
|
| Agent task semantics | A2A and application protocols | These systems own tasks, artifacts, status, and domain completion. Agent Bridge can carry their identifiers and payloads. |
|
|
14
14
|
| Durable mailbox | Agent Bridge | Agent Bridge owns cursored history, receipts, work claims, leases, retry state, and offline replay. |
|
|
15
15
|
| Live transport and brokers | SLIM, NATS, RabbitMQ, Kafka | A future adapter may use one of these systems for transport or wakeups. Cursored pull remains the recovery path. |
|
|
16
|
-
| Agent execution | LangGraph, AutoGen, agent-loop
|
|
16
|
+
| Agent execution | Codex, Claude Code, OpenClaw, Hermes, Pi, LangGraph, AutoGen, agent-loop | These harnesses decide what runs and how workflows advance. Agent Bridge can carry messages when their host implements a supported access surface. |
|
|
17
17
|
| Local operator experience | agmsg and similar tools | These tools may provide terminal placement, agent spawning, roles, and local coordination. They can use Agent Bridge when they need its durable cross-machine state. |
|
|
18
18
|
|
|
19
19
|
[ADR-0001](decisions/0001-protocol-layers-and-acknowledgment-semantics.md)
|
|
20
20
|
defines the protocol boundary and the separate meanings of read receipts, delivery
|
|
21
21
|
settlement, and external task completion.
|
|
22
|
+
[ADR-0003](decisions/0003-host-adapters-and-consumer-instance-keys.md) defines
|
|
23
|
+
the host layers and consumer instance-key contract.
|
|
24
|
+
|
|
25
|
+
## Harnesses, hosts, adapters, and access
|
|
26
|
+
|
|
27
|
+
Agent Bridge keeps four integration concepts separate:
|
|
28
|
+
|
|
29
|
+
- A harness runs an agent loop, such as Codex, Claude Code, OpenClaw, Hermes, or Pi.
|
|
30
|
+
- A host is the CLI, desktop application, daemon, CI job, or service that contains the
|
|
31
|
+
harness or invokes Agent Bridge.
|
|
32
|
+
- A host adapter configures that host to use Agent Bridge.
|
|
33
|
+
- An access surface is MCP over stdio, the CLI, the HTTPS API, or the Node library.
|
|
34
|
+
|
|
35
|
+
This distinction matters when one profile serves more than one host surface. The
|
|
36
|
+
`codex` adapter configures the profile shared by the Codex CLI and the Codex surface
|
|
37
|
+
in the ChatGPT desktop app. It does not create two independent Agent Bridge
|
|
38
|
+
registrations. Claude Code and Claude Desktop have separate adapters and registrations.
|
|
39
|
+
|
|
40
|
+
| Adapter or integration | Host coverage | Access | Support level |
|
|
41
|
+
| --- | --- | --- | --- |
|
|
42
|
+
| `codex` | Codex CLI and Codex in the ChatGPT desktop app | MCP stdio | Automated install |
|
|
43
|
+
| `claude-code` | Claude Code CLI | MCP stdio | Automated install |
|
|
44
|
+
| `claude-desktop` | Claude Desktop | MCP stdio | Automated install |
|
|
45
|
+
| `openclaw` | OpenClaw daemon or host | MCP stdio | Manifest included; operator-managed |
|
|
46
|
+
| `generic-mcp` | Any compatible MCP host | MCP stdio | Manifest included; operator-managed |
|
|
47
|
+
| Direct integration | Scripts, CI, daemons, and services | CLI, HTTPS, or Node library | No host adapter required |
|
|
48
|
+
| Generic harness integration | Hermes, Pi, and other harnesses | Any access surface their host supports | No dedicated adapter or conformance claim yet |
|
|
49
|
+
|
|
50
|
+
Scripts are orthogonal to harnesses. A script may start a harness, invoke the CLI,
|
|
51
|
+
call the HTTPS API, or embed the Node library. It is not a separate agent category.
|
|
52
|
+
The MCP server currently uses stdio. The gateway exposes the Agent Bridge HTTPS
|
|
53
|
+
protocol, not MCP over HTTP.
|
|
22
54
|
|
|
23
55
|
## Relationship to agmsg
|
|
24
56
|
|
|
@@ -49,6 +81,6 @@ vendors without forcing every participant into the same runtime or deployment st
|
|
|
49
81
|
## Interoperability direction
|
|
50
82
|
|
|
51
83
|
The next interoperability work is tracked in [ROADMAP.md](../ROADMAP.md). Planned
|
|
52
|
-
surfaces include an agmsg adapter, a thin A2A envelope mapping,
|
|
84
|
+
surfaces include an agmsg adapter, a thin A2A envelope mapping, host-adapter conformance
|
|
53
85
|
fixtures, and client libraries. Each integration must retain caller-bound identity,
|
|
54
86
|
idempotent publication, cursored replay, and at-least-once delivery semantics.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -81,6 +81,29 @@ Queued sends retain their idempotency keys. Long-lived MCP clients retry them, a
|
|
|
81
81
|
`agent-bridge sync` triggers the same bounded replay manually. Claims, lease changes,
|
|
82
82
|
delivery settlement, presence, and read-receipt writes still require the gateway.
|
|
83
83
|
|
|
84
|
+
## Migration gate reported by status or doctor
|
|
85
|
+
|
|
86
|
+
`clients migrate stage` does not begin a drain. `clients migrate cutover
|
|
87
|
+
<stage-operation-id> --exclusive-edge --apply` changes the source edge to `draining`
|
|
88
|
+
after it verifies both live gateways and their route challenge. In that state, normal
|
|
89
|
+
publication is blocked while the recorded lease worker completes existing outbox work.
|
|
90
|
+
`doctor` reports `draining` as degraded. A `retired` scope rejects new publication and
|
|
91
|
+
`doctor` reports it as failed.
|
|
92
|
+
|
|
93
|
+
Do not delete the edge database, alter the gate tables, or reopen a retired scope by
|
|
94
|
+
hand. Inspect the operation ID reported by status. Resume the matching v6 operation
|
|
95
|
+
with `clients resume <operation-id> [--recover-lock]`. A new worker cannot take an
|
|
96
|
+
unexpired drain lease. It must wait for the lease to expire. Reverse before the
|
|
97
|
+
predecessor grace cutoff is not supported. To return to the earlier endpoint, first
|
|
98
|
+
rotate a new owner credential for that endpoint, then run an ordinary forward cutover
|
|
99
|
+
with it as the successor. Finalization after grace retires the source. If no matching
|
|
100
|
+
operation exists, preserve the database and stop rather than changing the gate
|
|
101
|
+
manually.
|
|
102
|
+
|
|
103
|
+
A dry migration plan refuses an edge with live `-wal` or `-shm` sidecars. Stop the
|
|
104
|
+
writer and let SQLite checkpoint its state, then retry the plan. The plan never opens
|
|
105
|
+
the edge in write mode to inspect it.
|
|
106
|
+
|
|
84
107
|
## Report a defect
|
|
85
108
|
|
|
86
109
|
Include the client name, operating system, package version, sanitized `doctor --json`
|