CRUMB a card from devarno-cloud

REST API Surface

nestr intermediate 5 min read

ELI5

The Engine is a hotel front desk: /health and /metrics are the lobby (anyone can walk in), /api/* are the rooms (you need a key card unless reception turned key-checking off), and the desk clerk writes everyone’s arrival in a log.

Technical Deep Dive

All routes live in engine/internal/server/rest.go. The router is a stdlib http.ServeMux wrapped in a fixed middleware chain:

loggingMiddleware → corsMiddleware → withRateLimit → (optional) JWT → handler

Route Map

flowchart LR
R[ServeMux]
R --> H[/health/]
R --> RD[/ready/]
R --> M[/metrics/]
R --> WS[/ws/]
R --> API
subgraph API["/api/*"]
W[/workspace/]
S[/services/]
OPR[/operations/run/]
OPS[/operations/sync/]
OPA[/operations/assemble/]
PL[/pellets/]
PLI["/pellets/{id}/"]
PLC[/pellets/compress/]
PLE[/pellets/extract/]
PLS[/pellets/stats/]
PLP[/pellets/prune/]
end
H -.no auth.-> R
RD -.no auth.-> R
M -.no auth.-> R
API -.JWT if JWKS_URL set.-> R

Endpoint Reference

MethodPathBodyReturns
GET/health200 ok
GET/ready200
GET/metricsPrometheus text
GET/wsupgradeWebSocket frames
GET/api/workspaceWorkspace{id,name,root,status,services[]}
GET/api/servicesService[]
POST/api/operations/run{operation, services[]}OperationResult{success,message,logs[]}
POST/api/operations/sync{dryRun?}OperationResult
POST/api/operations/assemble{}OperationResult
GET/api/pelletsPellet[]
GET/api/pellets/{id}Pellet
POST/api/pellets/compress{source}{success, pellet?, message}
POST/api/pellets/extract{pelletId, targetPath?}{success, message, extractedTo?}
GET/api/pellets/statsCacheStats (see nestr-004)
POST/api/pellets/prune{days?, all?}{success, message, removed:int}

Response Envelope

Success responses are direct JSON of the resource (Pellet, Workspace, …) or an ad-hoc shape with a success: true flag for write endpoints. Errors are emitted via respondError(w, status, msg) as plain HTTP status + message — there is no uniform {error: {...}} wrapper. Every request also carries an X-Request-ID header injected by loggingMiddleware.

Key Terms

  • respondJSON / respondError → the two helpers in rest.go that all handlers funnel through.
  • withRateLimit → per-IP token bucket middleware (see nestr-006).
  • OperationResult → uniform return for run/sync/assemble: {success, message, logs[]}.

Q&A

Q: How does the server distinguish a 404 from a 405 on a known path? A: ServeMux returns 404 for unknown paths; handlers themselves check r.Method and return 405 explicitly when the path matches but the verb is wrong.

Q: Can I call /api/pellets/compress without a JWT? A: Only if JWKS_URL is unset at server startup. If set, the auth middleware rejects requests without a valid Bearer token before they reach the handler.

Q: What’s the OpenAPI source of truth? A: engine/docs/openapi.yaml; it documents the same set of routes and is the recommended client-generation input.

Examples

Compressing from cURL with auth disabled: curl -X POST :8080/api/pellets/compress -d '{"source":"./node_modules"}' returns {"success":true,"pellet":{"id":"171…","ratio":0.15,…},"message":"compressed"} and increments nestr_pellet_compress_total.

neighbors on the map