Solve a deterministic constraint-satisfaction / assignment problem
optimal/feasible/infeasible all return HTTP 200 — infeasible
carries the conflicting-constraint subset in data.conflicts, never a
4xx/5xx. A spec the solver rejects against its closed vocabulary
returns 422; the solver sidecar being unreachable returns 503.
POST /v1/solve
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Validates POST /v1/solve (HASP-575, ADR-KBGV3J).
The request body IS the declarative solve spec (version, resources, slots, constraints, preferences, options) — validation here is deliberately shallow, structure only. The solver service owns the closed-vocabulary validation and returns the full error list on rejection; this FormRequest must not reimplement any of it.
resources_from/slots_from are rejected: unlike the solve workflow
step and the solve.run agent tool, this endpoint is deliberately
literal-only. An integrator calling /v1/solve already holds its own
data and is sending it anyway, so requiring them to additionally name a
HASP project would be the odd requirement here.
resources/slots are required non-empty arrays — the same shallow
presence check {@see \App\Services\Workflow\Steps\SolveStep::fromConfig()}
already applies to the workflow step's spec, not a new validation layer.
Catching an obviously-empty spec here means a 422 VALIDATION_FAILED
instead of an unnecessary round trip to the solver sidecar for a request
that could never be solvable.
Response
A solve result — optimal/feasible satisfy every requirement; infeasible is equally a successful result, carrying the conflicting-constraint subset, never an error.