@bongos/core 1.24.95 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.bongos-core.json +97 -57
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +6 -0
  4. package/clients/bongos-client/index.cjs +6 -0
  5. package/clients/bongos-client/index.d.ts +9 -0
  6. package/clients/bongos-client/index.mjs +6 -0
  7. package/docs/api/openapi.json +179 -3
  8. package/docs/api-reference.md +6 -3
  9. package/docs/architecture.md +3 -1
  10. package/docs/copy-inventory.md +7 -7
  11. package/docs/copy-registry.json +7 -7
  12. package/docs/module-api-changelog.md +6 -0
  13. package/docs/page-inventory.json +2 -0
  14. package/docs/page-readings.json +6 -6
  15. package/migrations/core_298_card_step_up.sql +16 -0
  16. package/modules/autonomy/db.js +48 -0
  17. package/modules/autonomy/routes/autonomy.js +15 -0
  18. package/modules/economy/module.json +1 -1
  19. package/modules/economy/processor-stripe.js +292 -0
  20. package/modules/economy/routes/balances.js +4 -3
  21. package/modules/economy/routes/project-account.js +12 -1
  22. package/modules/economy/tests/processor_stripe.mjs +135 -0
  23. package/modules/government/catalog.js +1 -1
  24. package/modules/government/routes/government.js +2 -2
  25. package/modules/hall-ui/public/home-city-draw.js +24 -2
  26. package/modules/hall-ui/public/home-city.css +15 -0
  27. package/modules/hall-ui/public/home-city.js +3 -1
  28. package/modules/hall-ui/public/home-runner.js +248 -0
  29. package/modules/hall-ui/public/index.html +8 -5
  30. package/modules/hall-ui/public/visor.css +27 -0
  31. package/modules/hall-ui/public/visor.js +65 -2
  32. package/modules/hall-ui/records/home-runner.md +19 -0
  33. package/modules/hall-ui/records/visor.md +4 -0
  34. package/modules/render-deploy/routes/act.js +1 -1
  35. package/modules/render-deploy/routes/app.js +1 -1
  36. package/package-lock.json +2 -2
  37. package/package.json +1 -1
  38. package/release-notes.json +17 -0
  39. package/scripts/bongos/fitness.js +1 -1
  40. package/scripts/bongos/government-walk.js +2 -2
  41. package/scripts/hall-preview/server.js +4 -0
  42. package/src/bongos/passkeys.js +30 -0
  43. package/src/bongos/routes/auth.js +2 -2
  44. package/src/bongos/routes/builders.js +2 -1
  45. package/src/bongos/routes/module-payouts.js +4 -2
  46. package/src/bongos/routes/my-cash-outs.js +5 -3
  47. package/src/bongos/routes/my-passkeys.js +70 -0
  48. package/src/bongos/routes/payout-approvals.js +5 -3
  49. package/src/bongos/step-up.js +42 -0
  50. package/src/module-api.js +5 -1
  51. package/tests/autonomy_runner_goal_stats.mjs +92 -0
  52. package/tests/government_act_alone_buildings.mjs +2 -1
  53. package/tests/government_treasury.mjs +2 -1
  54. package/tests/hall_visor.mjs +20 -0
  55. package/tests/home_runner.mjs +115 -0
  56. package/tests/module_api.mjs +1 -0
  57. package/tests/my_passkeys.mjs +47 -1
  58. package/tests/rank_change_broadcast_port.mjs +2 -0
@@ -2946,6 +2946,54 @@
2946
2946
  ]
2947
2947
  }
2948
2948
  },
2949
+ "/autonomy/me/goals/{goalId}/stats": {
2950
+ "get": {
2951
+ "operationId": "get_autonomy_me_goals_goalId_stats",
2952
+ "tags": [
2953
+ "autonomy"
2954
+ ],
2955
+ "summary": "GET /autonomy/me/goals/:goalId/stats",
2956
+ "description": "ONE GOAL, SEEN FROM THE CALLER'S RUNNER (task 1005243): the game's runner card on Home — tasks it shipped there, the tokens they took, the average task length and what is left, so the card can say roughly how long the rest takes. Read-only and the caller's own, behind `autonomy.run` like the picks.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `autonomy.run` (all required).",
2957
+ "x-rank": "metic+archon",
2958
+ "x-source": "modules/autonomy/routes/autonomy.js",
2959
+ "x-permissions": [
2960
+ "autonomy.run"
2961
+ ],
2962
+ "parameters": [
2963
+ {
2964
+ "name": "goalId",
2965
+ "in": "path",
2966
+ "required": true,
2967
+ "schema": {
2968
+ "type": "string"
2969
+ },
2970
+ "description": "Path parameter `goalId`."
2971
+ }
2972
+ ],
2973
+ "responses": {
2974
+ "200": {
2975
+ "description": "Success."
2976
+ },
2977
+ "400": {
2978
+ "$ref": "#/components/responses/BadRequest"
2979
+ },
2980
+ "401": {
2981
+ "$ref": "#/components/responses/Unauthorized"
2982
+ },
2983
+ "403": {
2984
+ "$ref": "#/components/responses/Forbidden"
2985
+ },
2986
+ "404": {
2987
+ "$ref": "#/components/responses/NotFound"
2988
+ }
2989
+ },
2990
+ "security": [
2991
+ {
2992
+ "builderSession": []
2993
+ }
2994
+ ]
2995
+ }
2996
+ },
2949
2997
  "/autonomy/precheck": {
2950
2998
  "get": {
2951
2999
  "operationId": "get_autonomy_precheck",
@@ -16807,6 +16855,105 @@
16807
16855
  ]
16808
16856
  }
