Commit Graph

15 Commits

Author SHA1 Message Date
50ea97ec4b Merge: config validation + race testing (A-015, A-017) 2026-03-24 20:49:56 -07:00
41839b7284 Add comprehensive config validation and race testing target
Split config validation into validateFields() (pure logic) and
validateFiles() (filesystem checks) for testability. New validations:
TLS file existence, token TTL parseability/positivity, Argon2 params > 0,
valid log level, non-empty listen addresses. Added 18 tests covering all
validation paths. Added `make test-race` target. Resolves A-015 and A-017.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:49:16 -07:00
c5469c6bdf Document single-user model and MCIAS migration path in AUDIT.md
Single authenticated user by design. If multi-user is ever needed,
auth migrates to MCIAS — standalone auth won't be extended.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:23:57 -07:00
ea9375b6ae Security hardening: fix critical, high, and medium issues from audit
CRITICAL:
- A-001: SQL injection in snapshot — escape single quotes in backup path
- A-002: Timing attack — always verify against dummy hash when user not
  found, preventing username enumeration
- A-003: Notebook ownership — all authenticated endpoints now verify
  user_id before loading notebook data
- A-004: Point data bounds — decodePoints returns error on misaligned
  data, >4MB payloads, and NaN/Inf values

HIGH:
- A-005: Error messages — generic errors in HTTP responses, no err.Error()
- A-006: Share link authz — RevokeShareLink verifies notebook ownership
- A-007: Scan errors — return 500 instead of silently continuing

MEDIUM:
- A-008: Web server TLS — optional TLS support (HTTPS when configured)
- A-009: Input validation — page_size, stroke count, point_data alignment
  checked in SyncNotebook RPC
- A-010: Graceful shutdown — 30s drain on SIGINT/SIGTERM, all servers
  shut down properly

Added AUDIT.md with all 17 findings, status, and rationale for
accepted risks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:16:26 -07:00
51dd5a6ca3 Implement Phase 10: deployment (Dockerfile, systemd, install script)
- Multi-stage Dockerfile: golang:1.25-alpine builder, alpine:3.21 runtime
  CGO_ENABLED=0, stripped binary, non-root user
- systemd: service unit (hardened), backup oneshot, daily timer (02:00 UTC)
- Install script: create user, dirs, config, install units
- Updated PROGRESS.md with all completed phases

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:01:40 -07:00
169063cd00 Implement Phase 9: FIDO2/U2F WebAuthn support
- WebAuthnUser implementing webauthn.User interface
- NewWebAuthn factory with configurable RP settings
- Credential storage: store, load, list, delete, update sign count
- User lookup by credential ID for login flow
- go-webauthn/webauthn library integrated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:00:10 -07:00
5c4575a67f Implement Phase 8: Web UI with htmx templates
- HTML templates: layout, login, notebook list, notebook view, page viewer
- Web server with chi router, embedded templates via //go:embed
- Login/logout flow with session cookies
- Notebook list, page grid with SVG thumbnails, page viewer
- Share link views (same templates, no auth chrome)
- Server command wired to start gRPC + REST + web servers concurrently
- Graceful shutdown on SIGINT/SIGTERM

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:59:07 -07:00
fedb5e3301 Implement Phase 7: share link tests and expiry fix
- 4 tests: create/validate, expiry, revoke, list
- Fixed expiry check: negative durations now correctly expire links
  (was checking > 0 instead of != 0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:57:03 -07:00
37c2d35ceb Implement Phase 6: REST API with chi router
- Login endpoint (password → bearer token + session cookie)
- Auth middleware (bearer header or session cookie)
- Notebook list endpoint (authenticated)
- Page SVG/JPG rendering endpoints (authenticated)
- Notebook PDF download endpoint (authenticated)
- Share link endpoints: view, page SVG, page JPG, PDF (no auth)
- Route registration with chi groups

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:55:47 -07:00
5993d20995 Implement Phase 5: SVG, JPG, PDF rendering
- SVG: strokes → SVG path elements with dashed/arrow support,
  coordinates scaled from 300 DPI to 72 DPI
- JPG: rasterization at 300 DPI using Go image package, Bresenham
  line drawing with round pen circles
- PDF: minimal PDF generation with raw operators, no external library
- 6 tests: SVG output, dashed style, arrow heads, JPG magic bytes,
  PDF header, page size calculations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:54:32 -07:00
7d4e52ae92 Implement Phase 4: gRPC sync service
- Proto definitions (engpad.v1.EngPadSync) with 6 RPCs
- Generated Go gRPC code
- Auth interceptor: username/password from metadata
- SyncNotebook: upsert with full page/stroke replacement in a tx
- DeleteNotebook, ListNotebooks handlers
- Share link RPCs: CreateShareLink, RevokeShareLink, ListShareLinks
- Share link token management (32-byte random, optional expiry)
- gRPC server with TLS 1.3

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:52:47 -07:00
846a6fe42d Implement Phase 3: CLI commands (init, server, snapshot, status)
- Cobra CLI with init (create DB + admin user), server (placeholder),
  snapshot (VACUUM INTO backup), status (health check + counts)
- All commands load config via --config flag
- init prompts for username and password (masked)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:50:02 -07:00
286b886c06 Implement Phase 2: password auth (Argon2id + bearer tokens)
- Argon2id password hashing and verification with configurable params
- Bearer token generation (32-byte random), SHA-256 hashed storage,
  TTL-based expiry
- User creation and authentication helpers
- auth_tokens table added to migrations
- 6 tests: hash/verify, wrong password, create/auth user, token
  create/validate, token expiry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:49:07 -07:00
9077117e74 Implement Phase 0+1: project setup, config, database, migrations
- Go module, Makefile, .golangci.yaml, .gitignore, example config
- TOML config loading with validation
- SQLite database with WAL, foreign keys, busy timeout
- Schema migrations: users, webauthn_credentials, notebooks, pages,
  strokes, share_links with indexes and cascading deletes
- 4 tests: open+migrate, idempotent, foreign keys, cascade delete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:47:38 -07:00
0cce04b5b8 Initialize eng-pad-server with project documentation
- README.md: project overview, quick start, build commands
- CLAUDE.md: AI dev context, source tree, key conventions
- ARCHITECTURE.md: full system spec covering data model, auth
  (password + FIDO2/U2F), gRPC sync API, REST API, SVG/JPG/PDF
  rendering, web UI, configuration, deployment, security
- PROJECT_PLAN.md: 11 phases with discrete checkboxable steps
- PROGRESS.md: decision log and completion tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:42:38 -07:00