MicroFish/.kiro/steering/api-standards.md

144 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API Standards
These are the conventions for the **Flask backend** consumed by the
Vue frontend. Generic REST guidance is secondary to the patterns
already established in `backend/app/api/`.
## Philosophy
- The frontend is the only consumer; we optimize for *that* contract,
not for a hypothetical public API.
- Long-running work returns immediately with a `task_id`; clients
poll. There are no streaming responses or websockets.
- The backend is stateless across restarts of `Project`/`Task` data
(in-memory), with deterministic recovery on boot.
## URL Pattern
Routes live under `/api/<domain>/<action>` where domain matches the
Flask blueprint:
- `/api/graph/...``graph_bp` (`api/graph.py`)
- `/api/simulation/...``simulation_bp` (`api/simulation.py`)
- `/api/report/...``report_bp` (`api/report.py`)
Within a blueprint, resource sub-paths are accepted but **action-style
endpoints are equally common** (`/ontology/generate`,
`/project/<id>/reset`). Don't force REST verbs onto operations that
aren't naturally CRUD — match the surrounding file.
The Vite dev server proxies `/api/*` from `:3000` to `:5001`. Don't
hard-code the backend host in frontend code.
## Response Envelope
Every response uses this shape — do **not** invent a new one:
```json
// Success
{ "success": true, "data": { ... } }
// Failure
{ "success": false, "error": "Human-readable message" }
```
- `success` is always present and boolean.
- Successful responses put the payload under `data`. List endpoints may
also include sibling fields (`count`, etc.) — see
`/project/list` for the precedent.
- Error responses use `error: <string>`. There is no error-code enum.
Messages may be in English or Chinese to match the rest of the
module — keep both styles working.
- HTTP status follows the outcome: `200` on success, `400` for client
validation, `404` for missing entities, `500` for unhandled
exceptions.
## Long-Running Operations: The Task Polling Contract
This is the defining backend pattern. Anything that takes more than a
few seconds (ontology generation, graph build, profile generation,
simulation, report generation) **must** use it.
### Submit endpoint
- Validates input synchronously.
- Creates a `Task` via `TaskManager().create_task(task_type, metadata)`.
- Spawns a background `threading.Thread` that runs the work and
updates the task as it progresses.
- Returns immediately:
```json
{ "success": true, "data": { "task_id": "...", "project_id": "..." } }
```
### Background worker
- Calls `TaskManager().update_task(task_id, progress=…, message=…, progress_detail=…)`
at meaningful checkpoints (not every loop iteration).
- On success: `complete_task(task_id, result_dict)`.
- On failure: `fail_task(task_id, error_string)` — never let the
exception escape the thread; tasks must always reach a terminal
state.
### Status endpoint
- A polling endpoint (typically `/api/<domain>/task/<task_id>` or
similar) returns the current `Task.to_dict()`.
- The frontend service layer (`frontend/src/api/*.js`) handles
exponential backoff + a 5-min timeout; new endpoints don't need
custom retry logic on the client.
### Task lifecycle
`PENDING → PROCESSING → COMPLETED | FAILED`. Other status fields
(`progress` 0100, `progress_detail` dict) are advisory — the frontend
decides how to render them. Don't add new statuses without a
frontend-side change.
## Where Logic Belongs
- **`api/` (handlers)**: validate input, look up `Project`/`Task`,
dispatch to a service, format the envelope. No graph access, no LLM
calls, no `subprocess`.
- **`services/`**: all business logic, including spawning the
background thread for long-running work.
- **`models/`**: state shape only.
If a handler is doing more than a few lines of orchestration, the work
belongs in a service.
## Authentication
There is no user-level authentication today. Endpoints assume a
trusted operator on the same network (dev, Docker, internal
deployment). **Do not add ad-hoc auth checks scattered through
handlers** — if/when auth is needed, it goes through Flask middleware
and is documented in a new steering file. Until then, treat all
endpoints as authenticated by deployment.
## Versioning
No version prefix in URLs. The frontend ships with the backend in a
single repo, so backwards compatibility for the API is not a concern.
If that ever changes (public API, multiple frontend versions), version
the affected blueprint, not the whole API.
## Pagination
- `/project/list` accepts `?limit=<n>` (default 50). Match this
pattern for new list endpoints.
- Graph queries use `utils/zep_paging.py` for cursor-style paging
(legacy name; still the canonical helper).
## What Not to Do
- Don't return raw exceptions or stack traces in `error`.
- Don't bypass `TaskManager` for long-running work (e.g. with a custom
status field on `Project`).
- Don't add new response envelope shapes — extend `data`.
- Don't introduce streaming (SSE, websockets) without a steering-level
discussion; the polling model is intentional.
---
_Focus on patterns and decisions, not endpoint catalogs._