@bongos/core 1.21.70 → 1.21.72

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 (68) hide show
  1. package/.bongos-core.json +123 -63
  2. package/.claude/skills/goal-create/SKILL.md +21 -3
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +2 -0
  5. package/clients/bongos-client/index.cjs +2 -0
  6. package/clients/bongos-client/index.d.ts +5 -3
  7. package/clients/bongos-client/index.mjs +2 -0
  8. package/docs/adr/0368-red-and-blue-teams-practice-on-a-range-never-on-live.md +99 -0
  9. package/docs/adr/README.md +1 -0
  10. package/docs/api/openapi.json +46 -5
  11. package/docs/api-reference.md +4 -3
  12. package/docs/copy-inventory.md +388 -377
  13. package/docs/copy-registry.json +567 -448
  14. package/docs/file-map.md +1 -1
  15. package/docs/module-api-changelog.md +4 -0
  16. package/docs/page-readings.json +912 -931
  17. package/docs/recipes/core-release-pipeline.md +6 -0
  18. package/docs/recipes/upgrading-the-core.md +2 -0
  19. package/modules/hall-ui/public/settings-software-update.js +77 -2
  20. package/modules/hall-ui/public/settings.html +1 -1
  21. package/modules/lifecycle/db-tasks.js +12 -0
  22. package/modules/lifecycle/goal-spec-task.js +129 -0
  23. package/modules/lifecycle/routes/goals.js +7 -9
  24. package/modules/lifecycle/routes/task-write-routes.js +11 -1
  25. package/modules/lifecycle/upkeep-home.js +55 -0
  26. package/modules/public-landing/public/projects-hall-live.states.json +7 -1
  27. package/modules/public-landing/public/projects.html +581 -0
  28. package/modules/public-landing/public/projects.probes.json +2 -2
  29. package/modules/public-landing/public/projects.states.json +1 -1
  30. package/package-lock.json +2 -2
  31. package/package.json +1 -1
  32. package/release-notes.json +43 -0
  33. package/scripts/gds/claude-materialize.js +125 -31
  34. package/scripts/gds/claude-md-template.js +47 -10
  35. package/scripts/gds/cli-lib.js +4 -4
  36. package/scripts/gds/feedback-send.js +3 -3
  37. package/scripts/gds/paste-token.js +1 -1
  38. package/scripts/gds/provision-net.js +1 -8
  39. package/scripts/gds/provision-units.js +28 -2
  40. package/scripts/gds/reauth.js +1 -1
  41. package/scripts/gds/run-unit-tests.js +3 -0
  42. package/scripts/gds/setup.js +1 -1
  43. package/scripts/gds/start.js +4 -4
  44. package/scripts/gds/surface.js +15 -3
  45. package/scripts/gds/task.js +32 -5
  46. package/scripts/gds/upgrade-operator.js +73 -0
  47. package/scripts/gds/upgrade.js +7 -2
  48. package/scripts/hall-preview/server.js +3 -0
  49. package/src/bongos/routes/core-update.js +98 -4
  50. package/src/bongos/routes/feedback.js +11 -1
  51. package/src/bongos/upgrade-request.js +158 -0
  52. package/src/module-api.js +1 -1
  53. package/tests/claude_materialize.mjs +195 -18
  54. package/tests/cli_allowlist_permissions.mjs +6 -2
  55. package/tests/cli_surface.mjs +2 -2
  56. package/tests/fixtures/page-ledger.mjs +5 -0
  57. package/tests/goal_admission_override.mjs +1 -1
  58. package/tests/goal_category.mjs +1 -1
  59. package/tests/goal_create_spec_entry.mjs +61 -0
  60. package/tests/goal_spec_task.mjs +197 -0
  61. package/tests/goal_spec_task_db.mjs +95 -0
  62. package/tests/projects_hub_cloud_hop.mjs +303 -0
  63. package/tests/provision_settings_apply.mjs +25 -1
  64. package/tests/software_update.mjs +18 -1
  65. package/tests/start_env_guard.mjs +2 -2
  66. package/tests/upgrade_operator.mjs +105 -0
  67. package/tests/upgrade_request.mjs +348 -0
  68. package/tests/upkeep_home.mjs +156 -0
