agent-embassy 1.2.0 → 1.3.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/CONTRIBUTING.md +25 -7
  3. package/README.md +20 -12
  4. package/README.zh-CN.md +14 -13
  5. package/SECURITY.md +55 -41
  6. package/dist/src/gateway/claude-helper-supervisor.js +0 -1
  7. package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
  8. package/dist/src/gateway/claude-runtime.d.ts +0 -2
  9. package/dist/src/gateway/claude-runtime.js +6 -17
  10. package/dist/src/gateway/claude-runtime.js.map +1 -1
  11. package/dist/src/gateway/cli-copy.d.ts +1 -1
  12. package/dist/src/gateway/cli-copy.en.d.ts +3 -1
  13. package/dist/src/gateway/cli-copy.en.js +5 -3
  14. package/dist/src/gateway/cli-copy.en.js.map +1 -1
  15. package/dist/src/gateway/cli-copy.js +2 -0
  16. package/dist/src/gateway/cli-copy.js.map +1 -1
  17. package/dist/src/gateway/cli-copy.zh-CN.d.ts +3 -1
  18. package/dist/src/gateway/cli-copy.zh-CN.js +5 -3
  19. package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -1
  20. package/dist/src/gateway/cli.d.ts +2 -5
  21. package/dist/src/gateway/cli.js +30 -67
  22. package/dist/src/gateway/cli.js.map +1 -1
  23. package/dist/src/gateway/codex-app-server.d.ts +1 -7
  24. package/dist/src/gateway/codex-app-server.js +5 -52
  25. package/dist/src/gateway/codex-app-server.js.map +1 -1
  26. package/dist/src/gateway/codex-local-transport.d.ts +4 -10
  27. package/dist/src/gateway/codex-local-transport.js +13 -16
  28. package/dist/src/gateway/codex-local-transport.js.map +1 -1
  29. package/dist/src/gateway/compatibility.d.ts +0 -27
  30. package/dist/src/gateway/compatibility.js +1 -101
  31. package/dist/src/gateway/compatibility.js.map +1 -1
  32. package/dist/src/gateway/config.d.ts +0 -3
  33. package/dist/src/gateway/config.js +0 -10
  34. package/dist/src/gateway/config.js.map +1 -1
  35. package/dist/src/gateway/control.d.ts +1 -20
  36. package/dist/src/gateway/control.js +2 -33
  37. package/dist/src/gateway/control.js.map +1 -1
  38. package/dist/src/gateway/dashboard-copy.d.ts +1 -1
  39. package/dist/src/gateway/dashboard-copy.en.d.ts +6 -7
  40. package/dist/src/gateway/dashboard-copy.en.js +15 -16
  41. package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
  42. package/dist/src/gateway/dashboard-copy.js +6 -7
  43. package/dist/src/gateway/dashboard-copy.js.map +1 -1
  44. package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +6 -7
  45. package/dist/src/gateway/dashboard-copy.zh-CN.js +15 -16
  46. package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
  47. package/dist/src/gateway/dashboard-model.d.ts +3 -7
  48. package/dist/src/gateway/dashboard-model.js +41 -16
  49. package/dist/src/gateway/dashboard-model.js.map +1 -1
  50. package/dist/src/gateway/dashboard.js +5 -7
  51. package/dist/src/gateway/dashboard.js.map +1 -1
  52. package/dist/src/gateway/live-dashboard-app/app.js +17 -45
  53. package/dist/src/gateway/live-dashboard-command.d.ts +5 -1
  54. package/dist/src/gateway/live-dashboard-command.js +8 -6
  55. package/dist/src/gateway/live-dashboard-command.js.map +1 -1
  56. package/dist/src/gateway/live-dashboard-http.d.ts +0 -4
  57. package/dist/src/gateway/live-dashboard-http.js +19 -93
  58. package/dist/src/gateway/live-dashboard-http.js.map +1 -1
  59. package/dist/src/gateway/live-dashboard-protocol.d.ts +1 -5
  60. package/dist/src/gateway/live-dashboard-protocol.js +0 -42
  61. package/dist/src/gateway/live-dashboard-protocol.js.map +1 -1
  62. package/dist/src/gateway/live-dashboard-server.d.ts +2 -2
  63. package/dist/src/gateway/live-dashboard-server.js +18 -4
  64. package/dist/src/gateway/live-dashboard-server.js.map +1 -1
  65. package/dist/src/gateway/live-dashboard.d.ts +3 -6
  66. package/dist/src/gateway/live-dashboard.js +6 -42
  67. package/dist/src/gateway/live-dashboard.js.map +1 -1
  68. package/dist/src/gateway/provenance-envelope.js +1 -1
  69. package/dist/src/gateway/provenance-envelope.js.map +1 -1
  70. package/dist/src/gateway/providers.d.ts +1 -21
  71. package/dist/src/gateway/providers.js +15 -261
  72. package/dist/src/gateway/providers.js.map +1 -1
  73. package/dist/src/gateway/server.js +0 -3
  74. package/dist/src/gateway/server.js.map +1 -1
  75. package/dist/src/gateway/service.d.ts +3 -15
  76. package/dist/src/gateway/service.js +76 -257
  77. package/dist/src/gateway/service.js.map +1 -1
  78. package/dist/src/gateway/store.js +76 -18
  79. package/dist/src/gateway/store.js.map +1 -1
  80. package/dist/src/gateway/types.d.ts +0 -4
  81. package/dist/src/gateway/types.js.map +1 -1
  82. package/docs/GATEWAY-ARCHITECTURE.md +75 -63
  83. package/package.json +1 -1
  84. package/skills/embassy-peer/SKILL.md +25 -10
  85. package/dist/src/gateway/claude-compatibility-scratch.d.ts +0 -18
  86. package/dist/src/gateway/claude-compatibility-scratch.js +0 -158
  87. package/dist/src/gateway/claude-compatibility-scratch.js.map +0 -1
  88. package/dist/src/gateway/live-dashboard-bootstrap.d.ts +0 -36
  89. package/dist/src/gateway/live-dashboard-bootstrap.js +0 -176
  90. package/dist/src/gateway/live-dashboard-bootstrap.js.map +0 -1
  91. package/docs/DESIGN.md +0 -134
