infra/stacks/f1-stream/files/.planning/codebase/STRUCTURE.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

8.4 KiB

Codebase Structure

Analysis Date: 2026-02-17

Directory Layout

f1-stream/
├── main.go                 # Entry point, service initialization, signal handling
├── go.mod                  # Go module definition
├── go.sum                  # Dependency lock file
├── Dockerfile              # Container image definition
├── redeploy.sh            # Kubernetes redeployment script
├── index.html             # HTML template served at root
├── internal/              # Private Go packages
│   ├── auth/              # WebAuthn authentication and session management
│   ├── models/            # Domain data types
│   ├── server/            # HTTP handlers, routes, middleware
│   ├── store/             # File-based persistence layer
│   ├── scraper/           # Reddit content scraper
│   └── proxy/             # HTTP proxy with rate limiting
├── static/                # Frontend assets served to clients
│   ├── index.html         # Main SPA template
│   ├── css/               # Stylesheets
│   └── js/                # Client-side JavaScript modules
└── .planning/             # Planning/documentation directory
    └── codebase/          # Architecture analysis documents

Directory Purposes

Root Level:

  • Purpose: Service configuration and entry point
  • Contains: Go module, main executable, Docker configuration, shell scripts
  • Key files: main.go (service bootstrap), go.mod (dependencies)

internal/:

  • Purpose: Private packages (not importable by external code)
  • Contains: All business logic, separated by concern
  • Key pattern: Each subdirectory is a distinct Go package with clear responsibility

internal/auth/:

  • Purpose: User authentication, session management, context helpers
  • Contains: WebAuthn ceremony handlers, session token management, user-in-context utilities
  • Key files:
    • auth.go: Registration/login handlers, ceremony session storage, credential validation
    • context.go: Request context helpers for passing user data between middleware and handlers

internal/models/:

  • Purpose: Domain model definitions
  • Contains: User, Stream, ScrapedLink, Session type definitions
  • Key files: models.go (all types, includes WebAuthn interface implementations)

internal/server/:

  • Purpose: HTTP API and routing layer
  • Contains: Handler functions, route registration, middleware implementations
  • Key files:
    • server.go: Server struct, route registration, API handlers (streams, admin, public endpoints)
    • middleware.go: LoggingMiddleware, RecoveryMiddleware, AuthMiddleware, RequireAuth, RequireAdmin, OriginCheck

internal/store/:

  • Purpose: Persistent storage abstraction over file system
  • Contains: JSON file operations, per-entity storage methods, atomic write patterns
  • Key files:
    • store.go: Store struct, directory initialization, JSON helper functions (readJSON, writeJSON)
    • streams.go: Stream CRUD operations, publish toggle, seeding
    • users.go: User lookup, credential updates, admin count
    • sessions.go: Session creation, validation, expiry cleanup
    • scraped.go: Scraped link persistence, active link filtering

internal/scraper/:

  • Purpose: Background content aggregation
  • Contains: Interval-based scraper, Reddit-specific scraper logic
  • Key files:
    • scraper.go: Scraper service, interval-based run loop, manual trigger mechanism, deduplication logic
    • reddit.go: Reddit API polling, F1 keyword filtering, URL extraction (not included in sample reads but referenced)

internal/proxy/:

  • Purpose: HTTP content fetching with security controls and rate limiting
  • Contains: Rate limiter, private IP validation, response modification
  • Key files: proxy.go (implements http.Handler, rate limiting, content fetching, base tag injection)

static/:

  • Purpose: Frontend assets served to browser
  • Contains: HTML template and client-side code
  • Key files:
    • index.html: SPA HTML template (includes script tags loading js/)
    • js/app.js: Toast notifications, dialog system, tab switching, initialization
    • js/auth.js: Registration/login UI, WebAuthn client ceremony
    • js/streams.js: Stream display, filtering, admin operations
    • js/utils.js: Shared utilities (HTML escaping)
    • css/: Stylesheets for app UI

Key File Locations

Entry Points:

  • main.go: Service initialization, dependency injection, signal handling, goroutine startup

