humanish 0.26.0 → 0.27.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/dist/comms-inbox.d.ts +45 -0
- package/dist/comms-inbox.js +234 -0
- package/dist/comms-inbox.js.map +1 -0
- package/dist/comms-sandbox-catch.d.ts +15 -1
- package/dist/comms-sandbox-catch.js +44 -4
- package/dist/comms-sandbox-catch.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +1 -1
- package/docs/ramp/README.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CommsMessage } from "./comms-types.js";
|
|
2
|
+
/** [fromOrigin, toOrigin] pairs: rewrite a link/href whose origin is the app's in-sandbox origin into a
|
|
3
|
+
* lane-reachable origin, so the persona's browser can actually follow the verify link when it clicks. */
|
|
4
|
+
export type OriginMap = Array<[string, string]>;
|
|
5
|
+
export interface InboxRenderOptions {
|
|
6
|
+
originMap?: OriginMap;
|
|
7
|
+
}
|
|
8
|
+
/** One served file: a route path (no leading slash) + its body + content type. The host writes each to
|
|
9
|
+
* `<servedDir>/<path>`; the catch serves `<servedDir>/<pathname>` verbatim. */
|
|
10
|
+
export interface InboxSurfaceFile {
|
|
11
|
+
path: string;
|
|
12
|
+
contentType: "text/html; charset=utf-8" | "application/json; charset=utf-8";
|
|
13
|
+
body: string;
|
|
14
|
+
}
|
|
15
|
+
/** Rewrite a URL's origin per the map (origins are exact strings the harness minted). Leaves
|
|
16
|
+
* non-matching URLs — including sibling origins sharing a prefix — untouched. */
|
|
17
|
+
export declare function rewriteOrigin(url: string, originMap?: OriginMap): string;
|
|
18
|
+
/** Best-guess primary call-to-action: the first verify/confirm-looking link, else the first link. */
|
|
19
|
+
export declare function pickVerifyUrl(links: string[]): string | undefined;
|
|
20
|
+
/** The surface CSP — the browser-enforced, load-bearing protection against the app-authored email running
|
|
21
|
+
* script or hijacking navigation on the surface page. `script-src 'none'` blocks inline handlers,
|
|
22
|
+
* `javascript:` URLs, and any injected <script>; `object-src`/`frame-src 'none'` block plugins/frames;
|
|
23
|
+
* `base-uri 'none'` blocks <base> reroot. Images/styles stay permissive so the real email still renders.
|
|
24
|
+
* Set BOTH as a page() meta (covers direct render use) and as a catch response header (covers serving). */
|
|
25
|
+
export declare const INBOX_SURFACE_CSP = "default-src 'self'; script-src 'none'; object-src 'none'; base-uri 'none'; frame-src 'none'; img-src * data:; style-src 'unsafe-inline'; font-src * data:";
|
|
26
|
+
/** The inbox LIST page (semantic table; each row links to its message). */
|
|
27
|
+
export declare function renderInboxList(messages: CommsMessage[]): string;
|
|
28
|
+
/** One message, DEFAULT view: the app's real captured email in a minimal high-contrast shell. */
|
|
29
|
+
export declare function renderInboxMessage(message: CommsMessage, options?: InboxRenderOptions): string;
|
|
30
|
+
/** One message, SYNTHESIZED view: a guaranteed-legible reading pane (big verify button + big OTP). The
|
|
31
|
+
* reliability fallback when the app's real email is a vision minefield; opt-in, never the default. */
|
|
32
|
+
export declare function renderInboxMessageSynth(message: CommsMessage, options?: InboxRenderOptions): string;
|
|
33
|
+
/** JSON projection of one message (the programmatic/CLI actor surface + the reliability backstop). Raw
|
|
34
|
+
* runtime values (served in-sandbox only); links/verifyUrl origin-rewritten so a consumer can follow. */
|
|
35
|
+
export declare function inboxMessageJson(message: CommsMessage, options?: InboxRenderOptions): Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Build every served file for the inbox surface from the normalized messages. The host writes each to
|
|
38
|
+
* `<servedDir>/<path>`; the in-sandbox catch serves `<servedDir>/<pathname>`, falling back to
|
|
39
|
+
* `<pathname>/index` (so a URL like `/inbox` maps to the `inbox/index` file while `/inbox/{id}` stays a
|
|
40
|
+
* directory) — standard web-server index semantics that avoid a file-vs-directory path collision. The
|
|
41
|
+
* URLs the persona actually sees stay clean (`/inbox`, `/inbox/{id}`, `/inbox/{id}/synth`). Content type
|
|
42
|
+
* is inferred from the `/api/` prefix. Message ids are `comms-NNNN` (never `index`/`latest`), so leaf
|
|
43
|
+
* filenames never collide with an id.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildInboxSurface(messages: CommsMessage[], options?: InboxRenderOptions): InboxSurfaceFile[];
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// The persona-facing INBOX SURFACE (#297, slice B): a minimal, dependency-free, high-contrast set of
|
|
2
|
+
// pages a computer-use persona opens to read a captured verification email and click its link — the
|
|
3
|
+
// last step of the off-app comms funnel (redirect → capture → drain → evidence → SURFACE).
|
|
4
|
+
//
|
|
5
|
+
// Design (research-backed, 2026-08-04): agent/CUA benchmarks hand agents either NO ui or a DELIBERATELY
|
|
6
|
+
// simplified inbox (MiniWoB email-inbox); nobody hands a vision agent a chrome-heavy webmail client.
|
|
7
|
+
// Anthropic computer-use guidance: high contrast, single column, big hit-targets, minimal state. So the
|
|
8
|
+
// surface is minimal SEMANTIC HTML (native <a>/<table>, black-on-white, large targets) — NOT a component
|
|
9
|
+
// UI (shadcn/Base UI break both the no-build ethos AND vision-agent reliability). We render the app's
|
|
10
|
+
// REAL captured email by default (faithful to the app-under-test — an honest signal if its email is a
|
|
11
|
+
// legibility mess), with a synthesized clean view one path away, plus a JSON twin for programmatic
|
|
12
|
+
// actors. Route shape mirrors Mailpit/Inbucket (list, message, `latest` alias, JSON with pre-extracted
|
|
13
|
+
// links/otp).
|
|
14
|
+
//
|
|
15
|
+
// This module is PURE + typed + tested; it consumes the already-normalized CommsMessage[] the tested
|
|
16
|
+
// drain/route path produces (links + codes already extracted), and emits the route→content files the
|
|
17
|
+
// in-sandbox catch serves statically. Raw content here is runtime-only (rendered in-sandbox, served to
|
|
18
|
+
// the in-sandbox browser); it is never persisted — the persisted evidence stays digest-only.
|
|
19
|
+
const VERIFY_HINT = /verify|confirm|activate|validate|magic|token|account|sign[\s-]?up/i;
|
|
20
|
+
/** Replace `from` with `to` everywhere it ends on an ORIGIN BOUNDARY — end-of-string or one of the URL
|
|
21
|
+
* delimiters `/ ? # " ' <space> > \`. A bare prefix replace would mangle a sibling origin that shares
|
|
22
|
+
* `from` as a numeric prefix (`:30000` vs `:3000`) or a suffix-domain (`:3000.evil`); the boundary
|
|
23
|
+
* check prevents that. Works both for a single URL and inside a blob of email HTML. */
|
|
24
|
+
function replaceOriginBoundary(text, from, to) {
|
|
25
|
+
if (!from)
|
|
26
|
+
return text;
|
|
27
|
+
let out = "";
|
|
28
|
+
let i = 0;
|
|
29
|
+
for (;;) {
|
|
30
|
+
const idx = text.indexOf(from, i);
|
|
31
|
+
if (idx === -1)
|
|
32
|
+
return out + text.slice(i);
|
|
33
|
+
const after = text.charAt(idx + from.length); // "" past end-of-string
|
|
34
|
+
const atBoundary = after === "" || "/?#\"' >\\".includes(after);
|
|
35
|
+
out += text.slice(i, idx) + (atBoundary ? to : from);
|
|
36
|
+
i = idx + from.length;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Rewrite a URL's origin per the map (origins are exact strings the harness minted). Leaves
|
|
40
|
+
* non-matching URLs — including sibling origins sharing a prefix — untouched. */
|
|
41
|
+
export function rewriteOrigin(url, originMap = []) {
|
|
42
|
+
let out = url;
|
|
43
|
+
for (const [from, to] of originMap)
|
|
44
|
+
out = replaceOriginBoundary(out, from, to);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** Best-guess primary call-to-action: the first verify/confirm-looking link, else the first link. */
|
|
48
|
+
export function pickVerifyUrl(links) {
|
|
49
|
+
return links.find((link) => VERIFY_HINT.test(link)) ?? links[0];
|
|
50
|
+
}
|
|
51
|
+
function esc(value) {
|
|
52
|
+
return value
|
|
53
|
+
.replace(/&/g, "&")
|
|
54
|
+
.replace(/</g, "<")
|
|
55
|
+
.replace(/>/g, ">")
|
|
56
|
+
.replace(/"/g, """);
|
|
57
|
+
}
|
|
58
|
+
/** Defense-in-depth stripping before rendering the app's real email HTML. The LOAD-BEARING protection is
|
|
59
|
+
* the page CSP (`script-src 'none'`, set both as a page() meta and as a catch response header), which is
|
|
60
|
+
* browser-enforced and neuters inline handlers, `javascript:` URLs, and injected <script> regardless of
|
|
61
|
+
* what this misses. This strip additionally removes elements CSP does not cover (a redirecting
|
|
62
|
+
* <meta http-equiv=refresh>, a nav-rerooting <base>) and the obvious active tags, so the two layers
|
|
63
|
+
* together stop the app-authored (untrusted) email from executing script or redirecting the surface. */
|
|
64
|
+
function neutralizeEmailHtml(html, originMap) {
|
|
65
|
+
let out = html
|
|
66
|
+
// paired dangerous/framing elements + their content
|
|
67
|
+
.replace(/<(script|style|iframe|object|embed|svg|math|template)\b[\s\S]*?<\/\1\s*>/gi, "")
|
|
68
|
+
// stray or void dangerous tags, incl. unclosed openers and redirect/reroot tags
|
|
69
|
+
.replace(/<\/?(script|style|iframe|object|embed|svg|math|base|meta|link|form)\b[^>]*>/gi, "")
|
|
70
|
+
// inline event handlers, whether preceded by whitespace OR a "/" attribute separator
|
|
71
|
+
.replace(/[\s/]on[a-z]+\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, " ")
|
|
72
|
+
// javascript:/vbscript: in nav/resource attrs — quoted OR unquoted (data: is left for inline images)
|
|
73
|
+
.replace(/(href|src|xlink:href|formaction|action)\s*=\s*(?:"(?:javascript|vbscript):[^"]*"|'(?:javascript|vbscript):[^']*'|(?:javascript|vbscript):[^\s>]*)/gi, '$1="#"');
|
|
74
|
+
// Rewrite the app's origin inside the (now-neutralized) HTML so its own links resolve to a reachable host.
|
|
75
|
+
for (const [from, to] of originMap)
|
|
76
|
+
out = replaceOriginBoundary(out, from, to);
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
const PAGE_CSS = "body{font:16px/1.55 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#111;background:#fff;margin:0}" +
|
|
80
|
+
"a{color:#0645ad}" +
|
|
81
|
+
".bar{padding:10px 20px;background:#f4f4f4;border-bottom:1px solid #ccc;font-size:14px}" +
|
|
82
|
+
".hdr{padding:16px 20px;border-bottom:3px solid #111}" +
|
|
83
|
+
".hdr div{margin:2px 0}.hdr b{display:inline-block;min-width:72px;color:#444;font-weight:600}" +
|
|
84
|
+
".body{padding:20px;max-width:820px}" +
|
|
85
|
+
"table{border-collapse:collapse;width:100%;max-width:900px}" +
|
|
86
|
+
"th,td{text-align:left;padding:12px 16px;border-bottom:1px solid #ddd;font-size:16px}" +
|
|
87
|
+
"th{border-bottom:2px solid #111}" +
|
|
88
|
+
"tr:hover{background:#f7f7f7}" +
|
|
89
|
+
".verify{display:inline-block;padding:16px 32px;background:#111;color:#fff;text-decoration:none;font-size:18px;font-weight:600;border-radius:6px}" +
|
|
90
|
+
".otp{font:32px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:8px;background:#f0f0f0;padding:12px 18px;display:inline-block;border-radius:6px}" +
|
|
91
|
+
".muted{color:#666;font-size:13px}";
|
|
92
|
+
/** The surface CSP — the browser-enforced, load-bearing protection against the app-authored email running
|
|
93
|
+
* script or hijacking navigation on the surface page. `script-src 'none'` blocks inline handlers,
|
|
94
|
+
* `javascript:` URLs, and any injected <script>; `object-src`/`frame-src 'none'` block plugins/frames;
|
|
95
|
+
* `base-uri 'none'` blocks <base> reroot. Images/styles stay permissive so the real email still renders.
|
|
96
|
+
* Set BOTH as a page() meta (covers direct render use) and as a catch response header (covers serving). */
|
|
97
|
+
export const INBOX_SURFACE_CSP = "default-src 'self'; script-src 'none'; object-src 'none'; base-uri 'none'; frame-src 'none'; img-src * data:; style-src 'unsafe-inline'; font-src * data:";
|
|
98
|
+
function page(title, inner) {
|
|
99
|
+
return ("<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">" +
|
|
100
|
+
"<meta http-equiv=\"Content-Security-Policy\" content=\"" + INBOX_SURFACE_CSP + "\">" +
|
|
101
|
+
"<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">" +
|
|
102
|
+
"<title>" + esc(title) + "</title><style>" + PAGE_CSS + "</style></head><body>" +
|
|
103
|
+
inner +
|
|
104
|
+
"</body></html>");
|
|
105
|
+
}
|
|
106
|
+
function fmtTime(ms) {
|
|
107
|
+
// Deterministic, dependency-free UTC stamp (avoids Date locale/timezone drift in tests + sandbox).
|
|
108
|
+
if (!Number.isFinite(ms) || ms <= 0)
|
|
109
|
+
return "";
|
|
110
|
+
const d = new Date(ms);
|
|
111
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
112
|
+
return `${d.getUTCFullYear()}-${p(d.getUTCMonth() + 1)}-${p(d.getUTCDate())} ${p(d.getUTCHours())}:${p(d.getUTCMinutes())} UTC`;
|
|
113
|
+
}
|
|
114
|
+
function toValues(message) {
|
|
115
|
+
return message.to.map((address) => address.value);
|
|
116
|
+
}
|
|
117
|
+
/** The inbox LIST page (semantic table; each row links to its message). */
|
|
118
|
+
export function renderInboxList(messages) {
|
|
119
|
+
const rows = messages
|
|
120
|
+
.map((message) => "<tr><td><a href=\"/inbox/" + esc(message.id) + "\">" + esc(message.subject ?? "(no subject)") + "</a></td>" +
|
|
121
|
+
"<td>" + esc(message.from) + "</td>" +
|
|
122
|
+
"<td>" + esc(toValues(message).join(", ")) + "</td>" +
|
|
123
|
+
"<td class=\"muted\">" + esc(fmtTime(message.deliveredAt)) + "</td></tr>")
|
|
124
|
+
.join("");
|
|
125
|
+
const body = "<div class=\"bar\">Inbox — " + messages.length + " message" + (messages.length === 1 ? "" : "s") + "</div>" +
|
|
126
|
+
"<main class=\"body\"><table><thead><tr><th>Subject</th><th>From</th><th>To</th><th>Received</th></tr></thead>" +
|
|
127
|
+
"<tbody>" + (rows || "<tr><td colspan=\"4\" class=\"muted\">No messages yet.</td></tr>") + "</tbody></table></main>";
|
|
128
|
+
return page("Inbox", body);
|
|
129
|
+
}
|
|
130
|
+
/** One message, DEFAULT view: the app's real captured email in a minimal high-contrast shell. */
|
|
131
|
+
export function renderInboxMessage(message, options = {}) {
|
|
132
|
+
const originMap = options.originMap ?? [];
|
|
133
|
+
const realHtml = message.body ? neutralizeEmailHtml(message.body, originMap) : "";
|
|
134
|
+
const fallback = realHtml.trim().length > 0 ? realHtml : "<p class=\"muted\">(this message had no HTML body)</p>";
|
|
135
|
+
const body = "<div class=\"bar\"><a href=\"/inbox\">← Inbox</a> · <a href=\"/inbox/" + esc(message.id) + "/synth\">plain view</a></div>" +
|
|
136
|
+
"<div class=\"hdr\"><div><b>To</b> " + esc(toValues(message).join(", ")) + "</div>" +
|
|
137
|
+
"<div><b>From</b> " + esc(message.from) + "</div>" +
|
|
138
|
+
"<div><b>Subject</b> " + esc(message.subject ?? "(no subject)") + "</div></div>" +
|
|
139
|
+
"<main class=\"body\">" + fallback + "</main>";
|
|
140
|
+
return page(message.subject ?? "Message", body);
|
|
141
|
+
}
|
|
142
|
+
/** One message, SYNTHESIZED view: a guaranteed-legible reading pane (big verify button + big OTP). The
|
|
143
|
+
* reliability fallback when the app's real email is a vision minefield; opt-in, never the default. */
|
|
144
|
+
export function renderInboxMessageSynth(message, options = {}) {
|
|
145
|
+
const originMap = options.originMap ?? [];
|
|
146
|
+
const verify = pickVerifyUrl(message.links);
|
|
147
|
+
const verifyRewritten = verify ? rewriteOrigin(verify, originMap) : undefined;
|
|
148
|
+
const otp = message.codes[0];
|
|
149
|
+
const parts = [
|
|
150
|
+
"<div class=\"bar\"><a href=\"/inbox\">← Inbox</a> · <a href=\"/inbox/" + esc(message.id) + "\">real email</a></div>",
|
|
151
|
+
"<div class=\"hdr\"><div><b>From</b> " + esc(message.from) + "</div>" +
|
|
152
|
+
"<div><b>To</b> " + esc(toValues(message).join(", ")) + "</div>" +
|
|
153
|
+
"<div><b>Subject</b> " + esc(message.subject ?? "(no subject)") + "</div></div>",
|
|
154
|
+
"<main class=\"body\" style=\"text-align:center\">"
|
|
155
|
+
];
|
|
156
|
+
if (verifyRewritten) {
|
|
157
|
+
parts.push("<p style=\"margin:32px 0\"><a class=\"verify\" href=\"" + esc(verifyRewritten) + "\">Verify email</a></p>");
|
|
158
|
+
}
|
|
159
|
+
if (otp) {
|
|
160
|
+
parts.push("<p>Your code:</p><p><span class=\"otp\">" + esc(otp) + "</span></p>");
|
|
161
|
+
}
|
|
162
|
+
if (!verifyRewritten && !otp) {
|
|
163
|
+
parts.push("<p class=\"muted\">No verification link or code was found in this message. Open the <a href=\"/inbox/" + esc(message.id) + "\">real email</a>.</p>");
|
|
164
|
+
}
|
|
165
|
+
parts.push("</main>");
|
|
166
|
+
return page(message.subject ?? "Message", parts.join(""));
|
|
167
|
+
}
|
|
168
|
+
/** JSON projection of one message (the programmatic/CLI actor surface + the reliability backstop). Raw
|
|
169
|
+
* runtime values (served in-sandbox only); links/verifyUrl origin-rewritten so a consumer can follow. */
|
|
170
|
+
export function inboxMessageJson(message, options = {}) {
|
|
171
|
+
const originMap = options.originMap ?? [];
|
|
172
|
+
const links = message.links.map((link) => rewriteOrigin(link, originMap));
|
|
173
|
+
const verify = pickVerifyUrl(links);
|
|
174
|
+
return {
|
|
175
|
+
id: message.id,
|
|
176
|
+
from: message.from,
|
|
177
|
+
to: toValues(message),
|
|
178
|
+
subject: message.subject ?? null,
|
|
179
|
+
receivedAt: message.deliveredAt,
|
|
180
|
+
text: message.body,
|
|
181
|
+
links,
|
|
182
|
+
...(verify === undefined ? {} : { verifyUrl: verify }),
|
|
183
|
+
...(message.codes[0] === undefined ? {} : { otp: message.codes[0] })
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function inboxListJson(messages, options = {}) {
|
|
187
|
+
const originMap = options.originMap ?? [];
|
|
188
|
+
return messages.map((message) => {
|
|
189
|
+
const verify = pickVerifyUrl(message.links.map((link) => rewriteOrigin(link, originMap)));
|
|
190
|
+
return {
|
|
191
|
+
id: message.id,
|
|
192
|
+
from: message.from,
|
|
193
|
+
to: toValues(message),
|
|
194
|
+
subject: message.subject ?? null,
|
|
195
|
+
receivedAt: message.deliveredAt,
|
|
196
|
+
...(verify === undefined ? {} : { verifyUrl: verify }),
|
|
197
|
+
...(message.codes[0] === undefined ? {} : { otp: message.codes[0] })
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Build every served file for the inbox surface from the normalized messages. The host writes each to
|
|
203
|
+
* `<servedDir>/<path>`; the in-sandbox catch serves `<servedDir>/<pathname>`, falling back to
|
|
204
|
+
* `<pathname>/index` (so a URL like `/inbox` maps to the `inbox/index` file while `/inbox/{id}` stays a
|
|
205
|
+
* directory) — standard web-server index semantics that avoid a file-vs-directory path collision. The
|
|
206
|
+
* URLs the persona actually sees stay clean (`/inbox`, `/inbox/{id}`, `/inbox/{id}/synth`). Content type
|
|
207
|
+
* is inferred from the `/api/` prefix. Message ids are `comms-NNNN` (never `index`/`latest`), so leaf
|
|
208
|
+
* filenames never collide with an id.
|
|
209
|
+
*/
|
|
210
|
+
export function buildInboxSurface(messages, options = {}) {
|
|
211
|
+
const html = (path, body) => ({ path, contentType: "text/html; charset=utf-8", body });
|
|
212
|
+
const json = (path, value) => ({
|
|
213
|
+
path,
|
|
214
|
+
contentType: "application/json; charset=utf-8",
|
|
215
|
+
body: JSON.stringify(value, null, 2)
|
|
216
|
+
});
|
|
217
|
+
const files = [
|
|
218
|
+
html("inbox/index", renderInboxList(messages)),
|
|
219
|
+
json("api/inbox/index", inboxListJson(messages, options))
|
|
220
|
+
];
|
|
221
|
+
const latest = messages[messages.length - 1];
|
|
222
|
+
for (const message of messages) {
|
|
223
|
+
files.push(html("inbox/" + message.id + "/index", renderInboxMessage(message, options)));
|
|
224
|
+
files.push(html("inbox/" + message.id + "/synth", renderInboxMessageSynth(message, options)));
|
|
225
|
+
files.push(json("api/inbox/" + message.id, inboxMessageJson(message, options)));
|
|
226
|
+
}
|
|
227
|
+
if (latest) {
|
|
228
|
+
files.push(html("inbox/latest/index", renderInboxMessage(latest, options)));
|
|
229
|
+
files.push(html("inbox/latest/synth", renderInboxMessageSynth(latest, options)));
|
|
230
|
+
files.push(json("api/inbox/latest", inboxMessageJson(latest, options)));
|
|
231
|
+
}
|
|
232
|
+
return files;
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=comms-inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-inbox.js","sourceRoot":"","sources":["../src/comms-inbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { CommsAddress, CommsChannel } from "./comms-types.js";
|
|
1
|
+
import type { CommsAddress, CommsChannel, CommsMessage } from "./comms-types.js";
|
|
2
2
|
import { type CommsThreadArtifact } from "./comms-evidence.js";
|
|
3
|
+
import { type InboxRenderOptions } from "./comms-inbox.js";
|
|
3
4
|
import { type EmailSendProfile } from "./comms-email-catch.js";
|
|
4
5
|
import { type DetachedTimers } from "./e2b-detached.js";
|
|
5
6
|
import type { E2BDesktopSandbox } from "./e2b-desktop-launch.js";
|
|
@@ -32,6 +33,9 @@ export interface DeployedCommsCatch {
|
|
|
32
33
|
/** Inject THIS as the app's email-API base URL (e.g. RESEND_API_URL) — the sandbox's own loopback. */
|
|
33
34
|
baseUrl: string;
|
|
34
35
|
deliveriesPath: string;
|
|
36
|
+
/** In-sandbox dir the HOST renders the persona-facing inbox-surface files into (via writeInboxSurface);
|
|
37
|
+
* the catch serves them at /inbox and /api/inbox. */
|
|
38
|
+
surfaceDir: string;
|
|
35
39
|
/** Whether the catch's /health returned OUR service marker within the readiness budget. Callers MUST
|
|
36
40
|
* treat `ready === false` as fatal (do not inject baseUrl into a dead catch — the app's sends would
|
|
37
41
|
* silently fail with nothing captured). */
|
|
@@ -92,3 +96,13 @@ export declare function collectCommsThread(args: {
|
|
|
92
96
|
profiles?: EmailSendProfile[];
|
|
93
97
|
requestTimeoutMs?: number;
|
|
94
98
|
}): Promise<CommsThreadCollection>;
|
|
99
|
+
/**
|
|
100
|
+
* Render the persona-facing inbox surface (host-side, typed — see comms-inbox.ts) and write the files
|
|
101
|
+
* into the sandbox's served dir, so the catch serves a LIVE inbox the persona opens and clicks. Creates
|
|
102
|
+
* the nested route dirs first; overwrites idempotently, so call it whenever the message set changes
|
|
103
|
+
* (e.g. after a mid-run drain). Returns the number of files written. Raw content is written INTO the
|
|
104
|
+
* sandbox only (runtime-only, served to the in-sandbox browser); nothing here persists to the bundle.
|
|
105
|
+
*/
|
|
106
|
+
export declare function writeInboxSurface(desktop: E2BDesktopSandbox, surfaceDir: string, messages: CommsMessage[], options?: InboxRenderOptions & {
|
|
107
|
+
requestTimeoutMs?: number;
|
|
108
|
+
}): Promise<number>;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// parse them and route into the CommsChannel. A FIXED loopback port is chosen up front so the app's
|
|
8
8
|
// injected base-URL env (`http://127.0.0.1:<port>`) is known before the sandbox is created.
|
|
9
9
|
import { buildCommsThreadArtifact } from "./comms-evidence.js";
|
|
10
|
+
import { buildInboxSurface } from "./comms-inbox.js";
|
|
10
11
|
import { DEFAULT_EMAIL_PROFILES } from "./comms-email-catch.js";
|
|
11
12
|
import { startDetachedProcess } from "./e2b-detached.js";
|
|
12
13
|
/** The default in-sandbox loopback port for the catch. Fixed (not ephemeral) so the injected base-URL
|
|
@@ -27,15 +28,31 @@ function shq(value) {
|
|
|
27
28
|
*/
|
|
28
29
|
export const SANDBOX_CATCH_SCRIPT = [
|
|
29
30
|
'import { createServer } from "node:http";',
|
|
30
|
-
'import { appendFileSync, mkdirSync } from "node:fs";',
|
|
31
|
+
'import { appendFileSync, mkdirSync, readFileSync } from "node:fs";',
|
|
31
32
|
'import { dirname } from "node:path";',
|
|
32
33
|
'const port = Number(process.argv[2] || 8025);',
|
|
33
34
|
'const outFile = process.argv[3] || "/tmp/humanish-comms/deliveries.ndjson";',
|
|
35
|
+
// argv[4] is the dir the HOST renders the inbox-surface files into (host-side typed rendering; this
|
|
36
|
+
// server only serves them statically), defaulting to a `surface` sibling of the deliveries file.
|
|
37
|
+
'const servedDir = process.argv[4] || (dirname(outFile) + "/surface");',
|
|
34
38
|
'try { mkdirSync(dirname(outFile), { recursive: true }); } catch {}',
|
|
35
39
|
'const MAX = 5 * 1024 * 1024;',
|
|
36
40
|
'createServer((req, res) => {',
|
|
37
41
|
' const path = (req.url || "/").split("?")[0];',
|
|
38
42
|
' if (req.method === "GET" && (path === "/" || path === "/health")) { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ ok: true, service: "humanish-comms-catch" })); return; }',
|
|
43
|
+
' if (req.method === "GET" && (path === "/inbox" || path.indexOf("/inbox/") === 0 || path === "/api/inbox" || path.indexOf("/api/inbox/") === 0)) {',
|
|
44
|
+
' let rel; try { rel = decodeURIComponent(path); } catch { res.writeHead(400); res.end(); return; }',
|
|
45
|
+
' if (rel.indexOf("..") !== -1 || rel.indexOf("\\0") !== -1) { res.writeHead(400); res.end(); return; }',
|
|
46
|
+
' let data = null;',
|
|
47
|
+
' try { data = readFileSync(servedDir + rel); } catch { try { data = readFileSync(servedDir + rel + "/index"); } catch { data = null; } }',
|
|
48
|
+
' if (data === null) { res.writeHead(404, { "content-type": "text/html; charset=utf-8" }); res.end("<p>message not found</p>"); return; }',
|
|
49
|
+
' const isApi = rel.indexOf("/api/") === 0;',
|
|
50
|
+
' const headers = { "content-type": isApi ? "application/json; charset=utf-8" : "text/html; charset=utf-8" };',
|
|
51
|
+
// The load-bearing XSS protection: a browser-enforced CSP forbidding all script on the surface page,
|
|
52
|
+
// so the app-authored (untrusted) email HTML we render cannot run script or reroot navigation.
|
|
53
|
+
' if (!isApi) { headers["content-security-policy"] = "default-src \'self\'; script-src \'none\'; object-src \'none\'; base-uri \'none\'; frame-src \'none\'; img-src * data:; style-src \'unsafe-inline\'; font-src * data:"; }',
|
|
54
|
+
' res.writeHead(200, headers); res.end(data); return;',
|
|
55
|
+
' }',
|
|
39
56
|
' if (req.method !== "POST") { res.writeHead(404, { "content-type": "application/json" }); res.end(JSON.stringify({ error: "not found" })); return; }',
|
|
40
57
|
' let size = 0; const chunks = [];',
|
|
41
58
|
' req.on("data", (c) => { size += c.length; if (size > MAX) { req.destroy(); } else { chunks.push(c); } });',
|
|
@@ -83,11 +100,12 @@ export async function deployCommsCatch(desktop, options = {}) {
|
|
|
83
100
|
const requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
|
|
84
101
|
const scriptPath = `${dir}/catch.mjs`;
|
|
85
102
|
const deliveriesPath = `${dir}/deliveries.ndjson`;
|
|
86
|
-
|
|
103
|
+
const surfaceDir = `${dir}/surface`;
|
|
104
|
+
await desktop.commands.run(`mkdir -p ${shq(dir)} ${shq(surfaceDir)}`, { requestTimeoutMs });
|
|
87
105
|
await desktop.files.write(scriptPath, SANDBOX_CATCH_SCRIPT);
|
|
88
106
|
await startDetachedProcess(desktop, {
|
|
89
107
|
name,
|
|
90
|
-
command: `node ${shq(scriptPath)} ${port} ${shq(deliveriesPath)}`,
|
|
108
|
+
command: `node ${shq(scriptPath)} ${port} ${shq(deliveriesPath)} ${shq(surfaceDir)}`,
|
|
91
109
|
requestTimeoutMs
|
|
92
110
|
});
|
|
93
111
|
const ready = await catchHealthy(desktop, port, {
|
|
@@ -95,7 +113,7 @@ export async function deployCommsCatch(desktop, options = {}) {
|
|
|
95
113
|
requestTimeoutMs,
|
|
96
114
|
...(options.timers ?? {})
|
|
97
115
|
});
|
|
98
|
-
return { port, baseUrl: `http://127.0.0.1:${port}`, deliveriesPath, ready };
|
|
116
|
+
return { port, baseUrl: `http://127.0.0.1:${port}`, deliveriesPath, surfaceDir, ready };
|
|
99
117
|
}
|
|
100
118
|
/**
|
|
101
119
|
* Drain new captured sends from the in-sandbox NDJSON since `cursor` (a line count). Returns the fresh
|
|
@@ -186,4 +204,26 @@ export async function collectCommsThread(args) {
|
|
|
186
204
|
messages.sort((a, b) => a.deliveredAt - b.deliveredAt || a.id.localeCompare(b.id));
|
|
187
205
|
return { artifact: buildCommsThreadArtifact(messages), captured: sends.length, matched: messages.length };
|
|
188
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Render the persona-facing inbox surface (host-side, typed — see comms-inbox.ts) and write the files
|
|
209
|
+
* into the sandbox's served dir, so the catch serves a LIVE inbox the persona opens and clicks. Creates
|
|
210
|
+
* the nested route dirs first; overwrites idempotently, so call it whenever the message set changes
|
|
211
|
+
* (e.g. after a mid-run drain). Returns the number of files written. Raw content is written INTO the
|
|
212
|
+
* sandbox only (runtime-only, served to the in-sandbox browser); nothing here persists to the bundle.
|
|
213
|
+
*/
|
|
214
|
+
export async function writeInboxSurface(desktop, surfaceDir, messages, options = {}) {
|
|
215
|
+
const files = buildInboxSurface(messages, options);
|
|
216
|
+
// Create the union of parent dirs (inbox/<id>/synth etc.) in one mkdir before writing.
|
|
217
|
+
const dirs = new Set([surfaceDir]);
|
|
218
|
+
for (const file of files) {
|
|
219
|
+
const slash = file.path.lastIndexOf("/");
|
|
220
|
+
if (slash > 0)
|
|
221
|
+
dirs.add(`${surfaceDir}/${file.path.slice(0, slash)}`);
|
|
222
|
+
}
|
|
223
|
+
await desktop.commands.run(`mkdir -p ${[...dirs].map(shq).join(" ")}`, { requestTimeoutMs: options.requestTimeoutMs ?? 30_000 });
|
|
224
|
+
for (const file of files) {
|
|
225
|
+
await desktop.files.write(`${surfaceDir}/${file.path}`, file.body);
|
|
226
|
+
}
|
|
227
|
+
return files.length;
|
|
228
|
+
}
|
|
189
229
|
//# sourceMappingURL=comms-sandbox-catch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comms-sandbox-catch.js","sourceRoot":"","sources":["../src/comms-sandbox-catch.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,wGAAwG;AACxG,uGAAuG;AACvG,qGAAqG;AACrG,qGAAqG;AACrG,qGAAqG;AACrG,oGAAoG;AACpG,4FAA4F;AAG5F,OAAO,EAAE,wBAAwB,EAA4B,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAyB,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAuB,MAAM,mBAAmB,CAAC;AAG9E;;8EAE8E;AAC9E,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,CAAC;AAC/C,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAEhD,iDAAiD;AACjD,SAAS,GAAG,CAAC,KAAa;IACxB,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,2CAA2C;IAC3C,
|
|
1
|
+
{"version":3,"file":"comms-sandbox-catch.js","sourceRoot":"","sources":["../src/comms-sandbox-catch.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,8 +21,10 @@ export { FakeInbox, extractLinks, extractOtpCodes } from "./comms-fake-inbox.js"
|
|
|
21
21
|
export type { FakeInboxOptions } from "./comms-fake-inbox.js";
|
|
22
22
|
export { DEFAULT_EMAIL_PROFILES, genericEmailProfile, sendgridEmailProfile, startEmailCatchServer } from "./comms-email-catch.js";
|
|
23
23
|
export type { EmailCatchOptions, EmailCatchServer, EmailSendProfile, NormalizedSend } from "./comms-email-catch.js";
|
|
24
|
-
export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, collectCommsThread, deployCommsCatch, drainCommsCatch, routeCapturedSends } from "./comms-sandbox-catch.js";
|
|
24
|
+
export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, collectCommsThread, deployCommsCatch, drainCommsCatch, routeCapturedSends, writeInboxSurface } from "./comms-sandbox-catch.js";
|
|
25
25
|
export type { CommsThreadCollection, DeployCommsCatchOptions, DeployedCommsCatch, RawCapturedSend } from "./comms-sandbox-catch.js";
|
|
26
|
+
export { INBOX_SURFACE_CSP, buildInboxSurface, inboxMessageJson, pickVerifyUrl, renderInboxList, renderInboxMessage, renderInboxMessageSynth, rewriteOrigin } from "./comms-inbox.js";
|
|
27
|
+
export type { InboxRenderOptions, InboxSurfaceFile, OriginMap } from "./comms-inbox.js";
|
|
26
28
|
export { COMMS_THREAD_SCHEMA, buildCommsThreadArtifact } from "./comms-evidence.js";
|
|
27
29
|
export type { CommsThreadArtifact, CommsThreadEntry } from "./comms-evidence.js";
|
|
28
30
|
export type { CommsAddress, CommsChannel, CommsChannelKind, CommsMessage, InboundRaw, OutboundMessage } from "./comms-types.js";
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,8 @@ export { FakeInbox, extractLinks, extractOtpCodes } from "./comms-fake-inbox.js"
|
|
|
15
15
|
export { DEFAULT_EMAIL_PROFILES, genericEmailProfile, sendgridEmailProfile, startEmailCatchServer } from "./comms-email-catch.js";
|
|
16
16
|
// In-sandbox deployment of the catch + the host-side delivery bridge (the config-block core: the
|
|
17
17
|
// listener must live inside the subject sandbox, since 127.0.0.1 from the app is the sandbox loopback).
|
|
18
|
-
export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, collectCommsThread, deployCommsCatch, drainCommsCatch, routeCapturedSends } from "./comms-sandbox-catch.js";
|
|
18
|
+
export { DEFAULT_SANDBOX_CATCH_PORT, SANDBOX_CATCH_SCRIPT, collectCommsThread, deployCommsCatch, drainCommsCatch, routeCapturedSends, writeInboxSurface } from "./comms-sandbox-catch.js";
|
|
19
|
+
export { INBOX_SURFACE_CSP, buildInboxSurface, inboxMessageJson, pickVerifyUrl, renderInboxList, renderInboxMessage, renderInboxMessageSynth, rewriteOrigin } from "./comms-inbox.js";
|
|
19
20
|
export { COMMS_THREAD_SCHEMA, buildCommsThreadArtifact } from "./comms-evidence.js";
|
|
20
21
|
export { DESKTOP_RATE, MODEL_RATES, PRICING_SCHEMA, estimateActorCost, estimateDesktopCost } from "./pricing.js";
|
|
21
22
|
export { normalizeCliArgv } from "./argv.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC9B,MAAM,qBAAqB,CAAC;AAa7B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,oBAAoB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEjJ,OAAO,EACL,mCAAmC,EACnC,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EACL,uBAAuB,EACvB,gCAAgC,EAChC,6BAA6B,EAC9B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,EAChC,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAOhC,6FAA6F;AAC7F,iGAAiG;AACjG,iGAAiG;AACjG,0BAA0B;AAC1B,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEjF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAElI,iGAAiG;AACjG,wGAAwG;AACxG,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Date: 2026-06-02 (current-state note updated 2026-07-14)
|
|
4
4
|
|
|
5
5
|
Status: reference map for the major contracts shipped through source version
|
|
6
|
-
`0.
|
|
6
|
+
`0.27.0`; it is not an exhaustive inventory of command/result envelopes. Exported types,
|
|
7
7
|
schema constants, parsers, and validators in `src/` are authoritative. Rows
|
|
8
8
|
marked "reserved" name layering intent only — no code emits or validates them
|
|
9
9
|
yet. Do not emit a reserved schema.
|
package/docs/goals/current.md
CHANGED
|
@@ -16,7 +16,7 @@ Humanish should be the open-source CLI that lets a maintainer ask:
|
|
|
16
16
|
The answer should be observable, verifiable, public-safe, and easy to turn into
|
|
17
17
|
actionable feedback.
|
|
18
18
|
|
|
19
|
-
## Current Program Truth (source `0.
|
|
19
|
+
## Current Program Truth (source `0.27.0`)
|
|
20
20
|
|
|
21
21
|
The package source and repository implementation in this tree agree on these
|
|
22
22
|
points:
|
package/docs/ramp/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: public-safe contributor and agent ramp.
|
|
4
4
|
|
|
5
|
-
Package/source version in this tree: `0.
|
|
5
|
+
Package/source version in this tree: `0.27.0` (2026-08-04). The containment boundary introduced in
|
|
6
6
|
`0.15.1` remains in force: managed run and output paths bind to validated
|
|
7
7
|
physical filesystem identities, and stored provider IDs are evidence, not
|
|
8
8
|
cleanup authority. The bundled OSS meta-lab is dry-run only until
|
package/package.json
CHANGED