infra/stacks/f1-stream/files/.planning/STATE.md
Viktor Barzin c7c7047f1c [ci skip] Flatten module wrappers into stack roots
Remove the module "xxx" { source = "./module" } indirection layer
from all 66 service stacks. Resources are now defined directly in
each stack's main.tf instead of through a wrapper module.

- Merge module/main.tf contents into stack main.tf
- Apply variable replacements (var.tier -> local.tiers.X, renamed vars)
- Fix shared module paths (one fewer ../ at each level)
- Move extra files/dirs (factory/, chart_values, subdirs) to stack root
- Update state files to strip module.<name>. prefix
- Update CLAUDE.md to reflect flat structure

Verified: terragrunt plan shows 0 add, 0 destroy across all stacks.
2026-02-22 15:13:55 +00:00

3.9 KiB

Project State

Project Reference

See: .planning/PROJECT.md (updated 2026-02-17)

Core value: Users can find working F1 streams quickly -- the app automatically discovers, validates, and surfaces healthy streams while removing dead ones. Current focus: Phase 5: Sandbox Proxy Hardening (complete)

Current Position

Phase: 5 of 5 (Sandbox Proxy Hardening) Plan: 2 of 2 in current phase (complete) Status: ALL PHASES COMPLETE -- project finished Last activity: 2026-02-17 -- Completed 05-02 frontend shadow DOM sandbox

Progress: [██████████] 100%

Performance Metrics

Velocity:

  • Total plans completed: 8
  • Average duration: 2.1min
  • Total execution time: 0.28 hours

By Phase:

Phase Plans Total Avg/Plan
01-scraper-validation 1 3min 3min
02-health-check-infrastructure 2 4min 2min
03-auto-publish-pipeline 1 2min 2min
04-video-extraction-native-playback 2 5min 2.5min
05-sandbox-proxy-hardening 2 3min 1.5min

Recent Trend:

  • Last 5 plans: 2min, 3min, 2min, 2min, 1min
  • Trend: Stable

Updated after each plan completion

Accumulated Context

Decisions

Decisions are logged in PROJECT.md Key Decisions table. Recent decisions affecting current work:

  • Server-side health checks chosen over client-only (client can't inspect CORS responses)
  • 5 consecutive failures threshold to avoid flapping
  • Auto-publish for scraped streams that pass health check (health check is the quality gate)
  • 5-minute health check interval (freshness vs load balance)
  • String matching over DOM parsing for video detection (DOM reserved for Phase 4)
  • 2MB body limit for HTML inspection to prevent memory issues
  • 3 redirect limit to avoid infinite redirect chains on stream sites
  • HealthMap reads file without lock to avoid deadlock from cross-lock scenarios
  • Single HasVideoContent call covers both reachability and content checks
  • Orphaned health state entries pruned each cycle to prevent unbounded file growth
  • URLs not in health map assumed healthy to prevent new streams disappearing before first check
  • HealthMap called within streamsMu/scrapedMu read locks safely via lock-free file read
  • Source field uses string values (user/system/scraped) for readability over int enum
  • PublishScrapedStream deduplicates by exact URL match; normalized matching stays in scraper layer
  • Auto-publish iterates all validated links each cycle; deduplication makes repeat calls no-ops
  • DOM parsing with golang.org/x/net/html for structured video source extraction (Phase 4)
  • Dual extraction strategy: DOM walking + regex script parsing for maximum video URL coverage
  • Priority ordering HLS > DASH > MP4 > WebM for frontend source selection
  • 5-minute cache on extract endpoint to reduce upstream load
  • Empty sources array (not error) when no video found to distinguish from fetch failures
  • HLS.js loaded from jsDelivr CDN to avoid bundling complexity
  • Extraction runs async after card render -- progressive enhancement with shadow DOM sandbox fallback
  • DASH sources fall back to shadow DOM sandbox (dash.js too heavy for current scope)
  • Silent console.log on extraction failure -- no user-facing errors for extraction issues
  • 50+ ad/tracker domains in blocklist with parent-domain walk-up matching
  • Inline scripts kept for video players; blocked scripts removed by domain
  • CSP allows img/media/connect broadly since video sources come from arbitrary origins
  • Non-HTML sub-resources proxied as-is with CSP headers
  • Closed shadow DOM mode prevents external JS from accessing shadow root
  • Script element created via createElement for execution in shadow DOM (innerHTML scripts don't execute)
  • Direct link fallback when sandbox proxy fetch fails rather than broken state

Pending Todos

None yet.

Blockers/Concerns

None yet.

Session Continuity

Last session: 2026-02-17 Stopped at: Completed 05-02-PLAN.md (frontend shadow DOM sandbox) -- ALL PHASES COMPLETE Resume file: None