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:
71
CLAUDE.md
71
CLAUDE.md
@@ -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` |
|
||||
|
||||
Reference in New Issue
Block a user