@bongos/core 1.21.78 → 1.21.80

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 (77) hide show
  1. package/.bongos-core.json +108 -78
  2. package/.claude/skills/goal-create/SKILL.md +2 -1
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +8 -0
  5. package/clients/bongos-client/index.cjs +8 -0
  6. package/clients/bongos-client/index.d.ts +13 -0
  7. package/clients/bongos-client/index.mjs +8 -0
  8. package/docs/adr/0155-adopt-private-repo-widen-oauth-scope.md +1 -0
  9. package/docs/adr/0370-a-repo-we-create-is-private.md +29 -0
  10. package/docs/adr/README.md +1 -0
  11. package/docs/api/openapi.json +285 -3
  12. package/docs/api-reference.md +6 -2
  13. package/docs/copy-inventory.md +40 -33
  14. package/docs/copy-registry.json +125 -61
  15. package/docs/module-api-changelog.md +4 -0
  16. package/docs/page-inventory.json +4 -2
  17. package/docs/page-readings.json +216 -207
  18. package/migrations/core_273_module_install_reports.sql +66 -0
  19. package/modules/hall-ui/public/atlas.html +1 -1
  20. package/modules/hall-ui/public/blockers.html +1 -1
  21. package/modules/hall-ui/public/board-room.html +1 -1
  22. package/modules/hall-ui/public/city.html +1 -1
  23. package/modules/hall-ui/public/collab.html +1 -1
  24. package/modules/hall-ui/public/commands.html +1 -1
  25. package/modules/hall-ui/public/copy-desk.html +1 -1
  26. package/modules/hall-ui/public/deploy.html +1 -1
  27. package/modules/hall-ui/public/diagrams.html +1 -1
  28. package/modules/hall-ui/public/drachmae.html +1 -1
  29. package/modules/hall-ui/public/fleet.html +1 -1
  30. package/modules/hall-ui/public/gate.html +1 -1
  31. package/modules/hall-ui/public/goal-map.html +1 -1
  32. package/modules/hall-ui/public/goals.html +1 -1
  33. package/modules/hall-ui/public/government.html +1 -1
  34. package/modules/hall-ui/public/idea.html +1 -1
  35. package/modules/hall-ui/public/ideas.html +1 -1
  36. package/modules/hall-ui/public/index.html +1 -1
  37. package/modules/hall-ui/public/modules.html +1 -1
  38. package/modules/hall-ui/public/primer.html +1 -1
  39. package/modules/hall-ui/public/profile.html +1 -1
  40. package/modules/hall-ui/public/project-settings.html +1 -1
  41. package/modules/hall-ui/public/ranks.html +1 -1
  42. package/modules/hall-ui/public/roadmap.html +1 -1
  43. package/modules/hall-ui/public/roster.html +1 -1
  44. package/modules/hall-ui/public/sessions.html +1 -1
  45. package/modules/hall-ui/public/settings-usage-reports.js +96 -0
  46. package/modules/hall-ui/public/settings.html +19 -1
  47. package/modules/hall-ui/public/settings.states.json +1 -0
  48. package/modules/hall-ui/public/shell.js +61 -29
  49. package/modules/hall-ui/public/street.html +1 -1
  50. package/modules/hall-ui/public/studio.html +1 -1
  51. package/modules/hall-ui/public/task.html +1 -1
  52. package/modules/hall-ui/public/thinking.html +1 -1
  53. package/modules/hall-ui/public/tweak-editor-lib.js +22 -3
  54. package/modules/hall-ui/public/tweak-editor.html +1 -1
  55. package/modules/hall-ui/public/watch.html +1 -1
  56. package/modules/hall-ui/public/work.html +1 -1
  57. package/modules/hall-ui/records/tweak-editor.md +1 -1
  58. package/modules/public-landing/public/projects.html +5 -5
  59. package/package-lock.json +2 -2
  60. package/package.json +1 -1
  61. package/release-notes.json +28 -0
  62. package/scripts/gds/module-assess-installs.js +143 -0
  63. package/scripts/gds/module.js +29 -5
  64. package/scripts/hall-preview/live-identity.js +1 -0
  65. package/src/bongos/github-repos.js +7 -6
  66. package/src/bongos/module-usage-reports.js +112 -0
  67. package/src/bongos/routes/modules.js +96 -0
  68. package/src/module-api.js +1 -1
  69. package/tests/github_repos_helpers.mjs +5 -5
  70. package/tests/goal_map_page.mjs +1 -1
  71. package/tests/hall_commands.mjs +1 -1
  72. package/tests/hall_nav.mjs +42 -0
  73. package/tests/hall_tweak_editor.mjs +13 -1
  74. package/tests/module_assess_installs.mjs +272 -0
  75. package/tests/module_install.mjs +3 -0
  76. package/tests/module_update.mjs +3 -0
  77. package/tests/nav_permission_atoms.mjs +1 -1
