agent-embassy 3.1.0 → 4.0.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 +21 -0
- package/CONTRIBUTING.md +92 -202
- package/README.md +157 -155
- package/SECURITY.md +191 -348
- package/dist/src/gateway/broker-check.d.ts +26 -0
- package/dist/src/gateway/broker-check.js +89 -0
- package/dist/src/gateway/broker-check.js.map +1 -0
- package/dist/src/gateway/broker-control.d.ts +72 -0
- package/dist/src/gateway/broker-control.js +164 -0
- package/dist/src/gateway/broker-control.js.map +1 -0
- package/dist/src/gateway/broker.d.ts +117 -0
- package/dist/src/gateway/broker.js +186 -0
- package/dist/src/gateway/broker.js.map +1 -0
- package/dist/src/gateway/claude-peer.d.ts +1 -124
- package/dist/src/gateway/claude-peer.js +61 -1052
- package/dist/src/gateway/claude-peer.js.map +1 -1
- package/dist/src/gateway/codex-stateless-transport.d.ts +0 -12
- package/dist/src/gateway/codex-stateless-transport.js +8 -142
- package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
- package/dist/src/gateway/config.d.ts +2 -6
- package/dist/src/gateway/config.js +17 -27
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/coordinator.d.ts +57 -0
- package/dist/src/gateway/coordinator.js +217 -0
- package/dist/src/gateway/coordinator.js.map +1 -0
- package/dist/src/gateway/core-cli.d.ts +15 -0
- package/dist/src/gateway/core-cli.js +282 -0
- package/dist/src/gateway/core-cli.js.map +1 -0
- package/dist/src/gateway/core-service-command.d.ts +16 -0
- package/dist/src/gateway/core-service-command.js +71 -0
- package/dist/src/gateway/core-service-command.js.map +1 -0
- package/dist/src/gateway/endpoint-directory.d.ts +33 -0
- package/dist/src/gateway/endpoint-directory.js +223 -0
- package/dist/src/gateway/endpoint-directory.js.map +1 -0
- package/dist/src/gateway/federation.d.ts +89 -0
- package/dist/src/gateway/federation.js +632 -0
- package/dist/src/gateway/federation.js.map +1 -0
- package/dist/src/gateway/ledger-codec.d.ts +3 -0
- package/dist/src/gateway/ledger-codec.js +159 -0
- package/dist/src/gateway/ledger-codec.js.map +1 -0
- package/dist/src/gateway/ledger.d.ts +138 -0
- package/dist/src/gateway/ledger.js +319 -0
- package/dist/src/gateway/ledger.js.map +1 -0
- package/dist/src/gateway/local-control.d.ts +23 -0
- package/dist/src/gateway/local-control.js +489 -0
- package/dist/src/gateway/local-control.js.map +1 -0
- package/dist/src/gateway/native-destinations.d.ts +34 -0
- package/dist/src/gateway/native-destinations.js +272 -0
- package/dist/src/gateway/native-destinations.js.map +1 -0
- package/dist/src/gateway/owned-state.d.ts +57 -0
- package/dist/src/gateway/owned-state.js +398 -0
- package/dist/src/gateway/owned-state.js.map +1 -0
- package/dist/src/gateway/provenance-envelope.d.ts +3 -3
- package/dist/src/gateway/provenance-envelope.js +3 -23
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/runtime.d.ts +41 -0
- package/dist/src/gateway/runtime.js +175 -0
- package/dist/src/gateway/runtime.js.map +1 -0
- package/docs/CONFIGURATION.md +178 -266
- package/docs/DELIVERY.md +133 -82
- package/docs/GATEWAY-ARCHITECTURE.md +276 -949
- package/package.json +5 -5
- package/skills/embassy-peer/SKILL.md +38 -196
- package/skills/embassy-peer/agents/openai.yaml +2 -2
- package/dist/src/gateway/claude-helper-protocol.d.ts +0 -117
- package/dist/src/gateway/claude-helper-protocol.js +0 -122
- package/dist/src/gateway/claude-helper-protocol.js.map +0 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +0 -87
- package/dist/src/gateway/claude-helper-supervisor.js +0 -374
- package/dist/src/gateway/claude-helper-supervisor.js.map +0 -1
- package/dist/src/gateway/claude-helper.d.ts +0 -1
- package/dist/src/gateway/claude-helper.js +0 -252
- package/dist/src/gateway/claude-helper.js.map +0 -1
- package/dist/src/gateway/cli.d.ts +0 -56
- package/dist/src/gateway/cli.js +0 -1532
- package/dist/src/gateway/cli.js.map +0 -1
- package/dist/src/gateway/codex-socket-holder.d.ts +0 -26
- package/dist/src/gateway/codex-socket-holder.js +0 -76
- package/dist/src/gateway/codex-socket-holder.js.map +0 -1
- package/dist/src/gateway/control.d.ts +0 -279
- package/dist/src/gateway/control.js +0 -933
- package/dist/src/gateway/control.js.map +0 -1
- package/dist/src/gateway/peer-client.d.ts +0 -58
- package/dist/src/gateway/peer-client.js +0 -217
- package/dist/src/gateway/peer-client.js.map +0 -1
- package/dist/src/gateway/peer-mailbox.d.ts +0 -78
- package/dist/src/gateway/peer-mailbox.js +0 -168
- package/dist/src/gateway/peer-mailbox.js.map +0 -1
- package/dist/src/gateway/peer-protocol.d.ts +0 -110
- package/dist/src/gateway/peer-protocol.js +0 -79
- package/dist/src/gateway/peer-protocol.js.map +0 -1
- package/dist/src/gateway/peer-stdio.d.ts +0 -23
- package/dist/src/gateway/peer-stdio.js +0 -100
- package/dist/src/gateway/peer-stdio.js.map +0 -1
- package/dist/src/gateway/providers.d.ts +0 -164
- package/dist/src/gateway/providers.js +0 -975
- package/dist/src/gateway/providers.js.map +0 -1
- package/dist/src/gateway/server.d.ts +0 -46
- package/dist/src/gateway/server.js +0 -216
- package/dist/src/gateway/server.js.map +0 -1
- package/dist/src/gateway/service.d.ts +0 -371
- package/dist/src/gateway/service.js +0 -2335
- package/dist/src/gateway/service.js.map +0 -1
- package/dist/src/gateway/status-view.d.ts +0 -119
- package/dist/src/gateway/status-view.js +0 -484
- package/dist/src/gateway/status-view.js.map +0 -1
- package/dist/src/gateway/store.d.ts +0 -188
- package/dist/src/gateway/store.js +0 -2360
- package/dist/src/gateway/store.js.map +0 -1
- package/dist/src/gateway/types.d.ts +0 -541
- package/dist/src/gateway/types.js +0 -332
- package/dist/src/gateway/types.js.map +0 -1
package/SECURITY.md
CHANGED
|
@@ -2,365 +2,208 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported versions
|
|
4
4
|
|
|
5
|
-
Security fixes are
|
|
6
|
-
|
|
5
|
+
Security fixes are provided for the current release line. Version 4 uses a
|
|
6
|
+
reset-only state boundary and does not run compatibility code for older private
|
|
7
|
+
state or control protocols.
|
|
7
8
|
|
|
8
9
|
## Reporting a vulnerability
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Reports should contain the smallest synthetic reproduction possible. Do not
|
|
14
|
-
include credentials, OAuth material, Keychain data, message bodies, raw model
|
|
15
|
-
output, provider histories, local Embassy state, socket addresses, native
|
|
16
|
-
session or thread identifiers, or unredacted personal paths.
|
|
11
|
+
Open a private security report with the repository owner. Do not put message
|
|
12
|
+
bodies, credentials, native identifiers, socket paths, provider histories, or
|
|
13
|
+
raw diagnostic output in a public issue.
|
|
17
14
|
|
|
18
15
|
## Deployment boundary
|
|
19
16
|
|
|
20
|
-
Embassy is personal
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
recorded identity stays as written when the machine is later renamed. Run
|
|
26
|
-
every node only under an OS account that is yours alone and where you trust
|
|
27
|
-
every process already running as that user. Do not expose Embassy sockets or
|
|
28
|
-
state on a network, host it as a service, or use it to share a provider
|
|
29
|
-
subscription between users.
|
|
30
|
-
|
|
31
|
-
The broker is local; the agents are not. Embassy does not call a provider API,
|
|
32
|
-
but a delivered body becomes model input in the receiving product and may be
|
|
33
|
-
sent to and retained by Anthropic or OpenAI under that product's normal terms
|
|
34
|
-
and settings.
|
|
35
|
-
|
|
36
|
-
## Trust model
|
|
37
|
-
|
|
38
|
-
Embassy provides same-UID containment and route attribution, not authentication
|
|
39
|
-
against other processes running as the same OS user.
|
|
40
|
-
|
|
41
|
-
- A Codex route is attributed to the exact inherited `CODEX_THREAD_ID` of the
|
|
42
|
-
task that self-registers it. App Server attachment and endpoint generations
|
|
43
|
-
are current transport facts, never durable route authority.
|
|
44
|
-
- A Claude route is attributed to a validated live peer generation and native
|
|
45
|
-
session UUID. An inherited `CLAUDE_CODE_MESSAGING_SOCKET` is a transient
|
|
46
|
-
reply capability, not a credential.
|
|
47
|
-
- Aliases are labels. They do not grant authority and are re-resolved against
|
|
48
|
-
the exact private route binding before delivery.
|
|
49
|
-
- Immediately before provider delivery, Embassy places the body inside one
|
|
50
|
-
broker-owned `cross-session-message` textual frame. Its sender attribution
|
|
51
|
-
and first-child reply hint come from validated broker metadata, not from the
|
|
52
|
-
message body. This is a provenance boundary for the receiving model, not a
|
|
53
|
-
cryptographic signature or authentication against same-UID code.
|
|
54
|
-
- Any process already running as the same OS user may be able to present local
|
|
55
|
-
environment or socket capabilities. Embassy is not a sandbox for untrusted
|
|
56
|
-
same-user code.
|
|
17
|
+
Embassy is a personal, same-user gateway for user-owned Macs. The broker is a
|
|
18
|
+
foreground process or a per-user launchd agent. It has one private Unix-domain
|
|
19
|
+
control socket and no TCP or HTTP listener. Cross-machine delivery is an
|
|
20
|
+
outbound `/usr/bin/ssh` process to another explicitly configured Embassy
|
|
21
|
+
gateway.
|
|
57
22
|
|
|
58
|
-
|
|
23
|
+
The design assumes the login account and machines are trusted. It does not turn
|
|
24
|
+
one Unix user into multiple security principals, sandbox an untrusted agent, or
|
|
25
|
+
provide hostile multi-user isolation.
|
|
59
26
|
|
|
60
|
-
|
|
61
|
-
from every process this user runs.” The boundary below governs implementation,
|
|
62
|
-
review, and audit work.
|
|
27
|
+
## What Embassy defends, and what it deliberately does not
|
|
63
28
|
|
|
64
29
|
### What Embassy defends
|
|
65
30
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
31
|
+
Embassy defends the boundary between model-authored content and authority to
|
|
32
|
+
address or write to a live session. A body, alias, provider response, catalog
|
|
33
|
+
row, or persisted field cannot grant that authority by itself. Authority comes
|
|
34
|
+
from the current same-user process boundary, an exact endpoint identity,
|
|
35
|
+
owned private state, and fresh per-operation transport attestation.
|
|
36
|
+
|
|
37
|
+
Specifically, Embassy defends:
|
|
38
|
+
|
|
39
|
+
- exact Claude session and Codex task identity across alias changes;
|
|
40
|
+
- refusal rather than guessed routing when a name is absent or ambiguous;
|
|
41
|
+
- one bounded, private state document with atomic replacement and strict schema
|
|
42
|
+
validation;
|
|
43
|
+
- per-operation ownership, path, protocol, and artifact checks before every
|
|
44
|
+
native write;
|
|
45
|
+
- bounded bodies, queues, batches, deadlines, rates, in-flight operations, and
|
|
46
|
+
retained evidence;
|
|
47
|
+
- a durable `queued` → `reserved` → `armed` → `accepted` → `terminal` phase law
|
|
48
|
+
that never replays an uncertain write;
|
|
49
|
+
- structural provenance framing and identity-bound replies;
|
|
50
|
+
- authenticated, direct SSH handoff with a destination-owned queue and no
|
|
51
|
+
post-commit retry;
|
|
52
|
+
- redaction of native IDs, addresses, credentials, histories, raw frames, and
|
|
53
|
+
bodies from public status and errors;
|
|
54
|
+
- retirement and replacement that settle incident work without moving it to a
|
|
55
|
+
different endpoint.
|
|
56
|
+
|
|
57
|
+
Every proposed audit check or hardening rule must enforce one of these stated
|
|
58
|
+
boundaries. A new boundary requires an explicit product decision; it must not
|
|
59
|
+
arrive disguised as a regression test.
|
|
94
60
|
|
|
95
61
|
### What Embassy deliberately does not defend
|
|
96
62
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
`turn/interrupt`.
|
|
245
|
-
- The App Server 0.147.0 initialization this adapter targets enables `experimentalApi: true`
|
|
246
|
-
solely for `thread/resume.excludeTurns: true`. It adds no general
|
|
247
|
-
experimental method or authority. Missing, malformed, or nonempty returned
|
|
248
|
-
turns fail closed and are never retained.
|
|
249
|
-
- Queues, frames, bodies, callbacks, deadlines, deduplication,
|
|
250
|
-
rate limits, and transient conversations are bounded. Ambiguous writes are
|
|
251
|
-
never retried automatically.
|
|
252
|
-
- A peer catalog contains only bounded, body-free local metadata. It never
|
|
253
|
-
exports imported rows, message or conversation tokens, native identifiers,
|
|
254
|
-
provider frames, sockets, paths, credentials, or raw diagnostics. Each
|
|
255
|
-
destination broker owns its durable queue; loss after a federated write is
|
|
256
|
-
UNKNOWN and is never replayed.
|
|
257
|
-
- Raw-body classification and accounting happen before framing. In the
|
|
258
|
-
untrusted body only, Embassy case-insensitively neutralizes boundary-shaped
|
|
259
|
-
opening or closing copies of its reserved framing tags before composing the
|
|
260
|
-
real outer frame. Framing or size failure occurs before provider write and is
|
|
261
|
-
never an ambiguous write.
|
|
262
|
-
- Embassy creates no network listener at all. Everything enumerated above
|
|
263
|
-
concerns `embassy serve`.
|
|
264
|
-
|
|
265
|
-
## Filesystem boundary
|
|
266
|
-
|
|
267
|
-
Controller-owned state is a dedicated mode-0700 directory. Its files and
|
|
268
|
-
control socket are mode 0600 and validated against replacement, symlinks, and
|
|
269
|
-
unexpected ownership or permissions. Those files include message content:
|
|
270
|
-
the durable queue and the bounded recent-delivery ledger both retain message
|
|
271
|
-
bodies, so the state file holds mail at rest and not metadata alone. Anything
|
|
272
|
-
already running as the same OS user can read it.
|
|
273
|
-
|
|
274
|
-
The host-wide singleton has one fixed surface under the verified login home:
|
|
275
|
-
the private mode-0700 `~/.local/state/agent-embassy` directory and its mode-0600
|
|
276
|
-
`.gateway-host.lock`. Neither `EMBASSY_STATE_DIR` nor `XDG_STATE_HOME` relocates
|
|
277
|
-
that lease. Embassy executes the exact `/usr/bin/lockf` and `/bin/cat` helpers,
|
|
278
|
-
without a shell, to hold the kernel lease for the foreground process lifetime.
|
|
279
|
-
The lock file is retained and reused across restarts; process exit releases the
|
|
280
|
-
kernel lock.
|
|
281
|
-
|
|
282
|
-
Embassy's provider-facing access is intentionally enumerable:
|
|
283
|
-
|
|
284
|
-
- derive the fixed Claude registry and callback roots from the verified current
|
|
285
|
-
OS user, without reading a Claude launcher or configuration file;
|
|
286
|
-
- read the live Claude session registry and validate only the registry record,
|
|
287
|
-
peer socket, PID, workspace, state-root, and generation evidence used by the
|
|
288
|
-
current operation;
|
|
289
|
-
- fork advertisement helper processes for local non-Claude routes, each owning one
|
|
290
|
-
callback socket and one registry record (`codex-*` or `peer-*`); the tracked-count
|
|
291
|
-
admission cap is `maxRoutes` (default and maximum 128),
|
|
292
|
-
including pending creations in that cap;
|
|
293
|
-
- resolve the managed Codex installation and open one attested local App Server
|
|
294
|
-
connection per operation; and
|
|
295
|
-
- inspect canonical filesystem metadata needed to validate provider-advertised
|
|
296
|
-
endpoints and generations.
|
|
297
|
-
|
|
298
|
-
The Claude-owned external sessions registry root must be owned by the current
|
|
299
|
-
UID with exact mode 0700 before Embassy enumerates it; failure quarantines and
|
|
300
|
-
write-fences only Claude, including when that registry root is absent. Within
|
|
301
|
-
an admitted root, individual registry records
|
|
302
|
-
and peer sockets retain their bounded schema, file/socket type, PID/path and
|
|
303
|
-
allowed-root correlation, accessibility, liveness, and generation checks.
|
|
304
|
-
Embassy invents no additional owner or mode rule for those individual
|
|
305
|
-
provider-owned artifacts.
|
|
306
|
-
|
|
307
|
-
Embassy does not need or intentionally read credentials, Keychain items,
|
|
308
|
-
Claude project history, Codex or Claude transcripts, shell history, or provider
|
|
309
|
-
configuration contents. Report a bug if any normal code path attempts to do so.
|
|
310
|
-
|
|
311
|
-
## Persistence and disclosure
|
|
312
|
-
|
|
313
|
-
Raw provider frames, tool data, stderr, callback addresses, and socket paths
|
|
314
|
-
remain memory-only and are discarded on restart. Message bodies are the
|
|
315
|
-
exception: queued and recently delivered bodies are retained under bounded caps
|
|
316
|
-
in the mode-0600 state file. A queued or reserved message may resume once after
|
|
317
|
-
a broker restart against its still-exact logical route. An
|
|
318
|
-
armed or accepted message at crash settles ambiguous or unconfirmed and is
|
|
319
|
-
never replayed.
|
|
320
|
-
|
|
321
|
-
For a shell peer, durable route ownership stores only
|
|
322
|
-
`peer:<sha256(uid NUL alias NUL token)>`; the raw peer token and private mailbox
|
|
323
|
-
receipts never enter state, logs, snapshots, or routed frames.
|
|
324
|
-
Pending waiters, acknowledgements, and the bounded exact-duplicate receipt
|
|
325
|
-
tombstone are memory-only. A restart therefore cannot falsely confirm a
|
|
326
|
-
stdout write whose acknowledgement was not observed.
|
|
327
|
-
|
|
328
|
-
The full `conv_` token exposed to a CLI initiator or routed recipient travels
|
|
329
|
-
only inside the accepted CLI result or transient provider payload. It is never
|
|
330
|
-
persisted, journaled, logged, placed in a receipt, or projected through public
|
|
331
|
-
events or snapshots; public metadata may retain only an existing
|
|
332
|
-
non-reconstructable suffix. Broker-owned marker fields
|
|
333
|
-
introduce no socket paths, Codex thread IDs, Claude session UUIDs, endpoint
|
|
334
|
-
generations, or private route handles. The untrusted body remains opaque text
|
|
335
|
-
and may itself contain sender-provided strings.
|
|
336
|
-
|
|
337
|
-
The closed private binding store may retain the exact Codex thread ID and Claude
|
|
338
|
-
session UUID required for logical ownership. Native IDs are
|
|
339
|
-
forbidden from public snapshots, normalized events, aliases,
|
|
340
|
-
logs, errors, and CLI output. A Claude UUID may enter only as a user-supplied
|
|
341
|
-
explicit CLI selector (`embassy send --to <uuid>`); Embassy never discovers or
|
|
342
|
-
prints it publicly.
|
|
343
|
-
|
|
344
|
-
## Validation boundary
|
|
345
|
-
|
|
346
|
-
Routine tests use temporary directories, fake peers, and fake App Server
|
|
347
|
-
transports. They do not inspect live provider state or contact a model.
|
|
348
|
-
|
|
349
|
-
Broker/provider startup owns bounded validation of configured installations and
|
|
350
|
-
exact OS boundaries. Unsafe Embassy-owned or executed artifacts, callback,
|
|
351
|
-
control, or state paths remain startup-fatal; unsafe UID or mode evidence on
|
|
352
|
-
Claude's external sessions registry root quarantines only that provider.
|
|
353
|
-
Runtime derives no authority from version metadata. It reports best-effort connector health, observation
|
|
354
|
-
freshness, and last safe codes while strict record, frame, response, identity,
|
|
355
|
-
current used-artifact generation, correlation, and deadline checks decide each
|
|
356
|
-
operation. Claude registry parsing remains strict for every required and
|
|
357
|
-
consumed field while ignoring unknown top-level fields; bounded rejected-record
|
|
358
|
-
counts and an observed-empty registry are surfaced instead of hidden. Each
|
|
359
|
-
Codex delivery independently attests, connects, initializes, and resumes the
|
|
360
|
-
exact registered task before its final write authorization. No observation
|
|
361
|
-
traffic routes a user message or starts a model turn.
|
|
362
|
-
|
|
363
|
-
Passive live discovery, a live provider connection, a native message, and an
|
|
364
|
-
App Server turn are distinct authorization gates. Each requires an explicit
|
|
365
|
-
user request for that operation. Never infer permission for a live send from a
|
|
366
|
-
previous smoke test, and never enable live provider traffic in CI.
|
|
63
|
+
Embassy does not defend against the login user, root, a compromised user-owned
|
|
64
|
+
machine, the user's SSH configuration, or the provider applications
|
|
65
|
+
themselves. It does not cryptographically authenticate text inside a provider
|
|
66
|
+
conversation, prove a model read or understood a message, or make aliases
|
|
67
|
+
permanent identifiers.
|
|
68
|
+
|
|
69
|
+
Configured gateways belong to one same-user trust domain. A plain SSH login
|
|
70
|
+
is sufficient for federation; Embassy does not require a forced command or
|
|
71
|
+
dedicated per-node key and does not independently authenticate a logical host
|
|
72
|
+
label. A copied `nodes.json` with the wrong allowed `host` can therefore
|
|
73
|
+
misattribute a message's machine of origin. Correct host labels are trusted
|
|
74
|
+
operator configuration, not a separately attested property.
|
|
75
|
+
|
|
76
|
+
Provider availability and version metadata are observations, not authority.
|
|
77
|
+
`embassy health` proves the local broker control path. `embassy check` proves
|
|
78
|
+
the broker's ledger/coordinator/receipt loop without a live agent. Neither is a
|
|
79
|
+
provider readiness, model comprehension, or cross-machine proof.
|
|
80
|
+
|
|
81
|
+
The textual provenance envelope is a structural marker, not a signature. A
|
|
82
|
+
recipient must treat user-supplied text inside it as untrusted content. Embassy
|
|
83
|
+
neutralizes reserved envelope tags but does not sanitize general prompts.
|
|
84
|
+
|
|
85
|
+
## Identity and routing
|
|
86
|
+
|
|
87
|
+
An endpoint's opaque `(ID, host, provider)` tuple is routing authority. Its
|
|
88
|
+
`name@host` alias is a current lookup index. A name is resolved once before
|
|
89
|
+
admission; writes, replies, restart recovery, and settlement use the tuple.
|
|
90
|
+
Historical names never resolve, and queued work is never silently rebound.
|
|
91
|
+
|
|
92
|
+
Codex tasks self-register from inherited `CODEX_THREAD_ID`. Embassy never
|
|
93
|
+
accepts, prints, or guesses the value. Registration performs no provider I/O.
|
|
94
|
+
Each operation resumes and attests that exact task immediately before write.
|
|
95
|
+
|
|
96
|
+
Claude callers are resolved from inherited `CLAUDE_CODE_MESSAGING_SOCKET`,
|
|
97
|
+
which must be an absolute path. The path may become an in-memory `uds:`
|
|
98
|
+
capability only; it is never a CLI argument, public output, or persisted field.
|
|
99
|
+
Claude native session UUIDs are stored only in closed private route state.
|
|
100
|
+
Discovery accepts only compatible interactive/background same-user records and
|
|
101
|
+
checks the exact record and socket again before use.
|
|
102
|
+
|
|
103
|
+
Aliases may collide in discovered Claude state. In that case name lookup
|
|
104
|
+
refuses; user-supplied exact UUID selection can identify a Claude target, but
|
|
105
|
+
Embassy never publishes a UUID. A retired or replaced endpoint remains fenced
|
|
106
|
+
while its bounded retirement evidence is retained. Re-enrollment after that
|
|
107
|
+
evidence expires receives a fresh opaque ID, never the retired ID. Public
|
|
108
|
+
endpoint IDs can select exact local operator retirement without exposing a
|
|
109
|
+
native ID or authorizing remote mutation.
|
|
110
|
+
|
|
111
|
+
A remote peer's claimed host must be named in `nodes.json`; the claim and its
|
|
112
|
+
source tuple and alias are trusted within the SSH login boundary. The message's
|
|
113
|
+
source host must match the claim, so first contact does not rely on a
|
|
114
|
+
previously polled catalog. Catalogs are bounded memory-only
|
|
115
|
+
caches and are never write authority. `refresh` may replace a successful
|
|
116
|
+
node's rows or retain its last timestamped rows with
|
|
117
|
+
`PEER_TUNNEL_UNAVAILABLE`; `status` reads that observation without network I/O.
|
|
118
|
+
Named and exact routing still queries the owner.
|
|
119
|
+
|
|
120
|
+
## Delivery and uncertainty
|
|
121
|
+
|
|
122
|
+
One transaction admits a message. One coordinator reserves a bounded FIFO
|
|
123
|
+
batch for one exact destination and delivery class. Provider I/O occurs outside
|
|
124
|
+
the state transaction; authorization then revalidates the exact prepared bytes
|
|
125
|
+
and every locally owned endpoint ID, alias, and native handle under the
|
|
126
|
+
transaction immediately before the write.
|
|
127
|
+
|
|
128
|
+
Only a positive no-write result may return work to the queue. Reserved work may
|
|
129
|
+
recover after a process restart. Armed work becomes `ambiguous`; accepted work
|
|
130
|
+
becomes its recorded `ambiguous` or `unconfirmed` loss result. Neither is
|
|
131
|
+
replayed. A late callback cannot overwrite a terminal result.
|
|
132
|
+
|
|
133
|
+
The broker persists message bodies and opaque delivery/conversation values only
|
|
134
|
+
inside the bounded private ledger. It does not persist provider histories,
|
|
135
|
+
provider output, raw frames, tool data, callback sockets, or credentials.
|
|
136
|
+
Recent terminal delivery and retirement evidence is bounded by count, bytes,
|
|
137
|
+
and time; it is not a general analytics journal.
|
|
138
|
+
|
|
139
|
+
`STEER:` is recognized only as an exact leading prefix from Claude to Codex.
|
|
140
|
+
It targets the exact already-accepted operation at a safe tool-call boundary,
|
|
141
|
+
never interrupts a generation, and falls back to the ordinary bounded queue
|
|
142
|
+
when cleanly unavailable. Embassy never calls `turn/interrupt`, answers an
|
|
143
|
+
approval, or changes a task's approval or sandbox policy.
|
|
144
|
+
|
|
145
|
+
## Filesystem and process boundary
|
|
146
|
+
|
|
147
|
+
The state directory is a current-user-owned mode-0700 real directory. State and
|
|
148
|
+
configuration files are mode-0600 regular files. Reads and writes reject
|
|
149
|
+
symbolic links, ownership changes, mode changes, inode swaps, oversized data,
|
|
150
|
+
and unsupported schema. Atomic persistence uses an exclusive private temporary
|
|
151
|
+
file, file sync, rename, and directory sync. An unknown commit outcome poisons
|
|
152
|
+
the running store rather than guessing.
|
|
153
|
+
|
|
154
|
+
One fixed host-wide kernel lease is acquired before provider setup. Changing
|
|
155
|
+
`EMBASSY_STATE_DIR` does not create permission to run a second broker. The
|
|
156
|
+
control socket is accepted only at the expected private path with current-user
|
|
157
|
+
ownership and exact socket type. Mutating control requests that lose a reply
|
|
158
|
+
after write report an ambiguous outcome and are not retried.
|
|
159
|
+
|
|
160
|
+
The launchd agent records absolute executable paths, nonempty `EMBASSY_*`
|
|
161
|
+
values, and `XDG_STATE_HOME`. It copies no other shell state or arbitrary
|
|
162
|
+
`PATH`; operators must not place secrets in an `EMBASSY_*` variable.
|
|
163
|
+
`embassy serve` stays foreground and does not daemonize.
|
|
164
|
+
|
|
165
|
+
Claude registry failures quarantine Claude operations rather than authorizing a
|
|
166
|
+
guess. Embassy validates each consumed peer-protocol-1 field while tolerating
|
|
167
|
+
unknown top-level registry fields. Unsafe controller-owned state may refuse the
|
|
168
|
+
whole broker because its ownership is the broker's authority boundary.
|
|
169
|
+
|
|
170
|
+
## SSH boundary
|
|
171
|
+
|
|
172
|
+
Federation is direct and configured statically. Embassy runs the exact system
|
|
173
|
+
SSH client with batch mode, no TTY, no forwarding, no agent forwarding, no
|
|
174
|
+
local command, no tunnel, and no shell interpolation. Only the current user's
|
|
175
|
+
`HOME`, `USER`, `LOGNAME`, and `SSH_AUTH_SOCK` are forwarded to the process.
|
|
176
|
+
SSH establishes the trusted login using the user's configuration. Embassy's
|
|
177
|
+
correlated protocol checks protocol version, configured membership of the
|
|
178
|
+
peer's claimed host, and matching source hosts in handoffs. It does not inspect
|
|
179
|
+
how SSH authentication was performed or prove that the host label identifies
|
|
180
|
+
the physical machine that opened the connection.
|
|
181
|
+
|
|
182
|
+
The destination validates and durably enqueues a handoff before returning
|
|
183
|
+
acceptance. Only a protocol-proven pre-enqueue refusal is definite. Process
|
|
184
|
+
death, malformed data, wrong correlation, transport loss, and failure after the
|
|
185
|
+
commit boundary remain uncertain and are never replayed automatically.
|
|
186
|
+
|
|
187
|
+
## Public disclosure boundary
|
|
188
|
+
|
|
189
|
+
Public JSON is a closed projection. It may contain opaque Embassy endpoint IDs,
|
|
190
|
+
aliases, providers, hosts, queue depths, safe codes, phases/outcomes, ages,
|
|
191
|
+
recent retirement times, and bounded remote catalog rows and observation times.
|
|
192
|
+
It must never contain native IDs or handles, socket paths, message bodies,
|
|
193
|
+
delivery/conversation secrets, credentials, exceptions, raw diagnostics, or
|
|
194
|
+
provider histories. Human output is derived from the same validated shape.
|
|
195
|
+
|
|
196
|
+
Never write protocol diagnostics to stdout: stdout may itself be a framed
|
|
197
|
+
protocol channel. Operational hints use bounded safe codes and stderr.
|
|
198
|
+
|
|
199
|
+
## State reset and rollback
|
|
200
|
+
|
|
201
|
+
Private state schema 6 and control protocol 5 are the only v4 formats. Older or
|
|
202
|
+
unknown state refuses before mutation. There is no converter, compatibility
|
|
203
|
+
reader, or alias for removed commands. The operator must inspect and settle old
|
|
204
|
+
work with the old binary, stop the broker, preserve the old state, and start v4
|
|
205
|
+
with a fresh `gateway-state.json` while keeping `nodes.json`.
|
|
206
|
+
|
|
207
|
+
Reset invalidates all old routes, receipts, and conversation references. The
|
|
208
|
+
only rollback is the preserved old binary with its untouched old state. Embassy
|
|
209
|
+
does not merge schemas or promise conversation continuity across reset.
|