Story: Implement the operations journeys in ores.web
Table of Contents
This page documents a story in Sprint 27. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
The five Operations journeys – the running services, the compute grid, the message bus, the telemetry logs, and the versions and database – run as screens in ores.web against the real server.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 27 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-13 |
3. Acceptance
- The five journeys run in ores.web against the real server on the journey runtime the Setup group landed, and no journey entity is added.
- The whole grid is read under the permission the journey records, and the heartbeat carries its host.
- The services roster keeps every expected instance with its state word, and the login answer carries the database row.
- The Operations area carries the five screens with the footer, the system-administration menu carries the Operations entry, and the versions screen is offered in every mode.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Scaffold story: Implement the operations journeys in ores.web | DONE | 2026-10-04 | 2026-10-04 | Story scaffolding rides this task: documents, sprint wiring, and the scaffold PR. Close it before merging that PR. |
| Carry the host on the heartbeat | DONE | 2026-10-04 | 2026-10-04 | Initial task for: Implement the operations journeys in ores.web |
| Serve the services roster | DONE | 2026-10-06 | 2026-10-06 | Serve the installation's expected services and their replica counts, and the last report of every instance at any age, so the roster keeps every expected row with a state: running, stopped or missing. |
| Carry the database on the login answer | DONE | 2026-10-07 | Read the database row at login and carry it on the login answer beside the build it states already: fingerprint, environment, commit and created. No subject of its own. | |
| Read the whole grid | DONE | 2026-10-07 | Drop the session-tenant filter from the grid reads, keep the stored tenant id as attribution, and guard the read with the permission the journey records, so the whole grid comes back. | |
| Keep the failure fields on the node summary | DONE | 2026-10-07 | Carry the failed task count and the longest task into the node summary, so a node failing every task stops reading as idle. | |
| Build the operations screens in ores.web | DONE | 2026-10-08 | The five journeys as screens on the journey runtime, against the real server: services, grid, bus, logs and versions, with the Operations area, the BFF routes and the footer. | |
| State who reaches the operations screens | DONE | 2026-10-05 | 2026-10-06 | The documents state who reaches each operations screen: the four installation screens are the system administrator's in the Operations area, and the versions screen is any signed-in person's in every mode. |
5. Plan
| # | Step | What it leaves behind |
|---|---|---|
| 1 | Scaffold the story and wire it into the programme | The story, its tasks, the sprint row and the programme's order table. |
| 2 | State who reaches the screens | The access model on the group page, the five journeys, the story and the screens task: the four installation screens in the system-administration menu's area, the versions screen in every mode. |
| 3 | Close the data-model linkages | The four fixes, each with its evidence, and each capture moved out of the inbox. |
| 4 | Build the operations screens | The five screens, the Operations area and the footer in ores.web, on the runtime the Setup group landed. |
| 5 | Line up the shell side | The grid stats command follows the changed read, and the story records where the shell carries no operations journey. |
6. Decisions
The remainder is carried in Record service lifecycle events and surface them in system health.
- The accepted design is the build's input. The five journeys were written and walked against a clickable prototype in sprint 26, and the user accepted the walk on 2026-10-04. The prototype branch is the design record; this build ports its screens onto the journey runtime rather than merging them, and each task re-checks its own claims against the tree as it works.
- The data-model linkages are the story's first tasks. The walk found five linkages between the accepted screens and the models, and each one sits in the inbox as a capture. They are the story's first tasks, so the build sizes from them instead of finding them mid-screen.
- The grid belongs to the installation. The grid reads drop the session tenant's filter, and the stored tenant id stays on the sample as attribution. The read grows the permission the journey records, so the whole grid and who may see it stay two separate decisions.
- The heartbeat carries one new field, not a new entity. A host id on the service heartbeat answers both questions the record found — which node runs a wrapper, and which host runs an instance — and the publishing process already holds the id.
- The database rides the login answer. The versions panel needs no read of its own: the login answer states the deployment's build already, and it gains the database row beside it. The row's audience is the server build's audience.
- The roster keeps every expected row. A services screen drawn from samples alone fails worst when the list is short: the operator cannot tell what is missing. The screen draws the installation's expected services and their replicas, and the read that serves them is the roster task.
- The estate's state is a small subset of the old controller. Heartbeats
tell only whether an instance went quiet. The roster also needs what should
run, which the registry gives through a generated expected-services table,
and what each instance said about itself: every process announces
startedand a gracefulstoppedthrough the shared service lifecycle, and telemetry stores the events and raises aservice_restartednotification to the super administrators. Supervision stays systemd's, as it would be Kubernetes'; the decommissioned controller'spid, stderr and restart policy are not brought back. Settled with the operator on 2026-10-06 (Record service starts and stops, Notify super administrators of service restarts). - Both clients reach one operation. Where the shell carries an operations journey today — the grid stats command and its recipe — it follows the same subject when the read changes. Where it carries none, this story records that rather than inventing a shell surface.
- A journey a person cannot reach from a screen is not finished. Each journey's Related journeys list is links on the screen; a screen that omits them has not implemented the journey.
- The Operations area is offered in system administration alone. The four installation journeys' actor is the super administrator acting from the system tenant, so the system-administration menu carries the Operations entry and no other menu does: a tenant administrator and a regular user reach none of the four screens. The versions screen is the exception. Its actor is any signed-in person, so the shell offers it in every mode, beside the footer. The accepted walk ran the prototype in that mode.
- The screens follow the accepted contracts. The UX language, the UI design principles and the TypeScript Clean Standard bind the work.
- A cross-sprint group closes DONE and gets a successor. The programme's rule applies here: if the group does not close in sprint 26, what lands is recorded and the rest continues in a successor story.
- The node summary states the failures beside the completions. The node
sample already stored
tasks_failedandmax_task_duration_ms, and the summary dropped both, so a node failing every task read as a node doing nothing. The summary carries both, mapped from the node's newest sample, and the shell'scompute grid-statsnode table prints them under a header row. The handler has no test seam — a header-only class with an injected NATS client and repositories built inline — so the mapping is proved on the live fleet, not by an automated test, and the task says so. - The database row rides the login answer, refusals included. The answer
already states the deployment's build, so it gains a nested
database_infobeside it — fingerprint, environment, commit and created — read once per login fromores_database_info_tbl. The handler fills it on every reply path, both successes and both refusals, because the row rides with the build and a refusal still says what it talked to; a read that fails leaves the row empty rather than failing the sign-in. No subject, permission, BFF route or second read appears. The BFF keeps the row on the session record andGET /api/sessionrepeats it, so the versions panel adds no request. The read is a hand-authored repository helper so it can be tested against the real table; the header-only login handler has no seam and is not unit-tested.
7. Out of scope
- The journey documents, which the extraction pass and their stories own — where this build proves one wrong, the correction goes to the document and is recorded here.
- Host, workunit and app management — the pages behind the grid's read-only view — deferred by the record to Extract the ores.compute user journeys.
- The charts over the stored telemetry aggregates, which the logs journey records as a gap of its own (Expose the telemetry stats surface) — this group states the gap on the screen rather than building the charts.
- The system-wide permission gap for hand-written operation handlers (Nothing gates a hand-written operation handler) — this group gates the reads it adds or changes and links the capture for the rest.
8. Documents
| Document | Kind | Purpose |
|---|---|---|
| Operations journeys | knowledge | The group page: five journeys, who reaches each screen, and where the legacy screens went. |
| See the running services | user_journey | The roster, its state words and its version skew. |
| Watch the compute grid | user_journey | The nodes, the wrappers, and the failures. |
| Watch the message bus | user_journey | The server's vitals and the streams. |
| Read the telemetry logs | user_journey | The filter bar, the entries and the page count. |
| Check the versions and the database | user_journey | The three builds and the footer. |
| Document the operations journeys | story | The story that wrote the journeys and accepted the walk. |
| Prototype the operations journeys | task | The accepted prototype: branch prototype/operations-journeys at 285519db99. |
| The service heartbeat carries no host | capture | The grid's wrapper-to-node join and the services screen's instance-to-host question. |
| The services roster has no read | capture | The expected roster, the replica counts, and the states beyond running. |
| The login answer does not carry the database | capture | The versions panel's database row, on the login answer. |
| The grid read is scoped to the session tenant | capture | The filter the grid's ownership removes. |
| The node summary drops the failure fields | capture | The failures a node row must state. |
| Implement the user journeys in ores.web | story | The programme this group belongs to, and the order it keeps. |
| The journey runtime | knowledge | The step and the rail the screens use. |
| TypeScript Clean Standard | knowledge | The standard the screens are held to. |
| Journey execution | knowledge | The composition classes, and why no journey entity is added. |