@@ -174,8 +174,9 @@ A goal created from the hall's form has only a name, a description, a version an
174
174
  - **Scope:** `POST /api/bongos/goals/<N>/scope --body '{"add":["<key>"]}'` (keys only, safe inline). The goal's owner or a manager; an Archon for a protected key.
175
175
  - **Criteria:** `POST /api/bongos/versions/<ver>/done-when` with `"goal_id":<N>`, exactly as 5b.
176
176
  - **Seed tasks:** `POST /api/bongos/tasks` with `"goal_id":<N>`, exactly as 5c. **Each one is automatically made to wait on the spec task** — do not remove that edge, and **do not promote them**: they move to `ready` by themselves the moment the spec task ships (the ordinary auto-promotion). Add their own dependency edges (5d) as usual.
177
- - **Then ship the spec task** with `/builder-ship`. That ship is what releases the goal's work. Its value summary says what the goal now owns and which tasks became claimable.
177
+ - **Then ship the spec task** with `/builder-ship`. That ship is what releases the goal's work. Its value summary says what the goal now owns and which tasks became claimable. The spec task changes no files, so `ship.js` refuses with "Nothing to ship"; ship a `source: goal-spec` task with `--allow-empty` (only that kind of task) (the dry run in task 1004618 confirmed the seed tasks then move to `ready`).
178
178
  7. **If you do not own or manage the goal,** the scope and criteria writes are refused (403 / `400 bad_goal_id`, see above). Do not work around it: send the drafted scope, criteria and task table to the goal's owner (`/ask-for-help` naming them, or paste it on the spec task), file the seed tasks you are allowed to file, and leave the spec task claimed until the owner has written the rest. A spec task shipped with no scope and no criteria releases a goal that is still undefined, which is the state this task exists to prevent.
179
+ 8. **Making the goal on a version that is already `building`:** `POST /goals` returns `409 version_not_planning`. An Archon can admit the goal with `admit_reason`; anyone else asks an Archon or scopes it onto the planning version.
179
180
 
180
181
  ## The sibling advisory: `dependency_advisory` (task 1002827)
181
182
 
@@ -5,7 +5,7 @@ A **generated**, zero-dependency typed client for the Bongos API — produced fr
5
5
  by hand; it regenerates when the spec changes, so it can never drift from the routes.
6
6
 
7
7
  - API version: **v1** (served at `/api/bongos/v1`)
8
- - 527 operations across 75 resource groups
8
+ - 531 operations across 75 resource groups
9
9
 
10
10
  ## Use it from your project
11
11
 
@@ -1163,14 +1163,22 @@ function createClient(opts = {}) {
1163
1163
  getStoreModulesKeyEntitlement: (args) => request("GET", "/store/modules/{key}/entitlement", { hasBody: false }, args),
1164
1164
  // POST /store/modules/{key}/versions — rank: metic+archon — POST /store/modules/:key/versions
1165
1165
  postStoreModulesKeyVersions: (args) => request("POST", "/store/modules/{key}/versions", { hasBody: true }, args),
1166
+ // POST /store/modules/{key}/versions/{version}/error-count — rank: any-builder — POST /store/modules/:key/versions/:version/error-count
1167
+ postStoreModulesKeyVersionsVersionErrorCount: (args) => request("POST", "/store/modules/{key}/versions/{version}/error-count", { hasBody: true }, args),
1166
1168
  // GET /store/modules/{key}/versions/{version}/howto — rank: any-builder — GET /store/modules/:key/versions/:version/howto
1167
1169
  getStoreModulesKeyVersionsVersionHowto: (args) => request("GET", "/store/modules/{key}/versions/{version}/howto", { hasBody: false }, args),
1170
+ // POST /store/modules/{key}/versions/{version}/install-report — rank: any-builder — POST /store/modules/:key/versions/:version/install-report
1171
+ postStoreModulesKeyVersionsVersionInstallReport: (args) => request("POST", "/store/modules/{key}/versions/{version}/install-report", { hasBody: true }, args),
1168
1172
  // POST /store/modules/{key}/versions/{version}/reassess — rank: metic+archon — POST /store/modules/:key/versions/:version/reassess
1169
1173
  postStoreModulesKeyVersionsVersionReassess: (args) => request("POST", "/store/modules/{key}/versions/{version}/reassess", { hasBody: true }, args),
1170
1174
  // GET /store/modules/{key}/versions/{version}/tarball — rank: any-builder — GET /store/modules/:key/versions/:version/tarball
1171
1175
  getStoreModulesKeyVersionsVersionTarball: (args) => request("GET", "/store/modules/{key}/versions/{version}/tarball", { hasBody: false }, args),
1172
1176
  // GET /store/modules/latest — rank: any-builder — GET /store/modules/latest
1173
1177
  getStoreModulesLatest: (args) => request("GET", "/store/modules/latest", { hasBody: false }, args),
1178
+ // GET /store/usage-reporting — rank: any-builder — GET /store/usage-reporting
1179
+ getStoreUsageReporting: (args) => request("GET", "/store/usage-reporting", { hasBody: false }, args),
1180
+ // POST /store/usage-reporting — rank: any-builder — POST /store/usage-reporting
1181
+ postStoreUsageReporting: (args) => request("POST", "/store/usage-reporting", { hasBody: true }, args),
1174
1182
  },
