docs(01-02): complete database schema and driver storage plan

- 01-02-SUMMARY.md: TDD execution results, decisions, self-check passed
- STATE.md: progress updated (100% phase 1), 3 decisions recorded
- ROADMAP.md: phase 1 marked Complete (3/3 summaries)
This commit is contained in:
2026-04-10 11:33:20 +02:00
parent 88d9c5f0d2
commit 4d57528963
3 changed files with 153 additions and 10 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ ImpTune ships in five phases ordered by risk and dependency. The foundation phas
Decimal phases appear between their surrounding integers in numeric order. Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 1: Foundation** - Docker container scaffold, SQLite schema, and .intunewin format spike - [x] **Phase 1: Foundation** - Docker container scaffold, SQLite schema, and .intunewin format spike (completed 2026-04-10)
- [ ] **Phase 2: Driver Management** - Driver ZIP upload, INF parsing, DriverDesc dropdown, volume persistence - [ ] **Phase 2: Driver Management** - Driver ZIP upload, INF parsing, DriverDesc dropdown, volume persistence
- [ ] **Phase 3: Printer Configuration** - Full printer config form, client/tenant labels, SQLite persistence - [ ] **Phase 3: Printer Configuration** - Full printer config form, client/tenant labels, SQLite persistence
- [ ] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards - [ ] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards
@@ -108,7 +108,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5
| Phase | Plans Complete | Status | Completed | | Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------| |-------|----------------|--------|-----------|
| 1. Foundation | 2/3 | In Progress| | | 1. Foundation | 3/3 | Complete | 2026-04-10 |
| 2. Driver Management | 0/3 | Not started | - | | 2. Driver Management | 0/3 | Not started | - |
| 3. Printer Configuration | 0/3 | Not started | - | | 3. Printer Configuration | 0/3 | Not started | - |
| 4. Script Generation | 0/3 | Not started | - | | 4. Script Generation | 0/3 | Not started | - |
+12 -8
View File
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: executing status: executing
stopped_at: Completed 01-01-PLAN.md stopped_at: Completed 01-02-PLAN.md
last_updated: "2026-04-10T09:27:00.000Z" last_updated: "2026-04-10T09:33:07.640Z"
last_activity: 2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, test suite last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite"
progress: progress:
total_phases: 5 total_phases: 5
completed_phases: 0 completed_phases: 1
total_plans: 3 total_plans: 3
completed_plans: 2 completed_plans: 3
percent: 7 percent: 7
--- ---
@@ -50,6 +50,7 @@ Progress: [░░░░░░░░░░] 7%
- Trend: Consistent - Trend: Consistent
*Updated after each plan completion* *Updated after each plan completion*
| Phase 01-foundation P01-02 | 3 | 2 tasks | 7 files |
## Accumulated Context ## Accumulated Context
@@ -64,6 +65,9 @@ Recent decisions affecting current work:
- [Phase 01]: Inner .intunewin ZIP uses DEFLATE compression; outer ZIP uses STORED (matches C# reference implementation) - [Phase 01]: Inner .intunewin ZIP uses DEFLATE compression; outer ZIP uses STORED (matches C# reference implementation)
- [Plan 01-01]: Use asynccontextmanager lifespan instead of deprecated @app.on_event — required for FastAPI 0.115+ / Starlette 0.40+ - [Plan 01-01]: Use asynccontextmanager lifespan instead of deprecated @app.on_event — required for FastAPI 0.115+ / Starlette 0.40+
- [Plan 01-01]: TemplateResponse uses request= kwarg signature (not positional dict) — Starlette 0.40+ compatibility - [Plan 01-01]: TemplateResponse uses request= kwarg signature (not positional dict) — Starlette 0.40+ compatibility
- [Phase 01-foundation]: Deferred SqliteDatabase(None) pattern so tests can patch DB_PATH via monkeypatch without module reload
- [Phase 01-foundation]: Full 4-table schema created upfront in phase 1 — later phases add routes/logic only, no schema changes
- [Phase 01-foundation]: init_db() added to lifespan (not @app.on_event) consistent with 01-01 established pattern
### Pending Todos ### Pending Todos
@@ -76,6 +80,6 @@ None yet.
## Session Continuity ## Session Continuity
Last session: 2026-04-10T09:27:00Z Last session: 2026-04-10T09:33:07.637Z
Stopped at: Completed 01-01-PLAN.md Stopped at: Completed 01-02-PLAN.md
Resume file: .planning/phases/01-foundation/01-02-PLAN.md Resume file: None
@@ -0,0 +1,139 @@
---
phase: 01-foundation
plan: "02"
subsystem: database
tags: [peewee, sqlite, wal, orm, content-addressed-storage, sha256]
# Dependency graph
requires:
- phase: 01-01
provides: "FastAPI app shell with lifespan, config.py with DATA_DIR/DB_PATH/DRIVERS_DIR"
provides:
- "Peewee SqliteDatabase instance with WAL mode + foreign_keys pragma (imptune/db/database.py)"
- "Full ORM schema: Client, Driver, Printer, Icon models for phases 1-5 (imptune/db/models.py)"
- "SHA256 content-addressed DriverStore with deduplication (imptune/storage/driver_store.py)"
- "Auto-initializing database via FastAPI lifespan startup"
affects:
- phase-02-clients
- phase-03-drivers
- phase-04-printers
- phase-05-export
# Tech tracking
tech-stack:
added: [peewee==3.17.9]
patterns:
- "Deferred SqliteDatabase init (db.init() at runtime so tests can override DB_PATH)"
- "safe=True on create_tables() for idempotent schema creation"
- "SHA256 content-addressed file storage for deduplication"
key-files:
created:
- imptune/db/__init__.py
- imptune/db/database.py
- imptune/db/models.py
- imptune/storage/__init__.py
- imptune/storage/driver_store.py
- tests/test_db.py
modified:
- imptune/main.py
key-decisions:
- "Deferred SqliteDatabase pattern (SqliteDatabase(None)) so tests can patch imptune.config.DB_PATH without module reload"
- "Full schema created upfront in phase 1 per locked user decision — later phases only add routes/logic, no schema changes"
- "init_db() placed in lifespan (not @app.on_event) consistent with 01-01 decision — plan text was outdated"
patterns-established:
- "TDD: RED (failing tests) then GREEN (implementation) for all db/storage modules"
- "ORM: All models extend BaseModel which references shared db instance via Meta.database = db"
- "Storage: DriverStore encapsulates all filesystem operations for driver packages"
requirements-completed: [INFRA-01, INFRA-02]
# Metrics
duration: 3min
completed: 2026-04-10
---
# Phase 1 Plan 2: Database Schema and Driver Storage Summary
**Peewee ORM with deferred SQLiteDatabase, full 4-table schema (Client/Driver/Printer/Icon) for all phases, and SHA256-deduplicating DriverStore — wired into FastAPI lifespan**
## Performance
- **Duration:** ~3 min
- **Started:** 2026-04-10T09:29:54Z
- **Completed:** 2026-04-10T09:32:07Z
- **Tasks:** 2 (Task 1 with TDD + Task 2)
- **Files modified:** 7
## Accomplishments
- Full Peewee ORM schema with 4 tables covering all phases 1-5 (locked-in upfront design decision)
- WAL journal mode and foreign_keys pragma enforced via init_db() on every startup
- Deferred database pattern allows tests to safely redirect DB_PATH to tmp dirs without module reloads
- DriverStore provides SHA256 content-addressed storage with automatic deduplication on write
- init_db() integrated into FastAPI lifespan — database auto-creates at DATA_DIR/imptune.db on startup
## Task Commits
Each task was committed atomically:
1. **Task 1: Peewee models, database init, and driver storage** - `dea4148` (feat — TDD GREEN)
2. **Task 2: Wire database init into FastAPI startup** - `88d9c5f` (feat)
**Plan metadata:** (docs commit follows)
_Note: TDD — tests written first (RED), then implementation (GREEN). No separate refactor pass needed._
## Files Created/Modified
- `imptune/db/__init__.py` - Package marker
- `imptune/db/database.py` - Deferred SqliteDatabase instance + init_db() with WAL/FK pragmas
- `imptune/db/models.py` - BaseModel, Client, Driver, Printer, Icon ORM models
- `imptune/storage/__init__.py` - Package marker
- `imptune/storage/driver_store.py` - SHA256 content-addressed DriverStore class
- `tests/test_db.py` - 7 TDD tests (table creation, WAL, FK, idempotency, save, dedup, get_path)
- `imptune/main.py` - Added import and call to init_db() in lifespan
## Decisions Made
- **Deferred database pattern**: Used `SqliteDatabase(None)` + `db.init()` at runtime so pytest's `monkeypatch` on `imptune.config.DB_PATH` works without module reload side effects.
- **Lifespan over @app.on_event**: Plan text referenced `@app.on_event("startup")` but 01-01 established the lifespan pattern. Followed existing code — no deviation registered as this was alignment with an existing decision.
- **Full schema upfront**: All 4 tables created in phase 1 per user's locked decision, so phases 2-5 only add application logic.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] Installed missing peewee package**
- **Found during:** Task 1 setup
- **Issue:** peewee was in requirements.txt but not installed in the active Python environment
- **Fix:** Ran `python -m pip install peewee==3.17.*`
- **Files modified:** None (environment only)
- **Verification:** `import peewee` succeeds, all 7 tests pass
- **Committed in:** Not committed (environment dependency install)
---
**Total deviations:** 1 auto-fixed (1 blocking — missing dependency)
**Impact on plan:** No scope creep. peewee install was a prerequisite, not new scope.
## Issues Encountered
- Plan Task 2 referenced `@app.on_event("startup")` but the existing `main.py` from plan 01-01 already uses `asynccontextmanager lifespan` (per a decision recorded in STATE.md). Added `init_db()` to the lifespan function instead — no regression.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- Database layer complete — all ORM models importable and tested
- `init_db()` wired in — first app startup creates the database automatically in DATA_DIR
- DriverStore ready for driver upload routes (phase 3)
- All 24 tests pass (7 new + 17 existing), zero regressions
---
*Phase: 01-foundation*
*Completed: 2026-04-10*