Commit Graph

69 Commits

Author SHA1 Message Date
81fc110224 docs(04-ux-improvements): create phase plan 2026-03-24 09:41:36 +01:00
19d9724c9c docs(phase-04): research ux-improvements phase 2026-03-24 09:34:29 +01:00
2c1410f0b1 docs(state): record phase 4 context session 2026-03-24 09:28:58 +01:00
9810b4dc1b docs(04): capture phase context 2026-03-24 09:28:51 +01:00
46614574c4 docs(phase-03): evolve PROJECT.md after phase completion 2026-03-24 09:21:02 +01:00
b3fe58408e docs(phase-03): complete phase execution 2026-03-24 09:20:37 +01:00
5ae42692b1 fix(03): run go mod tidy to fix pgx/v5 indirect classification 2026-03-24 09:20:27 +01:00
35f04e039d feat(03-02): add Docker Compose postgres profiles and build-tagged test helper
- compose.yml: add postgres service with profiles, healthcheck, pg_isready
- compose.yml: add DATABASE_URL env var and conditional depends_on (required: false)
- compose.yml: add postgres-data volume; default deploy remains SQLite-only
- compose.dev.yml: add postgres service with port 5432 exposed for local dev
- compose.dev.yml: add DATABASE_URL env var and conditional depends_on
- pkg/diunwebhook/postgres_test.go: build-tagged NewTestPostgresServer helper
2026-03-24 09:16:29 +01:00
4f60f1c9a0 feat(03-02): wire DATABASE_URL branching in main.go and fix cross-dialect UNIQUE detection
- Add DATABASE_URL env var branching: pgx/PostgreSQL when set, SQLite when absent
- Blank-import github.com/jackc/pgx/v5/stdlib to register 'pgx' driver
- Log 'Using PostgreSQL database' or 'Using SQLite database at {path}' on startup
- Replace RunMigrations with RunSQLiteMigrations (rename from Plan 01)
- Fix TagsHandler UNIQUE detection to use strings.ToLower for cross-dialect compat
2026-03-24 09:16:25 +01:00
cf788930e0 docs(03-02): complete wire postgresql support plan
- Add 03-02-SUMMARY.md with execution results
- Update STATE.md: advance plan, record metrics, add decisions, update session
- Update ROADMAP.md: phase 03 complete (2/2 plans, all summaries present)
- Update REQUIREMENTS.md: mark DB-02 complete
2026-03-24 09:14:50 +01:00
f611545ae5 docs(03-01): complete PostgreSQL store and migration infrastructure plan
- Add 03-01-SUMMARY.md with full execution record
- Update STATE.md: advance to plan 2, record metrics and decisions
- Update ROADMAP.md: phase 03 in progress (1/2 plans complete)
- Update REQUIREMENTS.md: mark DB-01 and DB-03 complete
2026-03-24 09:10:48 +01:00
8820a9ef9f feat(03-01): add PostgresStore implementing all 9 Store interface methods
- PostgresStore struct with *sql.DB field (no mutex needed for PostgreSQL)
- NewPostgresStore constructor with pool config: MaxOpenConns(25), MaxIdleConns(5), ConnMaxLifetime(5m)
- UpsertEvent with $1..$15 positional params and ON CONFLICT DO UPDATE
- GetUpdates identical SQL to SQLiteStore (TEXT timestamps, COALESCE)
- AcknowledgeUpdate uses NOW() instead of datetime('now')
- ListTags identical to SQLiteStore
- CreateTag uses RETURNING id (pgx does not support LastInsertId)
- DeleteTag, UnassignTag, TagExists use $1 positional param
- AssignTag uses ON CONFLICT (image) DO UPDATE SET tag_id = EXCLUDED.tag_id
2026-03-24 09:09:29 +01:00
95b64b4d54 feat(03-01): add pgx/v5, PostgreSQL migrations, rename RunMigrations to RunSQLiteMigrations
- Add github.com/jackc/pgx/v5 v5.9.1 dependency
- Add golang-migrate pgx/v5 driver
- Create migrations/postgres/0001_initial_schema.up.sql with SERIAL PRIMARY KEY
- Create migrations/postgres/0001_initial_schema.down.sql
- Rename RunMigrations to RunSQLiteMigrations in migrate.go
- Add RunPostgresMigrations with pgxmigrate driver and 'pgx5' name
- Update export_test.go to use RunSQLiteMigrations (go vet compliance)
2026-03-24 09:08:53 +01:00
b6b7ca44dc fix(03): revise plans based on checker feedback 2026-03-24 09:04:19 +01:00
e8e0731adc docs(03-postgresql-support): create phase plan 2026-03-24 08:59:02 +01:00
535061453b docs(03): research PostgreSQL support phase 2026-03-24 08:53:53 +01:00
60ca038a7e docs(state): record phase 3 context session 2026-03-24 08:47:01 +01:00
515ad9a1dd docs(03): capture phase context 2026-03-24 08:46:52 +01:00
a72af59051 docs(phase-02): evolve PROJECT.md after phase completion 2026-03-24 08:43:21 +01:00
e62fcb03bc docs(phase-02): complete phase execution 2026-03-24 08:42:46 +01:00
7004e7fb3e docs(02-02): complete Server struct refactor and test isolation plan
- Add 02-02-SUMMARY.md: Server struct methods, NewTestServer pattern, per-test in-memory databases
- Update STATE.md: advance plan to 2/2, record metrics and decisions
- Update ROADMAP.md: Phase 2 Backend Refactor complete (2/2 plans)
- Update REQUIREMENTS.md: mark REFAC-02 complete (REFAC-01 and REFAC-03 already marked)
2026-03-24 08:39:29 +01:00
e35b4f882d test(02-02): rewrite all tests to use per-test in-memory databases via NewTestServer
All checks were successful
CI / build-test (push) Successful in 1m42s
- Remove TestMain (no longer needed; each test is isolated)
- Replace all diun.UpdatesReset() with diun.NewTestServer() per test
- Replace all diun.SetWebhookSecret/ResetWebhookSecret with NewTestServerWithSecret
- Replace all diun.WebhookHandler etc with srv.WebhookHandler (method calls)
- Replace diun.UpdateEvent with srv.TestUpsertEvent
- Replace diun.GetUpdatesMap with srv.TestGetUpdatesMap
- Update helper functions postTag/postTagAndGetID to accept *diun.Server parameter
- Change t.Fatalf to t.Errorf inside goroutine in TestConcurrentUpdateEvent
- Add error check on second TestUpsertEvent in TestDismissHandler_ReappearsAfterNewWebhook
- All 32 tests pass with zero failures
2026-03-23 22:05:09 +01:00
78543d79e9 feat(02-02): convert handlers to Server struct methods, remove globals
- Add Server struct with store Store and webhookSecret fields
- Add NewServer constructor
- Convert all 6 handler functions to methods on *Server
- Replace all inline SQL with s.store.X() calls
- Remove package-level globals db, mu, webhookSecret
- Remove InitDB, SetWebhookSecret, UpdateEvent, GetUpdates functions
- Update export_test.go: replace old helpers with NewTestServer, NewTestServerWithSecret, TestUpsertEvent, TestGetUpdatesMap
- Update main.go: sql.Open -> RunMigrations -> NewSQLiteStore -> NewServer -> routes
2026-03-23 22:02:53 +01:00
50805b103f docs(02-01): complete Store interface and migration infrastructure plan
- 02-01-SUMMARY.md: Store interface + SQLiteStore + golang-migrate v4.19.1
- STATE.md: advanced to plan 2 of 2, recorded decisions and metrics
- ROADMAP.md: phase 02 progress updated (1/2 summaries)
- REQUIREMENTS.md: REFAC-01 and REFAC-03 marked complete
2026-03-23 21:59:41 +01:00
6506d93eea feat(02-01): add migration infrastructure with golang-migrate and embedded SQL
- RunMigrations applies versioned SQL files via golang-migrate + embed.FS (iofs)
- ErrNoChange handled correctly - not treated as failure
- Migration 0001 creates full current schema with CREATE TABLE IF NOT EXISTS
- All three tables (updates, tags, tag_assignments) with acknowledged_at and ON DELETE CASCADE
- Uses database/sqlite sub-package (modernc.org/sqlite, no CGO)
- go mod tidy applied after adding dependencies
2026-03-23 21:56:34 +01:00
57bf3bdfe5 feat(02-01): add Store interface and SQLiteStore implementation
- Store interface with 9 methods covering all persistence operations
- SQLiteStore implements all 9 methods with exact SQL from current handlers
- NewSQLiteStore sets MaxOpenConns(1) and PRAGMA foreign_keys = ON
- UpsertEvent uses ON CONFLICT DO UPDATE with acknowledged_at reset to NULL
- AssignTag uses INSERT OR REPLACE for tag_assignments table
- golang-migrate v4.19.1 dependency added to go.mod
2026-03-23 21:53:05 +01:00
12cf34ce57 docs(02-backend-refactor): create phase plan 2026-03-23 21:46:57 +01:00
e72e1d1bea docs(phase-02): research backend refactor phase 2026-03-23 21:40:16 +01:00
fcc66b77e9 docs(phase-01): evolve PROJECT.md after phase completion 2026-03-23 21:30:12 +01:00
99813ee5a9 docs(phase-01): complete phase execution 2026-03-23 21:29:19 +01:00
03c3d5d6d7 docs(01-02): complete body-size-limits and test-hardening plan
- 01-02-SUMMARY.md: plan completion summary with deviations
- STATE.md: advanced plan position, added decisions, updated metrics
- ROADMAP.md: phase 01 marked complete (2/2 plans)
- REQUIREMENTS.md: DATA-03 and DATA-04 marked complete
2026-03-23 21:26:02 +01:00
7bdfc5ffec fix(01-02): replace silent test setup returns with t.Fatalf at 6 sites
- TestUpdateEventAndGetUpdates: UpdateEvent error now fails test
- TestUpdatesHandler: UpdateEvent error now fails test
- TestConcurrentUpdateEvent goroutine: UpdateEvent error now fails test
- TestDismissHandler_Success: UpdateEvent error now fails test
- TestDismissHandler_SlashInImageName: UpdateEvent error now fails test
- TestDismissHandler_ReappearsAfterNewWebhook: bare UpdateEvent call now checked
All 6 silent-return sites replaced; test failures are always visible to CI
2026-03-23 21:24:08 +01:00
98dfd76e15 feat(01-02): add request body size limits (1MB) to webhook and tag handlers
- Add maxBodyBytes constant (1 << 20 = 1 MB)
- Add errors import to production file
- Apply http.MaxBytesReader + errors.As(err, *http.MaxBytesError) pattern in:
  WebhookHandler, TagsHandler POST, TagAssignmentHandler PUT and DELETE
