Skip to content

Architecture decisions

An Architecture Decision Record (ADR) captures one decision that is expensive to reverse: its context, the choice, and the consequences. ADRs are never edited after acceptance except to mark them Superseded by NNNN; a changed mind is a new ADR.

Create one with /new-adr or by copying the template to the next free number.

#DecisionStatus
0001One monorepo; games independent through a contractAccepted
0002Games run in a sandboxed iframe on their own originAccepted; in production on games.toheplay.io.vn since 0039, 0040
0003Backend: .NET 10 modular monolith + PostgreSQLAccepted
0004Identity: households, adult accounts and child profilesSuperseded by 0023
0005Offline first: games keep working without the APIAccepted; a ranked run needs the network to start, since 0030
0006Docs as code, rendered by Starlight, written for humans and agentsAccepted
0007Immutable versioned game builds + a catalog indexed by the APIAccepted
0008Technology baselineAccepted; game default amended by 0012
0009Local environment: 47xx ports, compose, isolationAccepted
0010Environments: development and UAT on the homelabAccepted; production decided by 0021; UAT deploys a uat- tag since 0041
0011Sign in with username and password first; OAuth laterAccepted; invites removed by 0023; email sign-in by 0024; manage PIN and step-up by 0025; OAuth by 0026
0012Phaser 4 and the game kit are the default way to build gamesAccepted
0013Light and dark themes from shared design tokensAccepted
0014Live scores for runs that last across sittingsAccepted; boards follow the server’s clock and trust since 0029; ranked runs verified when they end since 0030
0015Collect technical telemetry from players’ devices, first-party and visibleAccepted; the switch is the account’s since 0023
0016Online rooms for turn-based games, refereed by the API with the game’s own rulesAccepted; the seed’s secrecy amended by 0017; household tables are account tables since 0023; calendar weeks and the two-people rule since 0029; invitations reach beyond the account by ID since 0033
0017Replay finished online hands with the game’s own rules moduleAccepted; a deleted player’s seat shows as such since 0034
0018Every game opens on its own main menu and has one menu buttonAccepted; the screens amended by 0019 and 0020
0019Give every game a title screen, a HUD and a pause that holds, from the kitAccepted; stages amended by 0020
0020Give every game a menu stage and a play stageAccepted
0021Release production through the Tò He Helm chart; one set of images configured at run timeAccepted; promotion follows a prod- tag since 0041; HSTS for subdomains and the site to serve only the docs by 0042
0022Send transactional email through an outbox and an SMTP relayAccepted
0023Accounts own their profiles; every profile has a public ID and a free nameAccepted; inviting by ID since 0033; deletion and retired IDs since 0034; the name filter since 0035
0024Email identifies an account; a code opens only the attempt it was sent forAccepted; email change behind step-up by 0025; signing up may need an invite code, or be closed, by 0028
0025Step up in two levels; sign up at 16 or older, accepting the termsAccepted
0026Sign in with Google, GitHub or an OpenID Connect issuer; link a provider by its subject, after proofAccepted; a configured provider can be switched off by 0028
0027Run the platform from an admin console on the hub’s origin; roles grant permissions; a setup token makes the first ownerAccepted; the console frames the games origin to watch a ranked run since 0032; the audit log keeps a year since 0034; the console moved to its own host, with a sign-in of its own, by 0042
0028Switch sign-in methods and registration at run time; communities join by invite codeAccepted; the proof-of-work switch since 0037
0029One integrity engine gives every result a trust level from its evidence; boards read by trustAccepted; a result left to people keeps its value since 0031; a deleted profile’s results go with their decisions since 0034
0030Ranked runs: the server deals the seed, the game hands in its moves, the server replays themAccepted; a ranked game also plays a run back to watch since 0032
0031People decide what the engine held: the console’s review, and profiles hidden from public boardsAccepted
0032Watch a ranked run in the game itself, in the admin consoleAccepted
0033Invite a profile to a table by its ID, as its owner allows; a child is never found from outsideAccepted
0034Delete a profile at once and an account after seven days, with everything of them; the append-only logs get one way out eachAccepted; after its seven days an account waits for an admin since 0038
0035Refuse names with an offensive word, matched as people write it; an owner renames a profile five times a dayAccepted
0036Export metrics for Prometheus with prometheus-net, on a port of the API’s ownAccepted
0037A self-hosted proof-of-work before a code by email, behind a switch of the consoleAccepted
0038After its seven days, an account waits for an admin to delete it; nothing deletes it by itselfAccepted
0039Serve games from a registrable domain of their ownAccepted; all of Tò He on toheplay.io.vn since 0040
0040Run all of Tò He on toheplay.io.vn, the games one level below the hubAccepted; hosts and paths laid out by 0042
0041Promote one build through the environments by tag; production runs only what ran on UATAccepted
0042Lay out Tò He by trust: one domain, a host per trust boundary, a path per componentAccepted
0043Every player is a profile of this device or of an account; the highest level any source needs is asked forAccepted; arrives in steps (I1, I2)