Files
ImpTune/.planning/phases/01-foundation/01-02-PLAN.md
T
kawaandClaude Opus 4.6 a8a27a44d3 docs(01): create phase 1 foundation plans
Three plans covering Docker scaffold, SQLite schema, and .intunewin spike.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:19:05 +02:00

8.3 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
01-foundation 02 execute 2
01-01
imptune/db/__init__.py
imptune/db/database.py
imptune/db/models.py
imptune/storage/__init__.py
imptune/storage/driver_store.py
imptune/main.py
tests/test_db.py
true
INFRA-01
INFRA-02
truths artifacts key_links
SQLite database initializes automatically on first run with all tables (Client, Driver, Printer, Icon)
Database uses WAL journal mode and has foreign keys enabled
Database file is created inside the DATA_DIR volume path, not inside the container filesystem
Schema creation is idempotent — repeated startups do not fail or duplicate tables
path provides exports
imptune/db/database.py Peewee SqliteDatabase instance with WAL mode and init_db function
db
init_db
path provides exports
imptune/db/models.py All ORM models for phases 1-5 (BaseModel, Client, Driver, Printer, Icon)
BaseModel
Client
Driver
Printer
Icon
path provides exports
imptune/storage/driver_store.py SHA256 content-addressed file storage abstraction for driver packages
DriverStore
path provides
tests/test_db.py Database initialization and schema validation tests
from to via pattern
imptune/main.py imptune/db/database.py startup event calling init_db() init_db
from to via pattern
imptune/db/models.py imptune/db/database.py BaseModel.Meta.database = db database = db
from to via pattern
imptune/db/database.py imptune/config.py DB_PATH from config DB_PATH|DATA_DIR
Create the full SQLite schema using Peewee ORM (all tables for phases 1-5) and the content-addressed driver storage abstraction. Wire database initialization into the FastAPI startup event.

Purpose: Establish the data layer that all subsequent phases depend on. The full schema is created upfront per the locked user decision, so later phases only add routes and logic — not schema changes. Satisfies INFRA-01 (SQLite auto-init) and INFRA-02 (no external DB). Output: Working database module with all models, driver storage helper, and startup wiring.

<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-foundation/01-CONTEXT.md @.planning/phases/01-foundation/01-RESEARCH.md

From imptune/config.py:

DATA_DIR: str   # env var, default "/data"
DB_PATH: str    # DATA_DIR + "/imptune.db"
DRIVERS_DIR: str  # DATA_DIR + "/drivers"

From imptune/main.py:

app = FastAPI(title="ImpTune")
# startup event already creates DATA_DIR/DRIVERS_DIR directories
# Executor must ADD init_db() call to the existing startup event
Task 1: Create Peewee models, database init, and driver storage imptune/db/__init__.py, imptune/db/database.py, imptune/db/models.py, imptune/storage/__init__.py, imptune/storage/driver_store.py - test_create_tables: calling init_db() creates all 4 tables (client, driver, printer, icon) in a fresh SQLite file - test_wal_mode: after init_db(), PRAGMA journal_mode returns "wal" - test_foreign_keys: after init_db(), PRAGMA foreign_keys returns 1 - test_idempotent: calling init_db() twice does not raise an error - test_driver_store_save: saving bytes returns their SHA256 hex digest and creates a file at DRIVERS_DIR/{sha256} - test_driver_store_dedup: saving the same bytes twice results in one file on disk (not two) - test_driver_store_get_path: get_path(sha256) returns the correct file path **imptune/db/database.py**: - Import SqliteDatabase from peewee, import DB_PATH from imptune.config - Create db = SqliteDatabase(None) (deferred init — path set at runtime so tests can override) - init_db() function: call db.init(DB_PATH, pragmas={"journal_mode": "wal", "foreign_keys": 1}), then db.connect(reuse_if_open=True), then import all models and call db.create_tables([Client, Driver, Printer, Icon], safe=True) - Use deferred database pattern so tests can point at a temp file
**imptune/db/models.py** (full schema for all phases per locked decision):
- BaseModel with Meta.database = db
- Client: name (CharField unique), created_at (DateTimeField default utcnow)
- Driver: sha256 (CharField unique, indexed), original_filename (CharField), size_bytes (IntegerField), uploaded_at (DateTimeField default utcnow), driver_desc (CharField null=True), inf_filename (CharField null=True), architecture (CharField null=True), has_cat_file (BooleanField default=False)
- Printer: name (CharField), ip_address (CharField), port_name (CharField), client (ForeignKeyField Client null=True backref="printers"), driver (ForeignKeyField Driver null=True backref="printers"), duplex_mode (CharField default="OneSided"), color_mode (BooleanField default=True), paper_size (CharField default="A4"), collate (BooleanField default=True), created_at, updated_at (both DateTimeField default utcnow)
- Icon: printer (ForeignKeyField Printer unique backref="icons"), sha256 (CharField), original_filename (CharField), size_bytes (IntegerField), uploaded_at (DateTimeField default utcnow)

**imptune/storage/driver_store.py**:
- Class DriverStore with __init__(self, base_dir: str)
- save(self, data: bytes) -> str: compute SHA256, write to base_dir/{sha256} if not exists, return hex digest
- get_path(self, sha256: str) -> Path: return Path(base_dir) / sha256
- exists(self, sha256: str) -> bool: check if file exists
cd C:/Users/SebastienQUEROL/Documents/projets/ImpTune && python -m pytest tests/test_db.py -x -v - All 7 tests pass - init_db() creates Client, Driver, Printer, Icon tables - WAL mode and foreign keys enabled - Idempotent — second call is no-op - DriverStore deduplicates by SHA256 Task 2: Wire database init into FastAPI startup imptune/main.py Modify the existing imptune/main.py (created by plan 01-01) to add database initialization on startup:
- Import init_db from imptune.db.database
- In the existing startup event handler, add a call to init_db() AFTER the directory creation logic
- This ensures the SQLite database is created inside DATA_DIR (which was just created/verified)
- Keep all existing code (StaticFiles mount, router includes, directory creation) — only ADD the init_db() call

Do NOT use async def for the startup handler — Peewee is sync-only. Use regular def with FastAPI's @app.on_event("startup") which already exists from plan 01-01.
cd C:/Users/SebastienQUEROL/Documents/projets/ImpTune && python -m pytest tests/test_health.py tests/test_db.py -x -v - main.py imports and calls init_db() on startup - Existing health and static tests still pass (no regression) - Database tests pass with init triggered via app startup - `python -m pytest tests/ -x -v` — all tests pass (health + static + db) - `python -c "from imptune.db.models import Client, Driver, Printer, Icon; print('Models OK')"` — imports without error - `python -c "from imptune.storage.driver_store import DriverStore; print('DriverStore OK')"` — imports without error

<success_criteria>

  • SQLite database auto-creates on app startup with 4 tables
  • WAL journal mode and foreign keys enabled via pragmas
  • Database file lives at DATA_DIR/imptune.db (volume-mounted path)
  • DriverStore saves files by SHA256 with deduplication
  • All existing tests continue to pass (no regression)
  • 7+ new tests pass for db and storage </success_criteria>
After completion, create `.planning/phases/01-foundation/01-02-SUMMARY.md`