16809
16857
  },
16858
+ "/me/passkeys/authenticate/options": {
16859
+ "post": {
16860
+ "operationId": "post_me_passkeys_authenticate_options",
16861
+ "tags": [
16862
+ "me"
16863
+ ],
16864
+ "summary": "POST /me/passkeys/authenticate/options",
16865
+ "description": "POST /api/bongos/me/passkeys/authenticate/options — start a card check. rank: any-builder (own identity only). The challenge is bound to the caller.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
16866
+ "x-rank": "any-builder",
16867
+ "x-source": "src/bongos/routes/my-passkeys.js",
16868
+ "requestBody": {
16869
+ "required": false,
16870
+ "content": {
16871
+ "application/json": {
16872
+ "schema": {
16873
+ "type": "object",
16874
+ "additionalProperties": true
16875
+ }
16876
+ }
16877
+ },
16878
+ "x-validated": true
16879
+ },
16880
+ "responses": {
16881
+ "200": {
16882
+ "description": "Success.",
16883
+ "content": {
16884
+ "application/json": {
16885
+ "schema": {
16886
+ "$ref": "#/components/schemas/PostMePasskeysAuthenticateOptionsResponse"
16887
+ }
16888
+ }
16889
+ }
16890
+ },
16891
+ "400": {
16892
+ "$ref": "#/components/responses/ValidationFailed"
16893
+ },
16894
+ "401": {
16895
+ "$ref": "#/components/responses/Unauthorized"
16896
+ },
16897
+ "403": {
16898
+ "$ref": "#/components/responses/Forbidden"
16899
+ }
16900
+ },
16901
+ "security": [
16902
+ {
16903
+ "builderSession": []
16904
+ }
16905
+ ]
16906
+ }
16907
+ },
16908
+ "/me/passkeys/authenticate/verify": {
16909
+ "post": {
16910
+ "operationId": "post_me_passkeys_authenticate_verify",
16911
+ "tags": [
16912
+ "me"
16913
+ ],
16914
+ "summary": "POST /me/passkeys/authenticate/verify",
16915
+ "description": "POST /api/bongos/me/passkeys/authenticate/verify — finish a card check. Body: { response } the browser's assertion. On success the CALLER'S session row is stamped; that stamp (never anything the client sends) is the step-up proof. rank: any-builder (own identity only).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
16916
+ "x-rank": "any-builder",
16917
+ "x-source": "src/bongos/routes/my-passkeys.js",
16918
+ "requestBody": {
16919
+ "required": false,
16920
+ "content": {
16921
+ "application/json": {
16922
+ "schema": {
16923
+ "$ref": "#/components/schemas/PostMePasskeysAuthenticateVerifyRequest"
16924
+ }
16925
+ }
16926
+ },
16927
+ "x-validated": true
16928
+ },
16929
+ "responses": {
16930
+ "200": {
16931
+ "description": "Success.",
16932
+ "content": {
16933
+ "application/json": {
16934
+ "schema": {
16935
+ "$ref": "#/components/schemas/PostMePasskeysAuthenticateVerifyResponse"
16936
+ }
16937
+ }
16938
+ }
16939
+ },
16940
+ "400": {
16941
+ "$ref": "#/components/responses/ValidationFailed"
16942
+ },
16943
+ "401": {
16944
+ "$ref": "#/components/responses/Unauthorized"
16945
+ },
16946
+ "403": {
16947
+ "$ref": "#/components/responses/Forbidden"
16948
+ }
16949
+ },
16950
+ "security": [
16951
+ {
16952
+ "builderSession": []
16953
+ }
16954
+ ]
16955
+ }
16956
+ },
16810
16957
  "/me/passkeys/browser.js": {
16811
16958
  "get": {
16812
16959
  "operationId": "get_me_passkeys_browser_js",
@@ -39720,6 +39867,35 @@
39720
39867
  },
39721
39868
  "additionalProperties": false
39722
39869
  },