@@ -1,158 +0,0 @@
1
- import { randomBytes, randomUUID } from "node:crypto";
2
- import { spawn as nodeSpawn, } from "node:child_process";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import { BridgeError } from "../errors.js";
6
- const MAX_SCRATCH_OUTPUT_BYTES = 64 * 1024;
7
- const SCRATCH_START_TIMEOUT_MS = 2_000;
8
- const SCRATCH_CLOSE_TIMEOUT_MS = 2_000;
9
- function waitForSpawn(child) {
10
- return new Promise((resolve, reject) => {
11
- const timer = setTimeout(() => {
12
- cleanup();
13
- reject(new Error("scratch spawn timeout"));
14
- }, SCRATCH_START_TIMEOUT_MS);
15
- timer.unref();
16
- const cleanup = () => {
17
- clearTimeout(timer);
18
- child.off("spawn", onSpawn);
19
- child.off("error", onError);
20
- child.off("exit", onExit);
21
- };
22
- const onSpawn = () => {
23
- cleanup();
24
- resolve();
25
- };
26
- const onError = (error) => {
27
- cleanup();
28
- reject(error);
29
- };
30
- const onExit = () => {
31
- cleanup();
32
- reject(new Error("scratch exited before ready"));
33
- };
34
- child.once("spawn", onSpawn);
35
- child.once("error", onError);
36
- child.once("exit", onExit);
37
- });
38
- }
39
- function waitForExit(child, timeoutMs) {
40
- if (child.exitCode !== null || child.signalCode !== null) {
41
- return Promise.resolve(true);
42
- }
43
- return new Promise((resolve) => {
44
- const timer = setTimeout(() => {
45
- cleanup();
46
- resolve(false);
47
- }, timeoutMs);
48
- timer.unref();
49
- const cleanup = () => {
50
- clearTimeout(timer);
51
- child.off("exit", onExit);
52
- };
53
- const onExit = () => {
54
- cleanup();
55
- resolve(true);
56
- };
57
- child.once("exit", onExit);
58
- });
59
- }
60
- export async function startClaudeCompatibilityScratch(runtime, dependencies = {}) {
61
- const user = (dependencies.userInfo ?? os.userInfo)();
62
- if (!path.isAbsolute(user.homedir) ||
63
- path.normalize(user.homedir) !== user.homedir ||
64
- user.homedir.includes("\0") ||
65
- !/^[A-Za-z0-9._-]{1,128}$/.test(user.username)) {
66
- throw new BridgeError("CLAUDE_CERTIFICATION_USER_INVALID", "The bounded Claude certification scratch requires one canonical local user.");
67
- }
68
- const sessionId = randomUUID();
69
- const name = `embassy-compat-${randomBytes(6).toString("hex")}`;
70
- const args = [
71
- "--print",
72
- "--input-format",
73
- "stream-json",
74
- "--output-format",
75
- "stream-json",
76
- "--verbose",
77
- "--session-id",
78
- sessionId,
79
- "--name",
80
- name,
81
- "--safe-mode",
82
- "--tools",
83
- "",
84
- "--strict-mcp-config",
85
- "--no-session-persistence",
86
- "--permission-mode",
87
- "dontAsk",
88
- "--settings",
89
- '{"crossSessionInbound":"accept"}',
90
- ];
91
- const spawn = dependencies.spawn ??
92
- ((command, argv, options) => nodeSpawn(command, [...argv], options));
93
- let child;
94
- try {
95
- child = spawn(runtime.claudeExecutable, args, {
96
- cwd: user.homedir,
97
- detached: false,
98
- env: {
99
- HOME: user.homedir,
100
- USER: user.username,
101
- LOGNAME: user.username,
102
- SHELL: "/bin/zsh",
103
- PATH: "/usr/bin:/bin:/usr/sbin:/sbin",
104
- TMPDIR: os.tmpdir(),
105
- },
106
- shell: false,
107
- stdio: "pipe",
108
- });
109
- }
110
- catch {
111
- throw new BridgeError("CLAUDE_CERTIFICATION_SCRATCH_UNAVAILABLE", "The bounded Claude certification scratch could not start.", true);
112
- }
113
- let outputBytes = 0;
114
- let outputOverflow = false;
115
- const observeOutput = (chunk) => {
116
- outputBytes += Buffer.byteLength(chunk);
117
- if (outputBytes > MAX_SCRATCH_OUTPUT_BYTES && !outputOverflow) {
118
- outputOverflow = true;
119
- child.kill("SIGTERM");
120
- }
121
- };
122
- child.stdout.on("data", observeOutput);
123
- child.stderr.on("data", observeOutput);
124
- try {
125
- await waitForSpawn(child);
126
- }
127
- catch {
128
- child.kill("SIGKILL");
129
- await waitForExit(child, SCRATCH_CLOSE_TIMEOUT_MS);
130
- throw new BridgeError("CLAUDE_CERTIFICATION_SCRATCH_UNAVAILABLE", "The bounded Claude certification scratch did not become ready.", true);
131
- }
132
- let closeOperation;
133
- return {
134
- name,
135
- sessionId,
136
- assertRunning: () => {
137
- if (outputOverflow ||
138
- child.exitCode !== null ||
139
- child.signalCode !== null) {
140
- throw new BridgeError("CLAUDE_CERTIFICATION_SCRATCH_EXITED", "The bounded Claude certification scratch exited before settlement.", true);
141
- }
142
- },
143
- close: () => {
144
- closeOperation ??= (async () => {
145
- child.stdin.end();
146
- if (await waitForExit(child, SCRATCH_CLOSE_TIMEOUT_MS))
147
- return;
148
- child.kill("SIGTERM");
149
- if (await waitForExit(child, SCRATCH_CLOSE_TIMEOUT_MS))
150
- return;
151
- child.kill("SIGKILL");
152
- await waitForExit(child, SCRATCH_CLOSE_TIMEOUT_MS);
153
- })();
154
- return closeOperation;
155
- },
156
- };
157
- }
158
- //# sourceMappingURL=claude-compatibility-scratch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-compatibility-scratch.js","sourceRoot":"","sources":["../../../src/gateway/claude-compatibility-scratch.ts"],"names":[],"mappings":"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"}
@@ -1,36 +0,0 @@
1
- import { type FileHandle } from "node:fs/promises";
2
- import { type DashboardLocale } from "./dashboard-copy.js";
3
- export type LiveDashboardRandomBytes = (size: number) => Uint8Array;
4
- export type LiveDashboardFileStat = Readonly<{
5
- dev: number;
6
- ino: number;
7
- mode: number;
8
- isDirectory(): boolean;
9
- isFile(): boolean;
10
- isSymbolicLink(): boolean;
11
- }>;
12
- export type LiveDashboardFileHandle = Pick<FileHandle, "writeFile" | "sync" | "stat" | "close">;
13
- export type LiveDashboardFileSystem = Readonly<{
14
- lstat(pathname: string): Promise<LiveDashboardFileStat>;
15
- mkdir(pathname: string, options: {
16
- mode: number;
17
- }): Promise<void>;
18
- open(pathname: string, flags: "wx", mode: number): Promise<LiveDashboardFileHandle>;
19
- readdir(pathname: string): Promise<string[]>;
20
- realpath(pathname: string): Promise<string>;
21
- unlink(pathname: string): Promise<void>;
22
- rmdir(pathname: string): Promise<void>;
23
- }>;
24
- export declare const defaultLiveDashboardFileSystem: LiveDashboardFileSystem;
25
- export type LiveDashboardBootstrapArtifacts = Readonly<{
26
- bootstrapPath: string;
27
- capability: string;
28
- close(): Promise<void>;
29
- }>;
30
- export declare function createLiveDashboardBootstrap(options: Readonly<{
31
- privateStateRoot: string;
32
- bootstrapTargetWithoutFragment: string;
33
- lang: DashboardLocale;
34
- fileSystem?: LiveDashboardFileSystem;
35
- random?: LiveDashboardRandomBytes;
36
- }>): Promise<LiveDashboardBootstrapArtifacts>;
@@ -1,176 +0,0 @@
1
- import { randomBytes } from "node:crypto";
2
- import { lstat, mkdir, open, readdir, realpath, rmdir, unlink, } from "node:fs/promises";
3
- import path from "node:path";
4
- import { assertDashboardLocale, getDashboardCopy, } from "./dashboard-copy.js";
5
- export const defaultLiveDashboardFileSystem = {
6
- lstat,
7
- mkdir: async (pathname, options) => {
8
- await mkdir(pathname, options);
9
- },
10
- open,
11
- readdir,
12
- realpath,
13
- unlink,
14
- rmdir,
15
- };
16
- function identity(stat) {
17
- return { device: stat.dev, inode: stat.ino };
18
- }
19
- function sameIdentity(stat, expected) {
20
- return stat.dev === expected.device && stat.ino === expected.inode;
21
- }
22
- function base64Url(bytes) {
23
- return Buffer.from(bytes).toString("base64url");
24
- }
25
- function escapeHtml(value) {
26
- return value
27
- .replaceAll("&", "&amp;")
28
- .replaceAll('"', "&quot;")
29
- .replaceAll("<", "&lt;")
30
- .replaceAll(">", "&gt;");
31
- }
32
- function bootstrapDocument(target, lang) {
33
- const copy = getDashboardCopy(lang);
34
- const escaped = escapeHtml(target);
35
- return `<!doctype html>
36
- <html lang="${lang}"><head><meta charset="utf-8"><meta name="referrer" content="no-referrer"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; navigate-to http://127.0.0.1:*"><meta http-equiv="refresh" content="0;url=${escaped}"><title>${escapeHtml(copy["live.bootstrap.title"])}</title></head><body><p><a rel="noreferrer" href="${escaped}">${escapeHtml(copy["live.bootstrap.open"])}</a></p></body></html>`;
37
- }
38
- export async function createLiveDashboardBootstrap(options) {
39
- assertDashboardLocale(options.lang);
40
- const fileSystem = options.fileSystem ?? defaultLiveDashboardFileSystem;
41
- const random = options.random ?? randomBytes;
42
- const targetMatch = /^http:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})\/[A-Za-z0-9_-]{16,128}\/bootstrap$/u.exec(options.bootstrapTargetWithoutFragment);
43
- if (targetMatch === null || Number(targetMatch[1]) > 65_535) {
44
- throw new Error("LIVE_DASHBOARD_BOOTSTRAP_TARGET_INVALID");
45
- }
46
- const requestedRoot = path.resolve(options.privateStateRoot);
47
- const rootPath = await fileSystem.realpath(requestedRoot);
48
- const rootStat = await fileSystem.lstat(rootPath);
49
- if (!rootStat.isDirectory() ||
50
- rootStat.isSymbolicLink() ||
51
- (rootStat.mode & 0o077) !== 0) {
52
- throw new Error("LIVE_DASHBOARD_STATE_ROOT_NOT_PRIVATE");
53
- }
54
- let runDirectory = "";
55
- let runIdentity;
56
- for (let attempt = 0; attempt < 4; attempt += 1) {
57
- const name = `live-${base64Url(random(16))}`;
58
- if (!/^live-[A-Za-z0-9_-]{22}$/u.test(name)) {
59
- throw new Error("LIVE_DASHBOARD_RANDOM_SOURCE_INVALID");
60
- }
61
- const candidate = path.join(rootPath, name);
62
- try {
63
- await fileSystem.mkdir(candidate, { mode: 0o700 });
64
- const candidateStat = await fileSystem.lstat(candidate);
65
- if (!candidateStat.isDirectory() ||
66
- candidateStat.isSymbolicLink() ||
67
- (candidateStat.mode & 0o077) !== 0) {
68
- throw new Error("LIVE_DASHBOARD_RUN_DIRECTORY_NOT_PRIVATE");
69
- }
70
- runDirectory = candidate;
71
- runIdentity = identity(candidateStat);
72
- break;
73
- }
74
- catch (error) {
75
- if (typeof error === "object" &&
76
- error !== null &&
77
- "code" in error &&
78
- error.code === "EEXIST") {
79
- continue;
80
- }
81
- throw error;
82
- }
83
- }
84
- if (runIdentity === undefined) {
85
- throw new Error("LIVE_DASHBOARD_RUN_DIRECTORY_COLLISION");
86
- }
87
- const capability = base64Url(random(32));
88
- if (!/^[A-Za-z0-9_-]{43}$/u.test(capability)) {
89
- throw new Error("LIVE_DASHBOARD_RANDOM_SOURCE_INVALID");
90
- }
91
- const target = `${options.bootstrapTargetWithoutFragment}#${capability}`;
92
- const bootstrapPath = path.join(runDirectory, "bootstrap.html");
93
- let handle;
94
- let bootstrapIdentity;
95
- try {
96
- handle = await fileSystem.open(bootstrapPath, "wx", 0o600);
97
- const openedStat = await handle.stat();
98
- if (!openedStat.isFile() ||
99
- openedStat.isSymbolicLink() ||
100
- (openedStat.mode & 0o177) !== 0) {
101
- throw new Error("LIVE_DASHBOARD_BOOTSTRAP_NOT_PRIVATE");
102
- }
103
- bootstrapIdentity = identity(openedStat);
104
- await handle.writeFile(bootstrapDocument(target, options.lang), {
105
- encoding: "utf8",
106
- });
107
- await handle.sync();
108
- await handle.close();
109
- handle = undefined;
110
- const bootstrapStat = await fileSystem.lstat(bootstrapPath);
111
- if (!bootstrapStat.isFile() ||
112
- bootstrapStat.isSymbolicLink() ||
113
- (bootstrapStat.mode & 0o177) !== 0) {
114
- throw new Error("LIVE_DASHBOARD_BOOTSTRAP_NOT_PRIVATE");
115
- }
116
- if (!sameIdentity(bootstrapStat, bootstrapIdentity)) {
117
- throw new Error("LIVE_DASHBOARD_BOOTSTRAP_REPLACED");
118
- }
119
- }
120
- catch (error) {
121
- await handle?.close().catch(() => undefined);
122
- try {
123
- const currentRun = await fileSystem.lstat(runDirectory);
124
- if (sameIdentity(currentRun, runIdentity)) {
125
- const entries = await fileSystem.readdir(runDirectory);
126
- if (entries.length === 1 && entries[0] === "bootstrap.html") {
127
- const currentBootstrap = await fileSystem.lstat(bootstrapPath);
128
- if (bootstrapIdentity !== undefined &&
129
- sameIdentity(currentBootstrap, bootstrapIdentity) &&
130
- currentBootstrap.isFile() &&
131
- !currentBootstrap.isSymbolicLink()) {
132
- await fileSystem.unlink(bootstrapPath);
133
- }
134
- }
135
- if ((await fileSystem.readdir(runDirectory)).length === 0) {
136
- await fileSystem.rmdir(runDirectory);
137
- }
138
- }
139
- }
140
- catch {
141
- // Never broaden cleanup after a startup error. A private empty artifact
142
- // is preferable to deleting a path whose exact ownership changed.
143
- }
144
- throw error;
145
- }
146
- let closed = false;
147
- return {
148
- bootstrapPath,
149
- capability,
150
- close: async () => {
151
- if (closed)
152
- return;
153
- const currentRun = await fileSystem.lstat(runDirectory);
154
- if (!sameIdentity(currentRun, runIdentity) ||
155
- !currentRun.isDirectory() ||
156
- currentRun.isSymbolicLink()) {
157
- throw new Error("LIVE_DASHBOARD_RUN_DIRECTORY_REPLACED");
158
- }
159
- const entries = await fileSystem.readdir(runDirectory);
160
- if (entries.length !== 1 || entries[0] !== "bootstrap.html") {
161
- throw new Error("LIVE_DASHBOARD_RUN_DIRECTORY_NOT_EXACT_OWNED");
162
- }
163
- const currentBootstrap = await fileSystem.lstat(bootstrapPath);
164
- if (bootstrapIdentity === undefined ||
165
- !sameIdentity(currentBootstrap, bootstrapIdentity) ||
166
- !currentBootstrap.isFile() ||
167
- currentBootstrap.isSymbolicLink()) {
168
- throw new Error("LIVE_DASHBOARD_BOOTSTRAP_REPLACED");
169
- }
170
- await fileSystem.unlink(bootstrapPath);
171
- await fileSystem.rmdir(runDirectory);
172
- closed = true;
173
- },
174
- };
175
- }
176
- //# sourceMappingURL=live-dashboard-bootstrap.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"live-dashboard-bootstrap.js","sourceRoot":"","sources":["../../../src/gateway/live-dashboard-bootstrap.ts"],"names":[],"mappings":"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"}
package/docs/DESIGN.md DELETED
@@ -1,134 +0,0 @@
1
- # Embassy Design System — "Porcelain & Seal"
2
-
3
- Canon for every user surface: marketing site, dashboard, README visuals, mark,
4
- and social imagery. One token system; no surface invents its own values.
5
- Agreed jointly (PM + engineering) 2026-08-08.
6
-
7
- > **PM amendment — 2026-08-09 (the warm/arch era).** The visual identity
8
- > moved on from this document's imagery on the operator's direction; the
9
- > honesty rules below remain canon, the imagery sections are historical.
10
- > What ships today: the **gate/archway mark** with an amber glow and pennant
11
- > (`assets/embassy-logo/mark.svg`, badge and lockup alongside; the tent
12
- > variants at `assets/mark.svg` / `assets/mark-seal.svg` remain as favicon
13
- > until superseded); the **warm anime banner** — three chibi agent mascots
14
- > exchanging envelopes before the glowing arch (`assets/social-preview.png`,
15
- > brief in `docs/BANNER-BRIEF.md`); and the **live dashboard's Cohere-token
16
- > chip system** (`assets/live-dashboard/app.css`) in place of the porcelain
17
- > palette and seal/receipt iconography described below — state is carried by
18
- > tinted chips (progress stone, positive green, qualified outline,
19
- > indeterminate purple, warning coral, failure red, inert outline), with the
20
- > same rules: progress is never green, `released` ≠ read, refusals are not
21
- > failures, and the brand accent is never a state color. A successor canon
22
- > document for the warm era is owed; until then, treat BANNER-BRIEF.md plus
23
- > the shipped dashboard tokens as the working truth for imagery and color.
24
-
25
- ## Idea
26
-
27
- Embassy's brand is the **receipt** — the seal that records a message
28
- crossing a boundary and how delivery settled. (A settlement record, not
29
- cryptographic proof: today `delivered` can mean the receiving App Server
30
- accepted the turn, not that the model consumed or completed it. Copy on any
31
- surface must never claim more than this.) The visual world is a light, unhurried diplomatic
32
- register: porcelain paper, near-black ink, hairline rules, and exactly one
33
- decisive color — seal red. Abstract, artistic, calm. No buildings, no flags,
34
- no vendor colors, no circuit-board "AI" imagery.
35
-
36
- ## Tokens
37
-
38
- ### Color
39
-
40
- | Token | Value | Use |
41
- | --- | --- | --- |
42
- | `--porcelain` | `#f8f4ec` | Page ground |
43
- | `--porcelain-raise` | `#fffdf8` | Cards, panels |
44
- | `--ink` | `#231f1a` | Primary text |
45
- | `--ink-soft` | `#6d6558` | Secondary text |
46
- | `--rule` | `#e4dccd` | Hairlines, borders |
47
- | `--seal` | `#b3382c` | Brand + one primary action per view — the cinnabar seal. **Never a state color.** |
48
- | `--jade` | `#557f68` | Healthy / delivered / positive states |
49
- | `--ochre` | `#a8842f` | Waiting / queued / in-progress states |
50
- | `--codeblock` | `#262019` | Terminal code blocks only — the one deliberate dark exception |
51
-
52
- Rules: cinnabar never decorates and never signals any state — it is the brand
53
- and the single most important action on screen. **There is no second red.**
54
- Failure is carried by SHAPE (the broken seal) rendered in `--ink`, never by a
55
- red that would compete with the brand at small sizes. Jade and ochre are
56
- semantic only and never used decoratively. Dark-mode variants are NOT provided in v1 —
57
- the light porcelain world is the committed identity (paint every ground
58
- explicitly; never inherit host backgrounds).
59
-
60
- ### Type
61
-
62
- | Role | Stack | Treatment |
63
- | --- | --- | --- |
64
- | Display | `"Iowan Old Style", "Palatino Nova", Palatino, Georgia, serif` | Large, tight-tracked (−0.01em), `text-wrap: balance` |
65
- | Body | `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, sans-serif` | 16–17px / 1.65, max width 65ch |
66
- | Utility | `ui-monospace, "SF Mono", Menlo, Consolas, monospace` | Commands, receipts, timestamps, stats; `font-variant-numeric: tabular-nums` |
67
- | Label | Body stack | 11–12px, uppercase, letter-spacing 0.14em, `--ink-soft` (or `--seal` for the active section) |
68
-
69
- ### Space & structure
70
-
71
- - Base unit 8px; section rhythm 72–96px on the site, 24–32px on the dashboard.
72
- - Hairline rules (`1px solid --rule`) separate; whitespace groups. Prefer
73
- asymmetric editorial layouts over centered symmetry on the site.
74
- - Cards: `--porcelain-raise`, 1px `--rule` border, radius 10px, no shadows
75
- heavier than `0 1px 2px rgb(35 31 26 / 4%)`.
76
- - Wide content (tables, code) scrolls in its own container; the page never
77
- scrolls horizontally.
78
-
79
- ## The mark
80
-
81
- An abstract seal: a circle holding two facing arcs that shelter a sealed
82
- center point — the parentheses of a meeting. **No diagonal strokes anywhere**
83
- (diagonals collapse into an error X at small sizes), **never radial from the
84
- hub** (reads as a clock), **nothing detached below center** (reads as a
85
- face). Two parties, one meeting point. At 20px and below, drop the outer
86
- ring. Sources:
87
-
88
- - `assets/mark.svg` — ink line version on light grounds.
89
- - `assets/mark-seal.svg` — solid seal-red disc with porcelain chevrons; used
90
- for favicon and small sizes (legible at 16px).
91
-
92
- Receipt iconography derives from the mark: **delivered** = intact seal
93
- (jade), **queued** = half-drawn seal (ochre), **expired/failed** = broken
94
- seal (ink — shape carries the failure; no red competes with the brand). The
95
- brand cinnabar seal itself never marks a state. No other icon family is
96
- used.
97
-
98
- ## Site first viewport
99
-
100
- Not an illustration with a title: a compact, authentic message exchange —
101
- two named agents, the seal at center, a delivered receipt — showing the
102
- product doing its one thing. Then accreditation/how-it-works, protocol
103
- truth, real dashboard proof, quickstart/security.
104
-
105
- ## Dashboard information architecture
106
-
107
- 1. **Exchange board** — Claude selection ↔ queue/pouch ↔ Codex registration;
108
- broker readiness and the next action inline.
109
- 2. **Needs attention** — ordered, actionable, hidden when empty.
110
- 3. **In transit** — queue count, oldest wait, and explicit stall state from the
111
- bounded public snapshot.
112
- 4. **Activity ledger** — receipt lifecycle; details on demand.
113
- 5. **Sessions & routes** — secondary.
114
- 6. **Compatibility & diagnostics** — collapsed by default.
115
-
116
- Every alert pairs the state with the exact next command. Raw data lives
117
- behind the questions, never in front of them. Review lenses: a new user must
118
- understand purpose / readiness / queue / next action within 10 seconds; a
119
- protocol expert must verify discovery ≠ selection ≠ registration,
120
- accepted ≠ delivered, progress ≠ failure, no private data, no overclaims,
121
- and correct ambiguity/restart/version semantics.
122
-
123
- ## Localization
124
-
125
- Runtime dashboards, CLI guidance, and native gateway notices render from
126
- closed, parity-tested `en` / `zh-CN` catalogs. Commands, JSON keys, enums,
127
- aliases, protocol tags, and safe codes stay English. English remains canonical
128
- for security meaning. The marketing site and README ship parallel locale
129
- artifacts rather than changing the runtime protocol.
130
-
131
- ## Review gate
132
-
133
- Every batch built under this system passes two adversarial reviews — a
134
- new-user lens and an AI-expert lens — before it ships.