@creatornader/agent-bridge 0.3.1 → 0.5.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 +222 -1
- package/README.md +312 -12
- package/ROADMAP.md +88 -7
- package/SECURITY.md +78 -5
- package/SKILL.md +108 -1
- package/dist/archive.d.ts +2 -2
- package/dist/archive.js +2 -2
- package/dist/{bridge-service-hX1ZQp4W.d.ts → bridge-service-CNBKdYXh.d.ts} +2 -1
- package/dist/{bridge-store-DPVSCwfs.d.ts → bridge-store-ByJ6CaJk.d.ts} +3 -0
- package/dist/bridge.d.ts +25 -8
- package/dist/bridge.js +19 -9
- package/dist/{chunk-MBPZXTJA.js → chunk-7VJI2MXI.js} +285 -42
- package/dist/chunk-7VJI2MXI.js.map +1 -0
- package/dist/{chunk-4VB44KJU.js → chunk-AWE3DFZV.js} +3 -2
- package/dist/chunk-AWE3DFZV.js.map +1 -0
- package/dist/{chunk-GADH244D.js → chunk-E4OWHGUE.js} +16 -5
- package/dist/chunk-E4OWHGUE.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-SPSMZOCJ.js → chunk-HUHG7XTB.js} +6 -5
- package/dist/chunk-HUHG7XTB.js.map +1 -0
- package/dist/{chunk-5GMB3A77.js → chunk-IVG4XWWS.js} +26 -14
- package/dist/chunk-IVG4XWWS.js.map +1 -0
- package/dist/{chunk-WAI2IYIQ.js → chunk-P635FAN4.js} +50 -7
- package/dist/chunk-P635FAN4.js.map +1 -0
- package/dist/{chunk-45BZGB77.js → chunk-QNXHDOJ5.js} +218 -24
- package/dist/chunk-QNXHDOJ5.js.map +1 -0
- package/dist/{chunk-UAHMP6GC.js → chunk-QPC6JHA3.js} +10 -7
- package/dist/chunk-QPC6JHA3.js.map +1 -0
- package/dist/{chunk-Q6PPMXJC.js → chunk-SN7PIVDF.js} +377 -21
- package/dist/chunk-SN7PIVDF.js.map +1 -0
- package/dist/{chunk-A6W4QALF.js → chunk-TC6A7GMF.js} +2 -2
- package/dist/{chunk-2DFNOLMO.js → chunk-XDNT6ZNZ.js} +9 -6
- package/dist/chunk-XDNT6ZNZ.js.map +1 -0
- package/dist/{chunk-CEXBMOI5.js → chunk-Z6JP6MYD.js} +2 -2
- package/dist/cli.js +5867 -438
- package/dist/cli.js.map +1 -1
- package/dist/client-runtime.d.ts +4 -2
- package/dist/client-runtime.js +7 -7
- 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-CW-61lvs.d.ts} +27 -3
- package/dist/gateway-main.js +71 -7
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +3 -3
- package/dist/index.js +8 -8
- package/dist/{postgres-bridge-store-Bfd3hRId.d.ts → postgres-bridge-store-C9KG9Z69.d.ts} +1 -1
- package/dist/postgres-production-preflight.d.ts +32 -0
- package/dist/postgres-production-preflight.js +249 -0
- package/dist/postgres-production-preflight.js.map +1 -0
- package/dist/server.js +8 -8
- package/dist/sqlite-edge-store-CdMIOrho.d.ts +148 -0
- package/dist/sqlite.d.ts +19 -80
- package/dist/sqlite.js +11 -3
- package/docs/architecture-v2.md +292 -15
- package/docs/decisions/0004-client-lifecycle-and-endpoint-migration.md +204 -0
- package/docs/deployment.md +349 -0
- package/docs/troubleshooting.md +23 -0
- package/llms.txt +69 -1
- package/openapi/agent-bridge-v2.openapi.json +1151 -124
- package/package.json +10 -2
- package/schemas/agent-bridge-v2.capabilities.json +26 -1
- package/schemas/agent-bridge-v2.mcp.json +11 -1
- package/schemas/agent-bridge-v2.schema.json +167 -0
- package/sql/migrations/007_runtime_role.sql +8 -4
- package/sql/migrations/013_row_isolation.sql +71 -8
- package/sql/migrations/014_owner_control_plane.sql +124 -31
- package/sql/migrations/015_portable_archives.sql +143 -41
- package/sql/migrations/016_native_dr_fence.sql +102 -35
- package/sql/migrations/017_gateway_authority_binding.sql +99 -0
- package/sql/migrations/018_endpoint_migration_challenges.sql +1054 -0
- package/sql/migrations/019_endpoint_migration_same_successor.sql +348 -0
- package/sql/migrations/020_managed_authority_compat.sql +698 -0
- package/sql/migrations/021_native_backup_reader.sql +421 -0
- package/sql/setup.sql +1 -3
- package/dist/chunk-2DFNOLMO.js.map +0 -1
- package/dist/chunk-45BZGB77.js.map +0 -1
- package/dist/chunk-4VB44KJU.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-SPSMZOCJ.js.map +0 -1
- package/dist/chunk-UAHMP6GC.js.map +0 -1
- package/dist/chunk-WAI2IYIQ.js.map +0 -1
- /package/dist/{chunk-A6W4QALF.js.map → chunk-TC6A7GMF.js.map} +0 -0
- /package/dist/{chunk-CEXBMOI5.js.map → chunk-Z6JP6MYD.js.map} +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
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
|
+
The schema owner may be a true PostgreSQL superuser or a managed-provider
|
|
123
|
+
administrator with `CREATEROLE` and the database privileges reported by the production
|
|
124
|
+
preflight. `CREATEROLE` is sufficient for migrations. Native backup requires the
|
|
125
|
+
schema owner to be a true superuser or hold `BYPASSRLS`. A restore target validates the
|
|
126
|
+
intentionally suspended restored schema-owner shell through its superuser session. Migrations create internal
|
|
127
|
+
roles with safe defaults and reject unsafe preexisting roles instead of trying to demote
|
|
128
|
+
them. PostgreSQL 16 and newer may store the schema owner's effective admin, inherit,
|
|
129
|
+
and set authority in two physical grant rows. A native DR restore may recreate it as one
|
|
130
|
+
combined bootstrap-superuser grant. Agent Bridge validates both forms and their
|
|
131
|
+
effective authority. The restricted runtime login must never receive either schema-owner
|
|
132
|
+
authority or `BYPASSRLS`.
|
|
133
|
+
|
|
134
|
+
Migration 021 creates a database-derived `NOLOGIN` backup-reader role. It receives
|
|
135
|
+
`SELECT` on Agent Bridge tables and sequences and is granted only to the schema owner.
|
|
136
|
+
This lets a managed schema owner retain `BYPASSRLS` while producing a complete native
|
|
137
|
+
backup. Do not grant the reader to the runtime login, control members, archive members,
|
|
138
|
+
or another external principal. Native backup and restore require this attestation.
|
|
139
|
+
Gateway runtime readiness does not, so an owner-only backup fault cannot stop normal
|
|
140
|
+
gateway traffic.
|
|
141
|
+
|
|
142
|
+
Use the platform's secret manager or private mounted secret files. Do not put raw
|
|
143
|
+
passwords, tokens, or complete database URLs in image layers, source control, command
|
|
144
|
+
arguments, deployment logs, or shared client config. Rotate each authority on its own
|
|
145
|
+
schedule and after any suspected exposure.
|
|
146
|
+
|
|
147
|
+
The runtime database password must contain at least 32 characters. The bootstrap job
|
|
148
|
+
fails before role creation or alteration when the mounted value is shorter.
|
|
149
|
+
|
|
150
|
+
## Fly.io reference hosting
|
|
151
|
+
|
|
152
|
+
[`deploy/fly.toml`](../deploy/fly.toml) is the maintained Fly gateway contract. It has
|
|
153
|
+
no app name, region, or release command. The operator chooses the account, app, region,
|
|
154
|
+
PostgreSQL service, and public hostname. Fly terminates HTTPS and forwards to port
|
|
155
|
+
8787. The service keeps at least one `shared-cpu-1x` machine with 512 MB running, checks
|
|
156
|
+
`GET /readyz`, and gives the Node process 30 seconds after SIGTERM to close listeners
|
|
157
|
+
and database pools.
|
|
158
|
+
|
|
159
|
+
Run the repository check before any Fly action:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npm run preflight:fly -- --json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The local check verifies Node, the Dockerfile, and the static Fly contract. If the app
|
|
166
|
+
already exists, add its name:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npm run preflight:fly -- --app <app> --json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
With `--app`, the command invokes only read-only Fly commands. It observes the active
|
|
173
|
+
account, app status, effective config, machines, and secret names. Its JSON includes
|
|
174
|
+
names and check results but never environment-variable values. A passing local check
|
|
175
|
+
does not prove that an external resource exists or that deployment is safe.
|
|
176
|
+
|
|
177
|
+
The long-running Fly machine may receive only the restricted
|
|
178
|
+
`AGENT_BRIDGE_RUNTIME_DATABASE_URL` database authority. Do not give it
|
|
179
|
+
`AGENT_BRIDGE_DATABASE_URL`, `AGENT_BRIDGE_OPERATOR_DATABASE_URL`,
|
|
180
|
+
`AGENT_BRIDGE_RUNTIME_PASSWORD`, a client bearer token, or a Supabase client key. The
|
|
181
|
+
preflight rejects those names. Keep schema-owner, control-operator, archive, and DR
|
|
182
|
+
authority in separate operator jobs.
|
|
183
|
+
|
|
184
|
+
### Operator order and gates
|
|
185
|
+
|
|
186
|
+
The following actions change external state and require an operator gate. The
|
|
187
|
+
repository does not perform them:
|
|
188
|
+
|
|
189
|
+
1. Create or select the Fly app and PostgreSQL authority. Keep PostgreSQL private.
|
|
190
|
+
2. Run the read-only production database preflight before any backup or migration:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
AGENT_BRIDGE_DATABASE_URL="..." npm run preflight:postgres:production -- --json --require-ssl
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The command opens a read-only transaction and reports only nonsecret capability
|
|
197
|
+
and schema facts. `authority.roles` reports migration authority. `authority.native_dr`
|
|
198
|
+
reports whether the source schema owner is a true superuser or has `BYPASSRLS`. A
|
|
199
|
+
`CREATEROLE` role can pass the migration check while failing the native DR check.
|
|
200
|
+
The command also checks supported server majors, migration-ledger drift, derived-role
|
|
201
|
+
collisions, and the legacy import shape. The PostgreSQL 15 through 18 test matrix
|
|
202
|
+
separately applies the full migration plan as both a superuser and a
|
|
203
|
+
managed-provider-style `CREATEROLE` administrator. `--require-ssl` is required for a
|
|
204
|
+
public database endpoint. The preflight cannot prove that later DDL will succeed. For
|
|
205
|
+
a session pooler, it checks the client TLS socket because PostgreSQL reports the
|
|
206
|
+
pooler's separate database connection.
|
|
207
|
+
3. Take and verify a native DR backup when upgrading an existing authority.
|
|
208
|
+
4. Run `agent-bridge migrate` once in an isolated job with
|
|
209
|
+
`AGENT_BRIDGE_DATABASE_URL`. Drain old gateways first when the migration notes
|
|
210
|
+
require it.
|
|
211
|
+
5. Run [`deploy/bootstrap-runtime.sql`](../deploy/bootstrap-runtime.sql) through a
|
|
212
|
+
separate trusted PostgreSQL session. Supply the schema-owner connection and the
|
|
213
|
+
runtime password to that job only. The bootstrap is transactional and changes an
|
|
214
|
+
existing login only when its attributes, ownership, and membership graph already
|
|
215
|
+
match the recorded runtime contract. It never adopts a restored `NOLOGIN` shell.
|
|
216
|
+
6. Construct the restricted runtime URL, set only
|
|
217
|
+
`AGENT_BRIDGE_RUNTIME_DATABASE_URL` on the Fly app, and run the app-aware read-only
|
|
218
|
+
preflight.
|
|
219
|
+
7. Deploy the immutable image with `fly deploy --config deploy/fly.toml --app <app>`.
|
|
220
|
+
Require `/readyz` before routing clients.
|
|
221
|
+
8. Run authenticated capability and status probes, then publish, pull, claim, and
|
|
222
|
+
settle a disposable targeted delivery.
|
|
223
|
+
9. Move clients only after the gateway proof passes. Preserve every source edge store
|
|
224
|
+
until its outbox is empty.
|
|
225
|
+
|
|
226
|
+
App creation, database provisioning, secret writes, migration, bootstrap, deployment,
|
|
227
|
+
traffic changes, and client cutover are all gated external actions. The preflight is
|
|
228
|
+
read-only and cannot authorize any of them.
|
|
229
|
+
|
|
230
|
+
### Fly rollback boundary
|
|
231
|
+
|
|
232
|
+
Before migration, stop a failed deployment and keep the prior image and authority. A
|
|
233
|
+
failed image rollout after a compatible migration can return traffic to the prior
|
|
234
|
+
image only if that image accepts the current schema. Never assume that an older image
|
|
235
|
+
can run against newer migrations.
|
|
236
|
+
|
|
237
|
+
After clients publish through the new gateway, preserve both authorities and every
|
|
238
|
+
edge database. Stop the cutover, drain queued outboxes, and reconcile authoritative
|
|
239
|
+
messages before choosing one authority. If schema or data recovery is required,
|
|
240
|
+
restore the verified native DR bundle into a fresh target and switch authority once.
|
|
241
|
+
Do not run the source and restored database as active authorities at the same time.
|
|
242
|
+
|
|
243
|
+
The manual `gateway production proof` GitHub Actions workflow runs this acceptance
|
|
244
|
+
proof against an existing HTTPS gateway. GitHub restricts it to `main`, and every job
|
|
245
|
+
uses the approval-protected `agent-bridge-production-proof` environment. Configure
|
|
246
|
+
`PROOF_SENDER_TOKEN`, `PROOF_RECEIVER_TOKEN`, `PROOF_HOST_SALT`, and `FLY_API_TOKEN` as
|
|
247
|
+
environment secrets. The sender and receiver credentials must bind the requested
|
|
248
|
+
workspace to the dedicated `proof-sender` and `proof-receiver` principals. The
|
|
249
|
+
sender credential needs `messages:write` and `messages:read`. The receiver needs
|
|
250
|
+
`messages:read`, `deliveries:claim`, `deliveries:settle`, and `deliveries:read`.
|
|
251
|
+
|
|
252
|
+
Run the workflow only when the Fly app has exactly one gateway machine. The cycle job
|
|
253
|
+
restarts that machine and queries the Fly Machines API before and after. It fails
|
|
254
|
+
unless the machine ID stays fixed, the runtime `instance_id` changes, the machine
|
|
255
|
+
returns to `started`, and `/readyz` succeeds. This changes production compute and
|
|
256
|
+
requires environment approval. It does not migrate the database or change secrets.
|
|
257
|
+
|
|
258
|
+
The sender first uses an unreachable loopback origin to force a leased publication
|
|
259
|
+
into its private SQLite outbox. It then synchronizes that row to the supplied gateway
|
|
260
|
+
and repeats the publication with the same idempotency key. A separate host finds the
|
|
261
|
+
exact message through `proof-receiver`, claims its delivery, and acknowledges it.
|
|
262
|
+
After the Fly machine cycle, the verifier uses a fresh instance key, edge database,
|
|
263
|
+
and cursor. It reads the immutable message and confirms that the prior delivery is
|
|
264
|
+
still `acked`.
|
|
265
|
+
|
|
266
|
+
Each phase writes an `agent-bridge-production-proof-v1` receipt. The runner rejects
|
|
267
|
+
unknown fields at the phase boundary and checks every receipt before use. Receipts may
|
|
268
|
+
record IDs, timestamps, principal and workspace labels, the gateway origin, boolean
|
|
269
|
+
checks, and salted SHA-256 host evidence. They never record bearer values, database
|
|
270
|
+
URLs, environment values, message content, lease tokens, cursor files, or edge
|
|
271
|
+
databases. Download all four workflow artifacts for the operator record. A passing
|
|
272
|
+
repository test still does not replace a completed external workflow run.
|
|
273
|
+
|
|
274
|
+
### Persistent data and backup
|
|
275
|
+
|
|
276
|
+
A database volume or managed PostgreSQL disk keeps runtime state. It does not protect
|
|
277
|
+
against operator error, catalog drift, account loss, or regional failure.
|
|
278
|
+
|
|
279
|
+
- Schedule native PostgreSQL DR backups with the exact PostgreSQL major tools.
|
|
280
|
+
- Store verified bundles on a separate failure domain.
|
|
281
|
+
- Record retention and deletion policy separately from message immutability.
|
|
282
|
+
- Run restore drills into a fresh database with the same name and PostgreSQL major.
|
|
283
|
+
- Never activate the source and restored target as authorities at the same time.
|
|
284
|
+
|
|
285
|
+
Portable archives complement native DR when an operator needs one workspace's messages
|
|
286
|
+
and eligible read receipts. They do not contain credentials, delivery state,
|
|
287
|
+
owner-control state, or security events.
|
|
288
|
+
|
|
289
|
+
## Upgrade procedure
|
|
290
|
+
|
|
291
|
+
1. Confirm the target image supports the deployed PostgreSQL major and current protocol
|
|
292
|
+
clients.
|
|
293
|
+
2. Drain or preserve each gateway client's SQLite outbox. Do not discard an edge store
|
|
294
|
+
with queued publications.
|
|
295
|
+
3. Drain old gateway instances or remove them from traffic before migration 017, then
|
|
296
|
+
keep them out of traffic before migration 018. An old process can serve ordinary
|
|
297
|
+
requests until it exits even though its `/readyz` probe
|
|
298
|
+
fails after the newer migration is applied.
|
|
299
|
+
4. Create and verify a native DR backup.
|
|
300
|
+
5. Stop schema-changing jobs other than the selected migration job.
|
|
301
|
+
6. Run the new image's migration command once with schema-owner authority.
|
|
302
|
+
7. Run the runtime bootstrap with separate runtime-login credentials.
|
|
303
|
+
8. Start the new gateway and require `/readyz`, an authenticated capability probe, and
|
|
304
|
+
an authenticated status probe.
|
|
305
|
+
9. Send, read, claim, and settle a disposable targeted delivery.
|
|
306
|
+
10. Roll clients forward only after the gateway proof passes.
|
|
307
|
+
11. Keep the previous authority available but inactive until the observation window
|
|
308
|
+
closes.
|
|
309
|
+
|
|
310
|
+
Run one migration job at a time. The migration ledger makes ordered application
|
|
311
|
+
idempotent, but it does not make concurrent deployment orchestration desirable.
|
|
312
|
+
|
|
313
|
+
## Rollback boundaries
|
|
314
|
+
|
|
315
|
+
| Failure point | Safe response |
|
|
316
|
+
| --- | --- |
|
|
317
|
+
| Before schema migration | Stop the new gateway and return to the prior image and configuration. |
|
|
318
|
+
| After migration, before client rollout | Keep clients on the old authority. Apply a forward fix, or restore the verified backup into a fresh target. |
|
|
319
|
+
| 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. |
|
|
320
|
+
| Database corruption or unrecoverable catalog drift | Restore native DR into a fresh target, verify readiness, then switch authority once. |
|
|
321
|
+
|
|
322
|
+
An older gateway may refuse a database with a newer migration plan. Starting the old
|
|
323
|
+
image is therefore not a general schema rollback. A volume snapshot is also not enough
|
|
324
|
+
unless its consistency and restore procedure have been proved for the database setup.
|
|
325
|
+
Migration 017 makes this readiness failure explicit for an old compiled migration
|
|
326
|
+
plan. It does not terminate an already-running old gateway. Drain it before applying
|
|
327
|
+
the migration.
|
|
328
|
+
|
|
329
|
+
## Operational checks
|
|
330
|
+
|
|
331
|
+
- `/healthz` proves the HTTP process is alive.
|
|
332
|
+
- `/readyz` proves the gateway can use the restricted database and that required
|
|
333
|
+
security attestations still match.
|
|
334
|
+
- `agent-bridge doctor --json` probes a configured client's remote path.
|
|
335
|
+
- `agent-bridge status` is passive and reports remote reachability as unknown until a
|
|
336
|
+
probe occurs.
|
|
337
|
+
- Gateway metrics require a credential with `gateway:metrics`.
|
|
338
|
+
|
|
339
|
+
Alert on readiness failure, repeated authorization denial, rate-limit pressure,
|
|
340
|
+
database connection exhaustion, due or blocked outbox rows, dead-letter growth, backup
|
|
341
|
+
failure, and restore-test failure. Keep tokens, database URLs, message content, and DR
|
|
342
|
+
bundle paths out of telemetry.
|
|
343
|
+
|
|
344
|
+
Related references:
|
|
345
|
+
|
|
346
|
+
- [Architecture](architecture-v2.md)
|
|
347
|
+
- [Security policy](../SECURITY.md)
|
|
348
|
+
- [Troubleshooting](troubleshooting.md)
|
|
349
|
+
- [Portable archives and native DR](../README.md#portable-archives)
|
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`
|
package/llms.txt
CHANGED
|
@@ -11,6 +11,10 @@ History uses mailbox `inbox` (default), `sent`, or `all`. Receipt state is `any`
|
|
|
11
11
|
- `npm install --global @creatornader/agent-bridge`
|
|
12
12
|
- `agent-bridge init --provider local`
|
|
13
13
|
- `agent-bridge demo`
|
|
14
|
+
- Development gateway: create `.secrets/postgres_password` and
|
|
15
|
+
`.secrets/runtime_password`, then run `docker compose up --build --wait gateway`.
|
|
16
|
+
Both checked-in port bindings are loopback-only. See `docs/deployment.md` before a
|
|
17
|
+
non-loopback deployment.
|
|
14
18
|
|
|
15
19
|
If an MCP client cannot attach, run `agent-bridge doctor --json` and see
|
|
16
20
|
`docs/troubleshooting.md`. Normal client installation resolves the MCP launch command;
|
|
@@ -30,6 +34,7 @@ services can call the CLI or HTTPS API or embed the Node library without a host
|
|
|
30
34
|
## Commands
|
|
31
35
|
|
|
32
36
|
- `agent-bridge --version` or `agent-bridge -V`: print the installed package version without loading backend configuration.
|
|
37
|
+
- `agent-bridge --help`, `agent-bridge -h`, or a command followed by either help flag: print help without loading backend configuration or dispatching the command.
|
|
33
38
|
- `agent-bridge capabilities`: print the canonical v2 operation and protocol capability document.
|
|
34
39
|
|
|
35
40
|
- agent-bridge init --provider local
|
|
@@ -38,14 +43,52 @@ services can call the CLI or HTTPS API or embed the Node library without a host
|
|
|
38
43
|
- `agent-bridge doctor`: active named checks; exits 0 ok, 2 degraded, 1 failed. Blocked outbox rows cannot be healthy.
|
|
39
44
|
- agent-bridge pending
|
|
40
45
|
- agent-bridge send, inbox, history, acknowledge
|
|
41
|
-
- agent-bridge claim, extend, ack, nack, deliveries, delivery-events, cancel, requeue
|
|
46
|
+
- agent-bridge claim [--message-id <uuid>], extend, ack, nack, deliveries, delivery-events, cancel, requeue
|
|
42
47
|
- agent-bridge sync, watch, join, presence
|
|
43
48
|
- agent-bridge clients install <runtime> --identity <principal>
|
|
49
|
+
- agent-bridge clients inspect <runtime> --identity <principal> --instance <stable-key> --backend-config <absolute path>
|
|
50
|
+
- agent-bridge clients adopt <runtime> --identity <principal> --instance <stable-key> --backend-config <absolute path> [--apply]
|
|
51
|
+
- agent-bridge clients repair <runtime> --identity <principal> --instance <stable-key> [--apply] [--resume <uuid>] [--recover-lock]
|
|
52
|
+
- agent-bridge clients update <runtime> --identity <principal> --instance <stable-key> [--command <command>] [--apply] [--resume <uuid>] [--recover-lock]
|
|
53
|
+
- agent-bridge clients uninstall <runtime> --identity <principal> --instance <stable-key> [--apply] [--resume <uuid>] [--recover-lock]
|
|
54
|
+
- agent-bridge clients rollback <update-operation-id> --identity <principal> [--apply] [--recover-lock]
|
|
55
|
+
- agent-bridge clients migrate stage <runtime> --identity <principal> --instance <stable-key> --enrollment-file <private-path> [--apply] [--recover-lock]
|
|
56
|
+
- agent-bridge clients migrate cutover <stage-operation-id> --exclusive-edge [--apply] [--recover-lock]
|
|
57
|
+
- agent-bridge clients migrate finalize <cutover-operation-id> --exclusive-edge [--apply] [--recover-lock]
|
|
58
|
+
- agent-bridge clients resume <operation-id> [--recover-lock] # resumes recorded v3, supported v4, v5 stage, or v6 migration authority
|
|
59
|
+
- agent-bridge clients operations [<operation-id>] # read-only resumable/classification-required/blocked/complete summaries
|
|
44
60
|
- agent-bridge owner provision|inventory|rotate|revoke
|
|
45
61
|
- agent-bridge clients install <runtime> --enrollment-file <private path>
|
|
46
62
|
- agent-bridge archive export|verify|import
|
|
47
63
|
- agent-bridge dr backup|verify|restore
|
|
48
64
|
|
|
65
|
+
Client inspection is local, read-only, secret-free, and reports absent, unmanaged,
|
|
66
|
+
managed, or drifted. Adoption is a plan unless `--apply` is explicit. It writes only
|
|
67
|
+
owner-private credential-free management metadata after the identity, stable instance,
|
|
68
|
+
backend path, scope, and launch contract match exactly; it never rewrites the host
|
|
69
|
+
registration or backend file. Enrollment-based first-time provisioning continues to
|
|
70
|
+
refuse registration and backend-file collisions. Metadata binds Desktop to its
|
|
71
|
+
normalized config path and Codex to its active profile config. Claude Code local and
|
|
72
|
+
project scope bind to the invocation directory because its native CLI exposes no
|
|
73
|
+
stronger registration target.
|
|
74
|
+
The backend and its immediate parent must pass the owner-only no-link policy. Codex
|
|
75
|
+
registration comparison ignores diagnostic fields and JSON property order but requires
|
|
76
|
+
exactly AGENT_BRIDGE_AGENT, AGENT_BRIDGE_INSTANCE, and AGENT_BRIDGE_CONFIG. Claude Code
|
|
77
|
+
connectivity status is not registration state. Desktop inspection uses the installer's
|
|
78
|
+
validated absolute launch resolver, and applied adoption re-inspects its postcondition.
|
|
79
|
+
Only Claude Code accepts `--scope`; only Claude Desktop accepts `--config-path` for
|
|
80
|
+
inspect and adopt. Repair, update, and uninstall derive those locators from strict managed metadata.
|
|
81
|
+
They reject backend, scope, and config-path authority flags. `--identity` binds the
|
|
82
|
+
metadata record and immutable request. Repair restores the recorded launch contract.
|
|
83
|
+
Update records a normalized credential-free launch request, including only fixed Agent
|
|
84
|
+
Bridge environment key names. Native commands are one executable contract and reject
|
|
85
|
+
arguments, URL-like selectors, and credential surfaces. Plan-only calls create no lock
|
|
86
|
+
or operation. Native changes prove remove then add. Desktop replaces only the Agent
|
|
87
|
+
Bridge config entry through a private operation-scoped temporary file. Its same-user
|
|
88
|
+
writer race is advisory because Node cannot provide an OS transaction. Resume requires
|
|
89
|
+
the same action and managed identity. Lock recovery requires
|
|
90
|
+
same-host process-death proof.
|
|
91
|
+
|
|
49
92
|
Archive export moves one workspace's immutable messages and read receipts between
|
|
50
93
|
canonical local SQLite and PostgreSQL stores. Import defaults to a rollback-backed dry
|
|
51
94
|
run and requires `--apply` to commit. PostgreSQL archive authority comes only from
|
|
@@ -75,14 +118,20 @@ excludes transient request, rate-limit, instance, and archive-authorization rows
|
|
|
75
118
|
normalizes claimed deliveries on restore. Never run source and restored target at the
|
|
76
119
|
same time. The package API is @creatornader/agent-bridge/dr. Bundle hashes detect
|
|
77
120
|
changed bytes but do not encrypt or authenticate the source.
|
|
121
|
+
The immutable PostgreSQL gateway authority UUID is preserved by native DR. It identifies
|
|
122
|
+
one logical authority across restore but does not fence a live clone.
|
|
78
123
|
|
|
79
124
|
## MCP tools
|
|
80
125
|
|
|
81
126
|
- `capabilities`: return operations, required scopes, provider-specific enforcement, and supported protocol versions. Gateway access needs an active credential but no named scope for this operation.
|
|
82
127
|
- Production gateway capabilities report `requestAuthority: true` and `rowIsolation: true` only after the migration and live catalog, role, policy, privilege, and function checks pass. PostgreSQL forces RLS on messages, receipts, deliveries, delivery events, and presence. Lease transitions and target-to-delivery membership remain service-enforced.
|
|
128
|
+
- Authenticated gateway `/v2/status` returns optional `gatewayAuthorityId` and
|
|
129
|
+
`credentialId` fields when PostgreSQL request authority is active. They are additive
|
|
130
|
+
in HTTP 2.1 and do not appear in capabilities.
|
|
83
131
|
|
|
84
132
|
Compatibility: post_context, get_context, ack_context.
|
|
85
133
|
Reliable messaging: send, history, claim, extend, acknowledge, negative_acknowledge, heartbeat, presence, sync.
|
|
134
|
+
Claim selects the next due delivery unless HTTP 2.1, MCP, or CLI supplies one messageId. The exact form atomically selects and maintains only that eligible recipient delivery. HTTP 2.0 rejects the additive field.
|
|
86
135
|
Publisher delivery intent: `deliveryPolicy` mode `mailbox|leased` with `maxAttempts`, `retryBaseDelayMs`, `retryMaxDelayMs`, `retryJitterRatio`, and optional `notBefore`. MCP delivery controls: `list_deliveries`, `list_delivery_events`, `cancel_delivery`, `requeue_delivery`. Consumer `maxAttempts` and `retryPolicy` are validated but ignored for one compatibility release.
|
|
87
136
|
|
|
88
137
|
Gateway MCP clients sync automatically and expose manual sync for bounded outbox replay and inbox cache refresh. Offline unacknowledged results are degraded candidates with unknown acknowledgement state, not proof that messages are unread or that no remote work exists.
|
|
@@ -122,6 +171,24 @@ workspace, and live MCP registration matches. Consumed-file deletion and lock re
|
|
|
122
171
|
report retained, missing, durable, and durability-unknown outcomes without claiming that
|
|
123
172
|
an unlinked path was retained.
|
|
124
173
|
|
|
174
|
+
`clients migrate stage` is a plan-first gateway migration preparation command. An
|
|
175
|
+
applied stage creates an owner-private successor backend and credential-free operation
|
|
176
|
+
record. It leaves the active registration, active backend, and source edge scope
|
|
177
|
+
active after initializing its gate. Staging requires an absolute, normalized source
|
|
178
|
+
edge database path and rejects `:memory:`.
|
|
179
|
+
|
|
180
|
+
`clients migrate cutover` requires a committed v5 stage and `--exclusive-edge`. Initial
|
|
181
|
+
preflight checks exact HTTP 2.1 status bindings at both gateways, one immutable
|
|
182
|
+
authority ID, the successor's `status:read` and `messages:write` grants, and a direct
|
|
183
|
+
predecessor-to-successor route challenge. Once it creates the journal, it uses a
|
|
184
|
+
retained normalized source URL and the successor credential for every route proof and
|
|
185
|
+
source outbox replay through the target gateway. `finalize` requires a fresh assertion
|
|
186
|
+
after grace expires and retires the source. To return to a former endpoint, rotate a
|
|
187
|
+
new owner credential and run an ordinary forward cutover to that endpoint. Dry runs
|
|
188
|
+
read private edge state without SQLite writes or gateway requests. They refuse live WAL
|
|
189
|
+
sidecars rather than read uncheckpointed outbox state. Resume uses only the retained v6
|
|
190
|
+
request and waits for an unexpired drain lease instead of taking it over.
|
|
191
|
+
|
|
125
192
|
Project is an optional immutable message label, not a tenant or identity selector. Omitted project reads include labeled and unlabeled messages. Exact project filters are supported by CLI, MCP, HTTP, and stores. Gateway workspace assertions must match the bound credential before network access.
|
|
126
193
|
Local CLI calls may override workspace for one invocation. The legacy Supabase schema is global and always reports workspace `*`; use project labels for legacy filtering.
|
|
127
194
|
|
|
@@ -132,6 +199,7 @@ Local CLI calls may override workspace for one invocation. The legacy Supabase s
|
|
|
132
199
|
- SECURITY.md: reporting process and security boundaries
|
|
133
200
|
- docs/ecosystem.md: relationship to adjacent protocols, brokers, and runtimes
|
|
134
201
|
- docs/troubleshooting.md: MCP startup and client recovery
|
|
202
|
+
- docs/deployment.md: Compose development stack and production deployment constraints
|
|
135
203
|
- docs/decisions/0001-protocol-layers-and-acknowledgment-semantics.md: protocol layers and acknowledgment semantics
|
|
136
204
|
- docs/decisions/0002-canonical-operation-contract-registry.md: generated contracts and version negotiation
|
|
137
205
|
- docs/decisions/0003-host-adapters-and-consumer-instance-keys.md: host layers and instance-key semantics
|