Bilko Demo Gate (TrialGatePlugin)
Bilko Demo Gate (TrialGatePlugin)
Šta je TrialGatePlugin
TrialGatePlugin je Ktor ApplicationPlugin koji se aktivira na AuthenticationChecked lifecycle hook-u i implementira dva paralelna guarda:
- Demo read-only guard: Demo sesije (gdje je
principal.isDemo == true) dobijaju 403DEMO_READ_ONLYna svim non-GET zahtjevima osim eksplicitno izuzetih putanja. - Trial expiry gate: Organizacije čiji je
trial_expires_at < now()i nemaju aktivnu pretplatu dobijaju 403TRIAL_EXPIREDna GATED_PREFIXES rutama (revenue-blocking feature gating).
Plugin radi na SVAKOM autentikovanom endpointu — nema per-ruta bypass osim early-return provjera na vrhu plugina.
Izuzeci (exemptions)
Plugin definira tri vrste izuzeća:
- EXEMPT_EXACT: Tačne putanje koje preskačaju OBJE provjere (demo read-only I trial expired).
- EXEMPT_PREFIXES: Prefiks putanje koji preskače OBJE provjere.
- DEMO_CHATBOT_EXEMPT_PATH: Samo
/api/v1/chatbot/message— preskače SAMO demo read-only guard unutar demo grane; trial-expired gate i dalje radi normalno. Korišten za MC #105459 da omogući AI chat na demo sesijama bez otvaranja rupe u trial enforcement-u.
Early-return logika se izvršava PRIJE demo guarda i trial gatea — ako putanja nije ni u jednom EXEMPT/GATED listi, guard se ne izvršava uopšte (implicitni allow).
Demo AI Chatbot Izuzetak (MC #105459)
Problem: Demo sesije koriste dijeljeni org (bez chat_conversations tablice, bez org-context-builder rute) i ne perzistiraju chat kontekst. TrialGatePlugin je blokirao POST /api/v1/chatbot/message na demo sesijama sa 403 DEMO_READ_ONLY.
Odluka: Dodati named-path izuzetak SAMO unutar demo-guard grane (if (principal.isDemo && method != GET && path != DEMO_CHATBOT_EXEMPT_PATH)), ne u EXEMPT_EXACT na vrhu plugina, jer EXEMPT_EXACT bi također izuzeo rutu od trial-expired gate-a (što nije poželjno — chatbot je GATED_PREFIXES feature i treba biti blokiran za organizacije sa isteklim trial-om).
Implementacija (commit e22af78f, PR 130):
TrialGatePlugin.kt:DEMO_CHATBOT_EXEMPT_PATH = "/api/v1/chatbot/message"konstanta + provera u demo-guard grani.ChatbotService.kt:isDemoparametar, stateless path za demo sesije (preskačechat_conversationsread/write iorg-context-builder), novicheckDemoChatRateLimit(per-IP 10/min, nezavisno od per-user limita).ChatbotRoutes.kt: WiringisDemo+checkDemoChatRateLimit; bacaTooManyRequestsExceptionza 429 (necall.respond()— StatusPages bug klasa #104962).ChatWidget.tsx: Demo-mode-aware error fallback (isDemoSessioniz auth-store).- Integracioni testovi:
ChatbotDemoIntegrationTest.kt(6 test case-ova).
Kanonski izvor u repo-u
BUILD-BLUEPRINT.mdsekcija "TrialGatePlugin / Demo Gate"apps/api/src/main/kotlin/no/alai/bilko/features/TrialGatePlugin.kt
Liveness Testing Lekcija
Svaki gate/guard plugin zahtijeva integracioni liveness test koji dokazuje da guard radi kroz CIJELI Ktor pipeline (ne samo unit test ili izolovani route test). TrialGate je jednom bio mrtav od shipovanja — aplikacija se pokrenula ali guard nije radio — što je otkriveno tek nakon deploy-a. ChatbotDemoIntegrationTest.kt je primjer: testira protiv real configureForTest() wiringa, sa live StatusPages handlers (koji su uhvatili latentni bug u 429 obradi tokom test-writing-a).
Evidence: ~/system/evidence/105459/implementation-report.md
Memo: technical_bilko_e2e_green_sprint_2026-07-10.md (TrialGate mrtav-od-shipovanja incident)
No comments to display
No comments to display