Repository navigation
EN Bridge What It Is
Français · Type: explanation · Audience: author, admin · Context: Reality Bridge · Status: ready · Applies from: 4.2.5
The Reality Bridge,
localprofile (SQLite) · contract: stable · verified by CI (support matrix of 4.4.0, 2026-10-23): Node 22.13+ with node:sqlite, on Ubuntu; Chromium and WebKit end to end · automated checks: jobsreality,reality-xcheck; CI planreality; 2 test files · people's passes: none · known limits:bridge-not-a-game-server,bridge-experimental-partsThe Reality Bridge,
distributedprofile (Postgres) · contract: experimental · verified by CI (support matrix of 4.4.0, 2026-10-23): Postgres 16 in CI; The qualification profile: HTTPS, three instances (ops/qualify/) · automated checks: jobsbridge-postgres,deployment-smoke; CI planreality; 1 test file · people's passes:bridge-postgres-httpsnot run (#77) · known limits:bridge-not-a-game-server,bridge-experimental-partsThe connectors (email, Telnet, SSH, Open Badges) · contract: experimental · verified by CI (support matrix of 4.4.0, 2026-10-23): Node 22 on Ubuntu (Telnet and SSH not on Windows) · automated checks: jobs
connectors,connector-archive-e2e; CI planreality; 3 test files · people's passes:connectors-real-securitynot run (#79) · known limits:bridge-not-a-game-server,bridge-experimental-parts
A quest'n'click game can react to a fact from the world outside: an email answered, a webhook called, a badge shown, a command typed in a terminal. The game itself never touches the network. A separate service, the Reality Bridge, turns the fact into a short signed signal, and the game applies it like a player's input: once, saved, and replayable offline. This page says what the pieces are and why they are cut this way. To try it, read Quick start; to run one, Install and run the Bridge.
Three hands carry a fact to the player, each one checking the one before:
| Piece | Runs where | Does | Holds |
|---|---|---|---|
| A connector (email, Telnet, SSH, Open Badges, or the Bridge's demonstration webhook) | its own process, beside the Bridge | reads the outside input as hostile, binds it to a player, proposes a declared signal with a deduplication key | its own Biscuit token, its own secrets (a mailbox password, a host key) |
The Bridge (bridge/src/, the package quest-n-click-bridge) |
a small Node service | authorises the connector (Biscuit), checks the signal against the game's manifest, deduplicates, numbers it per player, signs it (Ed25519), keeps it until the player acknowledges | the event-signing key, the hashes of the players' capabilities, the signals |
| The player (the game in the browser) | the player's device | verifies the signature before reading anything, applies the signal as an event, saves, then acknowledges | a capability that reads and acknowledges its own signals, nothing else |
A signal is only an identifier from a finite list the game declares (mail.answer.correct): no text, address or
payload from outside reaches the game. It arrives as the game's event of the same name. The engine applies it at most
once, as an entry of the session, saved before it is acknowledged (src/engine/reality/protocol.ts verifies,
WorldSignalPort is the transport, and a game without reality loads none of this code).
The Bridge exists since 4.1.1, the four connectors since 4.1.9, several instances and several tenants on one store
since 4.1.10. Its local profile (SQLite) is stable; its distributed profile (Postgres, several instances) and
the connectors are experimental (Stability and support).
-
The game stays a game. A game is a static page and a PWA: no socket, no secret, nothing that executes what
comes from outside. Everything that talks to strangers lives in processes the game never loads; the game's build
holds nothing of
connectors/(checked bytools/dist.ts). - A proof that does not need the world. Because a signal is a finite identifier applied like an input, the solver can prove a game in a world that never answers, in the worlds the author scripts, and in a hostile one, without contacting any service (Guarantees).
- One question, one mechanism. Biscuit answers "who may propose what" on the Bridge; a signature answers "what did the Bridge accept" in the player's hands. A token stolen at one step does not open the next (Security: Biscuit and signatures).
- Real networks repeat and drop. Delivery is at least once and applied once: every hop may retry with the same key, and the save remembers what was applied (Guarantees).
- The game calling services itself. Set aside: it would put sockets, secrets and untrusted text in the player, and make a proof depend on the network.
-
COSE instead of a compact JWS for the signed signal: it needs a CBOR decoder in the player for nothing a JWS
lacks here. It stays the fallback if a supported browser drops Ed25519 (D15,
docs/dev/reality-spike.md). - Biscuit in the player. The player never sees a Biscuit: it holds a narrow read-and-acknowledge capability (D16).
- "Exactly once" delivery. Not promised anywhere: delivery is at least once, applied idempotently, one logical effect per key (ADR 0008).
- Per-tenant keys derived by construction, which would make a signal's tenant implicit. Set aside: the player cannot check a derivation whose root it does not hold. A signal names its context instead (ADR 0010).
- Two formats to keep (Biscuit and the JWS), a Rust cross-check of Biscuit in CI (
npm run reality:xcheck), keys to rotate. - An author declares every signal, and a
requiredone names a fallback the player can use instead: more to write, and the game must be finishable with no outside at all. - An operator runs one more service (and one process per connector), with its store, its keys and its backups.
Limit ·
bridge-not-a-game-serverThe Bridge carries declared signals from outside to one player's game. It runs no game logic, holds no save, and does not share a game's state between players.
Limit ·
bridge-experimental-partsThe connectors and thedistributedprofile are experimental: every contract and abuse test runs in CI, but no person has yet run a connector against a real email provider, a real badge or a terminal exposed on a network, nor thedistributedprofile behind a real domain for 24 to 48 hours.
- ADR 0007: Biscuit authorises a connector; a signature attests an event.
- ADR 0008: a connector is a process of its own, behind one small SDK.
- ADR 0009: the Bridge keeps its state behind an asynchronous store.
- ADR 0010: a signed signal names the context it was signed for.
- The spike's measures behind D15 and D16:
docs/dev/reality-spike.md; the threat models:docs/dev/THREAT-MODEL.mdanddocs/dev/threat-models/.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits