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:
@@ -0,0 +1,43 @@
|
||||
// Abo-Pläne — eine Quelle der Wahrheit für Frontend (Preisanzeige) und Backend
|
||||
// (Stripe-Price-Mapping + Instanz-Limits beim Provisioning).
|
||||
import { env } from "./env.js";
|
||||
|
||||
export const PLANS = [
|
||||
{
|
||||
id: "solo",
|
||||
name: "Solo",
|
||||
priceChf: 19,
|
||||
interval: "Monat",
|
||||
stripePriceId: env.stripe.prices.solo,
|
||||
limits: { users: 1, projects: 25, storageGb: 2 },
|
||||
features: ["1 Benutzer", "25 Projekte", "2 GB Speicher", "Eigene Instanz"],
|
||||
},
|
||||
{
|
||||
id: "studio",
|
||||
name: "Studio",
|
||||
priceChf: 49,
|
||||
interval: "Monat",
|
||||
stripePriceId: env.stripe.prices.studio,
|
||||
limits: { users: 5, projects: 200, storageGb: 20 },
|
||||
features: ["Bis 5 Benutzer", "200 Projekte", "20 GB Speicher", "Eigene Instanz", "Support"],
|
||||
recommended: true,
|
||||
},
|
||||
{
|
||||
id: "business",
|
||||
name: "Business",
|
||||
priceChf: 99,
|
||||
interval: "Monat",
|
||||
stripePriceId: env.stripe.prices.business,
|
||||
limits: { users: 20, projects: 1000, storageGb: 100 },
|
||||
features: ["Bis 20 Benutzer", "1000 Projekte", "100 GB Speicher", "Eigene Instanz", "Prioritäts-Support"],
|
||||
},
|
||||
];
|
||||
|
||||
export function getPlan(id) {
|
||||
return PLANS.find((p) => p.id === id) || null;
|
||||
}
|
||||
|
||||
// Fürs Frontend: ohne interne Felder (Stripe-IDs müssen nicht raus).
|
||||
export function publicPlans() {
|
||||
return PLANS.map(({ stripePriceId, ...rest }) => rest);
|
||||
}
|
||||
Reference in New Issue
Block a user