Evidence produkčních incidentů a jejich řešení.
- Datum a čas
- Dopad (uživatelé/systém)
- Příčina
- Okamžité řešení
- Trvalá oprava
- Preventivní opatření
-
Pokud migrace hlásí
Cannot enforce AvailabilitySlot capacity = 1, zastav rollout a vylistuj sloty scapacity <> 1včetně navázaných aktivních rezervací. Teprve po provozním rozhodnutí oprav data a migraci spusť znovu. -
Riziko rollout/DB skewu:
release.shpo buildu zastaví web i worker, ověří jejich neaktivní stav a teprve potom aplikuje migraci před přepnutímcurrent. Při selhání migrace nebo nového runtime zůstanou writeři fail-closed zastavení; symlink se může vrátit, ale starý runtime se automaticky nespustí nad změněným schématem. DB se automaticky nevrací a případná oprava musí být dopředná, bez destruktivní down migrace. -
Zaplněný disk kvůli release artefaktům: ověř
du -sh /var/www/ppstudio/releasesa poslední výstuprelease.sh. Po úspěchu se automaticky ponechácurrentaprevious; pro delší rollback historii zvyš limit přes--keep-releases N, ale nikdy ručně nemaž cíl symlinků. -
next buildběhem staging releasu hlásí více lockfileů vreleases/.staging.*: ověřnext.config.tsa jehoturbopack.root. Musí mířit na__dirnameaktuálního release, nikoli na rodičovský adresář se všemi verzovanými release. -
Datum a čas: 2026-05-20 16:10 CEST Dopad (uživatelé/systém): v admin pracovním seznamu rezervací se po kliknutí na
Potvrditmohla karta zaseknout ve stavuUkládám..., i když booking stav už byl v DB změněný. Příčina:updateBookingStatusActiončekala (await) na Pushover dispatch v rámci stejné server action response; při pomalé externí API vrstvě zůstával klientskýuseFormStatus().pendingdlouho aktivní. Okamžité řešení: přepnutí Pushover dispatch ve status action na non-blocking volání (void ...catch(...)), aby response nečekala na síťový side-effect. Trvalá oprava: do vývojových pravidel doplněno, že adminuseActionStatezápisy nesmí synchronně čekat na externí notifikační HTTP volání. Preventivní opatření: při každé nové server action mutaci oddělit kritickou DB transakci od best-effort notifikací (Pushover, webhooky) a držet tyto kroky mimo kritickou latency cestu UI. -
Datum a čas: 2026-05-01 10:20 CEST Dopad (uživatelé/systém): lokální vývojový server padal během práce v
/admina přerušoval hot reload. Příčina: poškozená Turbopack dev cache (.next/dev/cache/turbopack), chybějící.sstsoubory při obnově task databáze. Okamžité řešení: zastavit dev server, vyčistit.nexta spustit znovu (npm run dev:clean); při opakování použít fallbacknpm run dev:webpack. Trvalá oprava: dopackage.jsonpřidány skriptyclean,dev:cleanadev:webpack, dokumentace doplněna o postup. Preventivní opatření: při prvních známkách Turbopack cache chyb neřešit symptomaticky po souborech, ale rovnou resetovat.next; při nestabilitě dočasně přepnout na webpack dev mód. -
Datum a čas: 2026-04-30 19:45 CEST Dopad (uživatelé/systém): release doběhl přes migrace, lint i build, ale skončil chybou při restartu
ppstudio-web.service; nová verze tak zůstala nenasazená do běžících procesů a rollout se musel ručně dohledávat. Příčina: server neměl nainstalované systemd units zdeploy/systemd/*a současně mu zůstal legacy PM2 runtime;deploy/release.shtehdy neověřoval ani přítomnost unitů, ani konflikt dvou process managerů. Okamžité řešení: nainstalovat units přessudo /var/www/ppstudio/deploy/deploy.sh, odstranitppstudio-web/ppstudio-email-workerz PM2, uložit prázdný PM2 dump a vypnoutpm2-root.service. Trvalá oprava:deploy/release.shnově fail-fast kontrolujeLoadStateproppstudio-web.serviceappstudio-email-worker.serviceještě přednpm ci/buildem a při nalezených PM2 procesech vypíše přesný převod na čistý systemd provoz. Preventivní opatření: na novém serveru nebo po obnově/etc/systemd/systemvždy nejdřív spustitdeploy/deploy.sh; při migraci z PM2 nejdřív odstraň staréppstudio-*procesy a vypnipm2-root.service, jinak hrozíEADDRINUSEnebo duplicitní worker. -
Datum a čas: 2026-04-20 14:46 CEST Dopad (uživatelé/systém): veřejné odeslání formuláře
/rezervacemohlo skončit obecnou chybouUNEXPECTED_ERRORmísto potvrzení rezervace, pokud klientka nevyplnila telefon. Příčina: drift mezi Prisma modelem a DB schématem;Booking.clientPhoneSnapshotbyl v DBNOT NULL, ale aplikační logika ho používá jako volitelné pole. Okamžité řešení: rollback neúspěšné migrace a bezpečné nasazení opravné migrace20260420125500_booking_client_phone_nullable_fix. Trvalá oprava: sloupecclientPhoneSnapshotje nullable; navíc byla přidána migrace20260420130500_rename_booking_primary_key_constraint, aby byl stav DB plně konzistentní se schématem. Preventivní opatření: před nasazením pouštětnpm run db:check-migrationsa po změnách schématu ověřit diffprisma migrate diff --from-config-datasource --to-schema prisma/schema.prisma --script. -
Ruční booking bez aplikované migrace
20260426123000_client_email_nullable_for_manual_booking; admin formulář po releasu dovolí prázdný e-mail, ale DB by pořád odmítla novou klientku bez adresy. Po deploy booking CRM změn vždy ověř i skutečně nasazené Prisma migrace. -
Datum a čas: 2026-04-26 21:40 CEST Dopad (uživatelé/systém):
ppstudio-email-workerběžel v PM2 crash loopu a zbytečně vytěžoval CPU; e-mail fronta a 24h reminder scan se nemohly spolehlivě spustit. Příčina: worker přessrc/lib/email/delivery.tsasrc/features/booking/lib/booking-reminders.tsimportoval Pushover modul simport "server-only", který mimo Next.js bundler v plain Node procesu okamžitě vyhodí chybu. Okamžité řešení: Pushover implementace byla oddělena dosrc/lib/notifications/pushover-core.tsa worker importy byly přepojené na worker-safe modul. Trvalá oprava:src/lib/notifications/pushover.tszůstává jen jako Next.jsserver-onlywrapper; standalone skripty nesmí importovat wrapper, ale přímopushover-core. Preventivní opatření: po změnách Pushover, e-mail delivery nebo reminder scheduleru ověřit alespoň import/start worker vrstvy mimo Next.js runtime.
- Duplicitní e-mail: ověř
EmailLog.processingToken,processingStartedAt,providerMessageIda počet běžícíchppstudio-email-workerprocesů. Resend REST má pro tentýžEmailLog.id24hodinovou deduplikaci; u SMTP nelze po provider ACK před DB zápisem přesně jednou garantovat, proto incident řeš jako at-least-once a nespouštěj ruční resend bez kontroly logu. - Nové GitHub workflow je v repu, ale branch protection / required checks na GitHubu pořád ukazují staré názvy jobů; typický symptom je PR, který má všechny nové checky zelené, ale merge blokuje neexistující historický status.
- CodeQL nebo Dependabot jsou v workflow/configu připravené, ale na úrovni GitHub repozitáře nejsou skutečně zapnuté alerts nebo security overview; po rollout CI/security změn vždy ověř i repo settings, ne jen přítomnost YAML souborů.
npm auditdoporučující automatický fix přes downgradenextneboprisma; před jakýmkolinpm audit fixvždy zkontroluj navržené cílové verze a diff lockfilu. V aktuálním stavu (2026-06-28) je správnéaudit fixnepouštět a čekat na kompatibilní upstream release.- Cross-origin blokace Next.js dev assetů (
/_next/webpack-hmr, overlay, refresh endpointy) při otevření lokálního dev serveru z jiného zařízení nebo hostname, který není vallowedDevOrigins. - Neplatné nebo chybějící env proměnné při startu aplikace.
- Chyby Prisma klienta po změně schematu nebo po nasazení bez
db:generate. - Build chyba
Invalid segment configuration export detectedpřinext build; nejdřív zkontroluj App Router route segment config exporty (revalidate,dynamic,fetchCache, atd.), jestli nepoužívají neanalyzovatelné výrazy místo literálů. - Regrese normalizace telefonu klientky: ověř
src/features/booking/lib/client-phone.ts, server action validaci veřejné i ruční rezervace a uložené hodnoty vClient.phone/Booking.clientPhoneSnapshot; text ani HTML se nesmí potichu očistit na platné číslo. - Selhání admin přihlášení kvůli špatnému
ADMIN_SESSION_SECRETnebo neaktivnímu DB účtu. Pro lockout obnov aktivního OWNERa offline příkazemnpm run admin:recover-owner -- --email … --name … --confirm < heslo.txt, pak ověř auditADMIN_RECOVERY_OWNER_RESTOREDa nový login; webový bootstrap fallback neexistuje. - Admin login/logout redirect nebo proxy přesměrování mířící na cizí doménu po podvrženém
Host/x-forwarded-host; okamžitě ověřNEXT_PUBLIC_APP_URL,NEXT_PUBLIC_SITE_DOMAIN,VOUCHER_PUBLIC_DOMAIN, reverse proxy hlavičky a helpersrc/lib/http/request-origin.ts. - Brute-force pokusy na
/api/auth/loginbez aktivace rate limit ochrany (error=rate_limitedse po sérii špatných pokusů neobjeví). - Chybný role redirect nebo neočekávaný přístup
SALONdo owner-only sekcí. - Nefunkční prefill klientky v admin ruční rezervaci (
/admin/.../rezervace?create=1&clientId=...), zejména po změně detailu klientky, booking draweru nebo shared owner/salon route factory. - Rozjezd owner-only sekce
Přístupy, kdy by seSALONdostal na/admin/uzivatelenebo by se v UI objevila jiná role nežOWNER/SALON. - Chybně označené systémové přístupy nebo rozbitý stav
Pozvánka čekápo nasazení migraceAdminUser.invitedAt. - Nefunkční aktivace pozvánky na
/admin/pozvanka/[token](expirace, použitý token, nebo chybějící migraceAdminUserInviteToken). - Bezpečnostní incident administrátorské pozvánky: při deaktivaci účtu ihned ověř
AdminUser.isActive = falseaAdminUserInviteToken.revokedAtpro všechny nepoužité tokeny. Starý odkaz musí vracet pouze obecnou chybu platnosti a nesmí zapsat heslo ani změnit aktivní stav; při pochybnosti účet ponech deaktivovaný a po prověření odešli novou pozvánku. - Veřejné kontaktní údaje nebo ceny ponechané v placeholder režimu po nasazení.
- Právní stránka
/obchodni-podminkyponechaná v draft nebo placeholder režimu; po release musí působit jako finální provozní dokument, ne jako interní návrh. - Nefunkční CTA odkazy mezi veřejným webem a rezervační částí.
- Chybně zapnutý nebo rozbitý Matomo tracking, který by posílal admin nebo tokenové URL, duplicitní první pageview, PII v event name, nebo by chybou
_paqovlivnil booking flow; helper musí zůstat bezpečný no-op. - Přihlášený admin otevře veřejný web a Matomo se přesto načte; po změnách
SiteShell/auth cookie vždy ověř, že přippstudio-admin-sessionseMatomoTrackerrenderujedisabledamatomo.jsse vůbec nenačte. - Přihlášený admin otevře veřejný web a Clarity se přesto načte; po změnách
SiteShell/auth cookie ověř, žeClarityTrackerrespektujedisabledguard a tag se nespustí. - Přihlášený admin otevře veřejný web a Google Ads tag se přesto načte; po změnách
SiteShell/auth cookie ověř, žeGoogleAdsTrackerrespektujedisabledguard agtag.jsse vůbec nenačte. - Meta Pixel posílá PII, tokenovou URL nebo neočekávané eventy mimo veřejný funnel; po změnách
meta-pixel*.ts(x), detailu služby nebo/rezervaceověř, že dofbqodchází jenPageView,ViewContent,InitiateCheckout,AddToCart,BookingDateSelected,BookingTimeSelected,BookingContactStartedaLeadbez e-mailu, telefonu, poznámky nebo tokenu. - Google Ads tag posílá pageview pro
/admin, tokenové self-service URL nebo citlivé query parametry; po změnáchgoogle-ads*.ts(x)a routingu ověř, žepage_pathzůstává sanitizovaný a tracker je bezpečný no-op mimo veřejný web. - Rozbitý server-side Matomo dashboard reporting kvůli chybějícímu
MATOMO_AUTH_TOKEN, špatnémuMATOMO_SITE_ID, nedostupnému Reporting API nebo omylem veřejně vystavenému tokenu; UI má zůstat na nulových fallback hodnotách a token nesmí mít prefixNEXT_PUBLIC_. - Regrese admin dashboardu zpět do analyticky přeplněného pohledu: hlavní obrazovka má zůstat denní provozní cockpit a detailní zdroje návštěv nebo funnel mají být schované až v rozbalení
Zobrazit analytiku. - Endpoint
/api/admin/analyticsomylem dostupný bez admin session nebo vracející detailní payload z Matomo; endpoint smí vracet jen agregovaná dashboard čísla bez PII a beztoken_auth. - Rozbita nebo pomala Pushover konfigurace (
PUSHOVER_ENABLED=truebezPUSHOVER_APP_TOKEN, spatny owner User Key nebo nedostupne Pushover API) nesmi rozbit rezervaci, potvrzeni, storno, presun, email worker ani reminder scan; spravne chovani je log + preskoceni nebo chybovy stav jen v testovacim tlacitku a HTTP pokus ma byt ukonceny nejpozdeji po 3 s timeoutu. SALONomylem vidi Pushover nastaveni nebo prijima Pushover notifikaci; UI i serverovy dotaz musi zustat omezeny naAdminRole.OWNER.- Pushover zprava obsahuje telefon, raw token, citlivou poznamku klientky nebo cely payload; notifikace maji posilat jen sluzbu, termin, zdroj, typ chyby a odkaz do adminu.
- Chybné označení klientky u
NEW_BOOKING(například podle shodného jména místo historie): status se musí určovat výhradně podle starší rezervace se stejnýmclientId; samotný štítek nesmí nést žádný kontaktní údaj. - Pushover spam při retry nebo opakovaném submitu; obecné události se stejným
type + bookingId/contextId/emailLogIdmají být v jednom procesu potlačeny 30s in-memory rate limitem, zatímco veřejné booking rate-limit blokace používají perzistentní 10minutový cooldown podlesourceHash. - DB outage s frekventovaným externím monitoringem:
/api/healthmusí vrátit503pouze se stabilnímerror.code=DATABASE_UNAVAILABLE, bez textu Prisma/driver chyby. Prohealth-db-checkse Pushover nespouští synchronně a smí projít jen jednou za 10 minut na runtime proces; deset po sobě jdoucích health requestů proto nesmí vytvořit více než jeden alert. - Release opakovaně selhává na
/api/health: endpoint provádí pouzeSELECT 1, takže ověř dostupnost DB a skutečnou Prisma chybu načti zjournalctl -u ppstudio-web.service -n 200 --no-pager. Detailní read model e-mailové fronty release readiness neblokuje. - Release opakuje obecnou hlášku
Health/smoke test zatím neprošel: nejdřív rozliš logHealth endpoint ...odHomepage smoke test .... Druhá větev znamená, že/api/healthuž mohl projít a je nutné diagnostikovat server render/, ne měnit naslepo health endpoint. - První request hned po
systemctl startskončícurl: (7) Failed to connect: nejde sám o incident, pokud web ještě otevírá port. Release helper čeká tiše až pět sekund; teprve hláška o neotevřeném endpointu po vyčerpání retry znamená reálný start failure. - Neocekavana serverova chyba skonci jen v
console.errorbez owner alertu; minimalne health DB check, analytics fallback, booking create/reschedule flow, public booking schema drift, fail enqueue reschedule emailu, planner mutace, kriticke voucher akce a owner resend invite flow maji posilatSYSTEM_ERRORPushover s bezpecnymcontextIda bez raw tokenu. - Opakované
EmailLog.status = FAILEDpo nasazení nové SMTP konfigurace. - Resend webhook tracking bez párování na
EmailLog.providerMessageId(např. přiEMAIL_TRANSPORT=smtpnebo chybějícímRESEND_WEBHOOK_SECRET) vede k trvale neutrálnímu tracking stavu; při incidentu ověřEMAIL_TRANSPORT,RESEND_API_KEY,RESEND_WEBHOOK_SECRETa konfiguraci endpointu/api/webhooks/resendv Resend dashboardu. - Nefunkční storno odkazy kvůli špatnému
NEXT_PUBLIC_APP_URLnebo proxy přepisu hosta. - Nefunkční self-service odkaz
Změnit termínkvůli špatnémuNEXT_PUBLIC_APP_URL, rozbité route/rezervace/sprava/[token]nebo chybně generovanémuBookingActionTokenType.RESCHEDULE. - Regrese UX self-service změny termínu, kdy se storno znovu objeví jako dominantní akce, kalendář předběhne nejbližší termíny, výběr slotu neaktualizuje potvrzení nebo na mobilu vznikne horizontální scroll.
- Matomo na tokenové self-service stránce omylem odešle pageview s raw tokenem nebo duplicitní date/time event při renderu; eventy smějí vznikat jen z interakcí a bez PII.
- Nefunkční approve/reject odkazy v provozním e-mailu kvůli špatnému
NEXT_PUBLIC_APP_URL, neaplikované migraci enumuBookingActionTokenTypenebo rozbitému veřejnému routingu/rezervace/akce/[intent]/[token]. - Approve/reject e-mail odkaz otevřený bez admin session nesmí změnit stav rezervace; očekávané chování je výzva k přihlášení a mutace až po aktivní session.
- Provozní e-mail o nové rezervaci nečitelný na mobilu nebo v Outlooku kvůli regresi v HTML šabloně; po zásahu do
admin-booking-notification-v1vždy ověř stackovaná tlačítka, normální letter-spacing a danger-light vizuál storna. - Regrese booking e-mailového design systému, kdy se vrátí duplicitní kontaktní věty, dominantní storno CTA, starý formát času bez mezer nebo kontakt odpojený od
SiteSettings; po zásahu dosrc/lib/email/templates.tsověř text/plain i HTML varianty všech booking šablon, mapový odkaz z aktuální adresy, fallback PP Studia a náhledy přesnpm run email:previews. - Chybějící nebo poškozená
.icspříloha v potvrzovacím klientském e-mailu kvůli chybě v renderu šablonybooking-approved-v1, SMTP transportu nebo generování iCalendar obsahu. - Nefunkční owner kalendářový feed kvůli špatnému
NEXT_PUBLIC_APP_URL, neaplikované migraciCalendarFeed, chybné rotaci tokenu nebo rozbité route/api/calendar/owner.ics. - Apple Calendar subscription vracející prázdný nebo nevalidní obsah kvůli chybě v ICS escapování, line folding nebo timezone mapování
Europe/Prague. - Zákaznická
.icsudálost posunutá o hodinu kvůli chybě vDTSTART/DTENDnebo chybějícímuVTIMEZONEblokuEurope/Prague. - Dvojí nebo chybné uplatnění voucheru: při incidentu porovnej
Voucher.remainingValueCzk,Voucher.status, navázanéVoucherRedemptionzáznamy a admin aktéra; public validace voucheru sama nikdy nemá vytvářet redemption ani odečítat zůstatek. - Badge nebo status v admin seznamu voucherů nesedí k řádku, chybně se láme nebo vizuálně mizí: zkontroluj
AdminStatePill, mapováníeffectiveStatus -> tonevadmin-vouchers-page.tsxa šířku desktopového sloupceStav; nesmí se tím měnit voucher business logika ani filtrace. - Veřejné ověření
/vouchery/overeniukáže citlivá voucherová data nebo změní zůstatek: okamžitě ověřverifyVoucherPublic(...), page output,VoucherRedemptionzáznamy a změnyremainingValueCzk/Voucher.status; route musí zůstat read-only a zobrazovat jen bezpečná pole. - Nečekané uplatnění voucheru z detailu rezervace: ověř server action
redeemBookingVoucherAction, roli přihlášeného admina, zadanývoucherCode, volitelnouamountCzk, navázanýbookingIda revalidované owner/salon route; žádná client-side logika nesmí sama měnit zůstatek. - Chybný stav v panelu
Úhradau rezervace: porovnejBooking.finalPriceCzk,Booking.servicePriceFromCzk, aktuálníService.priceFromCzk, součetVoucherRedemption.amountCzka součetBookingPayment.amountCzkpro danýbookingId; stav úhrady se neukládá do DB a musí odpovídat helperugetBookingPaymentSummary(...). - Chybný
CRM souhrnv detailu klientky: ověř, že read model načítá všechny rezervace klientky včetněfinalPriceCzk,servicePriceFromCzk,scheduledStartsAt,scheduledEndsAt,VoucherRedemption.amountCzkaBookingPayment.amountCzk; platební část musí dál odpovídat helperugetBookingPaymentSummary(...).Uhrazenomá ukazovat skutečně zapsané úhrady, aleNeuhrazenonesmí započítat budoucí aktivní rezervace aniCANCELLED/NO_SHOW. - Duplicitní nebo chybně smazaná platba mimo voucher: zkontroluj
BookingPayment.bookingId,amountCzk,method,paidAt,createdByUserIda auditní kontext v admin session. Mazání má být dostupné pouze proOWNER;SALONsmí platbu jen zapsat. - Voucher vystavený na špatnou službu nebo hodnotu: zkontroluj admin route
/admin/vouchery/novynebo/admin/provoz/vouchery/novy, payload server action, aktivitu vybrané služby a snapshot poleserviceNameSnapshot,servicePriceSnapshotCzk,serviceDurationSnapshot; první verze nemá editaci ani storno, oprava vyžaduje vědomý provozní zásah. - Voucher omylem zůstává uplatnitelný po ručním zrušení: ověř
Voucher.status = CANCELLED,cancelledAt,cancelledByUserId,cancelReason, veřejnéverifyVoucherPublic(...)a adminredeemVoucherForBooking(...); interní důvod se nesmí propisovat na/vouchery/overeni. - Zrušení voucheru selže u aktivního voucheru bez čerpání: zkontroluj počet
VoucherRedemptionprovoucherId, stav voucheru a existenci aktuálního admin uživatele vAdminUser; bootstrap session smí uložit audit jakonull, ale akce nemá padat. - Rezervace mimo stav
CONFIRMEDomylem zobrazené v owner kalendáři; feed má být jen read-only provozní přehled potvrzených termínů. - Opakované použití stejného email akčního odkazu, které musí bezpečně skončit stavem
už zpracováno, ne druhou změnou rezervace. - Rezervace potvrzená nebo zrušená jinou cestou ještě před otevřením email akce; confirmation screen musí vrátit korektní stav
už potvrzeno/už zrušeno, ne 500. - Ruční rezervace vytvořená mimo veřejnou dostupnost bez viditelného warningu nebo bez nastavení
manualOverride; provoz pak ztratí auditní stopu, proč termín neodpovídal veřejným slotům. - Nasazení kódu ruční rezervace bez aplikované migrace
20260422230500_manual_booking_admin_v1, což by způsobilo chyby nad chybějícími sloupciBooking.isManual/Booking.manualOverridenebo nad neaktuálním enumBookingSource. - Staré hodnoty enumu
BookingSource(PUBLIC_WEB,OWNER_ADMIN,SALON_ADMIN) ponechané v DB po nepovedené migraci; list/detail rezervací pak budou padat na neplatném mapování zdroje. - Worker běžící bez SMTP přístupu nebo bez
EMAIL_DELIVERY_MODE=backgrounda zůstávající frontaPENDINGlogů. - Zastavený
email:worker, kvůli kterému se nově nejen nedoručují pending e-maily, ale ani nevznikají 24h reminder joby pro zítřejší potvrzené rezervace. - Owner-only
GET /api/health/diagnosticsvracíwarningkvůli backlogu email fronty nebo nevyřešenému recipient incidentu; stale claim jeerror. Tyto stavy neblokují veřejný DB readiness, proto je monitoruj samostatně. - Pokud latence veřejného
/api/healthroste, kontroluj DB latenci. Latenci a stav detailního read modelu sleduj odděleně přes chráněnou diagnostiku a serverové logy. - Admin login po submitu vrací
error=origin_check_failed; nejdřív ověř, že request opravdu běží na veřejném originu zNEXT_PUBLIC_APP_URL, a pak zkontroluj proxyHost/X-Forwarded-Host. Typický symptom je redirect zpět na/admin/prihlasenihned po submitu bez pokusu o autentizaci. - Reminder omylem odeslaný po storno nebo přesunu rezervace; worker má před sendem vždy znovu ověřit
Booking.status,scheduledStartsAtareminder24hSentAt. - Přesun termínu uložený bez auditního logu nebo bez navýšení
Booking.rescheduleCount; reschedule flow musí vždy zapisovatBookingRescheduleLogi metadata posledního přesunu. - Změna ceny služby uložená bez auditní stopy; admin editace musí při skutečné změně
priceFromCzkvždy zapisovatServicePriceChangeLogs původní a novou hodnotou. - Voucher chybně odečtený už při veřejné rezervaci; správné chování je jen intent na
Booking, skutečné čerpání vzniká výhradně ručním admin zápisemVoucherRedemption. - Hodnotový voucher čerpaný souběžně bez transakční aktualizace
remainingValueCzk; budoucí admin akce musí uVALUEvoucherů zamykat/ověřit aktuální zůstatek a až potom vytvořitVoucherRedemption. - Rezervační přehled vracející špatné nebo neaktivní filtry po kliknutí na statistický box; klik na aktivní box musí vždy umět vrátit seznam do výchozího stavu bez ruční editace URL.
- Pracovní seznam rezervací po zásahu do query parametrů nebo toolbaru ztratí stav sekcí
Minulé/Zobrazit další; ověř, žeshowPasta skupinové*Limitparametry přežijí další filtrování i návrat přes historii prohlížeče. - Detail rezervace po UX refaktoru schová hlavní akce pod fold nebo mimo sticky header; po každém zásahu ověř, že
termín + stav + rychlé akcezůstávají viditelné bez dalšího scrollu. - Detail rezervace znovu smíchá reschedule flow do běžného status chooseru;
Přesunout termínmá zůstat samostatné CTA s vlastním drawerem, validací a historií. - Pokud se na telefonu vrátí překryv první akční karty v detailu rezervace, zkontroluj kombinaci sticky vrstev
AdminShellmobile topbaru a booking detail headeru; mobil nemá mít dva na sobě aktivní sticky panely se stejným scroll kontextem. - Click-to-open řádek rezervace, který při práci s checkboxem, kontaktem nebo row akcemi omylem otevírá detail; interaktivní prvky uvnitř řádku musí propagaci zastavit.
- Self-service přesun termínu zapsaný bez
changedByClient = true; veřejný manage flow musí být v historii odlišitelný od admin přesunu. - Přesun termínu provedený, ale starý interní override slot zůstal viset jako
DRAFTa dál blokuje původní čas; doménová služba musí orphanovaný override slot uvolnit. - Omylem spuštěné
prisma migrate devna produkčním serveru místoprisma migrate deploy. - Pokus o vytvoření nebo editaci překrývajícího se slotu, který by měl skončit user-friendly validační chybou místo neošetřeného 500.
- Slot omylem snížený pod počet aktivních rezervací nebo archivovaný navzdory aktivní rezervaci.
- Chybějící provozní feedback po slot akci (stav/smazání), kdy obsluha neví, proč se nic nestalo.
- Rozjeté chování owner vs salon route po změně shared factory wrapperů (např. rozdílný guard nebo chybějící
notFoundvalidace sekce). - Nasazený kód admin sekce
Službybez aplikované migrace20260419103000_service_public_bookability, což by vedlo na Prisma chyby nad chybějícím sloupcem. - Nasazený kód admin sekce
Službybez aplikované migrace20260525100000_service_cleanup_minutes_v1, což by vedlo na Prisma chyby nad chybějícím sloupcemService.cleanupMinutes. - Mylný předpoklad, že admin změna služby automaticky aktualizuje i veřejné stránky
/sluzbya/cenik; ten je už vyřešený, veřejný katalog teď čte z DB v request-time. - Omylem smazaná kategorie se službami; tohle má být nyní systémově blokované a provoz má místo toho použít deaktivaci.
- Neočekávané rozjetí pořadí kategorií mezi adminem a veřejným katalogem po ruční DB úpravě
sortOrder. - Rozbitá quick action v admin sekci
SlužbyneboKategorie služeb, která by po kliknutí nevrátila obsluhu do stejného filtrovaného kontextu; po změnách vždy ověř query-driven návrat na seznam. - Mobilní admin detail služeb nebo kategorií otevřený pod seznamem místo odděleného flow; po UI zásahu vždy ověř, že se na mobilu používá samostatný detailový režim.
- Desktop admin detail služeb nebo kategorií vykreslený mimo pravý overlay drawer (regrese zpět na inline/sticky panel), kvůli čemuž obsluha ztratí sjednocené list/detail chování mezi desktopem a mobilem.
- React warning
An optimistic state update occurred outside a transition or actionv admin UI je signál, žeuseOptimisticupdate běží mimostartTransition/action context; zkontroluj event helpery v klientských workspaces (toggle/move/savemutace) a optimistic dispatch obal do transition. - Overview dashboard zobrazující zastaralý počet dnešních rezervací nebo slotů po změně dat; overview musí zůstávat čistě server-rendered read model bez ručního cache layeru.
- Sender e-mail upravený v admin sekci
Nastavenína adresu, kterou SMTP provider ve skutečnosti nepovoluje; výsledek budou opakovanéEmailLog.status = FAILED. - Přehnaně přísný minimální předstih nebo příliš krátký horizont rezervace ve
SiteSettings, kvůli kterému veřejný booking náhle schová skoro všechny sloty. - Delší služba nabízená až zbytečně pozdě, přestože v kalendáři vizuálně vypadá dost volného času; po zavedení chainingu navazujících slotů je potřeba při podobném hlášení ověřit, že sousední publikované sloty mají opravdu kompatibilní kapacitu, stejná service restrictions a žádnou mezeru mezi segmenty.
- Poslední klientský termín v publikovaném slotu chybí jen kvůli cleanup přesahu, i když se samotná služba do okna vejde; po změnách booking enginu ověř, že nabídka časů používá hranici
scheduledEndsAt, zatímco kolize a další sloty dál respektujíblockedUntil. - Regrese po booking/reschedule chainingu, kdy admin planner ukáže volný začátek nebo konec coverage řetězce jako
Omezené; po zásahu dosplitSlotForEditingnebo coverage logiky vždy ověř, že se rozsekají i krajní segmenty řetězce, ne jen single-slot případ. - Browser warning
Encountered two children with the same keyv planner inspektoru je signál, že UI seznam používá příliš hrubý key typustartCell-endCell; po úpravách seznamů intervalů vždy ověř, že key obsahuje i den nebo jiný stabilní rozlišovač. - Legacy anchor slot po starším chainingu může zůstat v datech i po nasazení opravy enginu. Pro jednoduché single-booking případy použij
node scripts/repair-legacy-chained-slots.mjsa teprve po kontrolerepairablevýstupu případně--apply; případy se dvěma a více bookingy na jednom slotu řeš ručně. CANCELLEDbooking nesmí v planneru zůstávat jako viditelná blokace. Pokud se po storne v mřížce ukazuje barevný „technický“ blok, zkontroluj, jestli query vrstva archivovaný cancelled-only slot schovává.- Rozbitý reset vybraného času při změně dne v kroku 2
/rezervace, kvůli kterému by souhrn nebo hidden inputs držely stalestartsAtmimo aktuálně zobrazený den. - Regresní rozbití booking flow nebo týdenního planneru po čistě strukturálním refaktoru; po změnách v
booking-flow,booking-publicneboadmin-slotsvždy ověř build, základní booking smoke flow a admin planner akce. - Regrese přístupnosti kontaktního kroku
/rezervace: po zásahu dobooking-flow/contact-step.tsxzkontroluj explicitní label vazby,aria-describedbyna nápovědy/chyby, live oznámení chyb a viditelnýfocus-visiblestav při ovládání klávesnicí. - Storno limit nastavený příliš vysoko nebo omylem na
0, což změní chování self-service storno odkazů. - Chybějící nebo nečitelný
MEDIA_STORAGE_ROOT, kvůli kterému upload selže při zápisu nebo se veřejný asset fyzicky nikdy neuloží. - Upload root namountovaný do dočasného adresáře, který se smaže při deployi nebo restartu serveru.
- Nefunkční veřejné URL
/media/public/*nebo legacy/media/*kvůli ručnímu zásahu do souborů na filesystemu bez odpovídajícíhoMediaAssetzáznamu v DB. - Podezření na rozdílné zabezpečení kanonické
/media/public/*a legacy/media/*route: obě musí reexportovatGETzsrc/lib/media/public-media-route.ts; ověř regresní testsrc/app/media/media-route-aliases.test.tsa že repository dotaz zachováváisPublished: true. - Pokud voucherové PDF selže, ověř uložený
Voucher.templateId, publikovanouVoucherTemplatea její privátní master vMEDIA_STORAGE_ROOT; neznámá nebo neúplná šablona se záměrně odmítá bez fallbacku.SiteSettings.voucherPdfLogoMediaIdje legacy reference a aktuální renderer ji nečte. - Při hlášení špatného tisku ověř
/pdf/tisk, jednu stránku 216 × 105 mm, TrimBox 210 × 99 mm s offsetem 3 mm a umístění overlay dat. Při hlášení změny e-mailového PDF ověř, že e-mail stále používágenerateVoucherDigitalPdf(...)a attachment má 210 × 99 mm; žádná varianta už nevytváří A4 arch. - Pokus o nahrání nepodporovaného typu souboru nebo souboru nad velikostní limit, který musí skončit validační chybou místo 500.
- Pád admin stránky
Médiapo nahrání většího, ale stále povoleného obrázku. První kontrola:next.config.tsmusí mít pro Server Actions vyššíbodySizeLimitnež business limit uploadu; jinak Next.js request odmítne ještě před vlastní validací a uživatelka uvidí jen obecnou serverovou chybu. Failed to find Server Actionpo deployi nebo za load balancerem: nejdřív ověř, že všechny instance běží na stejném buildu, mají shodnýNEXT_SERVER_ACTIONS_ENCRYPTION_KEYa stejnýNEXT_DEPLOYMENT_IDpro daný release. Pokud měla uživatelka starý otevřený tab, po doplněnídeploymentIdmá následovat hard reload místo opakovaného selhání akce.ChunkLoadError: Failed to load chunk /_next/static/chunks/...v lokálnímnext dev: první podezření není/rezervaceani jiná business route, ale rozjetý Turbopack HMR/client cache po restartu serveru nebo invalidaci layoutu. Root layout teď v developmentu provede automatický hard reload už z inlinebeforeInteractiveguardu, takže záchrana funguje i při pádu root klientského chunku; guard má krátké 15s retry okno se dvěma pokusy a dočasný cache-busting query parametr, takže se nezasekne na trvalémsessionStoragelocku po prvním selhání. Pokud chyba přetrvá, použijnpm run dev:clean, případněnpm run dev:webpack.- Pro stejný incident nově používej i strukturované Next logy:
ppstudio.next.registerpro porovnánídeploymentId+serverActionsKeyFingerprintmezi instancemi appstudio.next.request-errorpro konkrétní request sx-deployment-id,routeType,digest, shrnutímnext-actionheaderu a odhadem příčiny. Log je záměrně sanitizovaný a nesmí obsahovat raw tokenové URL. - Pokud request error ukáže
nextAction.looksMalformed = truenebo krátký sample typu"x", prioritně to ber jako scan/probing nebo rozbitý cizí POST. Stale legitimní klient typicky pošle delší interní action ID a často i smysluplnýreferer. - Pokud
ppstudio.next.registerneukazujedeploymentId, problém nemusí být hned ve Next.js: nejdřív ověř, že web service načetla.release-envs aktuálním releasem. Bez runtime deployment env je build-time ochrana pořád aktivní, ale provozní diagnostika ztratí nejdůležitější srovnávací údaj. - Aktivní deployment ID ověř ve startup logu
ppstudio.next.registernebo po owner přihlášení přes/api/health/diagnostics; veřejný health ho záměrně nevrací. - Pokud po releasu běží stará systemd konfigurace, nejdřív ověř, jestli release helper opravdu synchronizoval
/etc/systemd/system/ppstudio-web.serviceappstudio-email-worker.service. Od této verze to dělá automaticky; ručnídeploy/deploy.shje potřeba hlavně pro první provisioning nebo recovery serveru. - Admin
Médiapo uploadu, editaci nebo publish/unpublish vrací obsluhu na špatný filtr, takže rychlá práce v knihovně působí chaoticky a je potřeba znovu ručně přepínat tabs. - Hero portrét na homepage nebo
/o-mneneodpovídá očekávané stránce, protože je médium uložené pod špatným typem (PORTRAIT_HOMEvsPORTRAIT_ABOUT); legacyPORTRAITuž veřejný web nepoužívá. - Certifikát nahraný v modulu
Média, ale neviditelný na/o-mnekvůli jinémuMediaTypenežCERTIFICATE, vypnutémuisPublished, neplatnéstoragePathnebo chybějícímu souboru ve storage rootu. - Fotka studia nahraná v modulu
Média, ale neviditelná na/studiokvůli jinémuMediaTypenežSALON_PHOTO, vypnutémuisPublished, neplatnéstoragePathnebo chybějícímu souboru ve storage rootu. - Broken image na
/studiopři publikovanémSALON_PHOTOzáznamu bez fyzického souboru; read model má orphan asset přeskočit a UI nesmí renderovat prázdný rozbitý box. - Kontaktní stránka nemá hero fotku, protože nebyl nahraný žádný publikovaný
CONTACT_PHOTO; očekávaný stav je placeholder, trvalá oprava je nahrát samostatnou fotku ve filtruKontakt. - Hlavní portrét na
/o-mnenahrazený neexistujícím nebo nevhodně ořezaným assetem vpublic/brand, kvůli čemuž by hero ztratil důvěryhodnost nebo vizuální kvalitu na mobilu. - Stránka
/o-mnepublikovaná jen s placeholder certifikáty nebo pracovní fotografií i po finálním dodání brand assetů; před release je potřeba ověřit, že placeholder stavy nejsou omylem ponechané jako produkční finální řešení.
- Přetrvávající text
Rendering...na admin detailu voucheru po dokončení načtení je UI regrese; voucher detail má používat loading stav jen během skutečného fetch/render přechodu a v klidovém stavu ukazovat už jen finální summary a provozní panely. - Historie Prisma migrací může obsahovat rollbacknuté záznamy
20260419140000_site_settings_singleton,20260419103000_service_public_bookabilitya20260428133959_voucher_pdf_logo_settings. Každý z nich má po rollbacknutém záznamu následný úspěšně dokončený záznam stejného názvu; jde o známou auditní stopu recover postupu. Nemaž je ručně z_prisma_migrations. Za problém je považuj až tehdy, kdyžnpm run db:check-migrationsneskončí stavemMigration history check: OK, nebo kdyžprisma migrate deployodmítne pokračovat. - Release helper očekává nainstalované systemd units
ppstudio-web.serviceappstudio-email-worker.service; po provisioning/recovery serveru je nejdřív zaveď přessudo /var/www/ppstudio/deploy/deploy.sh, jinak se nový release záměrně zastaví přednpm ci. - Produkční provoz
ppstudiouž nemá běžet současně přes PM2 i systemd. Smíšený stav způsobí buď port konflikt na3000, nebo dvojitý běh email workeru. - Sekce
volne-terminyje po resetu z2026-04-19záměrně minimalistická; incidentem je pouze neočekávaný pád route, ne absence starých planner funkcí. - Admin sekce
Email logyje citlivá na rozjezd mezi Prisma schématem a generovaným klientem. Projekt proto nyní předdevibuildautomaticky spouštíprisma generate. - Rozbitý týdenní planner po deployi: špatné zachování query parametrů
week/day/panel, kvůli kterému se obsluha po akci vrací na jiný den nebo na výchozí týden. - Rozbitý týdenní planner po deployi: špatné zachování query parametrů
week/day/panel/slot, kvůli kterému se obsluha po akci vrací na jiný den, jiný slot nebo na výchozí týden. - Sticky draft bar nebo badge
Neuloženo, které zůstávají viset i po návratu ke stejnému týdennímu stavu; indikace se má odvozovat z reálného diffu proti serverovým dnům, ne jen z ručně přepínaného flagu. - Batch create vytvářející jen část série: tohle nesmí nastat; workflow má běžet transakčně all-or-nothing.
- Mobilní planner s nečitelnými touch targety nebo horizontálním scrollem v kartách dnů.
- Regrese planner density passu, kdy se do horní části vrátí duplicita data týdne, vysoký hero nebo rozpad pravého panelu zpět do mnoha malých boxů; po dalších úpravách vždy ověř, že prioritu má grid a detail výběru zůstává soustředěný v jednom kompaktním panelu.
- Mobilní nebo tabletový inspektor dne, který překryje grid bez možnosti rychlého zavření nebo neukáže vybraný blok po tapnutí.
- Day workspace otevírající špatný slot po změně filtru stavu nebo týdne.
- Owner-only sekce
Nastavenímá dopad i na veřejný web a e-mailovou komunikaci; po každé změně je potřeba rychlá smoke kontrola footeru,/kontakt,/faq,/storno-podminkya/rezervace. - FAQ schema drift: po změně FAQ ověř, že
FAQPageJSON-LD vzniká ze stejnýchFaqItemjako viditelná stránka a neobsahuje skryté nebo staré otázky. - Storno stránka publikovaná se správným limitem hodin, ale se starými kontakty nebo opačným významem summary karet; po změně
SiteSettingsvždy ověř hero boxJak zrušit rezervacii textvíce než / méně než X hodin. - Zákaznický nebo admin termín posunutý o hodinu kolem změny času: zkontroluj, zda se slot/kopie počítá přes lokální
dateKey + cell indexvEurope/Prague, zda UI/e-mail/ICS formátují s explicitnímtimeZone: "Europe/Prague", a zda nebyl zaveden pevný offset nebo24hmillisecond shift.