39870
+ "PostMePasskeysAuthenticateOptionsResponse": {
39871
+ "type": "object",
39872
+ "properties": {
39873
+ "options": {}
39874
+ },
39875
+ "required": [
39876
+ "options"
39877
+ ]
39878
+ },
39879
+ "PostMePasskeysAuthenticateVerifyRequest": {
39880
+ "type": "object",
39881
+ "properties": {
39882
+ "response": {}
39883
+ },
39884
+ "additionalProperties": false
39885
+ },
39886
+ "PostMePasskeysAuthenticateVerifyResponse": {
39887
+ "type": "object",
39888
+ "properties": {
39889
+ "ok": {
39890
+ "type": "boolean"
39891
+ },
39892
+ "valid_for_seconds": {}
39893
+ },
39894
+ "required": [
39895
+ "ok",
39896
+ "valid_for_seconds"
39897
+ ]
39898
+ },
39723
39899
  "PostMePasskeysRegisterOptionsResponse": {
39724
39900
  "type": "object",
39725
39901
  "properties": {
@@ -43561,9 +43737,9 @@
43561
43737
  "description": "A required dependency/feature is not configured or is temporarily down."
43562
43738
  }
43563
43739
  },
43564
- "x-endpoint-count": 696,
43565
- "x-schema-count": 731,
43740
+ "x-endpoint-count": 699,
43741
+ "x-schema-count": 734,
43566
43742
  "x-undocumented-bodies": 12,
43567
- "x-response-schemas": 462,
43743
+ "x-response-schemas": 464,
43568
43744
  "x-generated-by": "scripts/bongos/gen-api-docs.js"
43569
43745
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Bongos API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 696 endpoints across 117 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 699 endpoints across 117 route files.
6
6
  > Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
7
7
 
8
8
  Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -106,7 +106,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
106
106
  | GET | `/api/bongos/auth/web/handoff` | `public` | — | GET /auth/web/handoff?code=&return= — the far side of the one-time session handoff (task 1004357). |
107
107
  | GET | `/api/bongos/auth/web/start` | `public` | — | /auth/web — browser flow (used by the /builders page). |
108
108
 
109
- ## `autonomy` (16)
109
+ ## `autonomy` (17)
110
110
 
111
111
  | Method | Path | Rank | Body | Description |
112
112
  |---|---|---|---|---|
@@ -118,6 +118,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
118
118
  | POST | `/api/bongos/autonomy/fence/priority` | `archon` | `goal_id` | The priority goal (task 1004453): which allowlisted goal the runner works first. |
119
119
  | POST | `/api/bongos/autonomy/heartbeat` | `any-builder` | `host`, `pid`, `started_at`, `mode`, `consecutive_failures`, `last_event`, `working_task_id`, `working_goal_id`, `head`, `disk_head`, `main_head`, `claude_account`, `hold_until` | The runner's check-in, once per loop. |
120
120
  | PUT | `/api/bongos/autonomy/me/goals` | `metic+archon` | `goal_ids` | A builder picks which allowlisted goals THEIR runner works. |
121
+ | GET | `/api/bongos/autonomy/me/goals/:goalId/stats` | `metic+archon` | — | ONE GOAL, SEEN FROM THE CALLER'S RUNNER (task 1005243): the game's runner card on Home — tasks it shipped there, the tokens they took, th… |
121
122
  | GET | `/api/bongos/autonomy/precheck` | `metic+archon` | — | |
122
123
  | GET | `/api/bongos/autonomy/runner-setup.ps1` | `public` | — | the Windows first lines; see the note above. |
123
124
  | GET | `/api/bongos/autonomy/runner-setup.sh` | `public` | — | the Mac first lines; see the note above. |
@@ -567,7 +568,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
567
568
  | PUT | `/api/bongos/market-watch/settings/key` | `metic+archon` | `key` | |
568
569
  | DELETE | `/api/bongos/market-watch/settings/key` | `metic+archon` | — | |
569
570
 
570
- ## `me` (63)
571
+ ## `me` (65)
571
572
 
572
573
  | Method | Path | Rank | Body | Description |
573
574
  |---|---|---|---|---|
@@ -608,6 +609,8 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
608
609
  | GET | `/api/bongos/me/model-allocation` | `any-builder` | — | |
609
610
  | PATCH | `/api/bongos/me/model-allocation` | `any-builder` | _undocumented_ | PATCH the model allocation. |
610
611
  | GET | `/api/bongos/me/passkeys` | `any-builder` | — | GET /api/bongos/me/passkeys — the caller's registered cards. |
612
+ | POST | `/api/bongos/me/passkeys/authenticate/options` | `any-builder` | validated | POST /api/bongos/me/passkeys/authenticate/options — start a card check. |
613
+ | POST | `/api/bongos/me/passkeys/authenticate/verify` | `any-builder` | `response` | POST /api/bongos/me/passkeys/authenticate/verify — finish a card check. |
611
614
  | GET | `/api/bongos/me/passkeys/browser.js` | `any-builder` | — | GET /api/bongos/me/passkeys/browser.js — the vetted @simplewebauthn/browser bundle, served same-origin so the page needs no CDN and no bu… |
