436 lines
14 KiB
Markdown
436 lines
14 KiB
Markdown
# BUILD_AND_TEST_PLAN.md
|
|
|
|
# Conductor — Build and Test Plan
|
|
|
|
This document defines the incremental build steps for the Conductor MVP.
|
|
Each step is self-contained and verifiable before the next begins.
|
|
|
|
---
|
|
|
|
## Step 1 — Project Scaffold
|
|
|
|
**Goal:** Create the repository structure with placeholder files for frontend, backend, and docs.
|
|
|
|
### Deliverables
|
|
|
|
- `frontend/` — React + TypeScript project scaffold (no UI logic yet)
|
|
- `backend/` — Node.js + Express + TypeScript project scaffold (no logic yet)
|
|
- `docs/` — Documentation directory containing all spec files
|
|
- `docker-compose.yml` — Root compose file wiring frontend and backend services
|
|
- `README.md` — Root readme with project overview and local dev instructions
|
|
- `.gitignore` — Ignores node_modules, build artifacts, SQLite files, .env files
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
# Confirm directory structure
|
|
ls -1
|
|
|
|
# Confirm docs
|
|
ls docs/
|
|
|
|
# Install dependencies
|
|
cd frontend && npm install
|
|
cd ../backend && npm install
|
|
|
|
# Confirm TypeScript compiles without errors
|
|
cd frontend && npx tsc --noEmit
|
|
cd ../backend && npx tsc --noEmit
|
|
```
|
|
|
|
### Does not include
|
|
|
|
- Backend health check endpoint
|
|
- Frontend UI components
|
|
- SQLite setup
|
|
- REST proxy
|
|
- Authentication
|
|
- AI features
|
|
|
|
---
|
|
|
|
## Step 2 — Backend Foundation
|
|
|
|
**Goal:** Stand up a running Express server with a health check endpoint and SQLite connection.
|
|
|
|
### Deliverables
|
|
|
|
- `GET /api/health` returns `{ status: "ok" }`
|
|
- SQLite database initialised on startup
|
|
- Basic project table created in SQLite
|
|
- Structured request logging (morgan or pino)
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
cd backend && npm run dev
|
|
curl http://localhost:4000/api/health
|
|
# Expected: { "status": "ok" }
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3 — Project API (CRUD)
|
|
|
|
**Goal:** Implement create, read, update, delete for projects.
|
|
|
|
### Deliverables
|
|
|
|
- `POST /api/projects` — create a project
|
|
- `GET /api/projects` — list all projects
|
|
- `GET /api/projects/:id` — get a single project
|
|
- `PUT /api/projects/:id` — update a project
|
|
- `DELETE /api/projects/:id` — delete a project
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
# Create
|
|
curl -X POST http://localhost:4000/api/projects \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"Test Project","description":"My first project"}'
|
|
|
|
# List
|
|
curl http://localhost:4000/api/projects
|
|
|
|
# Get by ID
|
|
curl http://localhost:4000/api/projects/1
|
|
|
|
# Update
|
|
curl -X PUT http://localhost:4000/api/projects/1 \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"Renamed Project"}'
|
|
|
|
# Delete
|
|
curl -X DELETE http://localhost:4000/api/projects/1
|
|
```
|
|
|
|
---
|
|
|
|
## Step 4 — Frontend Shell
|
|
|
|
**Goal:** React app loads, renders a basic shell layout, and communicates with the backend.
|
|
|
|
### Deliverables
|
|
|
|
- App shell with header and placeholder content area
|
|
- API client calling `GET /api/projects`
|
|
- Projects listed in the UI (names only)
|
|
- Development proxy configured so `/api/*` routes to backend
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
cd frontend && npm start
|
|
# Open http://localhost:3000
|
|
# Confirm project list renders (or empty state message)
|
|
```
|
|
|
|
---
|
|
|
|
## Step 5 — Canvas and Component Palette
|
|
|
|
**Goal:** Drag-and-drop canvas renders and components can be placed.
|
|
|
|
### Deliverables
|
|
|
|
- Canvas area renders in the editor view
|
|
- Component palette with: Button, Text Input, Text Area, Dropdown, Label, Table, JSON Viewer, Status Panel
|
|
- Drag a component from the palette onto the canvas
|
|
- Dropped component renders on canvas at drop position
|
|
- Selected component shows a visual selection indicator
|
|
|
|
### Verification
|
|
|
|
- Open editor view
|
|
- Drag Button onto canvas — button appears
|
|
- Drag Text Input onto canvas — input appears
|
|
- Click a component — selection indicator shows
|
|
|
|
---
|
|
|
|
## Step 6 — Project JSON Definition
|
|
|
|
**Goal:** Canvas state is represented as a canonical JSON project definition and persisted to the backend.
|
|
|
|
### Deliverables
|
|
|
|
- Canvas state serialises to project JSON on every change
|
|
- JSON Editor panel displays live project JSON
|
|
- Edits in JSON Editor update the canvas
|
|
- Save button persists JSON to `PUT /api/projects/:id`
|
|
- Load project from API on page load
|
|
|
|
### Verification
|
|
|
|
- Add a button to canvas
|
|
- JSON Editor panel shows button in JSON
|
|
- Manually edit button label in JSON Editor — canvas label updates
|
|
- Click Save — reload page — project restores
|
|
|
|
---
|
|
|
|
## Step 7 — Component Properties Panel
|
|
|
|
**Goal:** Selecting a component opens a properties panel for editing its configuration.
|
|
|
|
### Deliverables
|
|
|
|
- Properties panel opens when a component is selected
|
|
- Editable fields: name, label, placeholder, default value, visibility, disabled state
|
|
- Changes in properties panel update canvas and project JSON
|
|
|
|
### Verification
|
|
|
|
- Place a Text Input
|
|
- Select it — properties panel opens
|
|
- Change label — canvas updates immediately
|
|
- JSON Editor shows updated label
|
|
|
|
---
|
|
|
|
## Step 8 — REST Action Configuration
|
|
|
|
**Goal:** Users can define REST API actions on a project.
|
|
|
|
### Deliverables
|
|
|
|
- Actions panel lists defined REST actions
|
|
- Create action form: name, method, URL, headers, query params, body template, auth type
|
|
- Actions saved as part of project JSON
|
|
- Auth types: Anonymous, Basic, Bearer token, API key (header or query param)
|
|
|
|
### Verification
|
|
|
|
- Create a GET action pointing to `https://httpbin.org/get`
|
|
- Save project
|
|
- Reload — action persists
|
|
|
|
---
|
|
|
|
## Step 9 — Backend REST Proxy
|
|
|
|
**Goal:** Backend proxies REST API calls on behalf of the frontend.
|
|
|
|
### Deliverables
|
|
|
|
- `POST /api/proxy/execute` accepts action ID + runtime values
|
|
- Backend resolves action definition from project JSON
|
|
- Backend executes HTTP request to target endpoint
|
|
- Response returned to frontend
|
|
- Secrets/auth headers injected server-side, never exposed to browser
|
|
- Basic execution log saved to SQLite
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
curl -X POST http://localhost:4000/api/proxy/execute \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"projectId":"1","actionId":"action-1","inputs":{}}'
|
|
# Expected: proxied response from target
|
|
```
|
|
|
|
---
|
|
|
|
## Step 10 — Bindings and Preview Mode
|
|
|
|
**Goal:** Components are bound to actions; Preview mode allows end-to-end interaction.
|
|
|
|
### Deliverables
|
|
|
|
- Button can be bound to a REST action
|
|
- Dropdown can populate options from an API response
|
|
- Response mapping: `apiResponse.fieldPath -> component.property`
|
|
- Preview mode renders project as end-user view
|
|
- API calls fire in preview mode; responses update target components
|
|
|
|
### Verification
|
|
|
|
- Bind Button to a GET action
|
|
- In Preview: click button — API fires — JSON Viewer updates with response
|
|
- Bind Dropdown to GET action returning list — dropdown populates on page load
|
|
|
|
---
|
|
|
|
## Step 10.5 — Project Persistence
|
|
|
|
**Goal:** Connect the Visual Editor to the backend Project CRUD API via a React Project Context.
|
|
|
|
### Deliverables
|
|
|
|
- `ProjectProvider` wraps the entire app; all editor views share one context
|
|
- `ProjectContext` holds: current `ProjectDocument`, backend row ID, project name, dirty state, loading/saving state, project list, and all persistence operations
|
|
- `ProjectToolbar` renders: project name (click-to-rename), **New**, **Save / Update**, **Load** buttons
|
|
- Load picker lists all backend projects and loads the selected one
|
|
- Saving serialises the full canonical project JSON and calls `PUT /api/projects/:id` (or `POST` on first save)
|
|
- Loading calls `GET /api/projects/:id` and fully replaces context state
|
|
- Toast notifications for: save succeeded, save failed, load succeeded, load failed, network error
|
|
- Visual Editor renders from `ProjectContext` — no independent state
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
# Start backend
|
|
cd backend && npm run dev
|
|
|
|
# Start frontend
|
|
cd frontend && npm start
|
|
```
|
|
|
|
- Open http://localhost:3000 → Visual Editor
|
|
- Add components → click **Save** → toast confirms save; project appears in backend DB
|
|
- Reload page → click **Load** → select project → canvas restores
|
|
- Edit project name in toolbar → click **Update** → backend reflects new name
|
|
- Click **New** → fresh canvas; previous project unaffected on backend
|
|
|
|
---
|
|
|
|
## Step 11 — Validation and Error Handling
|
|
|
|
**Goal:** Schema validation, user-facing error states, and proxy error normalisation.
|
|
|
|
### Deliverables
|
|
|
|
- Project JSON validated against schema on save
|
|
- JSON Editor shows schema errors inline
|
|
- Preview mode shows error state on failed API call
|
|
- Proxy normalises and returns structured error responses
|
|
|
|
---
|
|
|
|
## Step 12 — Docker Compose Integration Test
|
|
|
|
**Goal:** Full stack runs via `docker-compose up`.
|
|
|
|
### Deliverables
|
|
|
|
- `docker-compose up` starts frontend and backend
|
|
- Frontend accessible at `http://localhost:3000`
|
|
- Backend accessible at `http://localhost:4000`
|
|
- Full Step 10 verification passes against Docker stack
|
|
|
|
---
|
|
|
|
## Step 13 — REST Action Model
|
|
|
|
**Goal:** Add support for defining REST actions inside the canonical Conductor project JSON. This step is model-only — no execution, no backend proxy, no binding.
|
|
|
|
### Deliverables
|
|
|
|
- JSON schema (`shared/schemas/conductor-project.schema.json`) fully defines the `Action` $def with all required and optional fields, all five authentication types, and correct validation rules
|
|
- TypeScript type `RestAction` in `frontend/src/types/project.ts` mirrors the schema with JSDoc comments
|
|
- `Project` type includes `actions: RestAction[]`
|
|
- JSON Editor allows REST actions to be added or edited through the canonical project JSON (apply + validate flow)
|
|
- `POST /api/projects/validate` validates REST actions against the schema
|
|
- Example files:
|
|
- `examples/project-definitions/valid-rest-actions.json` — seven actions covering all five `authenticationType` values
|
|
- `examples/project-definitions/valid-full.json` — includes two REST actions with path parameters, query parameters, and body templates
|
|
- `docs/SCHEMA.md` documents the correct `Action` shape (with `authenticationType`), field table, and validation commands for all example files
|
|
|
|
### REST Action Model
|
|
|
|
Each REST action supports the following fields:
|
|
|
|
| Field | Required | Description |
|
|
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
|
|
| `id` | ✅ | Unique identifier within the project. |
|
|
| `name` | ✅ | Human-readable name shown in the UI. |
|
|
| `description` | — | Optional description of the action's purpose. |
|
|
| `method` | ✅ | HTTP method:`GET` · `POST` · `PUT` · `PATCH` · `DELETE` |
|
|
| `url` | ✅ | Target URL template;`{{paramName}}` marks path parameter slots. |
|
|
| `headers` | — | Static request headers. Values may use`{{variableName}}` syntax. |
|
|
| `queryParameters` | — | URL query parameters. Values may use`{{variableName}}` syntax. |
|
|
| `pathParameters` | — | Path segment substitutions for`{{paramName}}` URL placeholders. |
|
|
| `bodyTemplate` | — | Request body template with`{{variableName}}` substitution slots. |
|
|
| `authenticationType` | ✅ | One of:`anonymous` · `bearerToken` · `basicAuth` · `apiKeyHeader` · `apiKeyQueryParameter` |
|
|
|
|
### Does not include
|
|
|
|
- Backend REST proxy
|
|
- REST action execution
|
|
- Button-to-REST binding
|
|
- Input-to-request binding
|
|
- Response mapping execution
|
|
- Secret storage
|
|
- Authentication credential execution
|
|
- AI features
|
|
|
|
### Verification
|
|
|
|
```bash
|
|
# Install ajv-cli if not already installed
|
|
npm install -g ajv-cli ajv-formats
|
|
|
|
# Validate the minimal example
|
|
ajv validate \
|
|
-s shared/schemas/conductor-project.schema.json \
|
|
-d examples/project-definitions/valid-minimal.json \
|
|
--spec=draft2020
|
|
|
|
# Validate the full example (includes REST actions)
|
|
ajv validate \
|
|
-s shared/schemas/conductor-project.schema.json \
|
|
-d examples/project-definitions/valid-full.json \
|
|
--spec=draft2020
|
|
|
|
# Validate the REST actions showcase (all five auth types)
|
|
ajv validate \
|
|
-s shared/schemas/conductor-project.schema.json \
|
|
-d examples/project-definitions/valid-rest-actions.json \
|
|
--spec=draft2020
|
|
|
|
# TypeScript type check (frontend)
|
|
cd frontend && npx tsc --noEmit
|
|
|
|
# TypeScript type check (backend)
|
|
cd backend && npx tsc --noEmit
|
|
```
|
|
|
|
### Manual verification checklist
|
|
|
|
- [ ] Open the JSON Editor in the browser
|
|
- [ ] Add a REST action to `project.actions` in the textarea:
|
|
```json
|
|
{
|
|
"id": "action_test",
|
|
"name": "Test Action",
|
|
"method": "GET",
|
|
"url": "https://httpbin.org/get",
|
|
"headers": { "Accept": "application/json" },
|
|
"queryParameters": {},
|
|
"pathParameters": {},
|
|
"bodyTemplate": "",
|
|
"authenticationType": "anonymous"
|
|
}
|
|
```
|
|
- [ ] Click **Apply** — validation passes, action count in sidebar increments
|
|
- [ ] Click **Save** — project persists to backend
|
|
- [ ] Reload page → **Load** project → REST action is present in JSON
|
|
|
|
|
|
|
|
## Validation Gate
|
|
|
|
Before proceeding from any step that changes the project JSON model, JSON schema, component model, REST action model, binding model, or persistence behavior, the change must be validated.
|
|
|
|
Validation must include:
|
|
|
|
- Running schema validation against valid examples.
|
|
- Running schema validation against invalid examples.
|
|
- Testing at least one realistic project document that uses the newly added feature.
|
|
- Confirming that the frontend JSON Editor accepts the document.
|
|
- Confirming that save/load preserves the document.
|
|
- Confirming that the runtime consumes the same model that the schema validates.
|
|
|
|
A step is not complete until the schema, frontend editor, backend validator, and runtime agree on the same JSON shape.
|
|
|
|
Do not proceed to the next step if:
|
|
|
|
- Example JSON fails validation.
|
|
- The JSON Editor reports a validation error.
|
|
- The runtime expects a different structure than the schema allows.
|
|
- The backend validation endpoint returns HTTP 500.
|
|
- A new model field is accepted by the frontend but rejected by the backend.
|
|
|
|
---
|