- Return HTTP 413 RequestEntityTooLarge when body exceeds limit
- Fix oversized body test strategy: use JSON prefix so decoder reads past limit
  (Rule 1 deviation: all-x body fails at byte 1 before MaxBytesReader triggers)
2026-03-23 21:20:52 +01:00
311e91d3ff test(01-02): add failing tests for oversized body (413) - RED
- TestWebhookHandler_OversizedBody: POST /webhook with >1MB body expects 413
- TestTagsHandler_OversizedBody: POST /api/tags with >1MB body expects 413
- TestTagAssignmentHandler_OversizedBody: PUT /api/tag-assignments with >1MB body expects 413
2026-03-23 21:18:39 +01:00
fb16d0db61 docs(01-01): complete UPSERT + FK enforcement plan
- Create 01-01-SUMMARY.md documenting both bug fixes and test addition
- Advance plan counter to 2/2 in STATE.md
- Record decisions and metrics in STATE.md
- Update ROADMAP.md plan progress (1/2 summaries)
- Mark requirements DATA-01 and DATA-02 complete
2026-03-23 21:16:49 +01:00
e2d388cfd4 test(01-01): add TestUpdateEvent_PreservesTagOnUpsert regression test
- Verifies tag survives a second UpdateEvent() for the same image (DATA-01)
- Verifies acknowledged_at is reset to NULL by the new event
- Verifies event fields (Status) are updated by the new event
2026-03-23 21:14:21 +01:00
7edbaad362 fix(01-01): replace INSERT OR REPLACE with UPSERT and enable FK enforcement
- Add PRAGMA foreign_keys = ON in InitDB() after SetMaxOpenConns(1)
- Replace INSERT OR REPLACE INTO updates with named-column INSERT ON CONFLICT UPSERT
- UPSERT preserves tag_assignments rows on re-insert (fixes DATA-01)
- FK enforcement makes ON DELETE CASCADE fire on tag deletion (fixes DATA-02)
2026-03-23 21:13:43 +01:00
b89e607493 docs(01-data-integrity): create phase 1 plans 2026-03-23 20:04:57 +01:00
19d757d060 docs(phase-01): research data integrity phase
Investigates SQLite UPSERT semantics, FK enforcement per-connection
requirement, http.MaxBytesReader behavior, and t.Fatal test patterns.
All four DATA-0x bugs confirmed with authoritative sources and line
numbers. No open blockers; ready for planning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 19:58:48 +01:00
112c17a701 docs: create roadmap (4 phases) 2026-03-23 19:51:36 +01:00
1f5df8c36a docs: define v1 requirements 2026-03-23 19:48:53 +01:00
e4d59d4788 docs: complete project research 2026-03-23 19:45:06 +01:00
5b273e17bd chore: add project config 2026-03-23 19:37:22 +01:00
256a1ddfb7 docs: initialize project 2026-03-23 19:35:56 +01:00
96c4012e2f chore: add GSD codebase map with 7 analysis documents
Parallel analysis of tech stack, architecture, structure,
conventions, testing patterns, integrations, and concerns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:13:23 +01:00
4358de87ba **feat(docs):** add Dockerfile and Nginx config for static site deployment
All checks were successful
CI / build-test (push) Successful in 1m1s
- Introduce `Dockerfile` for building and serving static site using Bun and Nginx
- Add `nginx.conf` for configuring static file caching and routing rules
- Expose port 80 for containerized deployment
2026-02-27 15:33:04 +01:00
d664e88fff **docs:** expand index.md with architecture, quick start, and tech stack
All checks were successful
CI / build-test (push) Successful in 1m2s
- Add detailed architecture and workflow diagram to explain dashboard functionality
- Include a "Quick Start" section with Docker Compose setup instructions
- Document tech stack and layers used in the project
- Enhance feature descriptions for better clarity and user guidance
2026-02-27 15:31:49 +01:00
eeddd812fa **chore(docs):** add .gitignore for docs and introduce bun.lock file
All checks were successful
CI / build-test (push) Successful in 1m2s
- Add `.gitignore` to exclude `node_modules/`, `.vitepress/cache/`, and `.vitepress/dist/` directories
- Include `bun.lock` for dependency management with Bun
2026-02-27 15:28:17 +01:00
bf77142641 **feat(compose):** add separate deploy and dev Docker Compose files
All checks were successful
CI / build-test (push) Successful in 1m3s
- Introduced `compose.yml` for deployment, pulling the image from the registry
- Added `compose.dev.yml` for local development, building the image from source
- Updated `README.md` and `.claude/CLAUDE.md` with instructions for both configurations
- Introduced `DB_PATH` environment variable to customize SQLite database file location
- Updated `main.go` to use `DB_PATH` with a default fallback (`./diun.db`)
2026-02-27 15:11:47 +01:00
c0746a7f02 **feat(webhook):** add WEBHOOK_SECRET for token authentication support
All checks were successful
CI / build-test (push) Successful in 1m28s
- Protect `/webhook` endpoint using the `Authorization` header
- Update `README.md` with setup instructions and examples for authentication
- Warn when `WEBHOOK_SECRET` is not configured
- Add tests for valid, missing, and invalid token scenarios
- Update `docker-compose.yml` to support `WEBHOOK_SECRET` configuration
2026-02-27 14:58:43 +01:00