612
615
  | POST | `/api/bongos/me/passkeys/register/options` | `any-builder` | validated | POST /api/bongos/me/passkeys/register/options — start adding a card. |
613
616
  | POST | `/api/bongos/me/passkeys/register/verify` | `any-builder` | `response`, `nickname` | POST /api/bongos/me/passkeys/register/verify — finish adding a card. |
@@ -273,6 +273,8 @@ store_module_prices(id, module_key, price_cents, price_credits, set_by, set_at)
273
273
 
274
274
  Passkey foundation (migration `core_277`, task 1004750, [ADR 0382](adr/0382-a-hardware-card-is-a-passkey-step-up-an-archon-switches-on-per-builder.md) D1/D6 — storage only; the ceremonies and routes are their own tasks; code in `src/bongos/passkeys.js`):
275
275
 
276
+ Card step-up gate (migration `core_298`, task 1004747, ADR 0382 D2/D5; code in `src/bongos/step-up.js`): `builders.require_card` (default false) + `builder_sessions.card_verified_at`, stamped only by `POST /me/passkeys/authenticate/verify`. `requireCardStepUp` (also `api.requireCardStepUp` for modules) refuses 403 `card_required` when the builder's flag is on and the session has no card tap in the last 10 minutes; it fails closed. Mounted on rank set, admin session revoke (the own-session panic button stays open), render-deploy act + PUT app, treasury pots/borrow answers. The Archon switch that sets the flag is task 1004748.
277
+
276
278
  ```
277
279
  passkey_credentials(id, credential_id UNIQUE, builder_id FK, public_key bytea, sign_count,
278
280
  transports[], aaguid, nickname, created_at, last_used_at)
@@ -322,7 +324,7 @@ payout_tax_details(id, builder_id, status collected|incomplete, collected_by pro
322
324
  -- POST /payouts/ndas, POST /payouts/tax-details (payout.approve + web session).
323
325
  ```
324
326
 
325
- Builder payouts (migration `core_290`, task 1003183, [ADR 0397](adr/0397-the-payment-rail-is-stripe-connect-with-one-connected-account-per-project.md) D7 — a builder is paid for a task exactly once; `src/bongos/builder-payouts.js`, routes `GET`/`POST /payouts/builder-payouts` gated `payout.approve` plus the person's own web session for the POST; the `payout` movement is booked through the economy module's `economy.account` port in the same transaction. No processor adapter exists yet, so every payout is recorded owed and held `no_processor`):
327
+ Builder payouts (migration `core_298`, task 1003183, [ADR 0397](adr/0397-the-payment-rail-is-stripe-connect-with-one-connected-account-per-project.md) D7 — a builder is paid for a task exactly once; `src/bongos/builder-payouts.js`, routes `GET`/`POST /payouts/builder-payouts` gated `payout.approve` plus the person's own web session for the POST; the `payout` movement is booked through the economy module's `economy.account` port in the same transaction. No processor adapter exists yet, so every payout is recorded owed and held `no_processor`):
326
328
 
