Task: Give the BFF the curve read routes

Table of Contents

This page documents a task in the Show a curve evolving in ores.web story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

The BFF exposes the identity, snapshot, slice and evolution reads, so a screen can reach what the server already answers.

2. Status

Field Value
State DONE
Parent story Show a curve evolving in ores.web
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-10

3. Acceptance

  • The BFF has a session-guarded route for each of the identity, snapshot, slice and evolution reads.
  • Each route sends the request to the server's subject, which checks its own permission, and returns a refusal as a reason.
  • Each route has a test, including a refused request.

4. Plan

One module, curves.ts, registers four POST routes under /api/curves/: series, snapshot, slice and evolution. Each checks the structure of the request with a strict schema, forwards it to the server's subject, and returns the reply without its success and message. The server checks the permission and the shape. A refused read becomes a 422 with the server's words. The module follows the shape of synthetic.ts. A test file drives each route through a canned client.

5. Measurements

Every number this task claims about a tree, with the command that produced it and the commit it was measured at. A number without both is not a measurement, because a clean-up record describes a tree and trunk moves under a branch: a consumer count, a gate's component count and a suite's size all change with no code changing, and the reader of a bare number cannot tell which tree it came from. Where the raw output matters, put it in an evidence/ file beside the task and name that file in the Command column.

What Value Command Commit
Curve route tests 14 pass npx vitest run src/curves.test.ts in packages/bff 785e1bda50 plus the uncommitted change
Whole BFF suite 52 files, 495 tests, pass npx vitest run in packages/bff 785e1bda50 plus the uncommitted change
BFF type check clean npx tsc --build in packages/bff 785e1bda50 plus the uncommitted change

6. Notes

7. 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
     

8. PRs

PR Title
#3092 [web] Give the BFF the curve read routes

9. Review

# Comment summary File Decision Notes
1 The NO_INSTANT sentinel could become a real query curves.ts Accept The constant now says the server reads the range only when no instants are stated. Two evolution tests pin the body.
2 No check that the range starts before it ends curves.ts Accept The slice and evolution schemas refuse a reversed range. A test shows no call reaches the server.
3 Instants and a range together drop the range silently curves.ts Accept The route now sends no range with a stated set, and a test shows it.
4 A permission denial might arrive as a refused read curves.ts Accept Checked: the client throws a forbidden error, which the BFF maps to 403. A test pins it.
5 Unused underscore names may trip a lint rule curves.ts Accept The reply is now filtered by key. The project has no eslint; prettier and tsc pass.
6 Only a canned client was used curves.test.ts Decline An integration run needs a running server and NATS. The limitation is in the PR body.

10. Result

The BFF now routes the four curve reads. A signed-in session can POST to /api/curves/series, /snapshot, /slice and /evolution with a typed identity and read what the server answers. The module is curves.ts, registered in server.ts.

Each route checks the structure of the request and nothing more. The schemas are strict, so a field the route does not know is refused, and an instant must be a wire timestamp. An evolution states its instants or both ends of its range, and a stated set is capped at

  1. The server keeps the permission and the shape rules. A refused read comes back as a

422 with the server's words, so the screen can show the reason.

Eleven tests drive the routes through a canned client: each read, the provenance flag, both evolution forms, three refused requests that never reach the server, a server refusal and a missing session. The whole BFF suite passes, and so do the web, route-auth, open-reads, reachability and handler-permissions checks.

Left for the screen task: a page that calls these routes. The routes do not draw anything.

Emacs 29.3 (Org mode 9.6.15)