Deploy / Betrieb (Cloudflare) — Runbook (OP-DEPLOY-1)
Stand: Vorbereitet; der erste echte Deploy steht aus (Domain-Transfer + Credentials, s. u.). Ziel: eine Subdomain
app.medidentas.combedient UI + API über einen Worker (Workers + Static Assets). Begründung: ein Origin → Cloudflare Access (R7) schützt UI und API in einer Policy, kein CORS, ein TLS-Zertifikat. Quelle des Stacks:Stack.md(A-4).
1. Architektur des Deploys
app.medidentas.com (Cloudflare Access davor, R7/OP-AUTH-1)
│
┌──────┴───────────────┐
Static Assets│ Worker medidentas-api│ (server/, Hono)
(Angular UI) │ /api/* → Hono │
dist/browser │ sonst → ASSETS │ ── D1 (medidentas) · Cron (R5)
└───────────────────────┘
- UI: Angular-Build (
client/dist/browser) als Static Assets desselben Workers (wrangler.toml [assets],binding = "ASSETS"). SPA-Deep-Links fallen inserver/src/index.tsaufindex.htmlzurück. - API: alles unter
/api/*→ Hono-App (unverändert). - DB: D1
medidentas(idempotente Auto-Migration beim Start,db/migrate.ts). - Cron: stündliche Wiedervorlage-Erinnerungen (R5,
[triggers]).
2. Entscheidungen (28.06.2026)
- Domain verfügbar:
medidentas.comliegt bereits im Cloudflare-Account (Zone aktiv) → der Custom-Domain-Deploy aufapp.medidentas.comist technisch nicht mehr blockiert. Die im OP genannte Übertragung an HQ ist eine organisatorische Folgeaufgabe (Eigentümer-/Account-Zuordnung), kein Deploy-Blocker mehr. - EU-Datenresidenz = Pflicht (G-5, OP-DSGVO-1, RISK-17): alle personenbezogenen Daten in der EU:
D1 mit EU-Location-Hint anlegen (
--location weur⟶ Western Europe), NextCloud EU-gehostet (A-1), Cloudflare Data Localization Suite (Regional Services + EU Metadata Boundary) für die Zone, keine US-Sub-Prozessoren ohne AVV/SCC (RISK-4/RISK-15). Vor Produktiv-Go-live verbindlich prüfen. - Deploy-Weg = CI:
CLOUDFLARE_API_TOKEN+CLOUDFLARE_ACCOUNT_IDals GitHub-Actions-Secrets → Deploy über den manuellen Workflowapp-deploy.yml(workflow_dispatch). - „Sofort absichern": Betrieb hinter Cloudflare Access mit
AUTH_ENFORCED=truevon Anfang an. ⚠️ Wichtig: Access (self-hosted) braucht einen Hostnamen in eurer Zone —*.workers.devlässt sich nicht mit Access schützen.AUTH_ENFORCED=trueohne Access davor ⇒ jeder/api-Request hat keinencf-access-…-Header ⇒ 401 (App unbedienbar). Konsequenz: der abgesicherte Test läuft aufapp.medidentas.com(Zone ist da), nicht auf*.workers.dev.
3. Voraussetzungen
- ✅ Domain
medidentas.com— im Cloudflare-Account vorhanden (Zone aktiv). HQ-Eigentümer- Zuordnung: organisatorischer Folgepunkt (OP-DEPLOY-1). - Deploy-Credential:
CLOUDFLARE_API_TOKEN(Scopes: Workers Scripts: Edit, D1: Edit, Workers KV/Assets, bei Custom Domain zusätzlich Zone: DNS/Workers Routes) +CLOUDFLARE_ACCOUNT_IDals GitHub-Actions-Secrets. Nie im Repo (RISK-8). - Secrets (per
wrangler secret put, nicht im Repo):NEXTCLOUD_URL/USER/APP_PASSWORD(R3/R9, EU- Hosting), späterSIGNATUR_PROVIDER+ Provider-Keys (R4/OP-SIGN-1).
4. D1-Datenbank anlegen (einmalig, EU-Residenz)
cd server
npx wrangler d1 create medidentas --location weur # EU (Western Europe) — Pflicht (G-5)
# → gibt eine database_id aus; in wrangler.toml unter [[d1_databases]] eintragen
# (Platzhalter REPLACE_WITH_D1_ID ersetzen). Die Auto-Migration läuft beim ersten Request.
5. Empfohlener Weg — abgesichert auf app.medidentas.com (EU)
„Sofort absichern" gewählt + Zone ist verfügbar ⇒ direkt auf die Subdomain (Access schützt keine
*.workers.dev). Reihenfolge:
- Secrets setzen (GitHub → Settings → Secrets → Actions):
CLOUDFLARE_API_TOKEN,CLOUDFLARE_ACCOUNT_ID. - D1 anlegen (Schritt 4,
--location weur) +database_idinwrangler.tomleintragen. - EU-Datenresidenz für die Zone sicherstellen (Data Localization Suite: Regional Services + EU Metadata Boundary) — G-5/RISK-17.
- Custom-Domain-Route in
wrangler.tomlaktivieren:routes = [{ pattern = "app.medidentas.com", custom_domain = true }]. - Cloudflare Access Application für
app.medidentas.comanlegen (IdP/SSO), Policy auf die berechtigten E-Mails;AUTH_ENFORCED=true+AUTH_BOOTSTRAP_ADMIN=<deine-mail>als Worker-Vars. - Deploy via GitHub Actions: Workflow App Deploy manuell starten (
workflow_dispatch). - Smoke-Test:
GET /api/health(authEnforced: true), UI lädt, Deep-Link…/mandant/xlädt (SPA-Fallback), Mandant anlegen → Audit-Eintrag mit echter Identität.
6. Optional: ungeschützter Vorab-Smoke-Test auf *.workers.dev
Da die Zone medidentas.com bereits verfügbar ist, ist dieser Schritt i. d. R. nicht nötig — der
abgesicherte Weg (§5) ist direkt möglich. Falls dennoch ein schneller Funktions-Check gewünscht ist:
ohne Access (Access schützt keine *.workers.dev), daher AUTH_ENFORCED nicht auf true
(Dev-Akteur = admin). Kein abgesicherter Betrieb, nur Dummy-Daten, keine produktiven
Provider-Secrets/PII. cd client && npm run build && cd ../server && npx wrangler deploy
→ https://medidentas-api.<account>.workers.dev.
7. CI-Deploy-Workflow
.github/workflows/app-deploy.yml (workflow_dispatch) baut Client + Worker und ruft wrangler deploy,
sobald CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID als Secrets gesetzt sind. Bricht nicht das
CI Gate (separater, nur manuell ausgelöster Job).
7a. Self-Service-Onboarding freischalten (Slice 9, OP-ONBOARD-1)
Die öffentliche Formularseite läuft außerhalb Cloudflare Access. Damit der Einladungslink nicht im Access-Login landet:
- Cloudflare Access → Application
Medidentas App: eine Bypass-Policy (Action „Bypass", Include „Everyone") nur für die Pfade/onboarding*und/oeffentlich*hinzufügen. (Alle anderen Pfade bleiben durch „HQ + MK" geschützt.) - Bot-Schutz (empfohlen): Cloudflare Turnstile-Widget anlegen →
TURNSTILE_SITEKEYals Worker-Var,wrangler secret put TURNSTILE_SECRET. Ohne Secret wird nicht geprüft (nur Token/Ablauf schützen). DEMO_MODE(wrangler.toml [vars]) ist aktuell"true"→ Einwilligung end-to-end testbar mit Fakes (NextCloud/Signatur), ohne echte eIDAS-Rechtswirkung. Auf"false"stellen, sobald echte NextCloud-/Signatur-Secrets gesetzt sind.- Einwilligungstext (
server/src/domain/einwilligung.ts) vor echtem Einsatz juristisch prüfen (RISK-18); bei TextänderungEINWILLIGUNG_VERSIONhochzählen.
8. Offene Punkte
- OP-DEPLOY-1 — Zone
medidentas.comist im Account; offen: Credentials/Secrets + erster Deploy + HQ-Eigentümer-Zuordnung (organisatorisch). S. Lastenheft §11. - EU-Datenresidenz (Pflicht, G-5/RISK-17): D1
--location weur, NextCloud EU-gehostet, Cloudflare Data Localization Suite (Regional Services + EU Metadata Boundary), keine US-Sub-Prozessoren ohne SCC. - Subdomain-Schema final:
app.(Anwendung) —www./Apex bleibt für eine spätere Marketing-Seite frei.