327
329
  ```
328
330
  builder_payouts_owed(id, builder_id FK, task_id FK, approval_id FK payout_approvals,
@@ -10,7 +10,7 @@
10
10
 
11
11
  | surface | lives at | files | strings |
12
12
  |---|---|---|---|
13
- | `builders-hall` | `modules/hall-ui/public` | 180 | 2072 |
13
+ | `builders-hall` | `modules/hall-ui/public` | 181 | 2072 |
14
14
  | `status-dashboard` | `modules/status-ui/public` | 4 | 89 |
15
15
  | `landing` | `modules/public-landing/public` | 10 | 1023 |
16
16
 
@@ -316,7 +316,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
316
316
  | `4df46e2be815` | certain | Clear the key? | `modules/hall-ui/public/market-watch-settings.js:218` |
317
317
  | `593dda3178eb` | certain | Click to copy | `modules/hall-ui/public/copy-on-click.js:137` |
318
318
  | `34624d39ff29` | certain | Clone the project to your machine and run | `modules/hall-ui/public/setup-gate.js:34` |
319
- | `3a426bad2c49` | certain | Close actions | `modules/hall-ui/public/visor.js:235` |
319
+ | `3a426bad2c49` | certain | Close actions | `modules/hall-ui/public/visor.js:293` |
320
320
  | `70f6a704d504` | certain | Close it | `modules/hall-ui/public/copy-desk.html:140` |
321
321
  | `053e576ba9a3` | certain | Close options | `modules/hall-ui/public/shell-game.js:454` |
322
322
  | `d12a2fb5730d` | certain | Close this flag | `modules/hall-ui/public/copy-desk.html:116` |
@@ -513,7 +513,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
513
513
  | `89d9c0962048` | certain | Everything that fell out of it | `modules/hall-ui/public/idea.js:420` |
514
514
  | `57d5ba0fdefb` | certain | Exit full screen | `modules/hall-ui/public/shell.js:622` |
515
515
  | `94339ddaeeea` | certain | Explore: the sky reveals itself as you follow routes from where you begin. | `modules/hall-ui/public/goal-map.html:75` |
516
- | `75bf2f13e4c0` | certain | Fast forward | `modules/hall-ui/public/home-city.js:336` |
516
+ | `75bf2f13e4c0` | certain | Fast forward | `modules/hall-ui/public/home-city.js:337` |
517
517
  | `8608a2dfdf61` | certain | File a blocker | `modules/hall-ui/public/blockers.js:316` |
518
518
  | `de62f4cc7d2e` | certain | File a bug or idea | `modules/hall-ui/public/ideas.html:55` |
519
519
  | `297a6d0a8608` | certain | File conflicts in your goals | `modules/hall-ui/public/goal-inbox.js:125` |
@@ -1411,7 +1411,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1411
1411
  | `6c3d88de42de` | certain | The primer | `modules/hall-ui/public/primer.html:37` |
1412
1412
  | `dea378cd4837` | certain | The primer did not load | `modules/hall-ui/public/primer.html:83` |
1413
1413
  | `08ec02eb31fb` | certain | The project city building up, week by week | `modules/hall-ui/public/shell-game.js:181` |
1414
- | `ca10fbab561e` | certain | The project this week | `modules/hall-ui/public/home-city.js:324` |
1414
+ | `ca10fbab561e` | certain | The project this week | `modules/hall-ui/public/home-city.js:325` |
1415
1415
  | `dc2d6fd0350a` | certain | The project’s life so far | `modules/hall-ui/public/genesis-home.js:156` |
1416
1416
  | `169a03d777a1` | certain | The rank above yours is {…}. | `modules/hall-ui/public/profile-own.js:101` |
1417
1417
  | `c0034db3281c` | certain | The reason is recorded in the audit log. This is recoverable: a retired task can be restored to the backlog wi | `modules/hall-ui/public/task.js:840` |
@@ -1486,7 +1486,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1486
1486
  | `9a685b01e2c6` | certain | This page opens at a higher rank. | `modules/hall-ui/public/watch.html:237` |
1487
1487
  | `e7a289134dc3` | certain | This page shows no words the reader could find. | `modules/hall-ui/public/tweak-editor.js:246` |
1488
1488
  | `d4b3b5556986` | certain | This page's reference docs | `modules/hall-ui/public/page-notes.js:166` |
1489
- | `79e4a934b434` | certain | This place | `modules/hall-ui/public/visor.js:237` |
1489
+ | `79e4a934b434` | certain | This place | `modules/hall-ui/public/visor.js:295` |
1490
1490
  | `5bdcbec770dd` | certain | This project has no slash commands yet. | `modules/hall-ui/public/commands.js:37` |
1491
1491
  | `f53b83bfbe54` | certain | This project has no watch rules yet. | `modules/hall-ui/public/market-watch-rules.js:62` |
1492
1492
  | `e97b2d549f10` | certain | This project is hosted on {…}, and that is where it is taken offline or removed. Both links below open this pr | `modules/hall-ui/public/project-settings.js:412` |
@@ -1499,10 +1499,10 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1499
1499
  | `09256febc32d` | certain | This sentence has {…} {…} where a value is dropped in when it is shown. | `modules/hall-ui/public/copy-desk.js:426` |
1500
1500
  | `9333d71e3e15` | certain | This speciality offers no skills to choose. | `modules/hall-ui/public/speciality-tools.js:125` |
1501
1501
  | `62b0940efd7d` | certain | This task is already retired. Promote restores it to the backlog. | `modules/hall-ui/public/task.js:816` |
1502
- | `1d77cc332601` | certain | This week's builders, ranked by what they did | `modules/hall-ui/public/home-city.js:327` |
1502
+ | `1d77cc332601` | certain | This week's builders, ranked by what they did | `modules/hall-ui/public/home-city.js:328` |
1503
1503
  | `4301ecd67891` | certain | This would fail. | `modules/hall-ui/public/deploy.js:524` |
1504
1504
  | `2ad5823d2cd7` | certain | Three dials, all settings rather than code: | `modules/hall-ui/public/government.html:55` |
1505
- | `3fe05a59a64d` | certain | Time, from the start of the version to live | `modules/hall-ui/public/home-city.js:339` |
1505
+ | `3fe05a59a64d` | certain | Time, from the start of the version to live | `modules/hall-ui/public/home-city.js:340` |
1506
1506
  | `f158ed1c24a2` | certain | Toggle fullscreen | `modules/hall-ui/public/diagram-viewer.js:105` |
1507
1507
  | `7dfdc26f9f79` | certain | Tokens refresh on use; re-issuing never signs you out anywhere else. | `modules/hall-ui/public/settings.html:183` |
1508
1508
  | `8f38bbae750b` | certain | Tool errors | `modules/hall-ui/public/watch.html:199` |
@@ -12,7 +12,7 @@
12
12
  "surfaces": {
13
13
  "builders-hall": {
14
14
  "at": "modules/hall-ui/public",
15
- "files": 180,
15
+ "files": 181,
16
16
  "strings": 2072
17
17
  },
18
18
  "status-dashboard": {
@@ -5208,7 +5208,7 @@
5208
5208
  "surface": "builders-hall",
5209
5209
  "text": "Close actions",
5210
5210
  "file": "modules/hall-ui/public/visor.js",
5211
- "line": 235,
5211
+ "line": 293,
5212
5212
  "origin": "js-markup",
5213
5213
  "confidence": "certain"
5214
5214
  },
@@ -6981,7 +6981,7 @@
6981
6981
  "surface": "builders-hall",
6982
6982
  "text": "Fast forward",
6983
6983
  "file": "modules/hall-ui/public/home-city.js",
6984
- "line": 336,
6984
+ "line": 337,
6985
6985
  "origin": "js-markup",
6986
6986
  "confidence": "certain"
6987
6987
  },
@@ -15063,7 +15063,7 @@
15063
15063
  "surface": "builders-hall",
15064
15064
  "text": "The project this week",
15065
15065
  "file": "modules/hall-ui/public/home-city.js",
15066
- "line": 324,
15066
+ "line": 325,
15067
15067
  "origin": "js-markup",
15068
15068
  "confidence": "certain"
15069
15069
  },
@@ -15738,7 +15738,7 @@
15738
15738
  "surface": "builders-hall",
15739
15739
  "text": "This place",
15740
15740
  "file": "modules/hall-ui/public/visor.js",
15741
- "line": 237,
15741
+ "line": 295,
15742
15742
  "origin": "js-markup",
15743
15743
  "confidence": "certain"
15744
15744
  },
@@ -15855,7 +15855,7 @@
15855
15855
  "surface": "builders-hall",
15856
15856
  "text": "This week's builders, ranked by what they did",
15857
15857
  "file": "modules/hall-ui/public/home-city.js",
15858
- "line": 327,
15858
+ "line": 328,
15859
15859
  "origin": "js-markup",
15860
15860
  "confidence": "certain"
15861
15861
  },
@@ -15882,7 +15882,7 @@
15882
15882
  "surface": "builders-hall",
15883
15883
  "text": "Time, from the start of the version to live",
15884
15884
  "file": "modules/hall-ui/public/home-city.js",
15885
- "line": 339,
15885
+ "line": 340,
15886
15886
  "origin": "js-markup",
15887
15887
  "confidence": "certain"
15888
15888
  },
@@ -3438,5 +3438,11 @@ is load-bearing: the script throws rather than guess if it is missing, and
3438
3438
  landed since 1.24.93 with no explicit bump. run 43302410261. (task 1002620)
3439
3439
  1.24.95 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3440
3440
  landed since 1.24.94 with no explicit bump. run 43304959846. (task 1002620)
3441
+ 1.24.96 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3442
+ landed since 1.24.95 with no explicit bump. run 43307125735. (task 1002620)
3443
+ 1.25.0 — adds `requireCardStepUp`, the hardware-card step-up gate a module mounts
3444
+ after its permission gate (task 1004747, ADR 0382). Additive, so MINOR.
3445
+ 1.25.1 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3446
+ landed since 1.25.0 with no explicit bump. run 43313162829. (task 1002620)
3441
3447
  ---------------------------------------------------------------------------
3442
3448
  ```
