Task: Make the reporting to compute handoff drive a job

Table of Contents

This page documents a task in the Run an example bundle through the compute grid from a report definition story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Make the reporting path's workunit reach a wrapper and run. The original note listed three defects in the submit path; the run-token task moved submission onto the compute dispatcher and closed one of them, so two remain:

  • The subject has no consumer. The dispatcher publishes each assignment on compute.v1.work.assignments.{run_tenant}.{platform}, and every wrapper subscribes on its own configured tenant, the system tenant, so a tenant's run is published where nobody listens. The platform's wrapper fleet is the deployment's shared pool and must consume every tenant's work.
  • The input URI is the wrong shape. prepare_ore_package answers with ores/ore/packages/{instance}/ore_package.tar.gz, a bucket and key, and the wrapper fetches it over the storage HTTP interface, which speaks /api/v1/storage/{bucket}/{key}. The package and output URIs the dispatcher sets are already paths.

2. Status

Field Value
State DONE
Parent story Run an example bundle through the compute grid from a report definition
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-07

3. Acceptance

  • A workunit submitted through the reporting path is picked up by a wrapper and executes.
  • The wrapper can download the package and the input, and has somewhere to put the output.
  • The subject, the URI shape and the workunit fields match what the working dispatcher produces.

4. Plan

The subject fix belongs in the wrapper, not the dispatcher: the stream already captures assignments.>, and the tenant segment is the routing key a tenant's own pool will filter on later, so the shared fleet widens its consumer to assignments.*.{platform} and keeps the tenant in the subject. The node's --tenant-id stays its own identity for the host row and telemetry; it is no longer a filter on the work it takes.

The URI fix belongs where the URI is built: prepare_ore_package builds it with storage_paths::make_object_path, the same helper the compute dispatcher uses for the package and the output.

5. Notes

Closed. The handoff drives a job end to end. Report instance 0b6d9908-d699-49ae-b633-cbc363d4b8e6 of the "Intercompany Exposure Matrix" definition reached the terminal completed state, and its result 9fd17163-d2a4-43d8-83ef-0b25edb84069 came back Done with outcome 1 from host ed10ef0f-ed48-5b3f-96ab-49e5eca325d7. The node downloaded the package and the input and uploaded the output, each authorised by the assignment's capability; the same URLs answer 401 without one. The mechanism is recorded in give a worker node a capability to reach its assignment's objects, which also records the two defects that had to be fixed first.

The live run reached the wrapper. Run f8275ac1-1ac5-4e2e-a485-97324ef3b13e, tenant 51e855c0-ce99-4726-a590-7272c89cf8b1:

  • The wrapper subscribes to compute.v1.work.assignments.*.x64-linux (durable compute_wrapper_shared_x64-linux), and at 14:24:57 it took the run's assignment. Defect 1 is closed.
  • The attempted package URL is http://localhost:20600/api/v1/storage/ores/compute/packages/ORE-1.8.17.0/..., the path shape storage speaks. Defect 3 is closed for the package; the input is built by the same helper.
  • It then failed HTTP 401. ores.compute.wrapper has no storage credential at all: application.cpp passes a constexpr empty storage_bearer_token to every get and put. A node needs a credential before it can download, and the design says that credential is the per-assignment capability Storage policy describes, which the isolation story owns. This task waits on it rather than inventing a standing service token the policy would replace.

A second finding: the JetStream assignments stream survives a database recreate. On the recreated environment the wrapper replayed assignments from the previous one and answered results.submit failed: Result not found for each, because the result rows were gone. The smoke-test story's "reproducible from a freshly recreated database" acceptance will meet this; the stream wants purging, or the handler wants to treat an unknown result as an expiry rather than an error.

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
#2740 [compute] Let the shared wrapper fleet take a tenant's work

8. Review

Comment summary File Decision Notes
       

9. Result

Partial, and landed: the two defects this task owned are fixed and proven.

  • The platform wrapper fleet consumes compute.v1.work.assignments.*.{platform}, so the shared pool serves every tenant. Proven live: the wrapper took run f8275ac1's assignment.
  • prepare_ore_package builds its tarball URI with storage_paths::make_object_path, so the wrapper's input URL is well formed.
  • The handoff's third defect was closed by the run-token task, which moved submission onto the compute dispatcher.

Still open, and why this task is BLOCKED rather than DONE: a wrapper cannot download, because a node holds no storage credential. That is the per-assignment capability the isolation story owns, not a handoff defect. The task closes when a node can authenticate to storage and a run executes.

Emacs 29.3 (Org mode 9.6.15)