Initial: RAPPORT-HOST Iteration 1 (proprietär)
Kommerzielle Hosting-/Abo-Plattform für Rapport-Instanzen. - React-Frontend (Vite/JSX): Landing, Register, Login, Plans, Dashboard - Node/Express-Backend: Auth (bcrypt+JWT), Stripe-Billing, Provisioning - HOST-Postgres-Schema: accounts, subscriptions, instances - Provisioning-Interface + Modell-A-Adapter (Studio im geteilten Stack) - MOCK-Modus: voller End-to-End-Flow ohne Stripe/Rapport-Stack testbar - Idempotentes Fulfillment (Upsert auf stripe_subscription_id) - docker-compose für lokale host-db; identisch auf Hetzner deploybar E2E lokal verifiziert: Register -> Checkout(mock) -> Instanz -> Idempotenz. Lizenz: proprietär (kein AGPL-Code eingebunden, nur Netzwerk-API zur Familie). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
# RAPPORT-HOST — Architektur
|
||||
|
||||
## 1 · Mentales Modell
|
||||
|
||||
RAPPORT-HOST ist die **kommerzielle Schicht** über der Rapport-Familie. Es
|
||||
verkauft und provisioniert Rapport-Instanzen, berührt aber die Tenant-Daten der
|
||||
Kunden nicht direkt — es spricht mit dem Rapport-Stack nur über dessen API.
|
||||
|
||||
```
|
||||
Browser ──/api──▶ Node/Express (server/) ──▶ HOST-Postgres (Konten/Abos/Instanzen)
|
||||
│ │
|
||||
│ ├──▶ Stripe (Checkout + Webhook)
|
||||
│ └──▶ Rapport-Stack-API (Provisioning, service_role)
|
||||
└── React (src/)
|
||||
```
|
||||
|
||||
## 2 · Lizenz-Abgrenzung (wichtig)
|
||||
|
||||
RAPPORT-HOST ist **proprietär**. Die übrigen Repos sind **AGPL-3.0**. Damit die
|
||||
AGPL nicht auf HOST „überspringt", gilt eine harte Regel: **kein AGPL-Code wird
|
||||
importiert oder kopiert.** Die Kommunikation läuft ausschließlich über
|
||||
Netzwerk-APIs (HTTP/REST). So bleibt HOST ein eigenständiges Werk.
|
||||
|
||||
## 3 · Verzeichnis-Karte
|
||||
|
||||
```
|
||||
RAPPORT-HOST/
|
||||
├── src/ React-Frontend (JSX, kein TS — wie APP)
|
||||
│ ├── App.jsx Mini-Pfad-Router
|
||||
│ ├── api.js fetch-Client + Token-Handling
|
||||
│ └── views/ Landing, Register, Login, Plans, Dashboard
|
||||
├── server/ Node/Express-Backend
|
||||
│ ├── index.js Entry; Webhook-Raw-Body vor json()
|
||||
│ ├── env.js Env laden + MOCK-Flags
|
||||
│ ├── db.js pg-Pool (HOST-DB)
|
||||
│ ├── auth.js bcrypt + JWT + requireAuth
|
||||
│ ├── plans.js Plan-Definitionen (Preise, Limits, Stripe-Price)
|
||||
│ ├── stripe.js Stripe-Client (null im Mock)
|
||||
│ ├── routes/ auth · billing · account
|
||||
│ ├── provisioning/ index (Interface) + studio-adapter (Modell A)
|
||||
│ ├── migrations/0001_init.sql HOST-Schema
|
||||
│ └── migrate.js Migrations-Runner
|
||||
├── docker-compose.yml host-db (+ app für Prod, auskommentiert)
|
||||
└── .env.example
|
||||
```
|
||||
|
||||
## 4 · Datenmodell (HOST-DB)
|
||||
|
||||
- **accounts** — zahlende Büros (Email + bcrypt-Hash). NICHT die Endnutzer.
|
||||
- **subscriptions** — Plan, Status, Stripe-IDs, Periodenende. `stripe_subscription_id`
|
||||
ist der Idempotenz-Key fürs Fulfillment.
|
||||
- **instances** — provisionierte Rapport-Instanzen (Modell A: `studio_id` +
|
||||
`studio_slug` im geteilten Stack, `instance_url`, Status).
|
||||
|
||||
Bewusst **getrennt** von der Rapport-/Kunden-Datenbank.
|
||||
|
||||
## 5 · Zahlungs-/Provisioning-Flow
|
||||
|
||||
```
|
||||
Plan wählen ─▶ POST /api/billing/checkout
|
||||
│
|
||||
Stripe? ──┤── nein (MOCK): fulfill() sofort ─▶ Erfolgs-URL
|
||||
│── ja: Stripe-Checkout-Session ─▶ Redirect zu Stripe
|
||||
│
|
||||
Stripe ─POST /api/billing/webhook (checkout.session.completed)
|
||||
│
|
||||
fulfill()
|
||||
├─ subscriptions upsert
|
||||
└─ provision() ─▶ instances insert
|
||||
```
|
||||
|
||||
`fulfill()` ist idempotent (Upsert auf `stripe_subscription_id`, Instanz nur wenn
|
||||
noch keine existiert) — Stripe kann Webhooks mehrfach senden.
|
||||
|
||||
## 6 · Provisioning-Modelle
|
||||
|
||||
Hinter dem Interface `provisioning/index.js`:
|
||||
|
||||
- **Modell A (jetzt, `studio-adapter.js`)**: ein isoliertes Studio im geteilten
|
||||
Rapport-Stack. Vermarktet als „eigene Instanz", technisch RLS-Mandant.
|
||||
Millisekunden, solo-betreibbar.
|
||||
- Echtes Provisioning braucht im Rapport-Schema noch ein server-seitiges
|
||||
RPC `create_studio_for_user(p_user_id, p_name, p_slug)` (da
|
||||
`create_studio_with_admin` auf `auth.uid()` baut). Bis dahin: MOCK-Modus.
|
||||
- **Modell B (später)**: eigener Container/Stack pro Kunde (volle Isolation,
|
||||
„Dedicated"-Tier). Neuer Adapter mit identischer Signatur — hier käme
|
||||
`SERVER-PROXMOX-LXC` als Provisioning-Backend ins Spiel.
|
||||
|
||||
## 7 · MOCK-Modus
|
||||
|
||||
Zwei unabhängige Schalter (in `env.js`):
|
||||
|
||||
- `stripeEnabled` — false ohne `sk_…`-Key ⇒ Checkout schaltet sofort frei.
|
||||
- `provisioningMock` — true ohne `RAPPORT_API_URL`/`SERVICE_KEY` ⇒ Instanz wird
|
||||
nur als DB-Eintrag mit synthetischer `studioId` simuliert.
|
||||
|
||||
So ist der komplette Flow lokal testbar, bevor Stripe-Account und Rapport-Stack
|
||||
stehen. In Produktion sind beide Schalter aus.
|
||||
|
||||
## 8 · Roadmap
|
||||
|
||||
- [ ] Iteration 1: Register/Login, Stripe-Checkout, Webhook, Dashboard (MOCK-fähig)
|
||||
- [ ] `create_studio_for_user`-RPC im Rapport-Schema → echtes Modell-A-Provisioning
|
||||
- [ ] Stripe Customer-Portal (Abo verwalten/kündigen)
|
||||
- [ ] Super-Admin (Kundenübersicht, Umsatz, sperren)
|
||||
- [ ] QR-Rechnung für Geschäftskunden
|
||||
- [ ] Modell B: Container-Provisioning-Adapter
|
||||
- [ ] Deploy auf Hetzner
|
||||
Reference in New Issue
Block a user