ADR-0005: POST Body Over Path Variables for Resource Operations
Status: ACCEPTED Date: 2026-03-23 Supersedes: N/A Superseded by: N/A
Context
The original API design used REST-style path variables (/workspaces/{id}/roles/{roleId}) to identify resources. This created several problems: ambiguous semantics (is {id} the user's workspace or the target workspace?), deeply nested URLs, and mixing of permission context with resource identifiers in the same path.
Source: docs/archive/specs/2026-03-23-workspace-context-header-design.md, DevPortal design spec (@PathVariable handling), governance rule in .proteus/ memory
Decision
All business parameters go in the request body (JSON), not in path variables. Path segments carry endpoint identity only (e.g., /workspaces/admin/query). GET endpoints that need resource identifiers are converted to POST to carry a body. Existing @PathVariable usage is flagged by the API toolkit parser with x-deprecated-path-variable: true in OpenAPI output. No new path variables are permitted.
Consequences
- Unambiguous API contracts: the body schema is the complete interface definition.
- Eliminates deeply nested URL patterns and the maintenance burden of URL routing rules.
- All admin/cross-entity endpoints become POST, which may feel non-RESTful but is consistent and unambiguous.
- Frontend and SDK consumers must adapt from URL construction to body construction for affected endpoints.
- Parser and linter enforce the rule; violations are caught at CI time.
Alternatives Considered
- Conventional REST paths: Rejected because nested resource hierarchies (
/workspaces/{id}/institutions/{instId}/portals/{portalId}) became unwieldy and semantically ambiguous. - Query parameters for resource IDs: Rejected because query parameters are logged by default in many infrastructure layers, creating potential data exposure for sensitive identifiers.