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

202 lines
8.4 KiB
Markdown

# 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*