--- phase: 04-script-generation plan: "02" subsystem: api tags: [powershell, jinja2, fastapi, intune, tdd] requires: - phase: 04-01 provides: [render_install, install.ps1.j2, script_generator module with Jinja2 env] provides: - render_uninstall function (Remove-Printer/Driver/Port in safe order) - render_detect function (Intune detection contract) - uninstall.ps1.j2 template - detect.ps1.j2 template - GET /printers/{id}/scripts/install endpoint - GET /printers/{id}/scripts/uninstall endpoint - GET /printers/{id}/scripts/detect endpoint - scripts.py APIRouter registered in main.py affects: [phase-05-packaging] tech-stack: added: [] patterns: - Shared _get_printer_and_driver() helper extracts ORM validation to avoid duplication across 3 endpoints - All script endpoints return PlainTextResponse with Content-Disposition attachment header - Integration tests use ORM directly (Driver.create/Printer.create) — no HTTP fixture for setup key-files: created: - imptune/templates/scripts/uninstall.ps1.j2 - imptune/templates/scripts/detect.ps1.j2 - imptune/api/scripts.py modified: - imptune/generators/script_generator.py - imptune/main.py - tests/test_script_generator.py key-decisions: - "_get_printer_and_driver() private helper centralises 404/422 validation for all 3 script endpoints" - "PlainTextResponse with Content-Disposition attachment; filename='{type}.ps1' on all script endpoints" - "Integration tests create ORM records directly (Driver.create/Printer.create) — same pattern as printer CRUD tests" patterns-established: - "Script endpoint pattern: validate printer -> validate driver -> validate inf -> parse driver_desc -> render -> return attachment" requirements-completed: [SCRPT-02, SCRPT-03] duration: ~2min completed: 2026-04-10 --- # Phase 4 Plan 02: Script Generator (Uninstall + Detect + API) Summary **Jinja2 uninstall/detect templates, render_uninstall/render_detect functions, and three downloadable PS1 script endpoints wired to the scripts router** ## Performance - **Duration:** ~2 min - **Started:** 2026-04-10T11:33:58Z - **Completed:** 2026-04-10T11:36:13Z - **Tasks:** 2 - **Files modified:** 6 ## Accomplishments - render_uninstall() produces Remove-Printer > Remove-PrinterDriver > Remove-PrinterPort with -ErrorAction SilentlyContinue (safe ordering) - render_detect() follows Intune detection contract: Get-Printer check, Write-Output + exit 0 when found, exit 1 when absent - Three GET endpoints /printers/{id}/scripts/{install,uninstall,detect} return PS1 scripts as file downloads - Full error handling: 404 for missing printer, 422 for missing driver/INF/driver_desc - Full test suite green: 75 tests (7 new tests added) ## Task Commits Each task was committed atomically: 1. **Task 1 RED: Failing tests for render_uninstall/detect** - `0f213df` (test) 2. **Task 1 GREEN: render_uninstall + render_detect + templates** - `6bff8f3` (feat) 3. **Task 2: Script API endpoints + router registration** - `b7b0d1b` (feat) _Note: TDD task split into RED + GREEN commits per TDD protocol_ ## Files Created/Modified - `imptune/templates/scripts/uninstall.ps1.j2` - PowerShell uninstall template (Remove-Printer/Driver/Port in order) - `imptune/templates/scripts/detect.ps1.j2` - PowerShell Intune detection template (Get-Printer + exit 0/1) - `imptune/generators/script_generator.py` - Added render_uninstall() and render_detect() functions - `imptune/api/scripts.py` - APIRouter with 3 script download endpoints, shared validation helper - `imptune/main.py` - Registered scripts.router - `tests/test_script_generator.py` - Added 2 unit tests + 5 integration tests ## Decisions Made - `_get_printer_and_driver()` private helper centralises 404/422 validation logic for all three endpoints — avoids repeating identical ORM+validation code 3 times - `PlainTextResponse` with `Content-Disposition: attachment; filename="{type}.ps1"` on all endpoints so browsers download the file rather than rendering it - Integration tests create ORM records directly via `Driver.create()`/`Printer.create()` — same established pattern as printer CRUD tests, no HTTP API calls for setup ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None - all tests passed on first run after implementation. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - All three script types downloadable via API — ready for Phase 5 packaging - render_install, render_uninstall, render_detect all available in script_generator module - scripts.py router registered and functional --- *Phase: 04-script-generation* *Completed: 2026-04-10*