# Draw

Personal freehand sketching on the WPDS app shell. Open a canvas, sketch with
pen, colors, and eraser, save named drawings, and continue them later with
their full stroke history. Single person, token-gated, file-backed.

Live at draw.danielk.am. Part of the WPDS app family (standalone host,
product-owned canvas, like Scene Designer and Storyboard Designer).

## Journeys

1. **Start a drawing** (primary): Overview → Start a drawing → sketch → Save.
2. **Continue your latest**: reopens the most recent drawing with its strokes.
3. **Browse the gallery**: every saved drawing as thumbnail cards.

## Stack

- `web/`: dependency-free frontend (hash router, canvas editor, WPDS shell with
  resize rails, collapse, appearance, local profile). No build step.
- `app/server.py`: stdlib Python HTTP server. Serves the frontend and the
  `wpds-draw/v1` REST API. See `docs/API.md`.
- `app/store.py`: file-backed store. One JSON document per drawing under the
  data dir, atomic writes, optimistic revisions, recoverable trash deletes.
- `mcp/server.py`: stdio MCP adapter over the same store. No second write path.

## Run locally

```sh
DRAW_TOKEN=dev python3 app/server.py
# http://localhost:7870 — unlock with token "dev"
```

## Configuration

| Variable | Default | Meaning |
| --- | --- | --- |
| `PORT` | `7870` | HTTP port. |
| `DRAW_DATA_DIR` | `./data` | Drawing and profile storage. Must survive updates. |
| `DRAW_WEB_DIST` | `./web` | Frontend root. |
| `DRAW_TOKEN` | none | Access token. Falls back to `/run/secrets/draw-token`. Without a token the API locks (503). |

## Safety and limits

- All drawing and profile routes need the bearer token; `/health`,
  `/api/v1/app`, and `/api/v1/status` are public and content-free.
- Deletes set a trash flag; restore over the API. Nothing is destroyed.
- Saves are revision-checked (`If-Match`); a stale save returns 409 instead of
  overwriting.
- Ask Draw fails closed: no AI transport is configured on this host, no
  provider is called, and the panel says so.

## Deploy

`compose.yaml` builds the container and routes `draw.danielk.am` through the
host's coolify/traefik network. Data lives in `./data`, the token in
`./secrets/draw-token` (not in git). Health check: `GET /health`.

## Verify

`tests/api-check.sh` runs the REST contract against a temporary server:
health, discovery, denied and allowed auth, CRUD, conflict, trash and restore.
`tests/mcp-check.sh` drives the MCP server over real stdio: initialize,
tools/list, and a read and write round-trip.
