STATUS: ROZHODOVACÍ PODKLAD — NE hotová UC. Tento dokument nadřazeně přerámovává UC-10009 postpaid hosting DESIGN pod ADR-026 (Environment first-class). LOCKED decisions DP-0/1/2/3/5/6 zůstávají platné a beze změny — jen se zasazují do environment kontextu. DP-4 se přeformulovává per-environment (sekce 3). Phase-2a UC-10008 je kompletní, model-agnostic, NEMĚNÍ se. Finální sekvence / API kontrakty / test tabulky se NEpíšou, dokud user neodsouhlasí ADR-026 + Open Decisions + pořadí fází (dle zadání).
0. Co se mění oproti UC-10009 DESIGN
| Aspekt | UC-10009 DESIGN (per-tenant-hosting) | ENVIRONMENT REVISION (per-environment) |
|---|---|---|
| Jednotka hosting attribution | tenant (tenant-{slug} ns), DP-4 řešil intra-ns label-split | prostředí (= namespace, ADR-026 §3 invariant) |
| Cost měření | C.2 aggregate=namespace + plánovaný label-split (be#125) | C.2 aggregate=namespace → mapování ns→environment (label-split z velké části padá) |
| Co je „hosting” vs „ai-dev” | hranice uvnitř jednoho ns (worker vs app pody) | hranice = hranice prostředí; worker+Preview = infra-postpaid náklad prostředí „TalkIDE” |
| Faktura | jeden hosting řádek per user | per prostředí řádka na „Hosting/Infrastructure” faktuře |
| DP-4 enforcement | „suspend published prod app pody” | „suspend prostředí” — granularita per env; default „TalkIDE” speciální (OD-2) |
| be#125 | tvrdá závislost (V1 label-aware C.2) | z velké části padá; reziduum jen přechod + orphan safety (ADR-026 §6) |
Nemění se: dvě billing vrstvy (AI prepaid / infra postpaid), ledger jako
účetní pravda, decoupled enforcement (⚠️ hosting_credit_* sloupce odstraněny
v be#142 — prepaid back-door zrušen 2026-05-23, DP-7),
žádná nová Stripe webhook infra, UC-10008 marže do účtování.
1. LOCKED decisions — zasazení do environment kontextu
Tyto zůstávají závazné a beze změny. Níže jen kontext-mapping.
| DP | LOCKED rozhodnutí (beze změny) | Environment zasazení |
|---|---|---|
| DP-0 | AI zůstává prepaid (UC-10007 + UC-10008). Postpaid jen hosting. | Infra postpaid = compute/db/storage per prostředí včetně talkide-worker+Preview podu (prostředí „TalkIDE”). AI prepaid = jen Anthropic token inference. Decoupling drží — naopak je čistší (worker compute je teď explicitně infra-postpaid řádka prostředí „TalkIDE”, ne sporné „misattribuováno”). |
| DP-1 | Konfigurovatelný trial_days (default ~14, 0=off). | trial_ends_at se počítá per prostředí při prvním nasazení projektu do daného prostředí (nebo per tenant — Open Decision OD-5). Default „TalkIDE” trial: viz OD-2/OD-5. |
| DP-2 | Separátní hosting_spending_limit_usd (NE reuse UC-10005). | Cap je agregovaný hosting (Σ všech prostředí) NEBO per prostředí — viz OD-1 (granularita). Default doporučení: agregovaný (jeden srozumitelný strop), per-env jako budoucí seam. |
| DP-3 | Dunning 3 retry +0/+2/+5 dní → PAST_DUE → ~7d grace → SUSPENDED. | Faktura je per prostředí (nebo konsolidovaná s per-env řádky — OD-6). Dunning rozvrh beze změny; SUSPENDED rozsah = DP-4 přerámované (sekce 3). |
| DP-5 | Anchor = 1. kalendářního dne; billing_anchor_day seam. | Beze změny. Anchor je per billing účet (per tenant), faktura nese per-environment rozpad řádků. |
| DP-6 | FE estimate = reálná data + non-binding projected. | FE breakdown nově per prostředí (řádka za každé env: accrued + projected). „Next invoice on 1st” pravdivé. Disclaimer beze změny. |
2. Cílový datový model (delta proti UC-10009 DESIGN)
Beze změny zůstává: user_budget, hosting_credit_ledger
(append-only; settlement_mode sloupec odstraněn v be#142 — prepaid back-door zrušen 2026-05-23),
hosting_invoice, hosting_cost_events (immutable), pricing_markup_config, UC-10008 markup kontrakt.
Delta — environment dimenze:
environment (NOVÁ — ADR-026 §1)
id, tenant_id, kind DEFAULT|USER_CREATED, name, slug,
resource_mode SHARED|DEDICATED, status ACTIVE|SUSPENDED|DEPROVISIONING,
config (sizing/db tier/storage tier), deletable, created_at, updated_at
hosting_cost_events (EXISTUJE — přidat dimenzi)
+ environment_id (FK, nullable během migrace; resolved z namespace→environment mapy)
hosting_credit_ledger (EXISTUJE — přidat dimenzi)
+ environment_id (FK, nullable; DEBIT řádek nese, do kterého prostředí náklad patří)
hosting_billing_account (z DESIGN — per tenant; faktura agreguje per-env řádky)
beze změny struktury; period/anchor per tenant
hosting_invoice (z DESIGN — per tenant per period; řádky rozpadeny per environment)
+ (volitelně) invoice_line per environment_id — viz OD-6
Mapování namespace → environment (klíč attribution): C.2 dnes mapuje
ns "tenant-<slug>" → tenant.owner. Nově: ns → environment (přes
environment.slug v ns jméně, ADR-026 §3) → tenant. Během migrace (Fáze 2)
existuje jen 1 prostředí „TalkIDE” mapované na celý dnešní tenant-{slug} ns,
takže attribution je zpočátku 1:1 a bezpečné.
Invariant zachován: hosting_cost_events / usage_events se NIKDY
nemutují. Přidání environment_id = nový sloupec (nullable, forward-only
Liquibase changeset, CLAUDE.md immutable migrace) + backfill „TalkIDE” pro
historické řádky.
3. DP-4 PŘERÁMOVÁNO per-environment (rozhodovací podklad — NErozhoduji)
DP-4 v UC-10009 DESIGN = „co se zastaví při neuhrazené hosting faktuře”. Pod ADR-026 se otázka mění z „published prod vs preview/dev pody” na „které prostředí se suspenduje” — protože prostředí je jednotka izolace, billingu i enforcement.
3.1 Co umožňuje environment model
- Faktura má per-environment řádky (OD-6). Při neuhrazení lze suspendovat konkrétní prostředí, ne plošně.
- talkide-worker + Preview žijí v default „TalkIDE” → AI vývoj je svázán s prostředím, které je nesmazatelné (ADR-026 §2). Jeho osud při neplacení je samostatná citlivá otázka (OD-2).
- User-created PROD/TEST prostředí jsou „obyčejná” — suspend je čistý (scale-to-zero / deprovision dle resource_mode).
3.2 Varianty DP-4 (per-environment) — pro usera
| # | Co se při neuhrazené infra faktuře suspenduje | Default „TalkIDE” | Pozn. |
|---|---|---|---|
| DP-4-E1 | Jen user-created prostředí s neuhrazenou řádkou (PROD/TEST). Default „TalkIDE” (worker+Preview) běží dál. | NIKDY nesuspend (AI vývoj chráněn) | DOPORUČENO. Maximálně drží DP-0 decoupling: hosting dluh ≠ zablokovaný AI vývoj. User dál vyvíjí v „TalkIDE”, jen jeho dedikovaná/extra prostředí jsou pozastavená. Konzistentní s Phase-1 B.1 + DP-0. |
| DP-4-E2 | User-created prostředí + Preview v „TalkIDE”, ale talkide-worker NE (AI runtime chráněn). | Preview suspend, worker běží | Tvrdší. Preview je „hostování” → padá; čistě AI runtime (worker) drží. Volba, pokud user chce, aby neplacení vzalo i preview URL, ale ne schopnost vyvíjet. |
| DP-4-E3 | Všechna prostředí včetně „TalkIDE” celé (worker+Preview taky). | Celé suspend | NEdoporučeno — porušuje DP-0 (hosting dluh shodí i AI vývoj placený zvlášť prepaid). Pro úplnost. |
Doporučení analytika: DP-4-E1. Suspenduj jen user-created prostředí s neuhrazenou řádkou; default „TalkIDE” se za neplacení infry NIKDY nesuspenduje (provázáno s OD-2). Drží DP-0 + Phase-1 B.1 decoupling nejčistěji a je možné bez be#125 label-splitu (per-environment ns invariant ADR-026 §3 dává nativní izolaci — suspend = scale-to-zero daného env namespace).
Hard dependency DP-4-E1: per-environment namespace cut-over (ADR-026
migrace Fáze 4). Do té doby (živý prod na tenant-{slug}) je enforcement
hrubší — viz migrační plán Fáze 2 (interim: žádný hard suspend, jen
notifikace/PAST_DUE) než per-env ns přistane.
4. BEZPEČNÝ FÁZOVANÝ MIGRAČNÍ PLÁN
Cíl: ze současného stavu (
tenant-{slug}jedno ns, živý prod user popelkam /todo-list.talkide.app, preview+published implicitní) na Environment model po fázích, každá samostatně nasaditelná, žádný big-bang, živý user nesmí spadnout.
Přehled fází
| Fáze | Co se mění | Foundation? | Dopad na živého usera |
|---|---|---|---|
| F0 | (hotovo / nezávislé) UC-10008 marže do účtování — Phase-2a. | — | žádný (marže 0 = no-op) |
| F1 | Entita environment + lazy default „TalkIDE” namapované na současný tenant-{slug} ns. Čistě záznamová vrstva. | ANO — foundation | žádný (jen nová tabulka + backfill 1 řádku „TalkIDE” per existující tenant; žádná infra/namespace změna) |
| F2 | Billing per-environment napojení (read-path) — C.2 mapuje ns→environment (zatím 1:1 „TalkIDE”=tenant-{slug}). hosting_cost_events.environment_id + backfill. FE breakdown per prostředí (zatím 1 řádka). Postpaid akruál + měsíční faktura (UC-10009 DESIGN sekvence) s per-env řádkem. Enforcement zatím SOFT (notifikace/PAST_DUE, žádný hard suspend). | navazuje na F1 | minimální — postpaid akruál začne měřit „TalkIDE” prostředí; 1. faktura malá; žádný suspend |
| F3 | Create/Manage Environment UC — user vytváří USER_CREATED SHARED prostředí. Nový SHARED env = nový namespace {tenant}-{env-slug} (aktivuje ADR-023 §5 / ADR-024 substrát) pro NOVÁ prostředí. Existující „TalkIDE” zůstává na starém tenant-{slug} ns (NEmigruje se hned). | navazuje na F2 | žádný — popelkam dál na „TalkIDE”/tenant-{slug}; nové prostředí je opt-in |
| F4 | Per-environment namespace cut-over pro „TalkIDE” — řízená migrace tenant-{slug} → {tenant}-talkide ns (nebo ekvivalent). Aktivuje ADR-024 worker-per-env substrát. Tady se zapíná DP-4 hard enforcement (per-env suspend). | navazuje na F3 | citlivá fáze — vyžaduje non-disruptive ns přechod živého todo-list.talkide.app (drain/dual-run/cut-over; rollback = ponechat starý ns). Detailně se NEfinalizuje, dokud user neschválí pořadí. |
| F5 | DEDICATED resource_mode — ADR-023 §7 escape hatch jako produkt (dedikovaný DB cluster per env). | navazuje na F4 | žádný (opt-in premium; nedotýká se SHARED/„TalkIDE”) |
Per-fáze detail
F1 (FOUNDATION — musí první):
- Mění: nová tabulka
environment; lazy create default „TalkIDE” (kind=DEFAULT,resource_mode=SHARED,deletable=false) per tenant při prvním úkonu nebo backfill skriptem pro existující tenanty; mapováníenvironment("TalkIDE") → namespace("tenant-{slug}")(záznamové, žádná infra akce). - Riziko: nízké — čistě additivní schema (forward-only changeset). Žádná namespace/provisioning/billing změna.
- Rollback: drop tabulky / feature-flag off; nic v infře se nezměnilo.
- Ověření: existující tenant (popelkam) má právě 1 řádek „TalkIDE”
deletable=falsemapovaný natenant-popelkam;todo-list.talkide.appběží beze změny; žádný nový namespace nevznikl.
F2 (billing read-path + postpaid akruál, SOFT enforcement):
- Mění: C.2 attribution ns→environment (1:1 „TalkIDE”); přidat
hosting_cost_events.environment_id(nullable) + backfill „TalkIDE”; postpaid akruál + měsíční Stripe faktura (UC-10009 DESIGN sekvence 2) s per-env řádkem; FE breakdown per prostředí. Enforcement = jen notifikace + PAST_DUE, ŽÁDNÝ hard suspend (per-env suspend není možný čistě, dokud F4 nedá per-env ns). - Riziko: střední — 1. reálná Stripe faktura živému userovi. Mitigace: trial (DP-1) + nízká částka + soft-only enforcement + projected disclaimer.
- Rollback: feature-flag postpaid akruál off (cost_events se dál sbírají read-only, faktura se negeneruje); enforcement už je soft (bezpečné).
- Ověření: faktura „TalkIDE” řádek = Σ DEBIT; částka odpovídá OpenCost
aggregate=namespaceprotenant-popelkam; žádný suspend nenastane; FE breakdown ukazuje 1 prostředí „TalkIDE”.
F3 (Create/Manage Environment, SHARED):
- Mění: Create/Update/Delete Environment UC; nový SHARED env →
{tenant}-{env-slug}ns (idempotentní provisioner, ADR-015 vzor); Project deployment-target → environment; env-slug RFC-1123 validace + reserved list; Delete odmítnedeletable=false. - Riziko: střední — nový namespace provisioning path. Mitigace: izolováno od „TalkIDE” (popelkam nedotčen, nová prostředí jsou opt-in, prázdná).
- Rollback: Create Environment feature-flag off; už vytvořená user prostředí deprovision (idempotentní teardown, ADR-023 ř.457 vzor).
- Ověření: user vytvoří „TEST” SHARED → vznikne
{tenant}-testns + ResourceQuota; nasazení projektu do „TEST” funguje; „TalkIDE” + popelkam beze změny; faktura ukáže 2 řádky (TalkIDE + TEST).
F4 (per-environment ns cut-over „TalkIDE” + DP-4 hard enforcement):
- Mění: řízená migrace
tenant-{slug}→ per-env ns pro default „TalkIDE”; aktivace ADR-024 worker-per-env; zapnutí DP-4 hard suspend (per-env, dle user rozhodnutí DP-4-E1/E2/E3). - Riziko: vysoké — dotýká se živého
todo-list.talkide.app. Vyžaduje non-disruptive strategii (dual-run / drain / DNS-stabilní cut-over); detailně se NEfinalizuje, dokud user neschválí ADR-026 + pořadí. - Rollback: ponechat starý
tenant-{slug}ns aktivní (cut-over je reverzibilní dokud se starý ns nesmaže); DP-4 hard enforcement feature-flag → zpět na soft (F2 chování). - Ověření:
todo-list.talkide.appdostupné po celou dobu (zero-downtime ověřeno health-checkem); worker v novém per-env ns; cost attributionaggregate=namespacestále sedí; DP-4 suspend testovaný na throwaway user-created prostředí, NIKDY na „TalkIDE”.
F5 (DEDICATED):
- Mění: per-env dedikovaný DB cluster provisioning (ADR-023 §7).
- Riziko: nízké pro existující — opt-in premium, ortogonální k SHARED.
- Rollback: DEDICATED feature-flag off; downgrade na SHARED = re-point Secret na pooler (ADR-023 §6 invariant — app kód se nemění).
- Ověření: user zvolí DEDICATED pro „PROD” → dedikovaný cluster provisionován; app mluví přes pooler; SHARED prostředí nedotčena.
Foundation vs navazující (shrnutí)
- Foundation (musí PRVNÍ, blokuje vše ostatní): F1 (entita + default „TalkIDE” záznamová vrstva).
- Navazující v pořadí: F2 (billing read + postpaid soft) → F3 (user prostředí SHARED) → F4 (per-env ns cut-over + DP-4 hard) → F5 (DEDICATED).
- Nezávislé: F0 / UC-10008 (už hotové, model-agnostic).
- Bezpečnostní princip: hard enforcement (DP-4 suspend) se zapíná až F4, kdy per-env ns dává čistou izolaci. Do té doby (F1–F3) je enforcement jen soft (notifikace/PAST_DUE) — živý user nemůže být shozen.
5. KONSOLIDOVANÉ OPEN DECISIONS (pro usera — varianty + doporučení, NErozhoduji)
Relayuje PM userovi. Doporučení = duch dosavadních LOCKED rozhodnutí přepočítaný na environment model.
OD-1 — Granularita hosting spend cap (navazuje na DP-2 LOCKED)
DP-2 LOCKED = separátní hosting_spending_limit_usd. Otázka pod multi-env:
je cap agregovaný (Σ všech prostředí) nebo per prostředí?
- A) Jeden agregovaný hosting cap (Σ všech env charged).
- B) Per-environment cap (každé prostředí vlastní strop).
- C) A + volitelný per-env override (default agregovaný, power-user per-env).
- Doporučení: A pro alfu (jeden srozumitelný měsíční $ strop, minimální
UX/enforcement složitost), model nese
environment_idseam → C/B aditivně později. (Konzistentní s duchem DP-2 „nejjednodušší mentální model”, separátní od AI capu.)
OD-2 — Osud default „TalkIDE” prostředí při neplacení infry (kritické)
„TalkIDE” je nesmazatelné a hostí worker+Preview (AI vývoj). Co když user neplatí infra faktury?
- A) „TalkIDE” se NIKDY nesuspenduje za neplacení infry — pouze user-created prostředí. (Drží DP-0 nejčistěji; riziko: trvale neplacený user dál spotřebovává sdílené resources „TalkIDE”.)
- B) „TalkIDE” se po dlouhé grace (delší než DP-3) degraduje: Preview scale-to-zero, worker zůstává (čistě AI runtime běží, AI prepaid ho stejně neplatí z infry).
- C) „TalkIDE” Preview i worker scale-to-zero po extended grace (tvrdé; user nemůže vyvíjet dokud nezaplatí — porušuje DP-0 ducha).
- Doporučení: A s pojistkou — „TalkIDE” se za neplacení nesuspenduje
(chrání DP-0/AI vývoj), ALE doplnit ochranu proti zneužití: hard
hosting_spending_limit_usdcap (OD-1) zastaví akruál runaway nákladu v „TalkIDE” i bez suspendu prostředí (cap = ekonomická brzda, ne suspend AI vývoje). Toto je nejcitlivější rozhodnutí — user musí potvrdit trade-off „chráněný AI vývoj vs. riziko neplatícího free-ridera na sdílené „TalkIDE” infře”.
OD-3 — Shared vs dedicated DEFAULT pro nově vytvořené prostředí
Když user klikne „Create Environment”, co je předvybráno?
- A) Default SHARED (dedicated opt-in, gated plánem).
- B) Default dle plánu (Free/Starter → jen SHARED; Pro+ → volba).
- Doporučení: A — SHARED je levné, rychlé, bezrizikové; DEDICATED (ADR-023 §7) má reálnou $/čas cenu → vědomá opt-in volba, ideálně gated plánem (ADR-103 tier). Pro alfu zvážit DEDICATED úplně vypnout (jen SHARED) a F5 odložit — viz OD-4.
OD-4 — Granularita konfigurace DEDICATED v alfě
- A) Žádný DEDICATED v alfě (jen SHARED; F5 odložené post-alfa).
- B) DEDICATED s přednastavenými třídami (S/M/L → fixní DB tier + ResourceQuota), žádné volné parametry.
- C) DEDICATED s volnými parametry (DB velikost, node pool, kvóty).
- Doporučení: A pro alfu, B jako první post-alfa krok. DEDICATED
provisioning (per-env DO Managed PG cluster) je drahý a operačně těžký;
alfa (1–10 tenantů) ho nepotřebuje. Model nese
resource_mode+configseam → B/C aditivně. (Konzistentní s ADR-023 §7 „NEimplementuje se teď”.)
OD-5 — Trial granularita (navazuje na DP-1 LOCKED)
DP-1 LOCKED = konfigurovatelný trial_days. Pod multi-env: trial per
prostředí nebo per tenant (1 trial celkem)?
- A) Per tenant (1 trial okno; po vyčerpání všechna prostředí metered).
- B) Per prostředí (každé nové prostředí má vlastní trial — riziko zneužití: user cyklí prostředí kvůli trvalému trialu).
- Doporučení: A — per tenant trial (jednoduché, neabusovatelné). „TalkIDE” trial start = první nasazení projektu / první Publish (DP-1 text beze změny, jen scope = tenant). B zamítnuto kvůli abuse vektoru.
OD-6 — Struktura faktury (per-env řádky vs separátní faktury)
- A) Jedna měsíční faktura per tenant, per-environment řádky (line items: „TalkIDE: $X”, „PROD: $Y”).
- B) Separátní faktura per prostředí.
- Doporučení: A — jedna faktura, čitelné per-env řádky (design handoff „Hosting/Infrastructure” jedna sekce; konzistentní s DP-5 jeden anchor per tenant). B = víc Stripe objektů, horší UX, žádný benefit pro alfu.
OD-7 — Pořadí fází migrace (potvrzení)
Navržené pořadí: F1 → F2 → F3 → F4 → F5 (F0 nezávislé).
- Doporučení: potvrdit navržené pořadí. F1 je tvrdá foundation (bez entity nic). F2 před F3 (billing read-path bezpečně otestován na 1 prostředí „TalkIDE” než přibudou user prostředí). F4 (rizikový ns cut-over živého usera) až po F3 (mechanika ověřena na throwaway prostředích). F5 (DEDICATED) poslední / odložitelné (OD-4=A). Alternativa k potvrzení: posunout F4 dřív (před F3) pokud user chce per-env ns izolaci pro „TalkIDE” co nejdřív — NEdoporučeno (zvyšuje riziko na živém userovi bez předchozího ověření mechaniky na throwaway prostředích).
6. FEEDBACK
- ADR-026 nic nesuperseeduje — Environment je nadřazená doménová abstrakce; ADR-015/023/024 se rozšiřují/aktivují/realizují, zůstávají autoritativní. ADR-103 + UC-10008 + DP-0..DP-6 LOCKED beze změny.
- be#125 z velké části PADÁ. Per-environment namespace invariant
(ADR-026 §3) dává nativní
aggregate=namespaceattribution → intra-ns label-split (DP-4 V1) je nadbytečný. Reziduum: (1) dočasný label/namespace-split jen pro migrační období Fází 2–4 (než per-env ns přistane), (2) trvalý orphan-namespace safety net (ns bez mapování na environment → WARN + NEfakturovat). Návrh textu issue update = ADR-026 sekce „be#125 issue update” (PM přenese do GitLab; tento dokument GitLab nevolá). - Worker compute přestává být sporný. Pod ADR-026 je talkide-worker + Preview compute legitimní infra-postpaid řádka prostředí „TalkIDE” (user ji vidí transparentně), ne „misattribuovaný hosting”. DP-0 decoupling (AI prepaid = jen token inference) tím nabývá čistšího významu, ne slabšího.
- DP-4 přerámováno per-environment (sekce 3): doporučení DP-4-E1 (suspend jen user-created prostředí; „TalkIDE” nikdy) — drží DP-0 nejčistěji, hard dependency = F4 per-env ns. NErozhoduji — user volí E1/E2/E3 + OD-2 (osud „TalkIDE”).
- Migrační plán je striktně non-disruptive. Hard enforcement (DP-4
suspend) se zapíná až F4 (per-env ns izolace); F1–F3 enforcement jen
soft (notifikace/PAST_DUE). Živý popelkam /
todo-list.talkide.appzůstává natenant-{slug}až do řízeného F4 cut-overu s reverzibilním rollbackem (starý ns se nemaže dokud F4 neověřeno zero-downtime). - F1 je jediná tvrdá foundation — čistě additivní záznamová vrstva, nulový infra dopad, bezpečně nasaditelná samostatně.
- Nejcitlivější otevřený bod = OD-2 (osud „TalkIDE” při neplacení): trade-off „chráněný AI vývoj (DP-0)” vs. „riziko neplatícího free-ridera na sdílené infře”. Doporučení A+cap, ale rozhoduje user.
- NEfinalizováno (dle zadání): žádné finální API/sekvence/test tabulky. Čeká na user odsouhlasení ADR-026 + Open Decisions + pořadí fází (OD-7). Po schválení se UC-10009 DESIGN + tato revize rozpadnou na finální UC (postpaid accrual / monthly invoice / environment CRUD).
Thanks for the feedback.