10 KiB
10 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 | 01 | execute | 1 |
|
true |
|
|
Purpose: Establish the running container and app shell that satisfies INFRA-01 (single Docker container) and INFRA-02 (no Node.js, no external DB). All subsequent phases add features to this scaffold. Output: A buildable Docker image that starts, serves the app shell on localhost:8000, and passes healthcheck.
<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 Task 1: Create Docker scaffold, FastAPI app, and app shell templates Dockerfile, docker-compose.yml, requirements.txt, imptune/__init__.py, imptune/main.py, imptune/config.py, imptune/api/__init__.py, imptune/api/pages.py, imptune/api/health.py, imptune/templates/base.html, imptune/templates/dashboard.html, imptune/static/app.css Create the full project scaffold following the architecture from RESEARCH.md. The app package is `imptune/` (not top-level modules).**Dockerfile** (python:3.12-slim-bookworm base):
- WORKDIR /app
- Single RUN layer: apt-get install curl, mkdir -p /app/imptune/static, download Pico CSS v2 (pico.min.css), HTMX 2.x (htmx.min.js), Alpine.js 3.x (alpine.min.js) into /app/imptune/static/ using curl with --fail flag, then purge curl and clean apt cache
- COPY requirements.txt and pip install --no-cache-dir
- COPY imptune/ into /app/imptune/ and other root files
- VOLUME ["/data"]
- HEALTHCHECK using python stdlib urllib (not curl): `python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"`
- EXPOSE 8000
- CMD ["uvicorn", "imptune.main:app", "--host", "0.0.0.0", "--port", "8000"]
**docker-compose.yml**:
- Service `imptune`, build context `.`, ports 8000:8000, volume `imptune_data:/data`, restart unless-stopped, env DATA_DIR=/data
**requirements.txt** (all dependencies for phases 1-5):
- fastapi==0.115.*, uvicorn[standard]==0.30.*, jinja2==3.1.*, python-multipart==0.0.9, pycryptodome==3.20.*, python-dotenv==1.0.*, peewee==3.17.*
**imptune/config.py**:
- Load DATA_DIR from env (default "/data"), PORT from env (default 8000)
- Derive DB_PATH as DATA_DIR/imptune.db, DRIVERS_DIR as DATA_DIR/drivers
**imptune/main.py**:
- Create FastAPI app (title="ImpTune")
- Mount StaticFiles from pathlib.Path(__file__).parent / "static" at "/static"
- Set up Jinja2Templates pointing to imptune/templates/
- Include health router and pages router
- Add startup event that creates DATA_DIR and DRIVERS_DIR directories if they don't exist
**imptune/api/health.py**:
- GET /health returning {"status": "ok"}
**imptune/api/pages.py**:
- GET / returning dashboard.html template (sync def, not async)
- Pass empty recent_printers=[] and recent_packages=[] context for now
**imptune/templates/base.html**:
- html lang="en" data-theme="auto" (Pico CSS auto dark/light)
- Head: meta charset, viewport, title "ImpTune", link to /static/pico.min.css, link to /static/app.css, script defer for alpine.min.js, script for htmx.min.js
- Body: flex container with persistent left sidebar nav and main content area
- Sidebar: flat equal-weight nav links for Dashboard (/), Drivers (/drivers), Printers (/printers), Clients (/clients), Packages (/packages). Use semantic nav element. Active link highlighted.
- Main: container class wrapping {% block content %}{% endblock %}
**imptune/templates/dashboard.html**:
- Extends base.html
- Quick action buttons at top: "New Printer", "Upload Driver", "Export Package" (links, non-functional in Phase 1 — link to # with disabled state)
- Recent activity section below: empty state message "No printers configured yet" and "No packages exported yet"
**imptune/static/app.css** (under 50 lines):
- Sidebar layout: flex, sidebar fixed width ~220px, main flex-grow
- Sidebar nav styling: vertical link list, active state highlight
- Quick action button row styling
- Keep minimal — Pico CSS handles most styling
All __init__.py files: empty or minimal.
**tests/conftest.py**:
- Import TestClient from fastapi.testclient (uses httpx under the hood)
- Fixture `client` that creates TestClient(app) from imptune.main
- Fixture `tmp_data_dir` using tmp_path that sets DATA_DIR env var to a temp directory before importing app, and creates the temp SQLite path
**tests/test_health.py**:
- test_health_returns_200: client.get("/health") returns 200 and JSON body {"status": "ok"}
**tests/test_static.py**:
- test_no_cdn_urls_in_templates: glob all .html files in imptune/templates/, read each, assert no matches for CDN domains (cdn.jsdelivr.net, unpkg.com, cdnjs.com) or https:// in href/src attributes
- test_dashboard_returns_200: client.get("/") returns 200
Run tests to confirm they pass (GREEN). The no-CDN test validates INFRA-02 at the template level.
<success_criteria>
- FastAPI app starts and serves GET /health with 200
- Dashboard page renders with sidebar navigation (5 sections)
- All static assets referenced via /static/ paths, zero CDN URLs
- Docker image builds from python:3.12-slim-bookworm with no Node.js
- Test suite passes with 4+ green tests </success_criteria>