@@ -570,6 +570,8 @@
570
570
  "modules/hall-ui/public/home-city-draw.js",
571
571
  "modules/hall-ui/public/home-gallery.js",
572
572
  "modules/hall-ui/public/home-idea-box.js",
573
+ "modules/hall-ui/public/runner-button.js",
574
+ "modules/hall-ui/public/home-runner.js",
573
575
  "modules/hall-ui/public/home-city.js",
574
576
  "modules/hall-ui/public/hall-ask.js",
575
577
  "modules/hall-ui/public/blockers-lib.js",
@@ -283,7 +283,7 @@
283
283
  "surface": "builders",
284
284
  "title": "The city",
285
285
  "states_read": ["city","fullscreen","focus","pins","living","card","card-ask"],
286
- "files_hash": "804ce56d156d7046",
286
+ "files_hash": "0367a0e57f2fcfb1",
287
287
  "reading_hash": "277096d903879a57",
288
288
  "counts": {"lines":26,"placed":9,"shared":6,"unplaced":11},
289
289
  "omitted": {"data":7},
@@ -613,7 +613,7 @@
613
613
  "surface": "builders",
614
614
  "title": "The sky",
615
615
  "states_read": ["tour","sky","wells","ledger","full","full-back","out"],
616
- "files_hash": "a5f2d9cada6d1773",
616
+ "files_hash": "9de2854d844d990f",
617
617
  "reading_hash": "4a879397a84631e3",