1175
1183
  "taskRecommendations": {
1176
1184
  // POST /task-recommendations — rank: any-builder — POST /task-recommendations
@@ -1162,14 +1162,22 @@ function createClient(opts = {}) {
1162
1162
  getStoreModulesKeyEntitlement: (args) => request("GET", "/store/modules/{key}/entitlement", { hasBody: false }, args),
1163
1163
  // POST /store/modules/{key}/versions — rank: metic+archon — POST /store/modules/:key/versions
1164
1164
  postStoreModulesKeyVersions: (args) => request("POST", "/store/modules/{key}/versions", { hasBody: true }, args),
1165
+ // POST /store/modules/{key}/versions/{version}/error-count — rank: any-builder — POST /store/modules/:key/versions/:version/error-count
1166
+ postStoreModulesKeyVersionsVersionErrorCount: (args) => request("POST", "/store/modules/{key}/versions/{version}/error-count", { hasBody: true }, args),
1165
1167
  // GET /store/modules/{key}/versions/{version}/howto — rank: any-builder — GET /store/modules/:key/versions/:version/howto
1166
1168
  getStoreModulesKeyVersionsVersionHowto: (args) => request("GET", "/store/modules/{key}/versions/{version}/howto", { hasBody: false }, args),
1169
+ // POST /store/modules/{key}/versions/{version}/install-report — rank: any-builder — POST /store/modules/:key/versions/:version/install-report
1170
+ postStoreModulesKeyVersionsVersionInstallReport: (args) => request("POST", "/store/modules/{key}/versions/{version}/install-report", { hasBody: true }, args),
1167
1171
  // POST /store/modules/{key}/versions/{version}/reassess — rank: metic+archon — POST /store/modules/:key/versions/:version/reassess
1168
1172
  postStoreModulesKeyVersionsVersionReassess: (args) => request("POST", "/store/modules/{key}/versions/{version}/reassess", { hasBody: true }, args),
1169
1173
  // GET /store/modules/{key}/versions/{version}/tarball — rank: any-builder — GET /store/modules/:key/versions/:version/tarball
1170
1174
  getStoreModulesKeyVersionsVersionTarball: (args) => request("GET", "/store/modules/{key}/versions/{version}/tarball", { hasBody: false }, args),
1171
1175
  // GET /store/modules/latest — rank: any-builder — GET /store/modules/latest
1172
1176
  getStoreModulesLatest: (args) => request("GET", "/store/modules/latest", { hasBody: false }, args),
1177
+ // GET /store/usage-reporting — rank: any-builder — GET /store/usage-reporting
1178
+ getStoreUsageReporting: (args) => request("GET", "/store/usage-reporting", { hasBody: false }, args),
1179
+ // POST /store/usage-reporting — rank: any-builder — POST /store/usage-reporting
1180
+ postStoreUsageReporting: (args) => request("POST", "/store/usage-reporting", { hasBody: true }, args),
1173
1181
  },
1174
1182
  "taskRecommendations": {
1175
1183
  // POST /task-recommendations — rank: any-builder — POST /task-recommendations
@@ -180,6 +180,7 @@ export interface GetSsoPubkeyResponse { alg: unknown; format: unknown; public_ke
180
180
  export interface GetStoreEntitlementsResponse { entitlements: unknown }
181
181
  export interface GetStoreModulesKeyVersionsVersionHowtoResponse { module_key: unknown; title: unknown; version: unknown; published_at: unknown; delisted: unknown; markdown: unknown; artifact_url: unknown }
182
182
  export interface GetStoreModulesLatestResponse { latest: unknown }
183
+ export interface GetStoreUsageReportingResponse { enabled: unknown }
183
184
  export interface GetTaskRecommendationsForMeResponse { recommendations: unknown; count: unknown }
184
185
  export interface GetTaskRecommendationsMineResponse { recommendations: unknown; count: unknown }
185
186
  export interface GetTasksClaimableResponse { claimable: unknown; claimable_total: unknown; active_claims: unknown }
@@ -517,8 +518,12 @@ export interface PostStoreModulesKeyAcquiredResponse { ok: boolean; entitlement:
517
518
  export interface PostStoreModulesKeyDelistRequest { reason?: string }
518
519
  export interface PostStoreModulesKeyDelistResponse { ok: boolean; module_key: unknown; status: unknown; delisted_at: unknown }
519
520
  export interface PostStoreModulesKeyVersionsResponse { ok: boolean; created_module: unknown; version: unknown }
521
+ export interface PostStoreModulesKeyVersionsVersionErrorCountRequest { day: string; count: number }
522
+ export interface PostStoreModulesKeyVersionsVersionInstallReportRequest { ok: boolean; error_code?: string }
520
523
  export interface PostStoreModulesKeyVersionsVersionReassessRequest { reason?: string }
521
524
  export interface PostStoreModulesKeyVersionsVersionReassessResponse { ok: boolean; queued: boolean; module_key: unknown; version: unknown; version_id: unknown }
525
+ export interface PostStoreUsageReportingRequest { enabled: boolean }
526
+ export interface PostStoreUsageReportingResponse { ok: boolean; enabled: unknown }
522
527
  export interface PostTaskRecommendationsRequest { task_id: number; recommended_to: number; reason: string }
523
528
  export interface PostTaskRecommendationsResponse { ok: boolean; recommendation: unknown }
524
529
  export interface PostTasksIdAttestGateRequest { head_sha: string }
@@ -1664,14 +1669,22 @@ export interface BongosClient {
1664
1669
  getStoreModulesKeyEntitlement(args?: RequestArgs): Promise<ApiResponse>;
1665
1670
  /** POST /store/modules/{key}/versions — rank: metic+archon */
1666
1671
  postStoreModulesKeyVersions(args?: RequestArgs): Promise<PostStoreModulesKeyVersionsResponse>;
1672
+ /** POST /store/modules/{key}/versions/{version}/error-count — rank: any-builder */
1673
+ postStoreModulesKeyVersionsVersionErrorCount(args: RequestArgs & { body: PostStoreModulesKeyVersionsVersionErrorCountRequest }): Promise<ApiResponse>;
1667
1674
  /** GET /store/modules/{key}/versions/{version}/howto — rank: any-builder */
1668
1675
  getStoreModulesKeyVersionsVersionHowto(args?: RequestArgs): Promise<GetStoreModulesKeyVersionsVersionHowtoResponse>;
1676
+ /** POST /store/modules/{key}/versions/{version}/install-report — rank: any-builder */
1677
+ postStoreModulesKeyVersionsVersionInstallReport(args: RequestArgs & { body: PostStoreModulesKeyVersionsVersionInstallReportRequest }): Promise<ApiResponse>;
1669
1678
  /** POST /store/modules/{key}/versions/{version}/reassess — rank: metic+archon */
1670
1679
  postStoreModulesKeyVersionsVersionReassess(args?: RequestArgs & { body?: PostStoreModulesKeyVersionsVersionReassessRequest }): Promise<PostStoreModulesKeyVersionsVersionReassessResponse>;
1671
1680
  /** GET /store/modules/{key}/versions/{version}/tarball — rank: any-builder */
1672
1681
  getStoreModulesKeyVersionsVersionTarball(args?: RequestArgs): Promise<ApiResponse>;
1673
1682
  /** GET /store/modules/latest — rank: any-builder */
1674
1683
  getStoreModulesLatest(args?: RequestArgs): Promise<GetStoreModulesLatestResponse>;
1684
+ /** GET /store/usage-reporting — rank: any-builder */
1685
+ getStoreUsageReporting(args?: RequestArgs): Promise<GetStoreUsageReportingResponse>;
1686
+ /** POST /store/usage-reporting — rank: any-builder */
1687
+ postStoreUsageReporting(args: RequestArgs & { body: PostStoreUsageReportingRequest }): Promise<PostStoreUsageReportingResponse>;
1675
1688
  };
1676
1689
  "taskRecommendations": {
1677
1690
  /** POST /task-recommendations — rank: any-builder */
@@ -1159,14 +1159,22 @@ export function createClient(opts = {}) {
1159
1159
  getStoreModulesKeyEntitlement: (args) => request("GET", "/store/modules/{key}/entitlement", { hasBody: false }, args),
1160
1160
  // POST /store/modules/{key}/versions — rank: metic+archon — POST /store/modules/:key/versions
1161
1161
  postStoreModulesKeyVersions: (args) => request("POST", "/store/modules/{key}/versions", { hasBody: true }, args),
1162
+ // POST /store/modules/{key}/versions/{version}/error-count — rank: any-builder — POST /store/modules/:key/versions/:version/error-count
1163
+ postStoreModulesKeyVersionsVersionErrorCount: (args) => request("POST", "/store/modules/{key}/versions/{version}/error-count", { hasBody: true }, args),
1162
1164
  // GET /store/modules/{key}/versions/{version}/howto — rank: any-builder — GET /store/modules/:key/versions/:version/howto
1163
1165
  getStoreModulesKeyVersionsVersionHowto: (args) => request("GET", "/store/modules/{key}/versions/{version}/howto", { hasBody: false }, args),
1166
+ // POST /store/modules/{key}/versions/{version}/install-report — rank: any-builder — POST /store/modules/:key/versions/:version/install-report
1167
+ postStoreModulesKeyVersionsVersionInstallReport: (args) => request("POST", "/store/modules/{key}/versions/{version}/install-report", { hasBody: true }, args),
1164
1168
  // POST /store/modules/{key}/versions/{version}/reassess — rank: metic+archon — POST /store/modules/:key/versions/:version/reassess
1165
1169
  postStoreModulesKeyVersionsVersionReassess: (args) => request("POST", "/store/modules/{key}/versions/{version}/reassess", { hasBody: true }, args),
1166
1170
  // GET /store/modules/{key}/versions/{version}/tarball — rank: any-builder — GET /store/modules/:key/versions/:version/tarball
1167
1171
  getStoreModulesKeyVersionsVersionTarball: (args) => request("GET", "/store/modules/{key}/versions/{version}/tarball", { hasBody: false }, args),
1168
1172
  // GET /store/modules/latest — rank: any-builder — GET /store/modules/latest
1169
1173
  getStoreModulesLatest: (args) => request("GET", "/store/modules/latest", { hasBody: false }, args),
1174
+ // GET /store/usage-reporting — rank: any-builder — GET /store/usage-reporting
1175
+ getStoreUsageReporting: (args) => request("GET", "/store/usage-reporting", { hasBody: false }, args),
1176
+ // POST /store/usage-reporting — rank: any-builder — POST /store/usage-reporting
1177
+ postStoreUsageReporting: (args) => request("POST", "/store/usage-reporting", { hasBody: true }, args),
1170
1178
  },
1171
1179
  "taskRecommendations": {
1172
1180
  // POST /task-recommendations — rank: any-builder — POST /task-recommendations
@@ -4,6 +4,7 @@
4
4
  - **Date:** 2026-08-04
5
5
  - **Deciders:** the owner chose the credential approach after being shown the trade-off; Claude diagnosed + built.
6
6
  - **Amends:** [ADR 0143](0143-onboarding-repo-picker-oauth-scope.md) §1 (its Decision 1 — scope choice). 0143 otherwise stands unchanged: opt-in per sign-in, lazy consent, encrypted short-TTL token store, personal repos only, 503-degrade. Per 0143's own append-only rule, this is a new ADR, not an edit.
7
+ - **Superseded in part by:** [ADR 0370](0370-a-repo-we-create-is-private.md) — Decision 3 (a repo we create stays public) is reversed: a repo we create is private.
7
8
  - **Related:** [ADR 0121](0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md) (greenfield vs brownfield onboarding).
8
9
 
9
10
  ## Context
@@ -0,0 +1,29 @@
1
+ # ADR 0370 — A repo we create for a new project is private
2
+
3
+ - **Status:** accepted
4
+ - **Date:** 2026-10-08
5
+ - **Task:** [task 1004645](https://cloudbongos.com/builders#/task/1004645) (goal 1000106, BONGOS-V2)
6
+ - **Supersedes:** [ADR 0155](0155-adopt-private-repo-widen-oauth-scope.md) Decision 3 ("a repo *we* create stays public"). The rest of 0155 stands.
7
+ - **Builds on:** [ADR 0176](0176-private-repo-deploy-keys.md) (a private target repo gets its own read-only deploy key before the first pull)
8
+ - **Decided with:** the owner, 2026-10-08: the public default is a major security issue, and the default must be private.
9
+
10
+ ## Context
11
+
12
+ When the create wizard makes a new GitHub repository for a project, `createUserRepo` (`src/bongos/github-repos.js`) sent `private: false`. ADR 0155 kept that on purpose: a Cloud Bongos instance was meant to be open source by design, and an owner who wanted private code had to make the repo on GitHub themselves and adopt it.
13
+
14
+ That put every new project's code on the public internet from its first push, without the owner ever choosing it. A first-time owner does not know to take the side door. Anything they commit by mistake, such as a key, a customer file or unreleased work, is world-readable and may already be copied before they notice.
15
+
16
+ The reason the public default was once forced has gone. ADR 0155 widened the token to `repo`, which can create a private repo. ADR 0176 taught provisioning to stand up a private repo: `ensurePrivateRepoAccess` registers the project's own read-only deploy key right after the scaffold push and before the first `git pull`. The greenfield push already uses the owner's token over HTTPS. The owner creates the repo in their own account, so they are its admin, which is what registering a deploy key needs.
17
+
18
+ ## Decision
19
+
20
+ 1. **`createUserRepo` sends `private: true`.** It is still not a parameter, so nothing can flip it by accident. The unit test pins `true` exactly; a dropped field would fall back to GitHub's own public default and red the test.
21
+ 2. **The wizard says so.** The "A new repo" choice reads "Private, set up for you", and the name field's hint says the new repo is private and can be made public later.
22
+ 3. **Going public stays the owner's choice.** The manage page's repo-visibility control (`makeRepoPublic`) is unchanged.
23
+
24
+ ## Consequences
25
+
26
+ - A new project's code is private unless its owner makes it public.
27
+ - Every new cloud-hosted project now takes the private standup path: one extra deploy key per project, registered on the owner's repo. That path has run on adopted private repos since ADR 0176.
28
+ - Projects created before this change keep their public repos. Nothing flips an existing repo.
29
+ - An instance that wants to be open source now makes that choice on the manage page instead of getting it by default.
@@ -488,3 +488,4 @@ These 20 numbers are each shared by exactly two files. They are **accepted histo
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
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 |
490
490
  | 0369 | [**Ship mode decides who starts a ship, not how it lands** ([task 1004628](https://cloudbongos.com/builders#/task/1004628), goal 1000106). **D1:** a `ship.mode` project setting, `auto` (the AI ships and lands a finished task with no commands) or `manual` (a person approves each ship), in `project_settings` with no migration. **D2:** Auto is the default, and the resolver reports whether anyone has chosen. **D3:** it is separate from deploy mode (`config/deploy.json`), which decides how a land happens. **D4:** any builder can read it (the AI must know), and `project.settings.manage` writes it, from the settings page or `bongos ship-mode`.](0369-ship-mode-decides-who-starts-a-ship-not-how-it-lands.md) | lifecycle / shipping / project settings |
491
+ | 0370 | [**A repo we create for a new project is private** ([task 1004645](https://cloudbongos.com/builders#/task/1004645), goal 1000106). Supersedes ADR 0155 Decision 3: `createUserRepo` sends `private: true`, still not a parameter, and the wizard says the new repo is private. Safe because ADR 0176 already gives a private repo its own read-only deploy key before the first pull; the owner can make it public from the manage page.](0370-a-repo-we-create-is-private.md) | onboarding / security / github |
@@ -21904,6 +21904,71 @@
21904
21904
  ]
21905
21905
  }
21906
21906
  },
21907
+ "/store/modules/{key}/versions/{version}/error-count": {
21908
+ "post": {
21909
+ "operationId": "post_store_modules_key_versions_version_error_count",
21910
+ "tags": [
21911
+ "store"
21912
+ ],
21913
+ "summary": "POST /store/modules/:key/versions/:version/error-count",
21914
+ "description": "**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
21915
+ "x-rank": "any-builder",
21916
+ "x-source": "src/bongos/routes/modules.js",
21917
+ "parameters": [
21918
+ {
21919
+ "name": "key",
21920
+ "in": "path",
21921
+ "required": true,
21922
+ "schema": {
21923
+ "type": "string"
21924
+ },
21925
+ "description": "Path parameter `key`."
21926
+ },
21927
+ {
21928
+ "name": "version",
21929
+ "in": "path",
21930
+ "required": true,
21931
+ "schema": {
21932
+ "type": "string"
21933
+ },
21934
+ "description": "Path parameter `version`."
21935
+ }
21936
+ ],
21937
+ "requestBody": {
21938
+ "required": true,
21939
+ "content": {
21940
+ "application/json": {
21941
+ "schema": {
21942
+ "$ref": "#/components/schemas/PostStoreModulesKeyVersionsVersionErrorCountRequest"
21943
+ }
21944
+ }
21945
+ },
21946
+ "x-validated": true
21947
+ },
21948
+ "responses": {
21949
+ "200": {
21950
+ "description": "Success."
21951
+ },
21952
+ "400": {
21953
+ "$ref": "#/components/responses/ValidationFailed"
21954
+ },
21955
+ "401": {
21956
+ "$ref": "#/components/responses/Unauthorized"
21957
+ },
21958
+ "403": {
21959
+ "$ref": "#/components/responses/Forbidden"
21960
+ },
21961
+ "404": {
21962
+ "$ref": "#/components/responses/NotFound"
21963
+ }
21964
+ },
21965
+ "security": [
21966
+ {
21967
+ "builderSession": []
21968
+ }
21969
+ ]
21970
+ }
21971
+ },
21907
21972
  "/store/modules/{key}/versions/{version}/howto": {
21908
21973
  "get": {
21909
21974
  "operationId": "get_store_modules_key_versions_version_howto",
@@ -21965,6 +22030,71 @@
21965
22030
  ]
21966
22031
  }
21967
22032
  },
22033
+ "/store/modules/{key}/versions/{version}/install-report": {
22034
+ "post": {
22035
+ "operationId": "post_store_modules_key_versions_version_install_report",
22036
+ "tags": [
22037
+ "store"
22038
+ ],
22039
+ "summary": "POST /store/modules/:key/versions/:version/install-report",
22040
+ "description": "**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
22041
+ "x-rank": "any-builder",
22042
+ "x-source": "src/bongos/routes/modules.js",
22043
+ "parameters": [
22044
+ {
22045
+ "name": "key",
22046
+ "in": "path",
22047
+ "required": true,
22048
+ "schema": {
22049
+ "type": "string"
22050
+ },
22051
+ "description": "Path parameter `key`."
22052
+ },
22053
+ {
22054
+ "name": "version",
22055
+ "in": "path",
22056
+ "required": true,
22057
+ "schema": {
22058
+ "type": "string"
22059
+ },
22060
+ "description": "Path parameter `version`."
22061
+ }
22062
+ ],
22063
+ "requestBody": {
22064
+ "required": true,
22065
+ "content": {
22066
+ "application/json": {
22067
+ "schema": {
22068
+ "$ref": "#/components/schemas/PostStoreModulesKeyVersionsVersionInstallReportRequest"
22069
+ }
22070
+ }
22071
+ },
22072
+ "x-validated": true
22073
+ },
22074
+ "responses": {
22075
+ "200": {
22076
+ "description": "Success."
22077
+ },
22078
+ "400": {
22079
+ "$ref": "#/components/responses/ValidationFailed"
22080
+ },
22081
+ "401": {
22082
+ "$ref": "#/components/responses/Unauthorized"
22083
+ },
22084
+ "403": {
22085
+ "$ref": "#/components/responses/Forbidden"
22086
+ },
22087
+ "404": {
22088
+ "$ref": "#/components/responses/NotFound"
22089
+ }
22090
+ },
22091
+ "security": [
22092
+ {
22093
+ "builderSession": []
22094
+ }
22095
+ ]
22096
+ }
22097
+ },
21968
22098
  "/store/modules/{key}/versions/{version}/reassess": {
21969
22099
  "post": {
21970
22100
  "operationId": "post_store_modules_key_versions_version_reassess",
@@ -22094,6 +22224,91 @@
22094
22224
  ]
22095
22225
  }
22096
22226
  },
22227
+ "/store/usage-reporting": {
22228
+ "get": {
22229
+ "operationId": "get_store_usage_reporting",
22230
+ "tags": [
22231
+ "store"
22232
+ ],
22233
+ "summary": "GET /store/usage-reporting",
22234
+ "description": "The caller's own reporting switch (Settings → Profile and privacy). On unless they turned it off.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
22235
+ "x-rank": "any-builder",
22236
+ "x-source": "src/bongos/routes/modules.js",
22237
+ "responses": {
22238
+ "200": {
22239
+ "description": "Success.",
22240
+ "content": {
22241
+ "application/json": {
22242
+ "schema": {
22243
+ "$ref": "#/components/schemas/GetStoreUsageReportingResponse"
22244
+ }
22245
+ }
22246
+ }
22247
+ },
22248
+ "400": {
22249
+ "$ref": "#/components/responses/BadRequest"
22250
+ },
22251
+ "401": {
22252
+ "$ref": "#/components/responses/Unauthorized"
22253
+ },
22254
+ "403": {
22255
+ "$ref": "#/components/responses/Forbidden"
22256
+ }
22257
+ },
22258
+ "security": [
22259
+ {
22260
+ "builderSession": []
22261
+ }
22262
+ ]
22263
+ },
22264
+ "post": {
22265
+ "operationId": "post_store_usage_reporting",
22266
+ "tags": [
22267
+ "store"
22268
+ ],
22269
+ "summary": "POST /store/usage-reporting",
22270
+ "description": "**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
22271
+ "x-rank": "any-builder",
22272
+ "x-source": "src/bongos/routes/modules.js",
22273
+ "requestBody": {
22274
+ "required": true,
22275
+ "content": {
22276
+ "application/json": {
22277
+ "schema": {
22278
+ "$ref": "#/components/schemas/PostStoreUsageReportingRequest"
22279
+ }
22280
+ }
22281
+ },
22282
+ "x-validated": true
22283
+ },
22284
+ "responses": {
22285
+ "200": {
22286
+ "description": "Success.",
22287
+ "content": {
22288
+ "application/json": {
22289
+ "schema": {
22290
+ "$ref": "#/components/schemas/PostStoreUsageReportingResponse"
22291
+ }
22292
+ }
22293
+ }
22294
+ },
22295
+ "400": {
22296
+ "$ref": "#/components/responses/ValidationFailed"
22297
+ },
22298
+ "401": {
22299
+ "$ref": "#/components/responses/Unauthorized"
22300
+ },
22301
+ "403": {
22302
+ "$ref": "#/components/responses/Forbidden"
22303
+ }
22304
+ },
22305
+ "security": [
22306
+ {
22307
+ "builderSession": []
22308
+ }
22309
+ ]
22310
+ }
22311
+ },
22097
22312
  "/task-recommendations": {
22098
22313
  "post": {
22099
22314
  "operationId": "post_task_recommendations",
@@ -27042,6 +27257,15 @@
27042
27257
  "latest"
27043
27258
  ]
27044
27259
  },
27260
+ "GetStoreUsageReportingResponse": {
27261
+ "type": "object",
27262
+ "properties": {
27263
+ "enabled": {}
27264
+ },
27265
+ "required": [
27266
+ "enabled"
27267
+ ]
27268
+ },
27045
27269
  "GetTaskRecommendationsForMeResponse": {
27046
27270
  "type": "object",
27047
27271
  "properties": {
@@ -32766,6 +32990,39 @@
32766
32990
  "version"
32767
32991
  ]
32768
32992
  },
32993
+ "PostStoreModulesKeyVersionsVersionErrorCountRequest": {
32994
+ "type": "object",
32995
+ "properties": {
32996
+ "day": {
32997
+ "type": "string",
32998
+ "maxLength": 10
32999
+ },
33000
+ "count": {
33001
+ "type": "integer"
33002
+ }
33003
+ },
33004
+ "required": [
33005
+ "day",
33006
+ "count"
33007
+ ],
33008
+ "additionalProperties": false
33009
+ },
33010
+ "PostStoreModulesKeyVersionsVersionInstallReportRequest": {
33011
+ "type": "object",
33012
+ "properties": {
33013
+ "ok": {
33014
+ "type": "boolean"
33015
+ },
33016
+ "error_code": {
33017
+ "type": "string",
33018
+ "maxLength": 40
33019
+ }
33020
+ },
33021
+ "required": [
33022
+ "ok"
33023
+ ],
33024
+ "additionalProperties": false
33025
+ },
32769
33026
  "PostStoreModulesKeyVersionsVersionReassessRequest": {
32770
33027
  "type": "object",
32771
33028
  "properties": {
@@ -32797,6 +33054,31 @@
32797
33054
  "version_id"
32798
33055
  ]
32799
33056
  },
33057
+ "PostStoreUsageReportingRequest": {
33058
+ "type": "object",
33059
+ "properties": {
33060
+ "enabled": {
33061
+ "type": "boolean"
33062
+ }
33063
+ },
33064
+ "required": [
33065
+ "enabled"
33066
+ ],
33067
+ "additionalProperties": false
33068
+ },
33069
+ "PostStoreUsageReportingResponse": {
33070
+ "type": "object",
33071
+ "properties": {
33072
+ "ok": {
33073
+ "type": "boolean"
33074
+ },
33075
+ "enabled": {}
33076
+ },
33077
+ "required": [
33078
+ "ok",
33079
+ "enabled"
33080
+ ]
33081
+ },
32800
33082
  "PostTaskRecommendationsRequest": {
32801
33083
  "type": "object",
32802
33084
  "properties": {
@@ -33825,9 +34107,9 @@
33825
34107
  "description": "A required dependency/feature is not configured or is temporarily down."
33826
34108
  }
33827
34109
  },
33828
- "x-endpoint-count": 527,
33829
- "x-schema-count": 568,
34110
+ "x-endpoint-count": 531,
34111
+ "x-schema-count": 573,
33830
34112
  "x-undocumented-bodies": 12,
33831
- "x-response-schemas": 377,
34113
+ "x-response-schemas": 379,
33832
34114
  "x-generated-by": "scripts/gds/gen-api-docs.js"
33833
34115
  }
@@ -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. 527 endpoints across 93 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 531 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`.
@@ -815,7 +815,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
815
815
  | GET | `/api/bongos/sso/pubkey` | `public` | — | GET /sso/pubkey — the hub's Ed25519 assertion-verification key (public). |
816
816
  | POST | `/api/bongos/sso/token` | `public` | `client_id`, `client_secret`, `code`, `redirect_uri` | POST /sso/token — server-to-server code redemption. |
817
817
 
818
- ## `store` (11)
818
+ ## `store` (15)
819
819
 
820
820
  | Method | Path | Rank | Body | Description |
821
821
  |---|---|---|---|---|
@@ -826,10 +826,14 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust
826
826
  | POST | `/api/bongos/store/modules/:key/delist` | `metic+archon` | `reason` | POST /api/bongos/store/modules/:key/delist — a Metic+ person takes a module out of the store (task 1003797, ADR 0338 D2). |
827
827
  | GET | `/api/bongos/store/modules/:key/entitlement` | `any-builder` | — | |
828
828
  | POST | `/api/bongos/store/modules/:key/versions` | `metic+archon` | _undocumented_ | POST /api/bongos/store/modules/:key/versions — publish one module version to the store (task 1004271, ADR 0338 D1). |
829
+ | POST | `/api/bongos/store/modules/:key/versions/:version/error-count` | `any-builder` | `day`, `count` | |
829
830
  | GET | `/api/bongos/store/modules/:key/versions/:version/howto` | `any-builder` | — | GET /api/bongos/store/modules/:key/versions/:version/howto — the how-to a version shipped with (task 1004366, ADR 0347 D1/D3), read from … |
831
+ | POST | `/api/bongos/store/modules/:key/versions/:version/install-report` | `any-builder` | `ok`, `error_code` | |
830
832
  | POST | `/api/bongos/store/modules/:key/versions/:version/reassess` | `metic+archon` | `reason` | POST /api/bongos/store/modules/:key/versions/:version/reassess — a Metic+ person asks for a published version's assessment to run again: … |
831
833
  | GET | `/api/bongos/store/modules/:key/versions/:version/tarball` | `any-builder` | — | |
832
834
  | GET | `/api/bongos/store/modules/latest` | `any-builder` | — | The newest published version of each named module — what `bongos upgrade` compares an instance's installed store modules against to repor… |
835
+ | GET | `/api/bongos/store/usage-reporting` | `any-builder` | — | The caller's own reporting switch (Settings → Profile and privacy). |
836
+ | POST | `/api/bongos/store/usage-reporting` | `any-builder` | `enabled` | |
833
837
 
834
838
  ## `task-recommendations` (4)
835
839