- VERIFICATION.md: 3/3 must-haves verified, 124/124 tests green - ROADMAP.md: Phase 15 marked complete - STATE.md: advanced to post-phase state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
67 lines
2.8 KiB
Markdown
67 lines
2.8 KiB
Markdown
# CLAUDE.md
|
||
|
||
Guide for Claude Code (claude.ai/code) work in repo.
|
||
|
||
## Commands
|
||
|
||
**Run tests:**
|
||
```bash
|
||
pytest tests/
|
||
pytest tests/unit/test_inf_parser.py # single test file
|
||
pytest tests/ -k "test_name" # single test by name
|
||
```
|
||
|
||
**Run dev server:**
|
||
```bash
|
||
export DATA_DIR=/tmp/imptune_data
|
||
uvicorn imptune.main:app --reload --port 8000
|
||
```
|
||
|
||
**Docker:**
|
||
```bash
|
||
docker-compose up
|
||
docker build -t imptune .
|
||
```
|
||
|
||
**Install deps:**
|
||
```bash
|
||
pip install -r requirements.txt -r requirements-dev.txt
|
||
```
|
||
|
||
## Architecture
|
||
|
||
ImpTune make printer deploy packages (`.intunewin` for Intune, `.zip` for NinjaRMM) from Windows driver ZIPs + web UI. No external services — single FastAPI + SQLite + Docker volume.
|
||
|
||
**Request flow:**
|
||
1. Driver upload → `api/drivers.py` → `services/inf_parser.py` parse INF → `storage/driver_store.py` store by SHA256 → Peewee `Driver` record
|
||
2. Printer config → `api/printers.py` → `db/models.py` `Printer` record (links Driver FK)
|
||
3. Icon upload → `api/icons.py` → Pillow validate PNG 256×256 → SHA256 storage → `Icon` record
|
||
4. Package export → `api/packages.py` → `generators/script_generator.py` render Jinja2 PS1 templates → `generators/intunewin_builder.py` encrypt ZIP (AES-256-CBC + HMAC-SHA256)
|
||
|
||
**Key modules:**
|
||
- `imptune/config.py` — `DATA_DIR`, `DB_PATH`, `DRIVERS_DIR`, `ICONS_DIR` from env
|
||
- `imptune/db/database.py` — SQLite WAL mode + `foreign_keys=1`; all models inherit `BaseModel`
|
||
- `imptune/services/inf_parser.py` — auto-detect encoding (UTF-16/UTF-8/cp1252), resolve `%TOKEN%` from `[Strings]`, handle multi-model INFs
|
||
- `imptune/generators/intunewin_builder.py` — Python-native `.intunewin` (ZIP-in-ZIP); IV 16 bytes (not 32); match reference tool `1.8.6.0` output
|
||
- `imptune/templates/scripts/` — Jinja2 templates for `install.ps1`, `uninstall.ps1`, `detect.ps1`
|
||
|
||
**UI stack:** Pico CSS + HTMX 2 + Alpine.js 3 + Jinja2 server-side templates.
|
||
|
||
**HTMX pattern:** Forms `hx-post`, swap `#driver-list` / `#printer-list` / `#client-list` targets. Errors return inline HTML fragments (HTTP 400/409) via `_error_response()`. Success return partials from `templates/partials/`.
|
||
|
||
**PowerShell install script notes:**
|
||
- WOW64 64-bit relaunch guard (Intune run 32-bit, `pnputil` need 64-bit)
|
||
- UAC self-elevation for user context (SYSTEM context skip)
|
||
- Two-step: `pnputil /add-driver` then `Add-PrinterDriver` + `Add-PrinterPort` + `Add-Printer`
|
||
- All idempotent (`-ErrorAction SilentlyContinue`)
|
||
|
||
## Test Setup
|
||
|
||
`conftest.py` monkeypatch `config.DATA_DIR` + `config.DB_PATH` to temp dir per test. `client` fixture yield `TestClient(app)` with isolated SQLite. E2E in `tests/e2e/` use Playwright.
|
||
|
||
## Environment Variables
|
||
|
||
| Var | Default | Purpose |
|
||
|-----|---------|---------|
|
||
| `DATA_DIR` | `/data` | Storage root (DB + drivers + icons) |
|
||
| `PORT` | `8000` | Server port | |