Task: Build the HTTP route facet and land ores.assets through it
Table of Contents
This page documents a task in the Generate HTTP routes from the models story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
ores.http serves every component through routes generated from that component's models, with one uniform security model, and ores.assets is the first component landed through it.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Generate HTTP routes from the models |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-09-27 |
3. Acceptance
- A codegen facet generates a route unit per entity, with a header, an implementation and a test, from the entity's model.
- The generated route speaks the canonical NATS protocol and carries the caller's session, so the service's own permission check governs access.
- Every route that needs a session is behind one by construction, declared in the model rather than by hand at the call site.
- The hand-written route file for ores.assets is deleted, and its endpoints still answer.
4. Plan
Land the work in five verifiable units, each green on its own: the facet with ores.assets, the wiring and the security declaration, refdata, the operation archetype with iam, and per-message exposure with the storage client. Delete a component's hand-written route file in the same unit that generates its replacement, so the two never coexist.
A generated route speaks the canonical NATS protocol rather than calling the component's service in process, which is what lets one generator serve both the shell and HTTP surfaces from the same models.
A route states its authentication position from the model. The route builder refuses silence, so a forgotten declaration cannot ship as a public endpoint.
5. Notes
6. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| #2229 | [agile] Close the codegen-http-routes story with the merged facts |
| #2210 | [http] Generate the gateway's routes from the component models |
8. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
9. Result
The facet exists, and three components are landed through it.
ores.cpp.http-route projects an entity model or an operation model onto
a route unit with a header, an implementation and a test. A generated
route builds the canonical request, sends it over NATS and maps the reply
to an HTTP response, so the gateway depends on the target's wire protocol
and not on its service library. The server stopped linking three
component libraries.
Ninety-two routes generate in total: ores.http.assets 29 (image, tag
and image_tag), ores.http.refdata 10 (currency) and ores.http.iam 53
(34 entity routes across account, role, permission, session and
login_info, and 19 operation routes). The gateway serves 99 endpoints:
those 92, the 5 storage and 1 variability routes that stay hand-written,
and the server's own /api/v1/info. Each landed component lost its
hand-written route file in the unit that replaced it. assets_routes,
risk_routes and iam_routes are deleted, not kept in parallel.
Every route states its authentication position from the model, and a
route that states neither position cannot be built or registered. The
gate check_route_auth_declarations.py fails the build when a registered
route is silent. The route forwards the caller's bearer token by
delegation, so each service's own permission check governs the real
caller.
Verified on the merged head af159c1084:
pytest projects/ores.codegen/testsis 787 passed.ctest -R 'http|storage'is 8 of 8.check_component_drift.py --all --dry-runreports no drift.check_route_auth_declarations.pyreports that every registered route states its position.- Model drift, protocol twin coverage, handler permissions, populate
references, the shell recipe inventory,
compass lintandvalidate_docs.sh(40 of 40 components) all pass.
Three failures remain and none belongs to this task: the whole tree does
not build, regenerate_cmake_component_files.py --all --check reports
stale lists in ores.workspace, and ores.iam.core.tests fails against
a restored database whose stored function predates the SQL fix. The
build break is the serious one, and * Out of scope on the story
records it. The libraries this task builds do build.