HTML Template Chain
DEMO_HTML (source of truth)
.replace() → gate + code
CHAT_HTML
.replace() → Claude API call
PUBLIC_HTML
one edit propagates everywhere
Rate Limiter
Map<ip, number[]>
Sliding window (e.g. 60s)
Prune old timestamps
Count ≥ limit → 429
Per-replica (not shared)
lost on restart — ok for demo
Access Gate (/chat)
First visit → gate page
POST code → compare env var
Set cookie (session)
Subsequent → CHAT_HTML
Mismatch → gate reshown
light auth — not enterprise SSO
L1–L4 Tier Prompts
L1: Helpdesk (concise, script-ready)
L2: Support (step-by-step, logs)
L3: Engineer (root cause, CLI)
L4: Senior/Architect (design, trade-offs)
UI pill buttons → system prompt swap
same model, different persona
Config & Secrets
ANTHROPIC_API_KEY (secret)
ACCESS_CODE (secret)
MODEL (env var, e.g. sonnet)
PORT (env var, default 8080)
Rate limit values (constants)
set via Azure Portal secrets
Observability
console.log → stdout
Container App log stream
Log Analytics workspace
/health probe → revision health
Azure Monitor alert rule (opt.)
Short Links & URLs
fetch('/api/chat', ...)
ReadableStream → chunks
addBubble() renders tokens
Level pills set currentLevel
resetChat() clears transcript
all JS inline in HTML string