docs(04-02): complete uninstall+detect templates and script API endpoints plan
- 04-02-SUMMARY.md: TDD execution, 3 commits, 6 files, 75 tests green - STATE.md: advanced to 04-02 complete, added 3 new decisions - ROADMAP.md: phase 4 marked complete (2/2 plans done) - REQUIREMENTS.md: SCRPT-02 and SCRPT-03 marked complete
This commit is contained in:
@@ -31,8 +31,8 @@ Requirements for initial release. Each maps to roadmap phases.
|
||||
### Script Generation
|
||||
|
||||
- [x] **SCRPT-01**: System generates PowerShell install script (pnputil staging + Add-PrinterPort + Add-PrinterDriver + Add-Printer + Set-PrintConfiguration)
|
||||
- [ ] **SCRPT-02**: System generates PowerShell uninstall script (Remove-Printer + Remove-PrinterDriver + Remove-PrinterPort)
|
||||
- [ ] **SCRPT-03**: System generates Intune detection script (registry check for printer name)
|
||||
- [x] **SCRPT-02**: System generates PowerShell uninstall script (Remove-Printer + Remove-PrinterDriver + Remove-PrinterPort)
|
||||
- [x] **SCRPT-03**: System generates Intune detection script (registry check for printer name)
|
||||
- [x] **SCRPT-04**: Generated install script detects SYSTEM vs. user context and self-elevates via UAC when run by user
|
||||
- [x] **SCRPT-05**: Generated install script includes 64-bit WOW64 relaunch guard for Intune's 32-bit execution context
|
||||
|
||||
@@ -101,8 +101,8 @@ Which phases cover which requirements. Updated during roadmap creation.
|
||||
| PRNT-09 | Phase 3 | Complete |
|
||||
| PRNT-10 | Phase 3 | Complete |
|
||||
| SCRPT-01 | Phase 4 | Complete |
|
||||
| SCRPT-02 | Phase 4 | Pending |
|
||||
| SCRPT-03 | Phase 4 | Pending |
|
||||
| SCRPT-02 | Phase 4 | Complete |
|
||||
| SCRPT-03 | Phase 4 | Complete |
|
||||
| SCRPT-04 | Phase 4 | Complete |
|
||||
| SCRPT-05 | Phase 4 | Complete |
|
||||
| PKG-01 | Phase 5 | Pending |
|
||||
|
||||
@@ -15,7 +15,7 @@ Decimal phases appear between their surrounding integers in numeric order.
|
||||
- [x] **Phase 1: Foundation** - Docker container scaffold, SQLite schema, and .intunewin format spike (completed 2026-04-10)
|
||||
- [ ] **Phase 2: Driver Management** - Driver ZIP upload, INF parsing, DriverDesc dropdown, volume persistence
|
||||
- [x] **Phase 3: Printer Configuration** - Full printer config form, client/tenant labels, SQLite persistence (completed 2026-04-10)
|
||||
- [ ] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards
|
||||
- [x] **Phase 4: Script Generation** - PowerShell install/uninstall/detection scripts with all correctness guards (completed 2026-04-10)
|
||||
- [ ] **Phase 5: Package Export** - .intunewin and NinjaRMM ZIP export, icon upload, command preview
|
||||
|
||||
## Phase Details
|
||||
@@ -108,5 +108,5 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5
|
||||
| 1. Foundation | 3/3 | Complete | 2026-04-10 |
|
||||
| 2. Driver Management | 1/2 | In Progress| |
|
||||
| 3. Printer Configuration | 2/2 | Complete | 2026-04-10 |
|
||||
| 4. Script Generation | 1/2 | In Progress| |
|
||||
| 4. Script Generation | 2/2 | Complete | 2026-04-10 |
|
||||
| 5. Package Export | 0/3 | Not started | - |
|
||||
|
||||
+30
-11
@@ -3,15 +3,30 @@ gsd_state_version: 1.0
|
||||
milestone: v1.0
|
||||
milestone_name: milestone
|
||||
status: executing
|
||||
stopped_at: Completed 04-01-PLAN.md
|
||||
last_updated: "2026-04-10T11:32:55.889Z"
|
||||
last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite"
|
||||
stopped_at: Completed 04-02-PLAN.md
|
||||
last_updated: "2026-04-10T11:37:48.308Z"
|
||||
last_activity: "2026-04-10 — Plan 04-02 complete: uninstall/detect templates, render_uninstall/render_detect, 3 script API endpoints, 75 tests green"
|
||||
progress:
|
||||
total_phases: 5
|
||||
completed_phases: 4
|
||||
total_plans: 9
|
||||
completed_plans: 9
|
||||
---
|
||||
|
||||
---
|
||||
gsd_state_version: 1.0
|
||||
milestone: v1.0
|
||||
milestone_name: milestone
|
||||
status: executing
|
||||
stopped_at: Completed 04-02-PLAN.md
|
||||
last_updated: "2026-04-10T11:36:13Z"
|
||||
last_activity: "2026-04-10 — Plan 04-02 complete: uninstall/detect templates, render_uninstall/render_detect, 3 script API endpoints, 75 tests green"
|
||||
progress:
|
||||
total_phases: 5
|
||||
completed_phases: 3
|
||||
total_plans: 9
|
||||
completed_plans: 8
|
||||
percent: 7
|
||||
completed_plans: 9
|
||||
percent: 89
|
||||
---
|
||||
|
||||
# Project State
|
||||
@@ -25,12 +40,12 @@ See: .planning/PROJECT.md (updated 2026-04-10)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 1 of 5 (Foundation)
|
||||
Plan: 2 of 3 in current phase (01-01 complete)
|
||||
Phase: 4 of 5 (Script Generation)
|
||||
Plan: 2 of 2 in current phase (04-02 complete)
|
||||
Status: Executing
|
||||
Last activity: 2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite
|
||||
Last activity: 2026-04-10 — Plan 04-02 complete: uninstall/detect templates, render_uninstall/render_detect, 3 script API endpoints, 75 tests green
|
||||
|
||||
Progress: [░░░░░░░░░░] 7%
|
||||
Progress: [█████████░] 89%
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
@@ -56,6 +71,7 @@ Progress: [░░░░░░░░░░] 7%
|
||||
| Phase 03-printer-configuration P01 | 7 | 2 tasks | 12 files |
|
||||
| Phase 03-printer-configuration P02 | 2 | 2 tasks | 4 files |
|
||||
| Phase 04-script-generation P01 | 2 | 1 tasks | 3 files |
|
||||
| Phase 04-script-generation P02 | 2 | 2 tasks | 6 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -85,6 +101,9 @@ Recent decisions affecting current work:
|
||||
- [Phase 03-02]: Detail page is a full-page template (not partial) — simpler than partial injection into printers.html
|
||||
- [Phase 03-02]: Route lives in pages.py (not printers.py) because it returns a full HTML page, not an HTMX fragment
|
||||
- [Phase 04-script-generation]: render_install() takes plain string args (not ORM object) for DB-free unit testability; _duplex_map translates LongEdge->TwoSidedLongEdge before template rendering
|
||||
- [Phase 04-02]: _get_printer_and_driver() private helper centralises 404/422 validation for all 3 script endpoints
|
||||
- [Phase 04-02]: PlainTextResponse with Content-Disposition attachment header on all script endpoints
|
||||
- [Phase 04-02]: Integration tests create ORM records directly (Driver.create/Printer.create)
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -97,6 +116,6 @@ None yet.
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-04-10T11:32:55.884Z
|
||||
Stopped at: Completed 04-01-PLAN.md
|
||||
Last session: 2026-04-10T11:37:48.305Z
|
||||
Stopped at: Completed 04-02-PLAN.md
|
||||
Resume file: None
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
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*
|
||||
Reference in New Issue
Block a user