Public: anyone can read this; the crew can change it.

forked from trevato/cs

The engine a visitor reads about is one they can take: /engine serves the guide and the packed package #391

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`/engine` is a new page where a visitor can read the engine's guide and download the engine as a single `cs-engine-<version>.tar.gz`, without cloning this repository. The page is rendered from what it describes: the version and the archive's size and sha256 come from the build that runs at start-up, and the module list is read off `src/engine/index.ts` with the comment the door writes above each m…

shipped production is serving it deploy ae07c2d

opened this

/engine is a new page where a visitor can read the engine's guide and download the engine as a single cs-engine-<version>.tar.gz, without cloning this repository. The page is rendered from what it describes: the version and the archive's size and sha256 come from the build that runs at start-up, and the module list is read off src/engine/index.ts with the comment the door writes above each module. The cost table uses the same numbers /example prints, plus the package's own size, and GUIDE.md is shown as escaped, preformatted text. /example now links to the new page. bun run test (typecheck and 1,622 tests) passes.

How the archive is made. src/archive.ts runs once before the server starts listening. It runs scripts/pack.ts into FORGE_APP_DATA/engine/cs-engine-<version>/, tars exactly the files the pack wrote with src/tar.ts, gzips them at level 9 with Bun, writes the .tar.gz beside them and reads it back once. On this machine that takes about 30 ms, and the boot log prints the figure. A request never builds an archive or opens a file; it serves bytes already in memory.

  • Download URL: the archive answers at /engine/cs-engine-<version>.<10 hex of sha256>.tar.gz. The hash is in the URL because the version tracks the door's names, not behaviour, so the version alone could not safely be cached as immutable. The response also carries content-length and content-disposition: attachment; filename="cs-engine-<version>.tar.gz".
  • Same bytes every time: every file has mtime 0 and owner 0, so the same source tree always produces the same archive and the same hash.
  • Version: it is VERSION from scripts/pack.ts, which is the version in src/engine/surface.json that the door is already checked against. There is no second copy of it.

Guide on the page. Every heading outside a code block gets a guide-<slug> anchor, duplicates get -2, -3, and there is a contents list above the text. Each module in the list links to the guide's section of the same name. There is no markdown renderer and no new dependency, and the page says a nicer rendering is a later change.

Security. The only new routes are two exact entries in the server's route table. No part of a request is used to build a path, and /engine/cs-engine-<version>.tar.gz without the hash, as well as .. paths, get the 404. The page has the standard security headers and its own style hash, and HEAD answers like GET. src/tar.ts refuses paths that are absolute, contain .., are not ASCII or don't fit the header.

Tests (each would fail without this change):

  • The route returns the exact bytes on disk under FORGE_APP_DATA, with the right length, caching, type and security headers, and no second gzip.
  • The page lists exactly the modules the pack ships.
  • Guide headings become anchors, and markup in the guide comes out escaped.
  • The archive unpacks to one directory whose package.json names the engine's version.
  • The tar header is checked byte by byte: field offsets, checksum, 512-byte padding and the two zero blocks at the end. Where the machine has a tar command, it unpacks the archive too; GNU tar does here, with nothing on stderr.
  • I added /engine to the page-size budgets at 40,000 bytes gzipped. It measures 37,166, because the page carries the whole 78 kB guide.

Not done:

  • No markdown rendering, registry or version history.
  • No link to #259: that command doesn't exist yet, so whichever issue lands second adds the link.
  • The terminal has nothing new. A download doesn't translate to it, and the guide already ships inside the archive.

To try it: open /engine on the preview, click Download, then run tar -xzf cs-engine-.tar.gz && bun build cs-engine-/example.ts --outdir out. Locally that builds the sample to a 19.7 KB example.js. /engine#guide-renderer jumps to one section of the guide.

🤖 Generated with Claude Code

Closes #225

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs