control api schema
August 10, 2026 ยท View on GitHub
Wolfpack's public HTTP control API and /ws/pty control-message runtime behavior is owned by the server routes and WebSocket handlers. src/control-api/schema.ts owns the generated client-facing schema artifact.
Generated artifact:
docs/generated/control-api.schema.json
Regenerate after contract changes:
bun run gen:schema
The generated schema is a client integration contract. Runtime routes remain authoritative for validation and behavior. The schema must not replace the existing server trust boundaries:
- project, session, branch, command, and plan validation stays in
src/validation.tsand route-specific checks. - named-project containment and explicit-directory canonicalization stay in
src/server/validate-project-dir.ts; selector exclusivity stays insrc/server/project-selection.ts. - broker JSON/RPC wire compatibility stays covered by broker protocol/codec tests.
Compatibility rules:
- Additive changes are allowed for new optional fields, new stable operations, and new server-to-client event types.
- Breaking changes include removing or renaming stable fields/routes/messages, making optional fields required, changing auth expectations, or tightening stable enum/pattern constraints.
- Breaking changes need release notes that name the changed operation/message and migration path.
tailnet discovery compatibility
GET /api/tailnet/v1/candidates is the canonical typed Tailnet candidate operation. It returns bounded local Tailscale-status facts only; clients probe candidate origins directly. The server never probes or proxies peer endpoints.
GET /api/discover remains the legacy discoverPeers operation for existing browser clients. Its { peers, error? } envelope contains only candidates whose local online fact is true, mapped to { hostname, url, name }. It sends Deprecation: true and a Link successor-version header for /api/tailnet/v1/candidates. Both routes preserve the same non-sensitive error when local Tailscale status is malformed or unavailable.
Schema compatibility checks live in tests/unit/control-api-schema.test.ts; representative runtime response checks live in integration tests.
pi tasks relay v2 boundary
/api/task-relay/v2/* is the Pi Tasks adapter contract. It preserves the v1 task routes and ledgers; relay v2 is a separate, content-blind transport and does not interpret task payloads or own task lifecycle.
The relay inherits Wolfpack's trusted local processes and trusted Tailnet machines boundary. It does not provide per-Pi-session authorization or per-session relay credentials in v2. Normal Wolfpack HTTP/JWT and Tailnet admission remain the authority for peer requests.
Relay endpoint fields are opaque IDs. A trusted local adapter qualifies a remote relay's local endpoint through POST /api/task-relay/v2/peer/resolve; its canonical Tailnet origin is persisted only in the local relay route directory, and the response contains only the opaque peer-qualified endpoint. Peer Tailnet origins never appear in generic Pi Tasks records or endpoint fields. Remote envelopes persist only in the sender's forwarding outbox until the target relay accepts them; the recipient mailbox is created solely by the target relay. Forwarding retries are single-flight per envelope, bounded, durable, and retain exhaustion diagnostics for cleanup.