@@ -1081,6 +1081,8 @@ function createClient(opts = {}) {
1081
1081
  "softwareUpdate": {
1082
1082
  // GET /software-update — rank: any-builder — GET /software-update
1083
1083
  getSoftwareUpdate: (args) => request("GET", "/software-update", { hasBody: false }, args),
1084
+ // POST /software-update/request — rank: archon — POST /software-update/request
1085
+ postSoftwareUpdateRequest: (args) => request("POST", "/software-update/request", { hasBody: true }, args),
1084
1086
  },
1085
1087
  "specialities": {
1086
1088
  // GET /specialities — rank: any-builder — GET /specialities
@@ -1080,6 +1080,8 @@ function createClient(opts = {}) {
1080
1080
  "softwareUpdate": {
1081
1081
  // GET /software-update — rank: any-builder — GET /software-update
1082
1082
  getSoftwareUpdate: (args) => request("GET", "/software-update", { hasBody: false }, args),
1083
+ // POST /software-update/request — rank: archon — POST /software-update/request
1084
+ postSoftwareUpdateRequest: (args) => request("POST", "/software-update/request", { hasBody: true }, args),
1083
1085
  },
1084
1086
  "specialities": {
1085
1087
  // GET /specialities — rank: any-builder — GET /specialities
@@ -167,7 +167,7 @@ export interface GetSessionsIdResponse { session: unknown }
167
167
  export interface GetSessionsIdTranscriptResponse { transcript: unknown }
168
168
  export interface GetSessionsMineResponse { sessions: unknown; count: unknown }
169
169
  export interface GetSessionsSearchResponse { sessions: unknown; count: unknown; total: unknown; totals: unknown; limit: unknown; offset: unknown; session_types: unknown }
170
- export interface GetSoftwareUpdateResponse { ok: boolean; update: unknown; door: unknown; can_update: unknown }
170
+ export interface GetSoftwareUpdateResponse { ok: boolean; update: unknown; door: unknown; can_update: unknown; ask: unknown }
171
171
  export interface GetSpecialitiesIdDocumentsResponse { documents: unknown }
172
172
  export interface GetSpecialitiesIdResponse { speciality: unknown }
173
173
  export interface GetSpecialitiesIdSkillsResponse { speciality: unknown; adopted: boolean; enabled: unknown; skills: unknown }
@@ -354,8 +354,8 @@ export interface PostGoalsIdTransferRequest { builder_id?: StringifiableId }
354
354
  export interface PostGoalsIdTransferResponse { ok: boolean; goal: unknown; changed: boolean }
355
355
  export interface PostGoalsReorderRequest { version_id: string; ordered_ids: number[] }
356
356
  export interface PostGoalsReorderResponse { ok: boolean; goals: unknown }
357
- export interface PostGoalsRequest { version_id: string; title: string; subtitle?: string; description?: string; scope_modules?: string[]; succeeds_goal_id?: number; category_id?: number; admit_reason?: string }
358
- export interface PostGoalsResponse { ok: boolean; goal: unknown; succeeds_goal_id: unknown; category_advisory: unknown; admitted: unknown }
357
+ export interface PostGoalsRequest { version_id: string; title: string; subtitle?: string; description?: string; scope_modules?: string[]; succeeds_goal_id?: number; category_id?: number; admit_reason?: string; spec_task?: boolean }
358
+ export interface PostGoalsResponse { ok: boolean; goal: unknown; succeeds_goal_id: unknown; category_advisory: unknown; admitted: unknown; spec_task: unknown }
359
359
  export interface PostGovernmentAssignmentsRequest { builder_id: number; rank_key: string }
360
360
  export interface PostGovernmentBoardCharterRequest { form?: string; franchise?: string; council_rank?: string; pass_rule?: string; rationale_md?: string; acknowledge_self_removal?: boolean }
361
361
  export interface PostGovernmentBoardCharterResponse { ok: boolean; amendment: unknown; item: unknown; reads_as: unknown }
@@ -1578,6 +1578,8 @@ export interface BongosClient {
1578
1578
  "softwareUpdate": {
1579
1579
  /** GET /software-update — rank: any-builder */
1580
1580
  getSoftwareUpdate(args?: RequestArgs): Promise<GetSoftwareUpdateResponse>;
1581
+ /** POST /software-update/request — rank: archon */
1582
+ postSoftwareUpdateRequest(args?: RequestArgs): Promise<ApiResponse>;
1581
1583
  };
1582
1584
  "specialities": {
1583
1585
  /** GET /specialities — rank: any-builder */
@@ -1077,6 +1077,8 @@ export function createClient(opts = {}) {
1077
1077
  "softwareUpdate": {
1078
1078
  // GET /software-update — rank: any-builder — GET /software-update
1079
1079
  getSoftwareUpdate: (args) => request("GET", "/software-update", { hasBody: false }, args),
1080
+ // POST /software-update/request — rank: archon — POST /software-update/request
1081
+ postSoftwareUpdateRequest: (args) => request("POST", "/software-update/request", { hasBody: true }, args),
1080
1082
  },
1081
1083
  "specialities": {
1082
1084
  // GET /specialities — rank: any-builder — GET /specialities
@@ -0,0 +1,99 @@
1
+ # ADR 0368 — Red and blue teams practise on a range, never on live
2
+
3
+ - **Status:** proposed
4
+ - **Date:** 2026-10-06
5
+ - **Goal:** goal 1000094 (Working area 10 — Security, BONGOS-V2)
6
+ - **Builds on:** [ADR 0016](0016-trust-boundary-server-enforced-permissions.md) (the server enforces rank), [ADR 0019](0019-red-team-bounty-payout-table.md) (the bounty table), [ADR 0188](0188-patrol-runs-on-ci-not-the-server.md) (the weekly deterministic patrol), [ADR 0292](0292-both-install-paths-stay-and-vendoring-is-the-production-one.md) (a project is built from a release package), [ADR 0346](0346-dev-boxes-are-retired.md) (no staging since the dev boxes went), [ADR 0361](0361-merges-publish-as-candidates-release-decides-what-others-are-offered.md) (releases publish as candidates before anyone is offered them)
7
+ - **Decided with:** the owner, in a 2026-10-06 scoping interview. Every decision below is theirs; the D-numbers record the answer, not a recommendation.
8
+
9
+ ## Context
10
+
11
+ Goal 1000094 states its target as *"Red-teaming is consistent"*, and says the server should not be hackable by Claude's latest model. What exists today is all prevention, and some of it is only partly real:
12
+
13
+ - **Report inbox.** `/builder-redteam` files to `vulnerability_reports` and the Archon adjudicates. Its SKILL.md promises an auto-repro subagent that does not exist (task 1003431).
14
+ - **Bounty table.** The table is in `modules/security/security.js` (10/50/200/1000, overridable with `GDS_BOUNTY_*`). **No bounty has ever been paid:** confirming a report sets `drachmae_awarded` on the report, but nothing writes to `credit_log`.
15
+ - **Patrol.** The weekly CI run (`scripts/gds/redteam-patrol.js`) checks secrets in git history, dependency drift and action pins. It cannot attack a running server.
16
+ - **Detection.** `audit_log` records every authenticated write, refused ones included. It does not record reads or anonymous requests, and nothing alerts anyone.
17
+ - **Rules.** The only written rules are one line in the `#red-team` Discord channel topic: responsible disclosure, no live exploitation.
18
+ - **Staging.** None. There is also no fixture of fake builders at each rank.
19
+ - **Candidates are frequent.** Every merge publishes a candidate (161 in the week to 2026-10-06, about 23 a day). Only the one the owner presses Release on reaches other projects.
20
+
21
+ The established professional practice has four parts. Bongos has fragments of the second and none of the rest:
22
+
23
+ 1. a practice copy (a *range*) running the exact release about to go live, on fake data;
24
+ 2. rules of engagement;
25
+ 3. a blue team that detects as well as defends;
26
+ 4. a loop that turns every break into a fix plus a permanent check.
27
+
28
+ ## Decision
29
+
30
+ **D1 — Outcome.** The first version delivers all four of these: an advisory release check (D7), a scoreboard, sides with points (D8), and live detection (D9).
31
+
32
+ **D2 — The range is its own small server.**
33
+ - It runs on its own server (~$12/month, about 2 GB), separate from the shared box, so attackers may go after the machine itself.
34
+ - **It tests the candidate about to be released, not every candidate.** On `/deploy` the owner marks a candidate "stage for attack". The range is then rebuilt from scratch from that exact version, using the same vendored package a real project gets (ADR 0292). It rebuilds only when the owner chooses to.
35
+ - There is one range at a time. Staging a new candidate replaces the old one.
36
+ - It holds only fake data: fake builders at every rank, at least two fake tenants, and planted *canary secrets* (fake keys whose appearance anywhere proves a breach).
37
+ - It uses stand-ins for GitHub and Discord, so attacking the ship/deploy pipeline or the bot never touches the real services.
38
+
39
+ **D3 — The range shares nothing with live.**
40
+ - **Logins are already separate.** A session is a random token looked up in each server's own database (`db-kernel.js` `lookupSession`). A range login is therefore unknown to cloudbongos.com, and the reverse holds too.
41
+ - **The real coupling is the identity hub.** An ordinary project signs builders in through cloudbongos.com and reports activity back to it (ADR 0141, `modules/platform-identity`). The range must do neither. It runs its own stand-in hub, and fake builders sign in there.
42
+ - **No real secret is ever placed on the range.** That covers GitHub app keys, the Discord token, npm tokens and DigitalOcean tokens. The range is also never seeded from a copy of the live database.
43
+ - **A test proves the separation.** The range's configuration must name no live hub address and hold no real secret. Only the planted canaries look like secrets.
44
+
45
+ **D4 — Rules of engagement.**
46
+ - **In bounds:** everything on the range: rank escalation, cross-tenant reach, credit minting, the ship/deploy pipeline (against the stand-ins), the bot stand-in, and the range server itself.
47
+ - **Always out of bounds:**
48
+ - cloudbongos.com and the real box;
49
+ - denial of service, meaning flooding the range until it goes down;
50
+ - social engineering of real people.
51
+
52
+ Breaking these rules is a ban, not a bounty. Real GitHub and Discord are out of reach by construction, because the range only knows the stand-ins.
53
+
54
+ **D5 — Who plays.**
55
+ - **Red (attack):** AI sessions, plus human builders at Metic or above.
56
+ - **Blue (defend):** any builder may take a fix task, as today. The blue area of the hall shows confirmed-but-unfixed breaks, so seeing it requires Metic or above, the same bar as red.
57
+ - **One side at a time.** A builder may switch sides once every 30 days. When a red builder switches, their unconfirmed attempts stay theirs: they are still adjudicated and still credited to that builder as finder. That builder may never claim the fix for their own finding.
58
+
59
+ **D6 — AI attacks run on subscriptions, never the metered API.**
60
+ - Attack sessions run in a builder's own Claude Code session or headless through the Claude CLI, including under Autobongos.
61
+ - No Bongos-paid API key is used, so the practice adds no model spend.
62
+ - A finding from a session is credited to the builder who ran it, Autobongos runs included.
63
+
64
+ **D7 — Release check: advisory now, a gate later.**
65
+ - Each candidate's bar is **at least 3 attack runs, on Claude's newest model, each starting as xenos from a fixed attack brief, with no confirmed high or critical break.**
66
+ - While only our own projects run on Bongos, the bar is **advisory**: the deploy page shows a candidate's result beside its Release button, and releasing is unchanged.
67
+ - It becomes a blocking gate when the first outside tenant goes live; that switch is its own decision. Once it blocks, only the Archon may override, and the override records a typed reason in Bongos.
68
+
69
+ **D8 — Visibility and rewards.**
70
+ - Red attempts are private to the attacker and the Archon. Blue sees a break only once it is confirmed and turned into a fix task.
71
+ - Red and blue each get **their own area of the hall**, with a shared scoreboard (runs per candidate, breaks by severity, fixes, detections).
72
+ - **Points only, no credits yet.** ADR 0019's table stays as the severity scale. Paying it out, the missing `credit_log` write, is deferred until the range has proven itself. When it pays, the finder is the session owner (D6).
73
+
74
+ **D9 — Live detection.** On cloudbongos.com, alert on three signals:
75
+ - **repeated refusals:** many `rank_forbidden`/`permission_forbidden` responses from one builder or token in a short window;
76
+ - **odd CLI-token use:** a new origin, or unusual volume. Tokens never expire ([ADR 0294](0294-cli-sessions-do-not-expire.md)), so a leaked token is the largest live risk;
77
+ - **credits without a ship:** a credit appearing with no matching shipped task.
78
+
79
+ Alerts go to a new private `#security-alerts` Discord channel, visible to Archons only and added through `docs/discord/channels.json`. They do not go to the existing channels:
80
+ - `#red-team` is open to every Metic and is where reports are filed;
81
+ - `#security-ship-feed` announces shipped fixes.
82
+
83
+ The first two signals can be built from `audit_log`, which already records refused authenticated writes. Mass-read detection is deferred, because reads are not logged today.
84
+
85
+ **D10 — Blue's starting backlog.**
86
+ - The goal's still-valid open tasks become blue's backlog. On 2026-10-06 it had 48 open tasks (44 ready, 1 blocked, 3 backlog), and an audit that day judged about 40 of them still real.
87
+ - The four most urgent go first: 1004380 (a non-ASCII pre-launch password guess crashes the server), 1003412 (the re-auth skill wrongly says re-issuing a token kills the leaked one), and 1004382 + 1004383 (rank, credit and fitness files missing from `protected-surfaces.json`).
88
+
89
+ ## Consequences
90
+
91
+ - **Cost** is ~$12/month for the range server, and there is no model spend.
92
+ - **Release speed is unchanged while the check is advisory.** Once it is a gate, releasing becomes two steps: stage the candidate, then wait for three attack runs to finish against it.
93
+ - **"Not hackable by Claude's latest model"** becomes a measured, per-release claim instead of an aspiration.
94
+ - **Deferred, each its own later decision:**
95
+ - credit payouts;
96
+ - the blocking gate;
97
+ - mass-read detection;
98
+ - outside researchers.
99
+ - **A known gap:** with no API spend, attack runs happen only when a builder or Autobongos picks one up. A candidate can sit with zero runs, and the check will show that plainly rather than pass it.
@@ -486,3 +486,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
486
486
  | 0365 | [**A guild engages a project through each member's own door** ([task 1002303](https://cloudbongos.com/builders#/task/1002303)). Amends ADR 0336 D7's invite half after ADR 0353. **D1:** the engagement row as D7 specified, plus `guild_id` on the echo (the latest application decides the label). **D2:** a guild applies = each member applies as themselves through the relay, naming the engagement. **D3:** a project invites a guild = the hub records it and returns one hall hand-off link per public-roster member; no hub-written invites, the one-step relay stays deferred. **D4:** a project is named only when on the map and public, for both kinds. **D5:** the label rides the applicant-profile read; the queue is R28's. **D6:** the D4.4 guild cards are their own task.](0365-a-guild-engages-a-project-through-each-members-own-door.md) | guilds / invites / applications |
487
487
  | 0366 | [**Hall planning is forms; a goal made there carries its own spec task, and the interviews stay in the CLI** ([task 1003461](https://cloudbongos.com/builders#/task/1003461), goal 1000089). Spike answer. **D1:** form-shaped, build in the hall: create a task under a goal, create a goal (name + subtitle, version, category, no scope field), attach a criterion to a goal you hold; every server refusal rendered as copy. **D2:** interview-shaped, deliberately absent from the hall: version planning, scope inference, drafting criteria and seed tasks, reuse-vs-create judgement, carry-forward. **D3 (owner):** a hall-made goal is created with a "Spec goal N" task (`POST /goals` `spec_task: true`, `source_ref goal-<id>-spec`) and every task in the goal depends on it until it ships; no new permission, no migration. **D4:** an optional "Plan with Claude" hand-off button.](0366-hall-planning-is-forms-and-a-goal-made-there-carries-its-own-spec-task.md) | lifecycle / planning |
488
488
  | 0367 | [**The Discord support bot answers from public docs only, under a monthly cap that fails closed** ([task 1002534](https://cloudbongos.com/builders#/task/1002534), goal 1000110). **D1:** one pinned channel, only when @-mentioned; the first gateway reply. **D2:** the corpus is an allowlist (`README.md`, `docs/onboarding/`, `docs/api-reference.md`) served by a new `memory.searchPublicDocs` port whose scope (doc, xenos, no owner, allowlisted ref) is fixed in SQL; the asker is never looked up. **D3:** no writes but the reply and one `audit_log` row per answer, which is also the spend ledger, so no migration. **D4:** a nonce-fenced prompt, no tools, mentions disabled. **D5:** `claude-haiku-4-5`, `DISCORD_SUPPORT_MONTHLY_CAP_USD` default $5, fail closed, with in-flight answers reserved at worst case. **D6:** off by default; its own switch and an env-only, namespaced key. **D7:** the channel's humans review wrong answers; the fix is the doc.](0367-the-support-bot-answers-from-public-docs-only.md) | discord / support / spend |
489
+ | 0368 | [**Red and blue teams practise on a range, never on live** (goal 1000094 — *Working area 10, Security*; proposed). **D2:** the range is its own small server, rebuilt from the candidate the owner marks "stage for attack". **D3:** it shares no identity hub, secret or data with live. **D5:** red is AI plus Metic+, with one side at a time and a 30-day switch. **D6:** attacks run on subscriptions, never the metered API. **D7:** 3 runs on the newest model with 0 high+ breaks, advisory until an outside tenant exists. **D8:** points only, no credits yet. **D9:** three live signals to `#security-alerts`.](0368-red-and-blue-teams-practice-on-a-range-never-on-live.md) | security / red-team / range |
@@ -20153,6 +20153,40 @@
20153
20153
  ]
20154
20154
  }
20155
20155
  },
20156
+ "/software-update/request": {
20157
+ "post": {
20158
+ "operationId": "post_software_update_request",
20159
+ "tags": [
20160
+ "software-update"
20161
+ ],
20162
+ "summary": "POST /software-update/request",
20163
+ "description": "POST /software-update/request — \"Ask for this upgrade\" (task 1004595). On a project the hub's operator runs, sends one request for the version this project is offered to the operator, through the direct feedback door, and remembers it so the page can say it is pending. The version is the server's own reading, never the caller's. Idempotent per version; a different version waits out a 24h cooldown (429). rank: core.pin.move — the same atom as the Update button the panel draws.\n\n**Rank:** `archon` — Archon only (rank and identity management + the escalation keys — the trust boundary).\n\n**Permissions:** `core.pin.move` (all required).",
20164
+ "x-rank": "archon",
20165
+ "x-source": "src/bongos/routes/core-update.js",
20166
+ "x-permissions": [
20167
+ "core.pin.move"
20168
+ ],
20169
+ "responses": {
20170
+ "200": {
20171
+ "description": "Success."
20172
+ },
20173
+ "400": {
20174
+ "$ref": "#/components/responses/BadRequest"
20175
+ },
20176
+ "401": {
20177
+ "$ref": "#/components/responses/Unauthorized"
20178
+ },
20179
+ "403": {
20180
+ "$ref": "#/components/responses/Forbidden"
20181
+ }
20182
+ },
20183
+ "security": [
20184
+ {
20185
+ "builderSession": []
20186
+ }
20187
+ ]
20188
+ }
20189
+ },
20156
20190
  "/specialities": {
20157
20191
  "get": {
20158
20192
  "operationId": "get_specialities",
@@ -26700,13 +26734,15 @@
26700
26734
  },
26701
26735
  "update": {},
26702
26736
  "door": {},
26703
- "can_update": {}
26737
+ "can_update": {},
26738
+ "ask": {}
26704
26739
  },
26705
26740
  "required": [
26706
26741
  "ok",
26707
26742
  "update",
26708
26743
  "door",
26709
- "can_update"
26744
+ "can_update",
26745
+ "ask"
26710
26746
  ]
26711
26747
  },
26712
26748
  "GetSpecialitiesIdDocumentsResponse": {
@@ -29690,6 +29726,9 @@
29690
29726
  "type": "string",
29691
29727
  "minLength": 8,
29692
29728
  "maxLength": 500
29729
+ },
29730
+ "spec_task": {
29731
+ "type": "boolean"
29693
29732
  }
29694
29733
  },
29695
29734
  "required": [
@@ -29707,14 +29746,16 @@
29707
29746
  "goal": {},
29708
29747
  "succeeds_goal_id": {},
29709
29748
  "category_advisory": {},
29710
- "admitted": {}
29749
+ "admitted": {},
29750
+ "spec_task": {}
29711
29751
  },
29712
29752
  "required": [
29713
29753
  "ok",
29714
29754
  "goal",
29715
29755
  "succeeds_goal_id",
29716
29756
  "category_advisory",
29717
- "admitted"
29757
+ "admitted",
29758
+ "spec_task"
29718
29759
  ]
29719
29760
  },
29720
29761
  "PostGovernmentAssignmentsRequest": {
@@ -33570,7 +33611,7 @@
33570
33611
  "description": "A required dependency/feature is not configured or is temporarily down."
33571
33612
  }
33572
33613
  },
33573
- "x-endpoint-count": 522,
33614
+ "x-endpoint-count": 523,
33574
33615
  "x-schema-count": 564,
33575
33616
  "x-undocumented-bodies": 12,
33576
33617
  "x-response-schemas": 374,
@@ -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. 522 endpoints across 93 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 523 endpoints across 93 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`.
@@ -307,7 +307,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
307
307
  | Method | Path | Rank | Body | Description |
308
308
  |---|---|---|---|---|
309
309
  | GET | `/api/bongos/goals` | `any-builder` | — | GET /goals?version=&status= — list goals (read); each row carries `viewer_is_member` for the reader. |
310
- | POST | `/api/bongos/goals` | `metic+archon` | `version_id`, `title`, `subtitle`, `description`, `scope_modules`, `succeeds_goal_id`, `category_id`, `admit_reason` | POST /goals — create a goal. |
310
+ | POST | `/api/bongos/goals` | `metic+archon` | `version_id`, `title`, `subtitle`, `description`, `scope_modules`, `succeeds_goal_id`, `category_id`, `admit_reason`, `spec_task` | POST /goals — create a goal. |
311
311
  | GET | `/api/bongos/goals/:id` | `any-builder` | — | GET /goals/:id — one goal with its members + linked criteria (read). |
312
312
  | PATCH | `/api/bongos/goals/:id` | `any-builder` | — | PATCH /goals/:id — correct a goal's own title/subtitle/description (tasks 1003102, 1003224). |
313
313
  | PATCH | `/api/bongos/goals/:id/accepting-requests` | `any-builder` | — | PATCH /goals/:id/accepting-requests { accepting_requests } — a private goal's lead closes or re-opens it to join-requests (task 1002971, … |
@@ -768,11 +768,12 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
768
768
  | GET | `/api/bongos/sky` | `any-builder` | — | GET /sky, the whole project sky (task 1004230, ADR 0331). |
769
769
  | GET | `/api/bongos/sky/mine` | `any-builder` | — | GET /sky/mine, every thought the SIGNED-IN builder filed with its state, size and descent, capped at 1000 (task 1004230). |
770
770
 
771
- ## `software-update` (1)
771
+ ## `software-update` (2)
772
772
 
773
773
  | Method | Path | Rank | Body | Description |
774
774
  |---|---|---|---|---|
775
775
  | GET | `/api/bongos/software-update` | `any-builder` | — | GET /software-update — Settings → Software update (task 1004296): this project's core, the newest release its channel allows, what the ve… |
776
+ | POST | `/api/bongos/software-update/request` | `archon` | — | POST /software-update/request — "Ask for this upgrade" (task 1004595). |
776
777
 
777
778
  ## `specialities` (15)
778
779