{"$comment":"Het architectuurmodel van Dorelli Cloud: één bron voor hoofdlijnen.md, de pagina /architecture en de tekeningen. Stand per onderdeel: live | gepland | idee. Teksten in nl en en, omdat de site Engels als hoofdtaal heeft.","versie":"2026-09-20.1","status":"versie 1, richting gekozen door Melle op 20 sep 2026 (ARCHITECTUUR.md §5, besluit 0004)","product":{"nl":"Managed hosting voor mensen en agents: bouwstenen onder eigen merk, op elke wolk.","en":"Managed hosting for people and agents: building blocks under one brand, on any cloud."},"keuzes":{"$comment":"De antwoorden op de dertien vragen die de pagina en de tekening sturen. Wijzigen is een nieuw besluit.","lezer":"customer","belofteCentraal":"brand","vasteLaag":"edge","leveranciersZichtbaar":"alleen in de laag providers, nooit in namen of hostnamen","multiCloud":{"doel":"onzichtbaar: het platform plaatst","optie":"voorkeur van de klant","buitenScope":"verdeeld over twee wolken, tot iemand ervoor betaalt"},"platform":"één blok; de splitsing in website en besturingsvlak staat als gepland onderdeel","werkplaats":"in de tekening, buiten het productiepad","publicatie":{"pagina":"/architecture","json":"/architecture.json","links":["footer","kennisbank"]}},"uitgangspunten":[{"sleutel":"cloud-only","nl":"Alleen cloud","en":"Cloud only"},{"sleutel":"cloud-native","nl":"Beheerd boven zelf draaien","en":"Cloud native"},{"sleutel":"cloud-agnostic","nl":"Wolk is een eigenschap, geen product","en":"Cloud agnostic"},{"sleutel":"agents","nl":"Agents bouwen en beheren","en":"Built and run by agents"},{"sleutel":"secure","nl":"Secure by design","en":"Secure by design"},{"sleutel":"flexible","nl":"Bouwstenen, geen pakketten","en":"Flexible"},{"sleutel":"scalable","nl":"Schaalt naar nul en omhoog","en":"Scalable"},{"sleutel":"for-everybody","nl":"Hosting voor iedereen","en":"Hosting for everybody"},{"sleutel":"proof","nl":"Bewijs, geen bewering","en":"Proof, not claims"},{"sleutel":"reversible","nl":"Omkeerbaar","en":"Reversible"},{"sleutel":"brand","nl":"Eigen merk, leverancier onzichtbaar","en":"One brand"},{"sleutel":"one-person","nl":"Eén persoon, dus alles automatisch","en":"Automated by necessity"},{"sleutel":"eu","nl":"Gegevens in de EU","en":"Data in the EU"}],"lagen":[{"id":"users","nl":"Mensen en agents","en":"People and agents","kort":{"nl":"Wie het platform gebruikt","en":"Who uses the platform"}},{"id":"edge","nl":"Rand: merk en schild","en":"Edge: brand and shield","leverancier":"cloudflare","kort":{"nl":"Alles wat de wereld ziet. Vaste laag, gaat nooit naar een andere leverancier.","en":"Everything the world sees. The fixed layer; never moves."}},{"id":"platform","nl":"Platform","en":"Platform","kort":{"nl":"Site, portaal, API en het besturingsvlak dat bouwstenen maakt, meet en afrekent.","en":"Site, portal, API and the control plane that provisions, meters and bills."}},{"id":"customer","nl":"Klantruntime","en":"Customer runtime","kort":{"nl":"Wat voor klanten draait, per klant afgeschermd en gemeten.","en":"What runs for customers, isolated and metered per customer."}},{"id":"workshop","nl":"Werkplaats","en":"Workshop","kort":{"nl":"Waar agents bouwen, testen en beslissen. Buiten het productiepad.","en":"Where agents build, test and decide. Outside the production path."}},{"id":"providers","nl":"Wolken","en":"Clouds","kort":{"nl":"Verwisselbaar per bouwsteen. Vandaag één, straks drie.","en":"Interchangeable per building block. One today, three tomorrow."}}],"onderdelen":[{"id":"customer-person","laag":"users","nl":"Klant","en":"Customer","kort":{"nl":"Bouwt zelf met Lovable, v0 of Claude en wil de laatste meter: domein, e-mail, factuur.","en":"Builds with Lovable, v0 or Claude and wants the last mile: domain, email, invoice."},"stand":"live","uitgangspunten":["for-everybody"]},{"id":"agent-user","laag":"users","nl":"AI-agent","en":"AI agent","kort":{"nl":"Zet een site of app neer via CLI, MCP of GitHub Action; foutcodes met docs-URL.","en":"Deploys a site or app via CLI, MCP or GitHub Action; error codes link to docs."},"stand":"live","uitgangspunten":["for-everybody","agents"],"bron":"packages/dorelli"},{"id":"operator","laag":"users","nl":"Beheerder","en":"Operator","kort":{"nl":"Eén persoon. Keurt besluiten goed via Telegram; de rest loopt vanzelf.","en":"One person. Approves decisions via Telegram; the rest runs itself."},"stand":"live","uitgangspunten":["one-person","agents"]},{"id":"dns","laag":"edge","nl":"DNS en domeinen","en":"DNS and domains","kort":{"nl":"dorelli.cloud, <slug>.dorelli.cloud als wildcard, klantdomeinen met e-mail.","en":"dorelli.cloud, wildcard <slug>.dorelli.cloud, customer domains with email."},"stand":"live","leverancier":"cloudflare","uitgangspunten":["brand"],"bron":"CLOUDFLARE.md"},{"id":"shield","laag":"edge","nl":"Proxy en schild","en":"Proxy and shield","kort":{"nl":"TLS, WAF, Turnstile tegen bots, Origin CA naar de wolk. De origin is nooit zichtbaar.","en":"TLS, WAF, Turnstile against bots, Origin CA to the cloud. The origin is never exposed."},"stand":"live","leverancier":"cloudflare","uitgangspunten":["secure","brand"]},{"id":"email-edge","laag":"edge","nl":"E-mail in en uit","en":"Email in and out","kort":{"nl":"support@ en abuse@ komen als ticket binnen; uitgaande mail met DKIM en DMARC.","en":"support@ and abuse@ arrive as tickets; outbound mail with DKIM and DMARC."},"stand":"live","leverancier":"cloudflare","uitgangspunten":["one-person"],"bron":"workers/inbound-mail"},{"id":"edge-workers","laag":"edge","nl":"Edge-functies","en":"Edge functions","kort":{"nl":"Statuspagina die ook werkt als het platform plat ligt; straks foutpagina's en registry-proxy.","en":"Status page that works even when the platform is down; error pages and registry proxy next."},"stand":"live","leverancier":"cloudflare","uitgangspunten":["proof","brand"],"bron":"workers/status"},{"id":"tunnel","laag":"edge","nl":"Tunnel naar de werkplaats","en":"Tunnel to the workshop","kort":{"nl":"Previews en interne tooling bereikbaar zonder één open poort.","en":"Previews and internal tooling reachable without a single open port."},"stand":"live","leverancier":"cloudflare","uitgangspunten":["secure"],"bron":"SERVER-NORTHSTAR.md"},{"id":"edge-storage","laag":"edge","nl":"Edge-opslag","en":"Edge storage","kort":{"nl":"R2 zonder uitgaande kosten: statische sites aan de rand, leverancieronafhankelijke bestanden.","en":"R2 without egress fees: static sites at the edge, provider-independent files."},"stand":"gepland","leverancier":"cloudflare","uitgangspunten":["cloud-agnostic","scalable"],"bron":"backlog/edge-serving.md"},{"id":"site","laag":"platform","nl":"Website en portaal","en":"Website and portal","kort":{"nl":"Zes talen, prijzen met bewijs, portaal per klant, admin voor de beheerder.","en":"Six languages, prices with proof, a portal per customer, admin for the operator."},"stand":"live","uitgangspunten":["for-everybody","proof"],"bron":"app/"},{"id":"api","laag":"platform","nl":"API en MCP","en":"API and MCP","kort":{"nl":"Eén API; CLI, MCP-server, GitHub Action en de agents zijn schillen eromheen.","en":"One API; the CLI, MCP server, GitHub Action and agents are shells around it."},"stand":"live","uitgangspunten":["for-everybody","agents"],"bron":"app/openapi.json"},{"id":"control-plane","laag":"platform","nl":"Besturingsvlak","en":"Control plane","kort":{"nl":"Maakt bouwstenen aan, meet per minuut, rekent dagelijks af, ruimt op. Fail closed en luid.","en":"Provisions building blocks, meters per minute, bills daily, cleans up. Fails closed and loud."},"stand":"live","uitgangspunten":["cloud-native","one-person","secure"],"bron":"lib/bouwstenen"},{"id":"platform-split","laag":"platform","nl":"Website en besturingsvlak los","en":"Website and control plane apart","kort":{"nl":"Vandaag één app; straks de site apart van het besturingsvlak, zodat uitrollen zonder onderbreking kan.","en":"One app today; the site separate from the control plane next, so releases never interrupt."},"stand":"gepland","uitgangspunten":["scalable","reversible"],"bron":"PLAN-VAN-AANPAK.md Blok D"},{"id":"platform-db","laag":"platform","nl":"Platformdatabase","en":"Platform database","kort":{"nl":"Beheerde Postgres, privé in het netwerk. De omslag van SQLite loopt.","en":"Managed Postgres, private in the network. Migration from SQLite in progress."},"stand":"gepland","leverancier":"azure","uitgangspunten":["cloud-native","secure"],"bron":"AUTONOMIE-INVOERING.md §17"},{"id":"identity","laag":"platform","nl":"Identiteit zonder sleutels","en":"Identity without keys","kort":{"nl":"Het platform praat met de wolk via zijn eigen identiteit; geen wachtwoorden in configuratie.","en":"The platform talks to the cloud through its own identity; no passwords in config."},"stand":"live","leverancier":"azure","uitgangspunten":["secure"]},{"id":"backup","laag":"platform","nl":"Back-up en herstel","en":"Backup and restore","kort":{"nl":"Dagelijks, met een geteste herstelprocedure. Een back-up die je niet terugzet is geen back-up.","en":"Daily, with a tested restore. A backup you never restored is not a backup."},"stand":"live","leverancier":"azure","uitgangspunten":["reversible","proof"],"bron":"BACKUP.md"},{"id":"billing","laag":"platform","nl":"Abonnementen en incasso","en":"Subscriptions and billing","kort":{"nl":"Mandaat, factuur, variabele incasso op gemeten verbruik, storno met pauze.","en":"Mandate, invoice, variable debit on metered usage, chargeback with pause."},"stand":"live","leverancier":"mollie","uitgangspunten":["one-person","flexible"],"bron":"lib/mollie.ts"},{"id":"observability","laag":"platform","nl":"Meten en bewijzen","en":"Measure and prove","kort":{"nl":"Gezondheid, uptime, verbruik per klant, wekelijkse audit met bewijs.","en":"Health, uptime, usage per customer, weekly audit with evidence."},"stand":"live","uitgangspunten":["proof"],"bron":"audits/"},{"id":"trial-sites","laag":"customer","nl":"Statische sites","en":"Static sites","kort":{"nl":"Upload of push, gemodereerd vóór publicatie, live op <slug>.dorelli.cloud binnen een minuut.","en":"Upload or push, moderated before publishing, live at <slug>.dorelli.cloud within a minute."},"stand":"live","leverancier":"azure","uitgangspunten":["for-everybody","secure"],"bron":"HOSTING-FUNNEL.md"},{"id":"containers","laag":"customer","nl":"App-containers","en":"App containers","kort":{"nl":"Eigen container per klant, schaalt naar nul, eigen domein, gemeten per minuut.","en":"A container per customer, scales to zero, own domain, metered per minute."},"stand":"live","leverancier":"azure","uitgangspunten":["scalable","flexible","cloud-native"],"bron":"VERBRUIK-INVOERING.md"},{"id":"customer-db","laag":"customer","nl":"Databases","en":"Databases","kort":{"nl":"Gedeelde Postgres met een database en rol per klant, of een eigen server.","en":"Shared Postgres with a database and role per customer, or a dedicated server."},"stand":"live","leverancier":"azure","uitgangspunten":["flexible","secure"]},{"id":"customer-storage","laag":"customer","nl":"Opslag, cache, taken, logs","en":"Storage, cache, jobs, logs","kort":{"nl":"Losse bouwstenen met een eigen tarief; alleen betalen voor wat aanstaat.","en":"Separate building blocks with their own rate; pay only for what is on."},"stand":"live","leverancier":"azure","uitgangspunten":["flexible"]},{"id":"registry","laag":"customer","nl":"Registry","en":"Registry","kort":{"nl":"Images per klant met een eigen push-token; straks registry.dorelli.cloud.","en":"Images per customer with their own push token; registry.dorelli.cloud next."},"stand":"live","leverancier":"azure","uitgangspunten":["brand","secure"],"bron":"lib/acr.ts"},{"id":"isolation","laag":"customer","nl":"Afscherming per klant","en":"Isolation per customer","kort":{"nl":"Eigen resources, eigen tags, eigen plafond. Een weesscan vindt wat nergens bij hoort.","en":"Own resources, own tags, own ceiling. An orphan scan finds what belongs to no one."},"stand":"live","uitgangspunten":["secure","one-person"],"bron":"architectuur/tags.md"},{"id":"vm","laag":"workshop","nl":"Eigen server","en":"Own server","kort":{"nl":"VM op eigen ijzer: agentrunner, buildrunner, previews. Geen inkomend verkeer, geen productie.","en":"VM on own hardware: agent runner, build runner, previews. No inbound traffic, no production."},"stand":"live","leverancier":"proxmox","uitgangspunten":["cloud-only","agents"],"bron":"SERVER-NORTHSTAR.md"},{"id":"agent-roles","laag":"workshop","nl":"Agentrollen","en":"Agent roles","kort":{"nl":"Directie, engineering, review, SRE, onderhoud; elk met draaiboeken, budget en examen.","en":"Management, engineering, review, SRE, maintenance; each with runbooks, budget and an exam."},"stand":"live","uitgangspunten":["agents","one-person"],"bron":"agents/"},{"id":"pipeline","laag":"workshop","nl":"Bouwstraat","en":"Pipeline","kort":{"nl":"Worktree per wijziging, pull request, groene ronde, merge; release als bewuste stap.","en":"A worktree per change, pull request, green run, merge; release as a deliberate step."},"stand":"live","leverancier":"github","uitgangspunten":["proof","reversible"],"bron":"AGENTS.md"},{"id":"decisions","laag":"workshop","nl":"Besluiten","en":"Decisions","kort":{"nl":"Wat geld kost, onomkeerbaar is of klanten raakt wordt een besluit voor de beheerder, via Telegram.","en":"Anything that costs money, is irreversible or touches customers becomes a decision for the operator, via Telegram."},"stand":"live","uitgangspunten":["agents","reversible"],"bron":"lib/telegram.ts"},{"id":"azure","laag":"providers","nl":"Wolk A","en":"Cloud A","kort":{"nl":"Vandaag: Container Apps, Postgres, Blob, registry, in Nederland en Ierland.","en":"Today: Container Apps, Postgres, Blob, registry, in the Netherlands and Ireland."},"stand":"live","leverancier":"azure","uitgangspunten":["cloud-native","eu"]},{"id":"google","laag":"providers","nl":"Wolk B","en":"Cloud B","kort":{"nl":"Tweede wolk voor containers, in Nederland. Zelfde bouwsteen, zelfde meting, zelfde prijsregel.","en":"Second cloud for containers, in the Netherlands. Same building block, same metering, same pricing rule."},"stand":"gepland","leverancier":"google","uitgangspunten":["cloud-agnostic","eu"],"bron":"backlog/multi-cloud.md"},{"id":"aws","laag":"providers","nl":"Wolk C","en":"Cloud C","kort":{"nl":"Derde wolk als een klant erom vraagt en ervoor betaalt.","en":"Third cloud when a customer asks and pays for it."},"stand":"idee","leverancier":"aws","uitgangspunten":["cloud-agnostic"],"bron":"backlog/multi-cloud.md"},{"id":"placement","laag":"providers","nl":"Plaatsing","en":"Placement","kort":{"nl":"Per bouwsteen kiest het platform account en wolk op regio, prijs en beleid; een klant mag een voorkeur opgeven. De keuze is uitlegbaar.","en":"Per building block the platform picks account and cloud by region, price and policy; a customer may state a preference. The choice is explainable."},"stand":"gepland","uitgangspunten":["cloud-agnostic","flexible"],"bron":"AUTONOMIE-INVOERING.md §6.3"}],"verbindingen":[{"van":"customer-person","naar":"shield","nl":"bezoekt en beheert via de site","en":"visits and manages via the site"},{"van":"agent-user","naar":"api","nl":"CLI, MCP, GitHub Action","en":"CLI, MCP, GitHub Action"},{"van":"operator","naar":"decisions","nl":"keurt goed via Telegram","en":"approves via Telegram"},{"van":"shield","naar":"site","nl":"proxy naar de origin","en":"proxies to the origin"},{"van":"shield","naar":"trial-sites","nl":"<slug>.dorelli.cloud","en":"<slug>.dorelli.cloud"},{"van":"shield","naar":"containers","nl":"eigen domein per app","en":"own domain per app"},{"van":"control-plane","naar":"containers","nl":"maakt aan, meet, stopt","en":"provisions, meters, stops"},{"van":"control-plane","naar":"customer-db","nl":"database en rol per klant","en":"database and role per customer"},{"van":"control-plane","naar":"placement","nl":"vraagt: waar zet ik dit","en":"asks: where does this go"},{"van":"placement","naar":"azure","nl":"vandaag alles","en":"everything today"},{"van":"placement","naar":"google","nl":"containers, straks","en":"containers, next"},{"van":"billing","naar":"customer-person","nl":"factuur en incasso","en":"invoice and debit"},{"van":"agent-roles","naar":"pipeline","nl":"pull requests","en":"pull requests"},{"van":"pipeline","naar":"control-plane","nl":"release, na besluit","en":"release, after a decision"},{"van":"tunnel","naar":"vm","nl":"previews, zonder open poort","en":"previews, no open port"},{"van":"backup","naar":"platform-db","nl":"dagelijkse kopie, geteste terugzet","en":"daily copy, tested restore"}],"vast":[{"nl":"Klanten en agents zien dorelli.cloud, nooit de naam van een wolk.","en":"Customers and agents see dorelli.cloud, never the name of a cloud."},{"nl":"Elke bouwsteen heeft een terugdraaipad, een eigenaar in zijn tags en een plafond.","en":"Every building block has a rollback path, an owner in its tags and a ceiling."},{"nl":"Wat geld kost, onomkeerbaar is of klanten raakt, is een besluit voor een mens.","en":"Anything that costs money, is irreversible or touches customers is a decision for a human."},{"nl":"Elke belofte op de site wijst naar een bestand en een regel in de code.","en":"Every promise on the site points to a file and a line in the code."}]}