---
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*