618
618
  "counts": {"lines":50,"placed":25,"shared":6,"unplaced":19},
619
619
  "omitted": {"data":10},
@@ -954,8 +954,8 @@
954
954
  "surface": "builders",
955
955
  "title": "Builders' Hall",
956
956
  "states_read": ["home","out","founding","genesis","decide","demo"],
957
- "files_hash": "057978d931dfd529",
958
- "reading_hash": "c46b0ff89002a2d9",
957
+ "files_hash": "36c7410d9c8aeae0",
958
+ "reading_hash": "45468116976bf674",
959
959
  "counts": {"lines":32,"placed":12,"shared":8,"unplaced":12},
960
960
  "omitted": {"data":5},
961
961
  "notes": ["founding: an action failed (page.focus: Timeout 6000ms exceeded.); read as it stood"],
@@ -977,7 +977,7 @@
977
977
  {"key":"L0015","section":"Needs your attention13","text":"Ideas awaiting triage","placement":"placed","file":"modules/hall-ui/public/builders.js","line":320,"string_id":"e181637c5a5e"},
978
978
  {"key":"L0016","section":"Needs your attention13","text":"Requires project {…} fix","placement":"unplaced"},
979
979
  {"key":"L0017","section":"footer","text":"Sign out","placement":"shared","file":"modules/hall-ui/public/shell.js","line":514,"string_id":"1883ad7f07fc"},
980
- {"key":"L0018","section":"Needs your attention13","text":"core 1.24.93","placement":"unplaced"},
980
+ {"key":"L0018","section":"Needs your attention13","text":"core 1.24.94","placement":"unplaced"},
981
981
  {"key":"L0019","section":"Needs your attention13","text":"Skip","placement":"unplaced"},
982
982
  {"key":"L0020","section":"Needs your attention13","text":"Built on","placement":"placed","file":"modules/hall-ui/public/welcome-boot.js","line":183,"string_id":"fef59346ffee"},
983
983
  {"key":"L0021","section":"Needs your attention13","text":"cloudbongos.com","placement":"unplaced"},
@@ -3159,7 +3159,7 @@
3159
3159
  "surface": "builders",
3160
3160
  "title": "Your thinking",
3161
3161
  "states_read": ["tour","sky","list","simple","full-idea","full","full-list","full-back","out"],
3162
- "files_hash": "fa151338327f0a86",
3162
+ "files_hash": "96c460b71d47125f",
3163
3163
  "reading_hash": "b73f848b46b0f9b8",
3164
3164
  "counts": {"lines":50,"placed":25,"shared":6,"unplaced":19},
3165
3165
  "omitted": {"data":10},
@@ -0,0 +1,16 @@
1
+ -- core_298 card step-up: the per-builder requirement flag and the per-session proof
2
+ -- Applied under task 1004747 (ADR 0382 D2, D4).
3
+ --
4
+ -- WHY. A builder who has a registered hardware card can be required to tap it before
5
+ -- the sensitive actions (rank changes, deploy, session revoke, payouts). The server
6
+ -- needs two things to keep: whether the requirement is on for a builder, and when a
7
+ -- given session last proved a card.
8
+ --
9
+ -- * builders.require_card default false: nothing changes for anybody until an
10
+ -- Archon switches it on (that switch is its own task). Read fresh per request.
11
+ -- * builder_sessions.card_verified_at set ONLY by the card verify route, on the
12
+ -- server-side session row. Nothing the client sends counts as proof, and a new
13
+ -- session starts with none.
14
+
15
+ ALTER TABLE builders ADD COLUMN IF NOT EXISTS require_card boolean NOT NULL DEFAULT false;
16
+ ALTER TABLE builder_sessions ADD COLUMN IF NOT EXISTS card_verified_at timestamptz;
@@ -429,6 +429,53 @@ async function removeRunner({ builderId, host }) {
429
429
  return r ? { host: r.host, session_id: r.session_id ? String(r.session_id) : null } : null;
430
430
  }
431
431
 
