Repository navigation
v4.1.9
"Gateways": the programme's second release, the same day as the first. Four connectors of the world
outside (email, Telnet, SSH, Open Badges) on one SDK, in a fourth package outside the player and the DSL, each with its
threat model and its abuse tests, all experimental until a real pass; the cadence itself (the CHANGELOG and the LOG
as fragments per branch, the CI in three tiers sized by the change, the mutation job off the pull request path).
Measured against 4.1.8 in docs/dev/baselines/4.1.9.md; what this release does not do is in the LOG and the passes
sheet (docs/dev/passes/4.1.9.md).
Fixed
npm run ship -- verifyon a release candidate (4.1.9). It looked forweb-scumm-4.1.8-rc.1.tgzwhere the
packages carrypackage.json's version (web-scumm-4.1.8.tgz): the rc's sums and eight attestations verified, then
the command failed on that name, inrelease.ymltoo. The tarball's name drops the tag's suffix.
Changes
-
The CHANGELOG and the LOG written as fragments per branch (4.1.9, lot 0 "cadence"). A branch that changes
the code writeschanges/<slug>.md(its bullets under### Breaking,### Fixedor### Changes) and, for a LOG
entry,changes/<slug>.log.md;npm run changes -- --assemblefolds them intoCHANGELOG.md'sUnreleasedand
numbers the LOG entries in the order the fragments reachedmain; CI'scheckjob fails a pull request that
touches the code without a fragment (npm run changes -- --check). During 4.1.8 every merge made the other open
branches conflict on those two files and re-run their CI: that is over (changes/README.md). -
CI in three tiers, sized by the change (4.1.9, lot 0). A pull request runs a fast tier on every change (
plan;
check: formatting, lint, knip, both type checks, the sample game's gates,build:gameinstead ofbuild, the
baseline, the proof;coverage: the unit suite once), then only the heavier jobs its diff can affect, as
tools/ci-plan.tsclassifies it (npm run ci:plan): a docs-only pull request opens no browser, no Windows runner and
no Node 24; a Bridge change runs Reality, a painter the browser rows and the reference chapter. The browser rows and
the Firefox PWA job play thedist/thatcheckbuilt instead of building it seven times;node-24runs the suite
withoutqualityagain;audit:depsruns when the lockfile moved. The seventeen checks the ruleset requires keep
their names and succeed with "not needed by the plan" when spared. The coverage ratchet warns on a pull request
(::warning::) and stays strict onmain, tags, the nightly and release-check. Onmain, on a tag and with the
full-cilabel, everything runs as before; a newpr-gatejob sums every result up, the candidate single required
check (CONTRIBUTING.md, "What CI runs";docs/en/SUPPORT.mdsays what a pull request no longer checks). Themutationjob no longer runs on a push tomaineither: a main run must stay short, since the release
chain waits for the run of the exact commit it tags and a later merge cancels one still going; the nightly and
release-checkmeasure the sets, afull-cilabel on a pull request too. The Firefox PWA job now plays the same build as the Chromium and WebKit PWA rows (the Studio demo included),
from the shared artefact. -
Four connectors of the world outside: email, Telnet, SSH and Open Badges (4.1.9, experimental, D19, ADR 0008).
Each is a process of its own (web-scumm-connector <id> --config <file>, ornpm run connector -- …in the
repository), never in the game nor its DSL, with one Biscuit attenuated to its own signals. Email: a provider's
signed webhook or an IMAP mailbox, the message read in a worker under limits, HTML made inert, attachments refused,
one signal perMessage-ID, a message the Bridge could not take left unseen for the next poll, IMAP without TLS
only to this machine. Telnet and SSH: a virtual terminal (the game's commands,help,exit) and, for SSH, a
virtual disk (ls,cd,cat); no host shell, noexec, nosftp, no forwarding; one shell per SSH
connection; line, rate and time limits, 20 seconds to pair, three connections per address and wrong codes counted
per address across reconnections. Open Badges 2.0 (hosted, signed) and 3.0 (VC-JWT, Data Integrityeddsa-jcs-2022), issuer,
recipient, dates and revocation checked, every document fetched under an SSRF-safe network policy; the verdict is
valid,invalid,expired,revokedorindeterminate. A player links a connector with the pairing code the
pause menu shows. Not done: replies to emails, DKIM and SPF, RDF-canonicalised proofs (indeterminate), a real
provider, badge or exposed terminal tried by a person (docs/en/SUPPORT.md). -
A game declares what its connectors may do, as data (4.1.9):
reality.connectorsholds the words of an email's
answers, a terminal's commands and replies, an SSH disk's files and the badge issuers a game trusts;npm run validatechecks that every signal named is declared, that commands are plain words and not the terminal's own,
and that paths stay inside. The Reality manifest carries the block (its hash changes only for a game that declares
it). A game runs without any connector. -
The connector SDK (4.1.9,
connectors/src/sdk.ts): a connector receives, validates, binds to a player, gives a
dedupeKey(sha256('<source>:<external id>'), the Bridge's existing deduplication key) and proposes; delivery is
at least once and applied once (a proposal whose answer was lost is sent again with the same key, the Bridge answers
duplicate). What a connector saw never leaves it: the Bridge receives the SHA-256 of its payload as
evidenceHash. Limits (size, a local quota, a timeout), metrics and/healthin JSON, a log that writes
[redacted]for anything that looks like content, SIGTERM drained in at most five seconds. -
web-scumm-connectors, a fourth package (4.1.9): one bundled module, its MIME worker beside it,ssh2(MIT)
its only dependency, whose optional native parts are refused (cpu-featuresandnanmap to a refusing stub): in the
repositorynpm cistill runs ssh2's install script, which attempts a native build and fails without thenan
headers, so no.nodefile results (tested); the package is installed with--ignore-scripts.npm run packmakes four tarballs;npm run fresh-installinstalls this one without native
code and runsweb-scumm-connector --help. -
A build that carries server code fails (4.1.9):
verify:dist(innpm run build) refuses a game's JavaScript
that holds any marker of the connectors or the Bridge (connectors/,ssh2,imapflow,web-scumm-bridge…). -
npm run solve:realityproves recorded replays too (4.1.9):games/<id>/replays/*.json(connector inputs and
the signals they made), proved finishable like the scenarios and replayed through the real connector code by a
test, with no network. The sample gamegames/signalsgains "the mailbox and the terminal": a letter opens the
shed, a command lights a lamp, a badge puts a ribbon on the bucket, all optional. -
Tools and CI (4.1.9):
npm run fuzz:connectors(seeded mutations of each connector's corpus, crashes and memory
counted); aconnectorsCI job (the contract on the four connectors against a real Bridge, abuse and replay
tests, a run under--disallow-code-generation-from-strings, half a minute of fuzzing, the tarball installed); a
nightly fuzz of a minute per connector, not gating yet; aconnectorsmutation set, outsideall, not gated yet;
e2e:realitysends one key three times from two connectors and proposes the sample chapter's replays. The Windows
job leaves out the Telnet and SSH tests until they are ported. -
Documentation (4.1.9):
docs/en/CONNECTORS.mdanddocs/en/PRIVACY.md(what is kept, where, how long, how to
delete), in French too; a threat model per connector (docs/dev/threat-models/); ADR 0008; D19.
Manual passes (D12: reported, not blocking)
0 of 12 done.
| Pass | Status | Who, when | Device, OS, browser, versions | What failed |
|---|---|---|---|---|
| A real email provider (webhook mode) delivering to a game | not done | |||
| A real IMAP mailbox polled by the email connector | not done | |||
| A real Open Badge (OB2 hosted, OB3 VC-JWT) from a real issuer verified | not done | |||
| SSH and Telnet exposed in a controlled environment, attacked by a person | not done | |||
| A Bridge behind HTTPS with a real connector, a signal delivered after a disconnection | not done | |||
Screen reader (docs/dev/SCREEN-READER.md) |
not done | |||
Safari offline (docs/dev/SAFARI-OFFLINE.md), iPhone install and update |
not done | |||
| Firefox offline on a real machine | not done | |||
Windows: npm run doctor, npm run dev, npm run build by hand |
not done | |||
| Real phone, frame rate of the heaviest scene (≥ 30 FPS) | not done | |||
Playtesters who do not know the puzzles (npm run verify:field) |
not done | |||
Recorded voices; listening; a signed tag (git tag -s) |
not done |