Skip to content

Architecture Decision Records

ADR Index

# Decision Status Date
ADR-001 Consolidate on gorilla/mux Accepted 2024-01
ADR-002 In-process event bus Accepted 2024-01
ADR-003 Backend relay for file chunks Accepted 2024-01
ADR-004 Binary WebSocket frames Accepted 2024-01
ADR-005 SHA-256 checksums Accepted 2024-01
ADR-006 Polling + Event Bus for frontend updates Accepted 2024-01
ADR-007 Keep Lit Web Components Accepted 2024-01
ADR-008 Schema SQL with auto-migration Accepted 2024-01
ADR-009 log/slog for logging Accepted (not yet implemented) 2024-01
ADR-010 robfig/cron for scheduling Accepted 2024-01

ADR-001: Consolidate on gorilla/mux

Context: The codebase has 3 incompatible HTTP router implementations (gorilla/mux, gin, gorilla/mux+Auth0).

Decision: Consolidate on gorilla/mux and delete gin/GORM code paths.

Rationale: gorilla/mux is already the most complete path, lightweight, and doesn't pull in unnecessary ORM dependencies.

Consequences: Delete pkg/api/, pkg/config/, pkg/domain/, internal/auth/auth0.go, internal/database/.


ADR-002: In-process event bus

Context: Need internal pub/sub for decoupling (e.g., transfer progress → SSE broadcast).

Decision: Use a simple in-process event bus (Go channels) for v1. Plan upgrade path to NATS for multi-instance.

Rationale: Keeps deployment simple (single binary), avoids infrastructure dependency for MVP.


ADR-003: Backend relay for file chunks

Context: How should file data flow between agents?

Decision: All file data flows through the backend. Agents never connect directly to each other.

Rationale: Simplifies network requirements (agents only need outbound to backend), enables audit logging, centralized access control.

Trade-off: Backend becomes a throughput bottleneck. Mitigated by chunking and future horizontal scaling.


ADR-004: Binary WebSocket frames

Context: How to transfer file chunks over WebSocket?

Decision: Use binary WebSocket frames with a structured header (transfer ID, chunk index, size).

Rationale: Binary frames avoid Base64 encoding overhead (~33% savings), enable streaming.


ADR-005: SHA-256 checksums

Context: How to verify transfer integrity?

Decision: SHA-256 checksum computed incrementally during read/write, verified at transfer completion.

Rationale: Industry standard, hardware-accelerated on modern CPUs, sufficient collision resistance.


ADR-006: Polling + Event Bus for frontend updates

Context: How to push real-time updates to the web frontend?

Decision: REST API polling combined with an in-app event bus (event-bus.ts).

Rationale: Simple, works through all proxies, no additional connection management. SSE was considered but not implemented due to limited browser EventSource API (no custom headers for auth).


ADR-007: Keep Lit Web Components

Context: Should we switch to React/Vue/Angular?

Decision: Keep Lit Web Components.

Rationale: Tiny bundle (~16KB), standards-based, no framework lock-in, existing code is functional.


ADR-008: Schema SQL with auto-migration

Context: How to manage database schema changes?

Decision: Single schema.sql file in backend/internal/db/ with idempotent DDL (IF NOT EXISTS). Applied automatically on startup via pgDB.Migrate(). golang-migrate CLI is available in Docker for optional manual migrations.

Rationale: Simple for single-instance deployment. The full schema is always visible in one file.


ADR-009: log/slog for logging

Context: Which logging library?

Decision: Use Go's standard log/slog (structured logging).

Rationale: No external dependency, structured JSON output, performant, standard library since Go 1.21.


ADR-010: robfig/cron for scheduling

Context: How to implement cron-based job scheduling?

Decision: Use robfig/cron/v3.

Rationale: Mature library, supports standard cron syntax, timezone-aware, widely used in Go ecosystem.