432
+ // ── one goal, seen from the builder's runner (task 1005243) ──────────────────
433
+ //
434
+ // readRunnerGoalStats — what the game's runner card says about ONE goal: how
435
+ // many tasks there the builder's runner has shipped, the tokens those sessions
436
+ // spent, their average length, and how many tasks are still to build. All of it
437
+ // is the ledger's answer: a runner's claim carries `autonomous` (set by the
438
+ // server from the claiming session, core_295), a shipped claim is outcome
439
+ // 'shipped', and a session's tokens and length are what ship.js uploaded to
440
+ // session_records. SCOPED TO ONE BUILDER, like the heartbeat read: nobody reads
441
+ // another builder's runner.
442
+ //
443
+ // ITS COST. `mine` starts from the caller's claims through core_263's
444
+ // idx_claims_builder_history (builder_id, claimed_at), so it reads one builder's
445
+ // claims, never the table; session_records goes through idx_session_records_builder,
446
+ // and the tasks count through the goal's own rows. The card asks only while it is
447
+ // open (home-runner.js, every 15 s while the tab is visible).
448
+ async function readRunnerGoalStats(builderId, goalId) {
449
+ const { rows } = await pool.query(
450
+ `WITH mine AS (
451
+ SELECT DISTINCT c.task_id
452
+ FROM claims c JOIN tasks t ON t.id = c.task_id
453
+ WHERE c.builder_id = $1 AND c.autonomous AND c.outcome = 'shipped' AND t.goal_id = $2
454
+ ), spent AS (
455
+ SELECT COALESCE(SUM(sr.total_tokens), 0)::bigint AS tokens,
456
+ AVG(sr.duration_seconds) FILTER (WHERE sr.duration_seconds > 0) AS avg_s
457
+ FROM session_records sr
458
+ WHERE sr.builder_id = $1 AND sr.task_ids && ARRAY(SELECT task_id FROM mine)
459
+ )
460
+ SELECT (SELECT COUNT(*) FROM mine)::int AS tasks_done,
461
+ spent.tokens, spent.avg_s,
462
+ -- what is left is told only for a goal the project opened to runners, so
463
+ -- the read is no window onto a goal's size the caller could not send to
464
+ CASE WHEN EXISTS (SELECT 1 FROM autonomy_allowed_goals WHERE goal_id = $2)
465
+ THEN (SELECT COUNT(*) FROM tasks WHERE goal_id = $2 AND status IN ('ready', 'active'))::int END AS tasks_left
466
+ FROM spent`,
467
+ [builderId, goalId]
468
+ );
469
+ const r = rows[0] || {};
470
+ const avg = r.avg_s == null ? null : Math.round(Number(r.avg_s));
471
+ return {
472
+ tasks_done: Number(r.tasks_done) || 0,
473
+ tokens: Number(r.tokens) || 0,
474
+ avg_task_seconds: Number.isFinite(avg) && avg > 0 ? avg : null,
475
+ tasks_left: r.tasks_left == null ? null : Number(r.tasks_left) || 0,
476
+ };
477
+ }
478
+
432
479
  module.exports = {
433
480
  recordAutonomyRun,
434
481
  lastAutonomyHead,
@@ -449,4 +496,5 @@ module.exports = {
449
496
  setBuilderGoals,
450
497
  setBuilderPause,
451
498
  readAllRunnerScopes,
499
+ readRunnerGoalStats,
452
500
  };
@@ -376,6 +376,21 @@ module.exports = function buildAutonomyRouter() {
376
376
  }
377
377
  });
378
378
 
379
+ // ONE GOAL, SEEN FROM THE CALLER'S RUNNER (task 1005243): the game's runner
380
+ // card on Home — tasks it shipped there, the tokens they took, the average
381
+ // task length and what is left, so the card can say roughly how long the rest
382
+ // takes. Read-only and the caller's own, behind `autonomy.run` like the picks.
383
+ router.get('/autonomy/me/goals/:goalId/stats', auth.requireBuilder, auth.requirePermission('autonomy.run'), async (req, res) => {
384
+ const goalId = Number(req.params.goalId);
385
+ if (!Number.isSafeInteger(goalId) || goalId <= 0) return res.fail('goal_id_invalid', { status: 400, message: 'goal id must be a positive integer' });
386
+ try {
387
+ res.json({ goal_id: goalId, ...(await db.readRunnerGoalStats(req.builder.id, goalId)) });
388
+ } catch (err) {
389
+ log.error('[gds] GET /autonomy/me/goals/:goalId/stats', err);
390
+ res.fail('runner_stats_unreadable', { status: 503, message: 'could not read the runner stats' });
391
+ }
392
+ });
393
+
379
394
  // The owner pauses or resumes ONE builder's runner without throwing the master
380
395
  // switch. Same atom as the kill switch: stopping a machine is the same act
381
396
  // whether it is everyone's or one person's, and the paused builder must not be
@@ -8,6 +8,6 @@
8
8
  "default": true,
9
9
  "maintenance": { "status": "core-maintained" },
10
10
  "contributes": { "migrations": true, "routes": ["cost", "credits", "earnings", "leaderboard", "project-account", "balances", "reward"], "pollers": ["ledger-check"] },
11
- "provides": ["reward", "economy.account"],
11
+ "provides": ["reward", "economy.account", "economy.processor"],
12
12
  "consumes": []
13
13
  }