Configuration:

  • Environment variables read in main.go (LISTEN_ADDR, DATA_DIR, SCRAPE_INTERVAL, etc.)
  • WebAuthn config passed to auth.New()
  • .env files not tracked (see .gitignore)

Core Logic:

  • Request routing: internal/server/server.go:registerRoutes()
  • Auth logic: internal/auth/auth.go
  • Data storage: internal/store/store.go and per-entity files
  • Scraping: internal/scraper/scraper.go
  • Proxying: internal/proxy/proxy.go

Testing:

  • No test files present in codebase (see TESTING.md concerns section)

Naming Conventions

Files:

  • Go source files: lowercase with underscores (e.g., auth.go, middleware.go)
  • JavaScript files: lowercase with hyphens or underscores (e.g., app.js, auth.js)
  • JSON data files: lowercase (e.g., streams.json, users.json, sessions.json)

Directories:

  • Go packages: lowercase, single word preferred (e.g., auth, store, models)
  • Frontend assets: plural nouns (e.g., static, css, js)

Functions:

  • Go: CamelCase (exported), camelCase (unexported)
  • JavaScript: camelCase throughout (e.g., loadPublicStreams(), showToast())

Types:

  • Go structs: CamelCase (e.g., User, Stream, Store, Auth)
  • Methods: CamelCase (e.g., BeginLogin(), AddStream())

Variables:

  • Go: camelCase (e.g., listenAddr, dataDir, adminUsername)
  • JavaScript: camelCase (e.g., container, userID, sessionToken)

Where to Add New Code

New Feature (e.g., new stream filter):

  • Primary code: Add handler in internal/server/server.go, register route in registerRoutes()
  • Store operations: Add method to appropriate file in internal/store/ (likely streams.go)
  • Frontend: Add UI in static/ and API call in static/js/streams.js or new module
  • Models: Extend types in internal/models/models.go if new fields needed

New Authentication Method:

  • Core implementation: New file in internal/auth/ (e.g., oauth.go)
  • Handlers: Add methods following WebAuthn pattern (BeginXxx, FinishXxx)
  • Routes: Register in registerRoutes()
  • Frontend: Add form/button in static/js/auth.js

New Background Service (e.g., content validator):

  • Implementation: New file in internal/ or new package internal/validator/
  • Integration: Initialize in main() alongside scraper.New()
  • Lifecycle: Use context pattern from scraper's Run(ctx) method
  • Storage: Use existing Store instance

Utilities/Helpers:

  • Shared by Go packages: Add to package where most useful, or create new internal/util/ package
  • Shared by frontend: Add to static/js/utils.js or create new module
  • Shared helpers pattern: Functions not tied to single package, used across multiple

Special Directories

internal/:

  • Purpose: Enforce package privacy (cannot be imported by external code)
  • Generated: No
  • Committed: Yes

static/:

  • Purpose: Served directly to clients via http.FileServer
  • Generated: No (hand-written frontend)
  • Committed: Yes

.planning/codebase/:

  • Purpose: Architecture documentation for development guidance
  • Generated: No (manually created by mapping process)
  • Committed: Yes

Data Directory (runtime):

  • Purpose: Persistent JSON files (streams.json, users.json, sessions.json, scraped.json)
  • Location: Specified by DATA_DIR env var (default /data)
  • Generated: Yes (created on first run)
  • Committed: No (varies per deployment environment)

Import Patterns

Go Package Imports:

  • Standard library first: import ("context" "fmt" "log")
  • Internal packages second: import ("f1-stream/internal/auth" "f1-stream/internal/store")
  • External third-party last: import ("github.com/go-webauthn/webauthn/webauthn")

Cross-Package Dependencies:

  • Server depends on: Auth, Store, Proxy, Scraper, Models
  • Auth depends on: Store, Models
  • Scraper depends on: Store, Models
  • Proxy depends on: none (standalone service)
  • Store depends on: Models
  • Models depends on: external WebAuthn library only

Structure analysis: 2026-02-17