agent-embassy 1.2.0 → 1.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 +41 -0
- package/CONTRIBUTING.md +50 -16
- package/README.md +57 -25
- package/README.zh-CN.md +45 -23
- package/SECURITY.md +68 -48
- package/dist/src/gateway/claude-helper-protocol.d.ts +1 -0
- package/dist/src/gateway/claude-helper-protocol.js +4 -2
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +1 -0
- package/dist/src/gateway/claude-helper-supervisor.js +3 -1
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
- package/dist/src/gateway/claude-runtime.d.ts +0 -2
- package/dist/src/gateway/claude-runtime.js +6 -17
- package/dist/src/gateway/claude-runtime.js.map +1 -1
- package/dist/src/gateway/cli-copy.d.ts +1 -1
- package/dist/src/gateway/cli-copy.en.d.ts +4 -1
- package/dist/src/gateway/cli-copy.en.js +7 -3
- package/dist/src/gateway/cli-copy.en.js.map +1 -1
- package/dist/src/gateway/cli-copy.js +3 -0
- package/dist/src/gateway/cli-copy.js.map +1 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +4 -1
- package/dist/src/gateway/cli-copy.zh-CN.js +7 -3
- package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +2 -5
- package/dist/src/gateway/cli.js +41 -67
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/codex-app-server.d.ts +2 -8
- package/dist/src/gateway/codex-app-server.js +36 -62
- package/dist/src/gateway/codex-app-server.js.map +1 -1
- package/dist/src/gateway/codex-local-transport.d.ts +4 -10
- package/dist/src/gateway/codex-local-transport.js +13 -16
- package/dist/src/gateway/codex-local-transport.js.map +1 -1
- package/dist/src/gateway/compatibility.d.ts +0 -27
- package/dist/src/gateway/compatibility.js +1 -101
- package/dist/src/gateway/compatibility.js.map +1 -1
- package/dist/src/gateway/config.d.ts +1 -4
- package/dist/src/gateway/config.js +0 -10
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/control.d.ts +2 -21
- package/dist/src/gateway/control.js +7 -36
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.d.ts +1 -1
- package/dist/src/gateway/dashboard-copy.en.d.ts +21 -8
- package/dist/src/gateway/dashboard-copy.en.js +40 -27
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.js +21 -8
- package/dist/src/gateway/dashboard-copy.js.map +1 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +21 -8
- package/dist/src/gateway/dashboard-copy.zh-CN.js +40 -27
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
- package/dist/src/gateway/dashboard-model.d.ts +4 -9
- package/dist/src/gateway/dashboard-model.js +159 -46
- package/dist/src/gateway/dashboard-model.js.map +1 -1
- package/dist/src/gateway/dashboard.js +27 -16
- package/dist/src/gateway/dashboard.js.map +1 -1
- package/dist/src/gateway/instance-lease.d.ts +2 -3
- package/dist/src/gateway/instance-lease.js +17 -140
- package/dist/src/gateway/instance-lease.js.map +1 -1
- package/dist/src/gateway/live-dashboard-app/app.js +62 -63
- package/dist/src/gateway/live-dashboard-command.d.ts +5 -1
- package/dist/src/gateway/live-dashboard-command.js +8 -6
- package/dist/src/gateway/live-dashboard-command.js.map +1 -1
- package/dist/src/gateway/live-dashboard-http.d.ts +0 -4
- package/dist/src/gateway/live-dashboard-http.js +20 -94
- package/dist/src/gateway/live-dashboard-http.js.map +1 -1
- package/dist/src/gateway/live-dashboard-protocol.d.ts +1 -5
- package/dist/src/gateway/live-dashboard-protocol.js +0 -42
- package/dist/src/gateway/live-dashboard-protocol.js.map +1 -1
- package/dist/src/gateway/live-dashboard-server.d.ts +2 -2
- package/dist/src/gateway/live-dashboard-server.js +18 -4
- package/dist/src/gateway/live-dashboard-server.js.map +1 -1
- package/dist/src/gateway/live-dashboard.d.ts +3 -6
- package/dist/src/gateway/live-dashboard.js +6 -42
- package/dist/src/gateway/live-dashboard.js.map +1 -1
- package/dist/src/gateway/progress-watch-machine.d.ts +6 -5
- package/dist/src/gateway/progress-watch-machine.js +6 -6
- package/dist/src/gateway/progress-watch-machine.js.map +1 -1
- package/dist/src/gateway/provenance-envelope.d.ts +1 -0
- package/dist/src/gateway/provenance-envelope.js +11 -4
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +2 -21
- package/dist/src/gateway/providers.js +21 -261
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.js +0 -3
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +5 -15
- package/dist/src/gateway/service.js +101 -265
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/store.d.ts +9 -21
- package/dist/src/gateway/store.js +360 -140
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +1 -6
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +102 -0
- package/docs/CONFIGURATION.zh-CN.md +72 -0
- package/docs/DASHBOARD.md +103 -0
- package/docs/DASHBOARD.zh-CN.md +47 -0
- package/docs/DELIVERY.md +84 -0
- package/docs/DELIVERY.zh-CN.md +53 -0
- package/docs/GATEWAY-ARCHITECTURE.md +249 -153
- package/package.json +8 -4
- package/skills/embassy-peer/SKILL.md +25 -10
- package/dist/src/gateway/claude-compatibility-scratch.d.ts +0 -18
- package/dist/src/gateway/claude-compatibility-scratch.js +0 -158
- package/dist/src/gateway/claude-compatibility-scratch.js.map +0 -1
- package/dist/src/gateway/live-dashboard-bootstrap.d.ts +0 -36
- package/dist/src/gateway/live-dashboard-bootstrap.js +0 -176
- package/dist/src/gateway/live-dashboard-bootstrap.js.map +0 -1
- package/docs/DESIGN.md +0 -134
|
@@ -18,16 +18,21 @@ queued turn after idle, and delivered the exact final reply back to Claude.
|
|
|
18
18
|
## Purpose and boundary
|
|
19
19
|
|
|
20
20
|
The gateway lets already-running Claude Code sessions and explicitly
|
|
21
|
-
registered native Codex tasks address one another by short aliases.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
registered native Codex tasks address one another by short aliases. Both
|
|
22
|
+
directions require an explicit permission edge. The broker runs in `paired`
|
|
23
|
+
inbound mode by default, so an inbound native Claude message is admitted only
|
|
24
|
+
from a session that already holds a pair edge to the addressed Codex task;
|
|
25
|
+
`embassy serve --inbound open` is the explicit opt-out that restores any exact
|
|
26
|
+
compatible live same-UID session as an inbound sender without making it
|
|
27
|
+
outbound-selected. Outbound Codex-to-Claude sends likewise require the pair
|
|
28
|
+
edge, created by `pair` or the one-task `select-claude` shorthand. It provides
|
|
29
|
+
a single private operational view across the two products without rebuilding
|
|
30
|
+
either agent runtime.
|
|
27
31
|
|
|
28
32
|
Its exact Claude Code 2.1.226 runtime/peer-protocol pin is fail-closed.
|
|
29
|
-
Still-running 2.1.224 sessions remain compatible during a patch
|
|
30
|
-
because their registry records use the same reviewed peer protocol 1
|
|
33
|
+
Still-running 2.1.224 and 2.1.225 sessions remain compatible during a patch
|
|
34
|
+
upgrade because their registry records use the same reviewed peer protocol 1
|
|
35
|
+
shape.
|
|
31
36
|
|
|
32
37
|
It is deliberately:
|
|
33
38
|
|
|
@@ -40,8 +45,8 @@ Embassy uses one private same-user Unix-domain control socket for its thin
|
|
|
40
45
|
clients and generates a private static dashboard page in each supported
|
|
41
46
|
language. `embassy serve` does not add a TCP listener, HTTP server, or public
|
|
42
47
|
API. The opt-in `embassy dashboard --live` companion is a separate foreground
|
|
43
|
-
process that binds an
|
|
44
|
-
on `127.0.0.1`; it is
|
|
48
|
+
process that binds an unauthenticated stable-port listener with four bounded
|
|
49
|
+
route actions on exact `127.0.0.1`; it is
|
|
45
50
|
described under [Live dashboard companion](#live-dashboard-companion).
|
|
46
51
|
|
|
47
52
|
### Why this uses the new feature, but is not skill-only
|
|
@@ -129,7 +134,7 @@ probed by this project.
|
|
|
129
134
|
│ │ callback replies
|
|
130
135
|
▼ ▼
|
|
131
136
|
┌──────────────────────── local singleton gateway ───────────────────────┐
|
|
132
|
-
│ private control UDS │
|
|
137
|
+
│ private control UDS │ retained bodies │ metadata state │ static HTML │
|
|
133
138
|
└──────────┬──────────┴──────────────────┴────────────────┴──────────────┘
|
|
134
139
|
│
|
|
135
140
|
├─ local Codex App Server ─ registered native local tasks
|
|
@@ -153,12 +158,12 @@ The status below is intentionally narrower than the target architecture.
|
|
|
153
158
|
|
|
154
159
|
| Component | Current evidence |
|
|
155
160
|
| --- | --- |
|
|
156
|
-
| Neutral gateway types, metadata store, route fencing, bounded queues, dedupe, rate limits, and public projection | **Implemented**, deterministic tests; message bodies persist under bounded retention
|
|
161
|
+
| Neutral gateway types, metadata store, route fencing, bounded queues, dedupe, rate limits, and public projection | **Implemented**, deterministic tests; message bodies persist under bounded retention |
|
|
157
162
|
| Private JSONL control protocol over a controller-owned UDS | **Implemented**, deterministic synthetic tests; no provider connection required |
|
|
158
163
|
| Static metadata-only dashboard renderer and atomic publisher | **Implemented**, deterministic security tests; the static renderer requires no browser or HTTP server |
|
|
159
|
-
| Opt-in live dashboard companion (`embassy dashboard --live`) | **Implemented**, deterministic tests over the loopback listener,
|
|
164
|
+
| Opt-in live dashboard companion (`embassy dashboard --live`) | **Implemented**, deterministic tests over the stable loopback listener, direct multi-browser access, projection, request guards, and four bounded route actions; it is a separate foreground process, never part of `embassy serve` |
|
|
160
165
|
| Claude registry/peer adapter pinned to 2.1.226 / peer protocol 1 | **Implemented** and live-tested, including 2.1.224–2.1.226 patch-overlap discovery, print-session discovery, native status frames, cancellation, and accessible-workspace attestation |
|
|
161
|
-
|
|
|
166
|
+
| Automatic exact Claude 2.1.226 binary/runtime validation | **Implemented**; executes only bounded `claude --version` with a scrubbed environment and derives but does not open provider roots |
|
|
162
167
|
| Allowlisted Codex App Server connector with bounded busy behavior | **Implemented** and live-tested against App Server 0.147.0 for external busy observation, registered-route reachability across settings changes, and an automatically started queued turn; exact `STEER:` boundary behavior is covered deterministically |
|
|
163
168
|
| Attach-only local Codex proxy transport and exact-owned cleanup | **Implemented**, five deterministic tests; no live App Server connection in routine tests |
|
|
164
169
|
| Local provider adapters | **Implemented**, focused synthetic tests cover genuine-interactive Claude discovery, exact send/callback/receipt settlement and post-dispatch refresh, plus exact opted-in Codex ownership, registered-route reachability, monitor-only fallback, and cleanup; remote adapters remain disabled |
|
|
@@ -210,13 +215,13 @@ connector positively observes that exact task on the current endpoint
|
|
|
210
215
|
generation.
|
|
211
216
|
|
|
212
217
|
An App Server endpoint-generation change is a fenced route transition, not a
|
|
213
|
-
new registration. Embassy stops dispatch through the old connector
|
|
214
|
-
replacement connector
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
new registration. Embassy stops dispatch through the old connector and creates
|
|
219
|
+
a monitor-only replacement connector. That exact generation must pass a fresh
|
|
220
|
+
automatic initialize and `thread/loaded/list` validation, where every retained
|
|
221
|
+
private thread ID must occur exactly once. The connector resumes that exact
|
|
222
|
+
task with history excluded; only then may the controller activate writes and
|
|
223
|
+
atomically re-anchor the same alias, owner lease, and pair edges to the new
|
|
224
|
+
endpoint generation. Each successful re-anchor is recorded in a bounded
|
|
220
225
|
private journal; neither thread IDs nor endpoint generations enter public
|
|
221
226
|
activity, diagnostics, logs, or CLI output. An incompatible endpoint, a
|
|
222
227
|
missing or duplicate exact task, or an unclean transition leaves the route
|
|
@@ -269,7 +274,7 @@ The thin skill/CLI exposes the same safe alias list to either provider.
|
|
|
269
274
|
thread identity, source alias, target Claude current name or session UUID,
|
|
270
275
|
and bounded text.
|
|
271
276
|
2. The gateway checks thread ownership, selector state, rate and size limits,
|
|
272
|
-
deadline,
|
|
277
|
+
deadline, and dedupe state.
|
|
273
278
|
3. It requires the selector to match an explicitly selected live UUID,
|
|
274
279
|
refreshes the UUID's current process/socket coordinates, and revalidates
|
|
275
280
|
the selected Claude peer's canonical workspace access and exact generation
|
|
@@ -278,7 +283,9 @@ The thin skill/CLI exposes the same safe alias list to either provider.
|
|
|
278
283
|
`cross-session-message` textual frame with bounded sender attribution and a
|
|
279
284
|
first-child reply hint containing the full conversation token, exact aliases,
|
|
280
285
|
and reply command. It then opens a short-lived connection and writes one
|
|
281
|
-
version-pinned peer frame
|
|
286
|
+
version-pinned peer frame immediately, regardless of whether the current
|
|
287
|
+
Claude registry observation says `idle`, `busy`, or `waiting`. A reply
|
|
288
|
+
request carries the gateway's own
|
|
282
289
|
anonymous callback UDS as the transport reply address; that path is never
|
|
283
290
|
exposed in the content frame.
|
|
284
291
|
5. It records only normalized delivery metadata. It does not retry an
|
|
@@ -286,12 +293,13 @@ The thin skill/CLI exposes the same safe alias list to either provider.
|
|
|
286
293
|
6. A reply received on the callback listener is correlated in memory and
|
|
287
294
|
routed to the owning explicitly registered Codex task.
|
|
288
295
|
|
|
289
|
-
A
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
A Claude-bound peer socket is a native mailbox, not an idle gate. Once the
|
|
297
|
+
pre-write route checks pass, Embassy attempts that mailbox write immediately;
|
|
298
|
+
an observed busy state never queues the body. `transport_written` proves the
|
|
299
|
+
mailbox write and is reduced to terminal `delivered` for this direction. That
|
|
300
|
+
still does not prove Claude read, consumed, or acted on the body. The adapter
|
|
301
|
+
distinguishes this transport boundary from Claude-to-Codex native `held`, which
|
|
302
|
+
is a progress signal only. Neither boundary permits a retry.
|
|
295
303
|
|
|
296
304
|
### Claude to Codex
|
|
297
305
|
|
|
@@ -309,9 +317,13 @@ final reply.
|
|
|
309
317
|
text as untrusted user-role input. This inbound observation grants only a
|
|
310
318
|
transient, in-memory capability for the correlated reply. It does not add a
|
|
311
319
|
Claude route, flip `selected`, or authorize a later unsolicited send.
|
|
312
|
-
In paired mode
|
|
313
|
-
message admission with `SENDER_NOT_PAIRED
|
|
314
|
-
|
|
320
|
+
In paired mode — the default — a sender without the exact permission edge is
|
|
321
|
+
refused before message admission with `SENDER_NOT_PAIRED`. No message is
|
|
322
|
+
accepted, so no delivery is created, but the refusal is not silent: the
|
|
323
|
+
broker records it as a `rejected` journal event carrying the direction, both
|
|
324
|
+
aliases, the byte count, and the safe error code, and increments the
|
|
325
|
+
rejected counters on the accounting, the source route, and any matching
|
|
326
|
+
pair.
|
|
315
327
|
3. The Claude process's inherited messaging-socket value may be accepted as a
|
|
316
328
|
transient reply address after strict validation. Claude Code exports
|
|
317
329
|
`CLAUDE_CODE_MESSAGING_SOCKET` as a raw absolute socket path; the CLI
|
|
@@ -337,12 +349,15 @@ final reply.
|
|
|
337
349
|
emit Claude's approval-specific native `held` control frame for ordinary
|
|
338
350
|
queueing.
|
|
339
351
|
8. In `merged` and `verbose` notice modes, if the delivery remains pending for
|
|
340
|
-
exactly `floor(messageDeadlineMs / 2)
|
|
341
|
-
originating Claude session at most one nonterminal
|
|
352
|
+
exactly `min(floor(messageDeadlineMs / 2), 120_000)` milliseconds, the
|
|
353
|
+
gateway may send the originating Claude session at most one nonterminal
|
|
342
354
|
`<gateway-delivery-stall>` user frame for that receipt. It contains only an
|
|
343
355
|
allowlisted reason and a bounded `queued-for-ms` age; it is not a native
|
|
344
|
-
`held` receipt and does not settle the delivery.
|
|
345
|
-
|
|
356
|
+
`held` receipt and does not settle the delivery. The two-minute ceiling is
|
|
357
|
+
deliberate: stall visibility must not scale with the deadline, so under the
|
|
358
|
+
default four-hour deadline the notice fires at two minutes, not two hours.
|
|
359
|
+
`quiet` suppresses this gateway-authored frame without changing native status
|
|
360
|
+
or dashboard state.
|
|
346
361
|
9. When the task becomes idle, the connector refreshes the exact task state and
|
|
347
362
|
starts the held message. A route retains at most three queued steering
|
|
348
363
|
messages; accepting a fourth atomically cancels the oldest with safe code
|
|
@@ -387,19 +402,24 @@ terminally settles accepted work, joins its bounded receipt writes, and only
|
|
|
387
402
|
then closes provider adapters. This orders `GATEWAY_SHUTDOWN` receipts ahead of
|
|
388
403
|
listener teardown instead of silently dropping late admitted work.
|
|
389
404
|
|
|
390
|
-
Claude's native peer socket is itself
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
Claude
|
|
405
|
+
Claude's native peer socket is itself a mailbox, so every Claude-bound body,
|
|
406
|
+
including a correlated Codex reply, is written regardless of Claude's observed
|
|
407
|
+
busy or idle state. The gateway still serializes its own writes, but it never
|
|
408
|
+
waits for Claude to become idle and thereby deadlocks a Claude turn that is
|
|
409
|
+
waiting for the reply. This does not change the opposite direction: ordinary
|
|
410
|
+
Codex-bound bodies remain idle-gated, and exact leading `STEER:` bodies keep the
|
|
411
|
+
next-tool-call-boundary rules above.
|
|
394
412
|
|
|
395
413
|
### Provenance framing and conversation continuation
|
|
396
414
|
|
|
397
415
|
The broker classifies `STEER:`, `TRACK:`, and `DONE:`, enforces raw-byte body
|
|
398
|
-
limits, deduplicates,
|
|
399
|
-
The store therefore retains only the raw
|
|
400
|
-
at the final semantic provider-write boundary so
|
|
401
|
-
same bytes with exactly one authoritative outer
|
|
402
|
-
|
|
416
|
+
limits, deduplicates, and queues before presentation framing.
|
|
417
|
+
The store therefore retains only the raw unframed body, never the composed
|
|
418
|
+
envelope. A pure composer runs at the final semantic provider-write boundary so
|
|
419
|
+
a clean retry produces the same bytes with exactly one authoritative outer
|
|
420
|
+
wrapper. Automatic provider
|
|
421
|
+
startup and endpoint-generation validation, receipt frames, and diagnostics do
|
|
422
|
+
not use this path.
|
|
403
423
|
|
|
404
424
|
Both provider directions use Claude-compatible textual framing with a
|
|
405
425
|
broker-owned `cross-session-message` outer element and an
|
|
@@ -416,17 +436,17 @@ broker-owned `cross-session-message` outer element and an
|
|
|
416
436
|
- In either direction, the first hint carries the full token in `conversation`
|
|
417
437
|
and the exact recipient alias in `reply-as`, followed by an exact stdin-based
|
|
418
438
|
`embassy reply --conversation ... --alias ...` instruction and the statement
|
|
419
|
-
that
|
|
439
|
+
that caller, conversation, and route policy are rechecked.
|
|
420
440
|
|
|
421
|
-
Embassy does not synthesize `from`, `from-session`,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
441
|
+
Embassy does not synthesize `from`, `from-session`, or `from-mode` attributes:
|
|
442
|
+
those names have provider-native meanings the broker cannot truthfully claim.
|
|
443
|
+
Native socket addresses, Codex thread IDs, Claude session UUIDs, endpoint
|
|
444
|
+
generations, and route handles never enter the content frame.
|
|
425
445
|
|
|
426
446
|
The outer structure and hint come only from validated broker metadata. Before
|
|
427
447
|
composition, the untrusted body case-insensitively neutralizes boundary-shaped
|
|
428
|
-
opening or closing occurrences of
|
|
429
|
-
|
|
448
|
+
opening or closing occurrences of Embassy's reserved framing tags by inserting
|
|
449
|
+
`\` immediately after the leading `<`.
|
|
430
450
|
Everything else remains raw text. This is not general XML, cryptographic
|
|
431
451
|
authentication, or proof that the message content is trustworthy; it is a
|
|
432
452
|
consistent structural provenance marker at the model input boundary. A native
|
|
@@ -435,8 +455,8 @@ beneath the Embassy wrapper.
|
|
|
435
455
|
|
|
436
456
|
The full token delivered in the hint lets the recipient call `reply`, but it is
|
|
437
457
|
only a participant-scoped conversation locator. The service still validates
|
|
438
|
-
the inherited caller, current conversation membership, current route
|
|
439
|
-
|
|
458
|
+
the inherited caller, current conversation membership, and current route
|
|
459
|
+
policy. The full token remains confined to the accepted control result
|
|
440
460
|
and transient provider payload, and is memory-only: it is never persisted,
|
|
441
461
|
journaled, logged, snapshotted, rendered on a dashboard, placed in a receipt,
|
|
442
462
|
or returned from suffix-only public correlation. Formatter,
|
|
@@ -505,16 +525,22 @@ never displaced to admit a new send. A pressure-evicted handle returns
|
|
|
505
525
|
|
|
506
526
|
### Replies and process restarts
|
|
507
527
|
|
|
508
|
-
Conversation IDs correlate replies,
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
528
|
+
Conversation IDs correlate replies, and callback addresses exist only in
|
|
529
|
+
memory, but queued message bodies are durable. After a gateway restart, each
|
|
530
|
+
queued message is triaged: one already past its deadline settles `expired`; one
|
|
531
|
+
whose target authority was transient, or whose target route is gone, settles
|
|
532
|
+
`abandoned` with `CONTROLLER_RESTARTED`; every other queued body is restored and
|
|
533
|
+
re-armed for dispatch, then sent exactly once after its exact route is
|
|
534
|
+
re-observed. A message in flight at the moment of the restart or crash settles
|
|
535
|
+
`ambiguous` with `CONTROLLER_RESTARTED` and is never replayed.
|
|
536
|
+
|
|
537
|
+
The prior Claude binding remains stored but stale. After authorized live
|
|
538
|
+
discovery, one exact UUID-bound selection may be reactivated under its latest
|
|
539
|
+
name. No pending reply, callback, native receipt handle, delivery token/status
|
|
540
|
+
tracker, or conversation capability survives the restart; a prior token
|
|
541
|
+
therefore returns `found: false`. A stale or offline selection can be explicitly
|
|
542
|
+
removed by its stored alias or a user-supplied UUID without requiring discovery
|
|
543
|
+
first.
|
|
518
544
|
|
|
519
545
|
## Gateway control plane
|
|
520
546
|
|
|
@@ -523,33 +549,41 @@ controller-owned mode-0700 state directory. The socket and state files are
|
|
|
523
549
|
mode 0600. Frames are size-bounded and closed against unknown keys, methods,
|
|
524
550
|
versions, and enum values.
|
|
525
551
|
|
|
526
|
-
The
|
|
552
|
+
The closed version 1 method family is exactly these sixteen methods:
|
|
527
553
|
|
|
528
|
-
- health and a safe public snapshot;
|
|
529
|
-
- a read-only
|
|
530
|
-
lifecycle deliveries before projecting
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
554
|
+
- `health` and `list_snapshot`, a safe public snapshot;
|
|
555
|
+
- `observe_snapshot`, a read-only projection that may settle already-due
|
|
556
|
+
lifecycle deliveries before projecting;
|
|
557
|
+
- `register_codex`, `unregister_codex`, and
|
|
558
|
+
`remove_stale_codex_registration` — explicit Codex registration and
|
|
559
|
+
succession, unregister, and broker-guarded removal of a stale orphan whose
|
|
560
|
+
owning endpoint generation is dead;
|
|
561
|
+
- `select_claude` and `unselect_claude`, from the current sanitized
|
|
534
562
|
available-peer inventory;
|
|
535
|
-
-
|
|
536
|
-
-
|
|
537
|
-
-
|
|
538
|
-
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
563
|
+
- `pair` and `unpair`, the two-endpoint permission edge;
|
|
564
|
+
- `delivery_status`, a lookup by opaque, memory-only correlation handle;
|
|
565
|
+
- `untrack`, which closes one active progress watch by conversation token;
|
|
566
|
+
- `send_to_claude` and `send_to_codex`, the provider-specific sends;
|
|
567
|
+
- `reply`, the correlated reply operation; and
|
|
568
|
+
- `refresh_dashboard`, which refreshes Claude discovery and republishes.
|
|
569
|
+
|
|
570
|
+
The live dashboard companion calls `observe_snapshot` for every read; its
|
|
571
|
+
mutation route additionally calls `pair`, `unpair`,
|
|
572
|
+
`remove_stale_codex_registration`, and `refresh_dashboard`, and nothing else.
|
|
573
|
+
|
|
574
|
+
The installed binary is `embassy`, and it is the only installed binary. Its
|
|
575
|
+
seventeen implemented commands are
|
|
576
|
+
`serve`, `health`, `status`, `delivery-status`, `wait-delivery`, `untrack`,
|
|
543
577
|
`refresh-dashboard`, `dashboard`, `register-codex`, `unregister-codex`,
|
|
544
|
-
`select-claude`, `unselect-claude`, `
|
|
545
|
-
`reply`. `dashboard` requires `--live` and accepts an
|
|
546
|
-
`--lang en|zh-CN
|
|
547
|
-
control request. Message bodies are non-empty
|
|
548
|
-
with a 16 KiB ceiling; they are never accepted
|
|
549
|
-
client emits one bounded normalized JSON line and
|
|
550
|
-
provider-native ID, path, address, or message body.
|
|
551
|
-
foreground broker, except that `serve` starts it in
|
|
552
|
-
never daemonizes itself.
|
|
578
|
+
`select-claude`, `unselect-claude`, `pair`, `unpair`, `send-to-claude`,
|
|
579
|
+
`send-to-codex`, and `reply`. `dashboard` requires `--live` and accepts an
|
|
580
|
+
optional `--lang en|zh-CN` and `--port <n>`; it starts the companion process
|
|
581
|
+
rather than issuing a single control request. Message bodies are non-empty
|
|
582
|
+
UTF-8 from standard input only, with a 16 KiB ceiling; they are never accepted
|
|
583
|
+
in an argument or file. The client emits one bounded normalized JSON line and
|
|
584
|
+
never returns a thread ID, provider-native ID, path, address, or message body.
|
|
585
|
+
These commands require the foreground broker, except that `serve` starts it in
|
|
586
|
+
the current terminal. It never daemonizes itself.
|
|
553
587
|
|
|
554
588
|
`select-claude --alias <current-name@host>` and
|
|
555
589
|
`select-claude --session <uuid>` select the same logical session.
|
|
@@ -562,9 +596,19 @@ Codex registration, unregister, and Codex-to-Claude send require only a valid
|
|
|
562
596
|
`CODEX_THREAD_ID`; they fail if a non-empty Claude messaging socket is also
|
|
563
597
|
inherited. Claude-to-Codex send requires only the raw inherited Claude socket
|
|
564
598
|
path and fails if a non-empty Codex thread ID is also present. `reply` likewise
|
|
565
|
-
fails with both identities or neither.
|
|
566
|
-
|
|
567
|
-
|
|
599
|
+
fails with both identities or neither. `pair` and `unpair` also require an
|
|
600
|
+
exclusive inherited `CODEX_THREAD_ID`: naming both endpoints does not make them
|
|
601
|
+
operator commands, and they fail `CODEX_IDENTITY_REQUIRED` from a plain terminal
|
|
602
|
+
or `CALLER_IDENTITY_CONFLICT` from inside a Claude session.
|
|
603
|
+
|
|
604
|
+
`select-claude` and `unselect-claude` are the operator-runnable shorthand.
|
|
605
|
+
They do not ignore provider identity — they consume an inherited
|
|
606
|
+
`CODEX_THREAD_ID` when one is present, to resolve the Codex end, and reject a
|
|
607
|
+
malformed one — but they tolerate its absence and then resolve the Codex end
|
|
608
|
+
from the sole registered task. Selection is not a weaker operation than
|
|
609
|
+
`pair`: it atomically creates the same permission edge. The health, status,
|
|
610
|
+
dashboard refresh, live dashboard, untrack, and serve commands are the ones
|
|
611
|
+
that genuinely ignore provider identities.
|
|
568
612
|
|
|
569
613
|
The foreground command is:
|
|
570
614
|
|
|
@@ -572,21 +616,27 @@ The foreground command is:
|
|
|
572
616
|
embassy serve
|
|
573
617
|
```
|
|
574
618
|
|
|
575
|
-
|
|
619
|
+
`--inbound open` is the one security-relevant option:
|
|
620
|
+
|
|
621
|
+
```text
|
|
622
|
+
embassy serve --inbound open
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
The default is `paired`. `open` is the explicit opt-out that lets any exact
|
|
626
|
+
compatible live same-UID Claude session send inbound without a pair edge; it is
|
|
627
|
+
never implied and cannot be set through an environment variable.
|
|
628
|
+
|
|
629
|
+
Before provider validation, listener creation, or App Server attachment, the
|
|
576
630
|
launcher acquires one fixed host-wide crash-reclaimable owner lease under the
|
|
577
631
|
verified login home. The lease is independent of `EMBASSY_STATE_DIR`, so two foreground
|
|
578
632
|
controllers cannot be started for the same login account by choosing different
|
|
579
|
-
state roots.
|
|
580
|
-
|
|
581
|
-
pre-existing legacy lock blocks startup as `GATEWAY_INSTANCE_IN_USE` and is
|
|
582
|
-
preserved; the operator may remove that exact stale lock only after confirming
|
|
583
|
-
no prototype process remains. Missing, unsafe, or unrecognized legacy roots
|
|
584
|
-
are not created, imported, or mutated.
|
|
633
|
+
state roots. It is the only instance lock Embassy takes: the pre-rename
|
|
634
|
+
prototype state root is no longer read, locked, or mutated.
|
|
585
635
|
|
|
586
636
|
It emits one normalized ready line, publishes the private dashboard, and
|
|
587
637
|
holds the process until `SIGINT` or `SIGTERM`, when exact-owned resources are
|
|
588
|
-
closed. Startup
|
|
589
|
-
controller-owned UDS listeners, but does not discover a Claude peer, write a
|
|
638
|
+
closed. Startup automatically validates the exact-pinned local Claude and Codex
|
|
639
|
+
runtimes and binds controller-owned UDS listeners, but does not discover a Claude peer, write a
|
|
590
640
|
provider socket, start a model turn, or contact a remote host. Its ready result
|
|
591
641
|
reports local host `this-mac`, dashboard filename `gateway-dashboard.html`, and
|
|
592
642
|
`codexMode: "native_messaging"` without exposing paths.
|
|
@@ -599,6 +649,27 @@ Same-UID socket access is a local containment boundary, not proof of a trusted
|
|
|
599
649
|
agent process. Every mutation additionally checks route ownership, exact
|
|
600
650
|
thread/session generation, source alias, bounds, and conversation state.
|
|
601
651
|
|
|
652
|
+
### Progress watches
|
|
653
|
+
|
|
654
|
+
`send-to-claude`, `send-to-codex`, and `reply` each accept an opt-in `--track`
|
|
655
|
+
flag that opens one progress watch over the resulting conversation, plus an
|
|
656
|
+
optional `--idle-minutes <n>` that sets how long the watched thread may sit idle
|
|
657
|
+
before the watch reports a stall. `n` is an integer from 1 through 1440 and
|
|
658
|
+
defaults to 5; supplying it without `--track` is an argument error. A body with
|
|
659
|
+
an exact leading `TRACK:` prefix opens the same watch at the default idle window
|
|
660
|
+
without the flag.
|
|
661
|
+
|
|
662
|
+
`untrack --conversation conv_<token>` closes an active watch explicitly, and a
|
|
663
|
+
body with an exact leading `DONE:` prefix closes it as completed; one message
|
|
664
|
+
may not both open and complete a watch (`PROGRESS_WATCH_SIGNAL_CONFLICT`). The
|
|
665
|
+
global `EMBASSY_TRACKING_ENABLED` switch is on by default and exact `0` disables
|
|
666
|
+
the surface; `EMBASSY_MAX_WATCHES` bounds concurrent watches at 32 by default
|
|
667
|
+
(hard cap 256).
|
|
668
|
+
|
|
669
|
+
A watch is independent evidence about thread activity, not delivery evidence. It
|
|
670
|
+
may outlive an opener whose own delivery expired, so check the opener's
|
|
671
|
+
`delivery-status` separately before assuming the assignment text arrived.
|
|
672
|
+
|
|
602
673
|
## Codex connectors and remote hosts
|
|
603
674
|
|
|
604
675
|
In the target multi-host design, each allowlisted execution host has a separate
|
|
@@ -636,11 +707,12 @@ Missing, malformed, or nonempty turns fail closed and are never emitted or
|
|
|
636
707
|
persisted. The capability does not add an experimental client method or change
|
|
637
708
|
the closed RPC allowlist.
|
|
638
709
|
|
|
639
|
-
|
|
640
|
-
may initialize, list, resume, and expose
|
|
641
|
-
|
|
642
|
-
unavailable. No Claude-initiated turn
|
|
643
|
-
|
|
710
|
+
Automatic generation validation and controller write activation are distinct
|
|
711
|
+
gates. A replacement connector may initialize, list, resume, and expose
|
|
712
|
+
normalized monitor state after its exact version and required schemas validate
|
|
713
|
+
while still reporting its write gate as unavailable. No Claude-initiated turn
|
|
714
|
+
can start until the controller activates that exact endpoint generation and
|
|
715
|
+
explicit route ownership is established.
|
|
644
716
|
|
|
645
717
|
Registration resumes the exact task and establishes reachability. Embassy does
|
|
646
718
|
not read or retain reported working-directory or policy fields. Before
|
|
@@ -720,8 +792,9 @@ The one Desktop restart needed for the local shared-App-Server feasibility
|
|
|
720
792
|
test has already been completed. Building, running synthetic tests, starting
|
|
721
793
|
the gateway, rendering the dashboard, and a future Claude peer-socket test do
|
|
722
794
|
not themselves require another Desktop restart. A provider or Desktop upgrade
|
|
723
|
-
|
|
724
|
-
separately announced controlled
|
|
795
|
+
outside this release's exact pins requires an updated, reviewed Embassy
|
|
796
|
+
adapter and, if its attachment mode changes, a separately announced controlled
|
|
797
|
+
restart.
|
|
725
798
|
|
|
726
799
|
## Dashboard
|
|
727
800
|
|
|
@@ -738,50 +811,62 @@ A static page is a point-in-time snapshot and never refreshes itself: it emits
|
|
|
738
811
|
no meta refresh and the page tells the operator to re-run
|
|
739
812
|
`embassy refresh-dashboard` and reload, or to use `embassy dashboard --live`.
|
|
740
813
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
- aggregate gateway
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
-
|
|
749
|
-
|
|
814
|
+
Each page assembles seven sections:
|
|
815
|
+
|
|
816
|
+
- **Exchange** — aggregate gateway health plus the pair graph: every explicit
|
|
817
|
+
Claude↔Codex edge and its per-edge counters.
|
|
818
|
+
- **Attention** — allowlisted alerts such as stale route, protocol mismatch,
|
|
819
|
+
queue full, or ambiguous delivery.
|
|
820
|
+
- **Transit** — queued-message depth and bytes in flight.
|
|
821
|
+
- **Progress supervision** — active progress watches and their state.
|
|
822
|
+
- **Operator activity** — the broker's bounded public journal of accepted
|
|
823
|
+
operator actions.
|
|
824
|
+
- **Sessions** — available/selected Claude aliases, registered Codex aliases,
|
|
825
|
+
provider, host, compatibility, state, and queue depth.
|
|
826
|
+
- **Diagnostics** — compatibility attestations per provider, per-host connector
|
|
827
|
+
health and protocol, deadline-pressure buckets, accounting totals, and the
|
|
828
|
+
omission counters below. Normalized message direction and delivery state,
|
|
829
|
+
timestamp, latency, byte count, and a short opaque message-ID suffix appear
|
|
830
|
+
with the delivery rows.
|
|
750
831
|
|
|
751
832
|
It never shows message content, prompts, replies, transcripts, titles, working
|
|
752
833
|
directories, native IDs, PIDs, socket paths, endpoint paths, tool data, raw
|
|
753
|
-
events, stderr, credentials, or configuration contents
|
|
754
|
-
|
|
755
|
-
a
|
|
756
|
-
|
|
834
|
+
events, stderr, credentials, or configuration contents — retained bodies reach
|
|
835
|
+
only the live companion, never these files. This is a controller-owned UI
|
|
836
|
+
artifact, not a shared task file. The public snapshot has a 240 KiB projection
|
|
837
|
+
budget and reports explicit omission counters whenever bounded rows are
|
|
838
|
+
truncated: connectors, available peers, routes, pairs, progress watches,
|
|
839
|
+
upstream and projected progress-watch events, upstream message events, message
|
|
840
|
+
groups, message events, upstream alerts, attention items, and upstream and
|
|
841
|
+
projected activity events.
|
|
757
842
|
|
|
758
843
|
### Live dashboard companion
|
|
759
844
|
|
|
760
|
-
`embassy dashboard --live` is the opt-in browser view of
|
|
845
|
+
`embassy dashboard --live` is the opt-in browser view of broker state,
|
|
846
|
+
including bounded retained bodies in delivery detail; the static dashboard's
|
|
847
|
+
public projection remains metadata-only.
|
|
761
848
|
It is a separate foreground process, not a mode of `embassy serve`: it holds no
|
|
762
849
|
provider capability, owns no registry record, and reaches the broker over the
|
|
763
850
|
same private control socket every other client command uses, so it reports the
|
|
764
851
|
gateway as unavailable when nothing is serving.
|
|
765
852
|
|
|
766
|
-
- **Bind.** One `http.createServer` listener
|
|
767
|
-
port
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
path-scoped `HttpOnly` `SameSite=Strict` session cookie; the fragment never
|
|
776
|
-
reaches the server as part of a request line.
|
|
853
|
+
- **Bind.** One `http.createServer` listener binds exact `127.0.0.1` on stable
|
|
854
|
+
port `41961` by default, or the integer from the per-invocation `--port <n>`
|
|
855
|
+
option in the closed range 1024 through 65535. The direct root URL is
|
|
856
|
+
`http://127.0.0.1:<port>/`. A collision fails with
|
|
857
|
+
`LIVE_DASHBOARD_PORT_IN_USE` and directs the operator to `--port`; there is no
|
|
858
|
+
ephemeral-port fallback. No other interface is bound.
|
|
859
|
+
- **Access.** The root URL is usable concurrently from multiple windows, tabs,
|
|
860
|
+
and browsers. There is no capability token, URL fragment, cookie, browser
|
|
861
|
+
session, random instance path, or bootstrap file.
|
|
777
862
|
- **Request checks.** The exact Host header is validated on every request.
|
|
778
|
-
Navigation GETs may omit Origin
|
|
779
|
-
|
|
780
|
-
|
|
863
|
+
Navigation GETs may omit Origin; every POST requires the exact Origin plus
|
|
864
|
+
`X-Embassy-Request: 1`. `OPTIONS` is not accepted, there are no CORS headers,
|
|
865
|
+
and cross-origin reads are unavailable.
|
|
781
866
|
- **Projection and actions.** The companion observes through
|
|
782
867
|
`observe_snapshot`. Its only mutations are exact two-endpoint `pair`,
|
|
783
868
|
`unpair`, `refresh_dashboard`, and `remove_stale_codex_registration`
|
|
784
|
-
control calls behind one closed
|
|
869
|
+
control calls behind one closed `/action` route. The recovery
|
|
785
870
|
action carries only a canonical public `codex-*` alias and is accepted only
|
|
786
871
|
after the broker revalidates that the route is stale and its endpoint
|
|
787
872
|
generation is dead; native task and generation IDs never enter the browser
|
|
@@ -796,9 +881,11 @@ gateway as unavailable when nothing is serving.
|
|
|
796
881
|
fresh observation. An observation may
|
|
797
882
|
settle already-due lifecycle deliveries before projecting, which is a broker
|
|
798
883
|
timer effect, not additional browser authority.
|
|
799
|
-
- **Containment.**
|
|
800
|
-
|
|
801
|
-
|
|
884
|
+
- **Containment.** The loopback server deliberately performs no local-process
|
|
885
|
+
or UID authentication. It assumes a trusted single-user machine: any local
|
|
886
|
+
software that can reach or spoof loopback can read the live view and invoke
|
|
887
|
+
the bounded actions. Host, Origin, and sentinel checks constrain ambient
|
|
888
|
+
browser-origin requests; they do not authenticate local software.
|
|
802
889
|
|
|
803
890
|
`--lang en|zh-CN` selects the companion's display language. It has no effect on
|
|
804
891
|
the static pair, which is always written in both languages.
|
|
@@ -814,9 +901,12 @@ The private store may retain:
|
|
|
814
901
|
accounting and dashboard projection;
|
|
815
902
|
- timestamps, counters, dedupe/rate-limit records, and safe error codes.
|
|
816
903
|
|
|
817
|
-
It
|
|
818
|
-
|
|
819
|
-
|
|
904
|
+
It also retains message bodies under bounded caps — the queued body of every
|
|
905
|
+
undelivered message and the recent delivery ledger's retained bodies, evicted
|
|
906
|
+
oldest-first against a 1 MiB budget by default. It must never retain provider
|
|
907
|
+
output, tool input/output, raw App Server or Claude frames, stderr, histories,
|
|
908
|
+
credentials, Claude registry payloads, or callback/socket paths. The public
|
|
909
|
+
snapshot is a
|
|
820
910
|
strict projection that also removes private route handles and endpoint
|
|
821
911
|
generations. The state directory is mode 0700 and binding state is mode 0600;
|
|
822
912
|
provider-native identifiers never enter normalized events, public snapshots,
|
|
@@ -825,14 +915,15 @@ every restored route begins stale and unusable. An authorized discovery may
|
|
|
825
915
|
reactivate only the byte-identical durable Claude UUID after the current
|
|
826
916
|
provider endpoint, workspace, complete unique discovery, and ownership lease
|
|
827
917
|
all revalidate. The public `selected` bit flips only after that atomic private
|
|
828
|
-
rebind succeeds.
|
|
829
|
-
reply capability is restored, and no
|
|
830
|
-
reconstructed.
|
|
918
|
+
rebind succeeds. Queued bodies are restored and re-armed for dispatch; no
|
|
919
|
+
callback, receipt handle, conversation, or reply capability is restored, and no
|
|
920
|
+
delivery token or status tracker is reconstructed.
|
|
831
921
|
|
|
832
922
|
The delivery-token mapping, queryable status tracker, native receipt handle,
|
|
833
923
|
and one-stall-notice state are always memory-only. Durable delivery metadata
|
|
834
|
-
does not contain enough information to reconstruct any of those capabilities
|
|
835
|
-
|
|
924
|
+
does not contain enough information to reconstruct any of those capabilities.
|
|
925
|
+
A restored body is re-sent exactly once and only into its own exact
|
|
926
|
+
re-observed route; it is never replayed into a reconstructed capability.
|
|
836
927
|
|
|
837
928
|
## Minimum filesystem and process access
|
|
838
929
|
|
|
@@ -858,20 +949,20 @@ and fake App Server transports.
|
|
|
858
949
|
|
|
859
950
|
### Exact default roots on macOS
|
|
860
951
|
|
|
861
|
-
The
|
|
952
|
+
The automatic exact-version validator derives these paths from the current OS user's
|
|
862
953
|
verified home; it does not scan the home directory. These are the reviewed
|
|
863
954
|
boundaries exercised by the live gateway; routine tests substitute synthetic
|
|
864
955
|
paths, peers, and transports:
|
|
865
956
|
|
|
866
957
|
| Path/capability | Minimum purpose |
|
|
867
958
|
| --- | --- |
|
|
868
|
-
| `~/.local/bin/claude` and derived expected target `~/.local/share/claude/versions/2.1.226` | Stat the owned launcher/path components and read/execute only the resolved pinned target for bounded `--version`; live launcher
|
|
959
|
+
| `~/.local/bin/claude` (or the absolute `EMBASSY_CLAUDE_BIN` override) and derived expected target `~/.local/share/claude/versions/2.1.226` | Stat the owned launcher/path components and read/execute only the resolved pinned target for bounded `--version`; `PATH` and interactive shell profiles are never searched; live launcher validation succeeded |
|
|
869
960
|
| `~/.claude/sessions` | Read/enumerate only live registry JSON during the separately authorized passive-discovery gate |
|
|
870
961
|
| `/tmp/cc-socks` | At foreground startup, validate the private directory and create/remove only `/tmp/cc-socks/<gateway-pid>.sock` after inode/generation checks; search/stat genuine peers at passive discovery and connect one validated target only at the separately authorized send gate |
|
|
871
962
|
| `~/.local/state/agent-embassy/.agent-embassy-state` | Validate or establish the exact ownership marker before creating the fixed host lease; an existing non-empty unmarked root is rejected without mutation |
|
|
872
963
|
| `/usr/bin/lockf` and `/bin/cat` | Hold one fixed, non-waiting macOS advisory lease for the foreground controller; the helper receives no shell text, provider data, or model-supplied argument |
|
|
964
|
+
| `/usr/bin/open` | Executed only by the opt-in `embassy dashboard --live` companion, to open the loopback dashboard URL in the operator's browser; no shell, a scrubbed fixed environment, and a bounded timeout and output cap |
|
|
873
965
|
| `~/.local/state/agent-embassy/.gateway-host.lock` | Fixed per-login kernel-held lease acquired before provider setup; it remains here even when `EMBASSY_STATE_DIR` is overridden. Its bounded PID/token record is exact-cleanup metadata, not a path-only stale-lock authority; a crash releases the kernel lock and the next foreground process may acquire the existing file |
|
|
874
|
-
| `~/.local/state/claude-agent-bridge/gateway/.claude-codex-gateway-state` and `.gateway-controller.lock` | For one release, bounded-read the exact legacy ownership marker and lock record; create and hold the lock only when absent, preserve any pre-existing lock, and read no other legacy state or message data |
|
|
875
966
|
| `~/.local/state/agent-embassy` (or explicit `EMBASSY_STATE_DIR`) | Default controller-owned store, control UDS, state lock, and static dashboard; an explicit absolute configuration may replace only these state surfaces |
|
|
876
967
|
| `~/.codex/packages/standalone` and `~/.codex/app-server-control/app-server-control.sock` | Resolve the pinned managed Codex binary and attach to the already-running private local App Server; never bootstrap or unlink it |
|
|
877
968
|
|
|
@@ -922,9 +1013,14 @@ the preferred least-context setup, but it is not mandatory.
|
|
|
922
1013
|
fail-closed. Only exact retry is permitted until the old route is confirmed
|
|
923
1014
|
unregistered and the controller is restarted.
|
|
924
1015
|
- No ambiguous mutation is retried automatically.
|
|
925
|
-
-
|
|
926
|
-
|
|
927
|
-
|
|
1016
|
+
- A queued body survives process loss under bounded retention and is re-sent
|
|
1017
|
+
exactly once after its exact route is re-observed. A message in flight when
|
|
1018
|
+
the process was lost settles `ambiguous` with `CONTROLLER_RESTARTED`; a
|
|
1019
|
+
message whose target authority was transient, or whose target route no longer
|
|
1020
|
+
exists, settles `abandoned` with the same code.
|
|
1021
|
+
- A provider or Desktop update outside the release's exact reviewed pins fails
|
|
1022
|
+
closed; retained state never admits an unreviewed version or activates an
|
|
1023
|
+
unvalidated replacement endpoint generation.
|
|
928
1024
|
|
|
929
1025
|
## Validation boundary
|
|
930
1026
|
|