@botiverse/porthole 0.1.7 → 0.1.8

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.
@@ -119,7 +119,7 @@ export const LIMIT_PROBES = [
119
119
  {
120
120
  id: "14.silent",
121
121
  item: 14,
122
- title: "what the sandbox blocks fails silently: nothing loads, a fetch rejects, nothing is shown",
122
+ title: "what the sandbox blocks shows nothing on the page: nothing loads, a fetch rejects; the host hears of it where reportError is declared, and nothing where it isn't",
123
123
  async run(context) {
124
124
  const canary = await context.http();
125
125
  const seen = watch(context.page);
@@ -143,6 +143,21 @@ export const LIMIT_PROBES = [
143
143
  });
144
144
  expect(canary.requests()).toEqual([]);
145
145
  expect(seen.dialogs).toEqual([]);
146
+ // Where reportError is declared, each block is reported to the host (the manual says where
147
+ // it goes, by \`errors\`, #4); where it isn't, nothing is.
148
+ await expect
149
+ .poll(async () => (await display.errors()).some((each) => each.startsWith("Blocked by the sandbox:")))
150
+ .toBe(true);
151
+ const quiet = await context.launch({
152
+ config: inline({ errors: "none" }),
153
+ content: attack(`
154
+ r.fetch = await fetch(${js(`${c}/quiet`)}).then(() => "sent", (e) => "rejected " + e.name);`, `<img src="${c}/quiet.png">`),
155
+ });
156
+ expect(await context.result(quiet, 15_000)).toMatchObject({ fetch: "rejected TypeError" });
157
+ await settle();
158
+ expect(await quiet.errors()).toEqual([]);
159
+ expect(canary.requests()).toEqual([]);
160
+ expect(seen.dialogs).toEqual([]);
146
161
  },
147
162
  },
148
163
  {
@@ -81,7 +81,15 @@ export function manualLimits(config, network) {
81
81
  : documents === "never"
82
82
  ? "It always shows in light: the app doesn't theme it, so style it yourself; prefers-color-scheme may report the reader's system setting, so don't rely on it."
83
83
  : 'It shows in light, as you style it; to follow the person\'s light or dark theme, declare it in its head (<meta name="color-scheme" content="light dark">) and draw with the variables below.');
84
- add("silent", "What the sandbox blocks fails silently: a blocked script, style or image just doesn't load, a blocked fetch rejects, and nothing shows an error.");
84
+ // What a block does on the page, and where it is reported: as the Errors line says (#4).
85
+ const blocked = "a blocked script, style or image just doesn't load and a blocked fetch rejects";
86
+ add("silent", !declared.has("reportError")
87
+ ? "What the sandbox blocks fails silently: a blocked script, style or image just doesn't load, a blocked fetch rejects, and nothing shows an error."
88
+ : config.errors === "agent"
89
+ ? `What the sandbox blocks shows nothing on the page: ${blocked}. Each block comes back to you as an error, so check them.`
90
+ : config.errors === "host"
91
+ ? `What the sandbox blocks shows nothing on the page: ${blocked}. The app is told of each block, but you aren't: test what you write.`
92
+ : `What the sandbox blocks shows nothing on the page: ${blocked}. Each block is reported to the app.`);
85
93
  add("network", network);
86
94
  // Assets: what isn't opened goes inline (Network: none already says "everything inline").
87
95
  const anywhere = (kind) => (config.egress.anyHttps ?? []).some((each) => each === kind);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/porthole",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A host-side sandbox for agent-made HTML: isolation, egress hardening, a themed shell, gated host functions, and the agent manual, from one config.",
5
5
  "license": "Apache-2.0",
6
6
  "files": [
@@ -150,7 +150,7 @@ export const LIMIT_PROBES: readonly Probe[] = [
150
150
  id: "14.silent",
151
151
  item: 14,
152
152
  title:
153
- "what the sandbox blocks fails silently: nothing loads, a fetch rejects, nothing is shown",
153
+ "what the sandbox blocks shows nothing on the page: nothing loads, a fetch rejects; the host hears of it where reportError is declared, and nothing where it isn't",
154
154
  async run(context) {
155
155
  const canary = await context.http();
156
156
  const seen = watch(context.page);
@@ -177,6 +177,26 @@ export const LIMIT_PROBES: readonly Probe[] = [
177
177
  });
178
178
  expect(canary.requests()).toEqual([]);
179
179
  expect(seen.dialogs).toEqual([]);
180
+ // Where reportError is declared, each block is reported to the host (the manual says where
181
+ // it goes, by \`errors\`, #4); where it isn't, nothing is.
182
+ await expect
183
+ .poll(async () =>
184
+ (await display.errors()).some((each) => each.startsWith("Blocked by the sandbox:")),
185
+ )
186
+ .toBe(true);
187
+ const quiet = await context.launch({
188
+ config: inline({ errors: "none" }),
189
+ content: attack(
190
+ `
191
+ r.fetch = await fetch(${js(`${c}/quiet`)}).then(() => "sent", (e) => "rejected " + e.name);`,
192
+ `<img src="${c}/quiet.png">`,
193
+ ),
194
+ });
195
+ expect(await context.result(quiet, 15_000)).toMatchObject({ fetch: "rejected TypeError" });
196
+ await settle();
197
+ expect(await quiet.errors()).toEqual([]);
198
+ expect(canary.requests()).toEqual([]);
199
+ expect(seen.dialogs).toEqual([]);
180
200
  },
181
201
  },
182
202
  {
@@ -110,9 +110,17 @@ export function manualLimits(config: PortholeConfig, network: string): ManualLim
110
110
  : 'It shows in light, as you style it; to follow the person\'s light or dark theme, declare it in its head (<meta name="color-scheme" content="light dark">) and draw with the variables below.',
111
111
  );
112
112
 
113
+ // What a block does on the page, and where it is reported: as the Errors line says (#4).
114
+ const blocked = "a blocked script, style or image just doesn't load and a blocked fetch rejects";
113
115
  add(
114
116
  "silent",
115
- "What the sandbox blocks fails silently: a blocked script, style or image just doesn't load, a blocked fetch rejects, and nothing shows an error.",
117
+ !declared.has("reportError")
118
+ ? "What the sandbox blocks fails silently: a blocked script, style or image just doesn't load, a blocked fetch rejects, and nothing shows an error."
119
+ : config.errors === "agent"
120
+ ? `What the sandbox blocks shows nothing on the page: ${blocked}. Each block comes back to you as an error, so check them.`
121
+ : config.errors === "host"
122
+ ? `What the sandbox blocks shows nothing on the page: ${blocked}. The app is told of each block, but you aren't: test what you write.`
123
+ : `What the sandbox blocks shows nothing on the page: ${blocked}. Each block is reported to the app.`,
116
124
  );
117
125
  add("network", network);
118
126
  // Assets: what isn't opened goes inline (Network: none already says "everything inline").