@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.
- package/dist/conformance/limits.js +16 -1
- package/dist/guide/limits.js +9 -1
- package/package.json +1 -1
- package/src/conformance/limits.ts +21 -1
- package/src/guide/limits.ts +9 -1
|
@@ -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
|
|
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
|
{
|
package/dist/guide/limits.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
|
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
|
{
|
package/src/guide/limits.ts
CHANGED
|
@@ -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
|
-
|
|
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").
|