Public: anyone can read this; the crew can change it.
forge-webspec fetches through the same compression seam production uses, and compression leaves its known list #3147
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/3144-forge-webspec-fetches-through-the-same-c → main 1 commit fork
1 file
changed +15
−10
test/forge-webspec.test.ts +15 −10
| @@ -7,10 +7,12 @@ import { afterAll, beforeAll, expect, test } from "bun:test"; | ||
| 7 | 7 | import { mkdtemp, rm } from "node:fs/promises"; |
| 8 | 8 | import { tmpdir } from "node:os"; |
| 9 | 9 | import { join } from "node:path"; |
| 10 | import { brotliDecompressSync } from "node:zlib"; | |
| 10 | 11 | import { createApp, type App } from "../src/app.ts"; |
| 11 | 12 | import { openIssue } from "../src/actions/issues.ts"; |
| 12 | 13 | import { commitToBranch, createRepo } from "../src/actions/repos.ts"; |
| 13 | 14 | import { createUser } from "../src/core/users.ts"; |
| 15 | import { compress } from "../src/http/compress.ts"; | |
| 14 | 16 | import { securityFloor } from "../src/http/respond.ts"; |
| 15 | 17 | import { forgeHttp, type ForgeHttp } from "../src/http/server.ts"; |
| 16 | 18 | import { webspec } from "../src/release/webspec.ts"; |
| @@ -20,16 +22,8 @@ quietLogs(); | ||
| 20 | 22 | |
| 21 | 23 | const PATHS = ["/", "/signin", "/signup", "/explore", "/alice/notes", "/alice/notes/issues", "/alice/notes/issues/1"]; |
| 22 | 24 | |
| 23 | /** | |
| 24 | * `check path` -> [section, why it stands]. Every one is expected on every | |
| 25 | * page it names; one fixed fails the test, one new fails it too. "compression" | |
| 26 | * is an edge finding (set by the CDN in front of the forge): listed, not hidden. | |
| 27 | */ | |
| 25 | /** `check path` -> [section, why it stands]. Every one is expected on every page it names; one fixed fails the test, one new fails it too. */ | |
| 28 | 26 | const KNOWN: Record<string, [string, string]> = {}; |
| 29 | const WHY: Record<string, [string, string]> = { | |
| 30 | compression: ["https://specification.website/", "bodies leave the forge uncompressed: compression is set at the edge (edge: true)"], | |
| 31 | }; | |
| 32 | for (const [check, why] of Object.entries(WHY)) for (const path of PATHS) KNOWN[`${check} ${path}`] = why; | |
| 33 | 27 | |
| 34 | 28 | let dir = ""; |
| 35 | 29 | let app: App; |
| @@ -62,7 +56,18 @@ afterAll(async () => { | ||
| 62 | 56 | }); |
| 63 | 57 | |
| 64 | 58 | test("the forge's signed-out pages raise exactly the findings named in KNOWN", async () => { |
| 65 | const fetcher = (input: string, init?: RequestInit) => http.handle(new Request(input, init)).then(securityFloor); | |
| 59 | // The seam production uses (server.ts): compress, then the security floor. | |
| 60 | // Like fetch, the body arrives decoded while Content-Encoding stays for webspec to read. | |
| 61 | const fetcher = async (input: string, init?: RequestInit) => { | |
| 62 | const request = new Request(input, init); | |
| 63 | if (!request.headers.has("accept-encoding")) request.headers.set("accept-encoding", "br, gzip"); | |
| 64 | const response = await compress(request, await http.handle(request)).then(securityFloor); | |
| 65 | const encoding = response.headers.get("content-encoding"); | |
| 66 | if (encoding !== "br" && encoding !== "gzip") return response; | |
| 67 | const bytes = new Uint8Array(await response.arrayBuffer()); | |
| 68 | const plain = encoding === "br" ? brotliDecompressSync(bytes) : Bun.gunzipSync(bytes); | |
| 69 | return new Response(plain, response); | |
| 70 | }; | |
| 66 | 71 | const found = await webspec("http://forge.test", PATHS, fetcher, { site: true }); |
| 67 | 72 | const keyOf = (f: { check: string; path: string }) => `${f.check} ${f.path}`; |
| 68 | 73 | // New: not named, or citing another section than the one named. |
new above
offline