feat: Script Generator Phase 1+2 — backend, engine, API, frontend, template editor, parameter detector

Complete Script Generator feature including:

Backend:
- ScriptCategory, ScriptTemplate, ScriptGeneration models
- ScriptTemplateEngine with substitution, filters, sanitization
- CRUD + share API endpoints with permission checks
- Integration tests for permissions and sharing
- Migration 057 with AD User Management seed templates

Frontend — Script Library:
- Browse templates with category tabs and search
- Configure pane with parameter form and script generation
- Script preview with live substitution and copy/download
- scriptGeneratorStore Zustand store

Frontend — Template Editor:
- Full CRUD form with metadata, script body (Monaco Editor), parameters
- ParameterSchemaBuilder with visual builder + JSON toggle
- ScriptManagePage with routing and nav link

Frontend — Parameter Detector:
- Client-side PowerShell parameter detection engine
- Detects script-level param() blocks and variable assignments
- Type inference from PS type annotations and value patterns
- ParameterDetectorStepper one-by-one review UI with accept/skip

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #105.
This commit is contained in:
chihlasm
2026-03-14 20:18:59 -04:00
committed by GitHub
parent 83b13fcd26
commit d4dbf44781
50 changed files with 11916 additions and 11 deletions

View File

@@ -30,6 +30,7 @@
- **Rebrand guide:** [REBRAND-IMPLEMENTATION-GUIDE.md](REBRAND-IMPLEMENTATION-GUIDE.md)
**Component styling rules:**
- Primary buttons: `bg-gradient-brand` (cyan `135deg`) with `shadow-lg shadow-primary/20`, hover `opacity-0.9`, active `scale(0.97)`
- Secondary buttons: `bg-[rgba(255,255,255,0.04)]` with `border-[rgba(255,255,255,0.06)]`, hover brightens border
- Active nav items: `bg-primary/10` background + 3px left cyan gradient accent bar
@@ -47,6 +48,7 @@ When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradie
- Prefer correct architecture over minimal diff
- If two approaches exist, implement the one that scales, not the one that's faster to write
- Flag any "simpler approach" tradeoffs for product owner review before proceeding
---
## Current State
@@ -77,6 +79,7 @@ When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradie
## Tech Stack
### Backend
- **Framework:** Python FastAPI
- **Database:** PostgreSQL 16 (async via SQLAlchemy 2.0 + asyncpg)
- **Migrations:** Alembic
@@ -85,6 +88,7 @@ When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradie
- **Scheduling:** APScheduler 3.x (async, in-process with FastAPI lifespan) + croniter + pytz
### Frontend
- **Framework:** React 19 + Vite + TypeScript
- **Styling:** Tailwind CSS v3 — dark-first with purple gradient accents (see Branding section)
- **State:** Zustand (with immer + zundo for undo/redo)
@@ -131,6 +135,7 @@ patherly/
## Environment Variables
### Backend (`backend/.env`)
```bash
APP_NAME=ResolutionFlow
DEBUG=true
@@ -143,12 +148,54 @@ REQUIRE_INVITE_CODE=true
```
### Frontend (`frontend/.env.local` - optional)
```bash
VITE_API_URL=http://localhost:8000
```
---
## ConnectWise PSA Integration
ResolutionFlow integrates with ConnectWise PSA (formerly Manage) as the primary PSA integration. All ConnectWise API reference materials live in `docs/connectwise/`.
### Best Practices Documentation
Official ConnectWise developer guides live in `docs/connectwise/best-practices/`. Read these BEFORE implementing any CW API integration code:
- `PSA-API-Requests.md` — HTTP methods, response codes, condition query syntax, PATCH format, URL encoding, partial responses, custom fields. READ FIRST.
- `PSA-Callbacks.md` — Callback type/level matrix, retry behavior, URL parameter gotcha, HMAC signature verification.
- `PSA-Pagination.md` — Navigable vs Forward-Only pagination, Link headers, while-loop pattern.
- `PSA-Service-Tickets.md` — Ticket field philosophy, recommended field mappings.
- `PSA-Versioning.md` — Pin API version via Accept header. Use `application/vnd.connectwise.com+json; version=2025.16`.
- `PSA-Cloud-URL-Formatting.md` — Dynamic base URL construction via `/login/companyinfo/{companyId}`.
- `Bundled-Requests.md` — Batch multiple API calls into one request via `/system/bundles`.
- `PSA-Markdown.md` — Ticket notes support markdown. Format session documentation output accordingly.
- `PSA-Company-Synchronization.md` — Filter companies by Status/Type for mapping UI.
- `PSA-Data-Protection.md` — Security role model, request minimal permissions (MY not ALL).
### Reference Files (read in this order)
1. `docs/connectwise/CONNECTWISE-API-REFERENCE.md` — Read FIRST. Quick reference covering auth patterns, tiered endpoint map, key field mappings, and integration architecture flows.
2. `docs/connectwise/connectwise-psa-resolutionflow-reference.json` — Extracted OpenAPI 3.0.1 spec (v2025.16) with only the 670 endpoints and 342 schemas relevant to ResolutionFlow. Use for exact field types, request/response shapes, and parameter details.
3. `docs/connectwise/connectwise-psa-openapi-full.json` — Complete ConnectWise PSA OpenAPI spec (1838 endpoints, 842 schemas). Only consult if you need an endpoint outside the extracted subset.
### Integration Architecture
- **Session → Ticket Notes:** Post auto-generated session documentation to ConnectWise tickets as internal analysis notes via `POST /service/tickets/{id}/notes`
- **Ticket Context → Session Runner:** Pull ticket details, company info, and attached configurations to give FlowPilot AI real-world context
- **Callbacks:** Register webhooks via `/system/callbacks` for real-time ticket event notifications to suggest relevant Flows
### Key Implementation Rules
- Auth: API Key auth (Base64 of `companyId+publicKey:privateKey`) + `clientId` header on every request
- All ConnectWise integration code belongs in a dedicated service layer (e.g., `services/connectwise/`) — do NOT scatter CW API calls across the codebase
- Each MSP tenant provides their own CW credentials — ResolutionFlow stores these per-team, never per-user
- Design for the Autotask integration following the same service layer pattern (future PSA)
- Respect CW API: cache board/status/priority lookups, paginate with max 1000 per page, handle retries gracefully
---
## Development Commands
```powershell
@@ -190,11 +237,13 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
```
### URLs
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/api/docs
- Frontend: <http://localhost:5173>
- Backend API: <http://localhost:8000>
- API Docs: <http://localhost:8000/api/docs>
### Test Users (seeded via `scripts/seed_test_users.py`)
- All share password: `TestPass123!`
- `admin@resolutionflow.example.com` (super_admin), `teamadmin@resolutionflow.example.com` (team_admin), `engineer@resolutionflow.example.com` (engineer), `pro@resolutionflow.example.com` (solo pro)
@@ -205,6 +254,7 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
### Top Gotchas (most commonly hit)
**1. DateTime Handling — Always timezone-aware:**
```python
# CORRECT
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
@@ -212,6 +262,7 @@ created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezo
```
**2. SQLAlchemy Async — No lazy loading on new objects:**
```python
# WRONG — MissingGreenlet error
new_tree = Tree(...); db.add(new_tree); await db.flush()
@@ -222,6 +273,7 @@ await db.execute(tree_tag_assignments.insert().values(tree_id=new_tree.id, tag_i
```
**3. React State — Don't store object snapshots:**
```tsx
// WRONG — snapshot won't update
const [editingNode, setEditingNode] = useState(node)
@@ -231,17 +283,20 @@ const editingNode = editingNodeId ? findNode(editingNodeId, tree?.tree_structure
```
**4. Modal Draft State — Exclude store-managed fields:**
```tsx
const { children, ...draftWithoutChildren } = draft
updateNode(node.id, draftWithoutChildren) // Don't overwrite children
```
**5. Multiple FKs to same table — Specify `foreign_keys` on BOTH sides:**
```python
author = relationship("User", foreign_keys=[author_id], back_populates="trees")
```
**6. PostgreSQL NULL in UUID columns:**
```sql
SELECT 'tag', 'slug', NULL::uuid as team_id -- Must cast NULL to uuid
```
@@ -255,6 +310,7 @@ SELECT 'tag', 'slug', NULL::uuid as team_id -- Must cast NULL to uuid
**9. Public endpoints with optional auth:** Use manual `_get_optional_user(request, db)` helper, NOT `Optional[User]` param (FastAPI treats it as Pydantic field).
**10. React Router — Clear dirty state before navigation:**
```tsx
markSaved() // Clear isDirty BEFORE navigate()
navigate(`/trees/${newTree.id}/edit`)
@@ -352,6 +408,8 @@ navigate(`/trees/${newTree.id}/edit`)
**57. Node field priority for display/context:** Nodes use different label fields by type — procedural steps use `title`+`description`, decision nodes use `question`, action/solution nodes use `title`. When reading a node's label generically, check: `title``question``description``content``label`. See `copilot_service.py` `_build_flow_context()`.
**58. `scriptGeneratorStore.generate()` has an optional `sessionId` param:** `generate(sessionId?: string)` — do NOT pass it as a bare `onClick={generate}` handler (TypeScript error: MouseEvent not assignable to string). Always wrap: `onClick={() => generate()}`.
---
## RBAC & Permissions
@@ -408,19 +466,24 @@ navigate(`/trees/${newTree.id}/edit`)
## Coding Standards
### Python
- Type hints everywhere, async/await for DB, Pydantic for validation, `DateTime(timezone=True)` always
### TypeScript
- Interfaces for all data, `const` over `let`, functional components + hooks, reusable logic in custom hooks
### Git
- Format: `type: description` (feat, fix, refactor, docs, test, chore)
- Always include `Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>`
- Always create feature branch BEFORE committing: `git checkout -b feat/feature-name`
- Large features: commit per phase with `npm run build` validation
### After Completing Work
When a feature, fix, or significant piece of work is finished and merged/committed:
1. **Update `CURRENT-STATE.md`** — move completed items, update "In Progress" and "What's Next" sections
2. **Update `03-DEVELOPMENT-ROADMAP.md`** — check off completed work, update phase status
3. **Close related GitHub Issues** — use `gh issue close #N` for any issues resolved by the work
@@ -451,7 +514,7 @@ When a feature, fix, or significant piece of work is finished and merged/committ
| What | Where |
|------|-------|
| API Docs | http://localhost:8000/api/docs |
| API Docs | <http://localhost:8000/api/docs> |
| Detailed Status | [CURRENT-STATE.md](CURRENT-STATE.md) |
| Development Roadmap | [03-DEVELOPMENT-ROADMAP.md](03-DEVELOPMENT-ROADMAP.md) |
| GitHub Issues | `gh issue list --state open` |