@bongos/core 1.17.0 → 1.17.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 (90) hide show
  1. package/.bongos-core.json +154 -83
  2. package/CLAUDE.md +11 -238
  3. package/bin/bongos.js +1 -0
  4. package/clients/bongos-client/README.md +4 -4
  5. package/clients/bongos-client/bongos-client.global.js +14 -1
  6. package/clients/bongos-client/index.cjs +14 -1
  7. package/clients/bongos-client/index.d.ts +19 -2
  8. package/clients/bongos-client/index.mjs +11 -1
  9. package/clients/bongos-client/package.json +1 -1
  10. package/docs/adr/0133-github-app-manifest-onboarding-signin.md +2 -0
  11. package/docs/adr/0134-private-first-npm-distribution.md +20 -6
  12. package/docs/adr/0135-module-upstream-submission-interim-queue.md +34 -0
  13. package/docs/adr/README.md +5 -4
  14. package/docs/api/openapi.json +315 -6
  15. package/docs/api-reference.md +10 -5
  16. package/docs/architecture.md +1 -1
  17. package/docs/file-map.md +2 -2
  18. package/docs/modules-contract.md +2 -0
  19. package/docs/recipes/instance-deploy.md +4 -4
  20. package/docs/recipes/instance-first-run.md +51 -0
  21. package/docs/recipes/packaging-the-core.md +5 -5
  22. package/docs/recipes/private-npm-distribution.md +22 -12
  23. package/docs/recipes/self-host.md +1 -1
  24. package/docs/recipes/upgrading-the-core.md +8 -8
  25. package/migrations/core_191_module_submissions.sql +45 -0
  26. package/modules/autonomy/CLAUDE.md +11 -45
  27. package/modules/builder-settings/CLAUDE.md +11 -54
  28. package/modules/dev-box/CLAUDE.md +11 -34
  29. package/modules/discord/CLAUDE.md +11 -46
  30. package/modules/economy/CLAUDE.md +11 -44
  31. package/modules/grading/CLAUDE.md +11 -38
  32. package/modules/hall-ui/CLAUDE.md +11 -57
  33. package/modules/hall-ui/public/goals-page.js +227 -22
  34. package/modules/hall-ui/public/goals.html +16 -0
  35. package/modules/hall-ui/public/new-project-wizard.js +5 -4
  36. package/modules/ideas/CLAUDE.md +11 -33
  37. package/modules/lifecycle/CLAUDE.md +11 -59
  38. package/modules/lifecycle/routes/goals.js +80 -0
  39. package/modules/memory/CLAUDE.md +11 -36
  40. package/modules/onboarding/CLAUDE.md +11 -51
  41. package/modules/security/CLAUDE.md +11 -40
  42. package/modules/sessions/CLAUDE.md +11 -35
  43. package/modules/status-ui/CLAUDE.md +11 -43
  44. package/package-lock.json +2 -2
  45. package/package.json +1 -1
  46. package/public-landing/create.html +58 -12
  47. package/public-landing/index.html +40 -21
  48. package/scripts/gds/CLAUDE.md +11 -140
  49. package/scripts/gds/claude-materialize.js +151 -18
  50. package/scripts/gds/claude-md-template.js +84 -0
  51. package/scripts/gds/cli-lib.js +112 -2
  52. package/scripts/gds/gen-api-client.js +10 -10
  53. package/scripts/gds/init.js +53 -13
  54. package/scripts/gds/migration-namespace.js +1 -1
  55. package/scripts/gds/module.js +118 -4
  56. package/scripts/gds/npmrc.js +93 -0
  57. package/scripts/gds/onboard.js +13 -24
  58. package/scripts/gds/package-core.js +56 -14
  59. package/scripts/gds/provision.js +102 -17
  60. package/scripts/gds/seed-adopt-tasks.js +1 -1
  61. package/scripts/gds/status.js +6 -1
  62. package/scripts/gds/task.js +166 -0
  63. package/scripts/gds/upgrade.js +58 -18
  64. package/src/bongos/CLAUDE.md +11 -60
  65. package/src/bongos/auth.js +11 -0
  66. package/src/bongos/module-submissions.js +56 -0
  67. package/src/bongos/route-rank-check.js +6 -0
  68. package/src/bongos/routes/CLAUDE.md +11 -39
  69. package/src/bongos/routes/auth.js +6 -1
  70. package/src/bongos/routes/modules.js +123 -21
  71. package/src/instance-config.js +1 -1
  72. package/src/module-api.js +13 -1
  73. package/tests/claude_materialize.mjs +105 -0
  74. package/tests/device_flow_start.mjs +73 -0
  75. package/tests/first_run_engine_check.mjs +79 -0
  76. package/tests/goal_membership_requests.mjs +33 -3
  77. package/tests/hook_user_agents.mjs +62 -0
  78. package/tests/init.mjs +59 -6
  79. package/tests/instance_mismatch_guard.mjs +101 -0
  80. package/tests/module_cli.mjs +130 -2
  81. package/tests/module_submissions.mjs +135 -0
  82. package/tests/npmrc.mjs +105 -0
  83. package/tests/onboard.mjs +49 -0
  84. package/tests/package_core.mjs +68 -22
  85. package/tests/platform_boot.mjs +5 -2
  86. package/tests/provision.mjs +107 -8
  87. package/tests/provisioning_github_app_routes.mjs +29 -2
  88. package/tests/served_paths_shipped.mjs +2 -2
  89. package/tests/task_cli.mjs +99 -0
  90. package/tests/upgrade.mjs +89 -25
@@ -4281,6 +4281,56 @@
4281
4281
  }
4282
4282
  },
4283
4283
  "/goals/{id}/requests": {
4284
+ "get": {
4285
+ "operationId": "get_goals_id_requests",
4286
+ "tags": [
4287
+ "goals"
4288
+ ],
4289
+ "summary": "GET /goals/:id/requests",
4290
+ "description": "GET /goals/:id/requests — the goal's own pending invite/join-request queue (task 1953): every pending row on THIS goal, both kinds — outstanding invites the goal has sent (awaiting the invitee) and join-requests awaiting approval. db.listPendingRequestsForGoal was built for this route in task 1952's landing but never wired to HTTP; this is the goals-page manager view alongside the cross-goal GET /goals/inbox. rank: any-builder (requireBuilder) + the in-handler owner|manager|Archon gate (authorizeGoalManagement) — same wall as visibility/invite/request-respond.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4291
+ "x-rank": "any-builder",
4292
+ "x-source": "modules/lifecycle/routes/goals.js",
4293
+ "parameters": [
4294
+ {
4295
+ "name": "id",
4296
+ "in": "path",
4297
+ "required": true,
4298
+ "schema": {
4299
+ "type": "string"
4300
+ },
4301
+ "description": "Path parameter `id`."
4302
+ }
4303
+ ],
4304
+ "responses": {
4305
+ "200": {
4306
+ "description": "Success.",
4307
+ "content": {
4308
+ "application/json": {
4309
+ "schema": {
4310
+ "$ref": "#/components/schemas/GetGoalsIdRequestsResponse"
4311
+ }
4312
+ }
4313
+ }
4314
+ },
4315
+ "400": {
4316
+ "$ref": "#/components/responses/BadRequest"
4317
+ },
4318
+ "401": {
4319
+ "$ref": "#/components/responses/Unauthorized"
4320
+ },
4321
+ "403": {
4322
+ "$ref": "#/components/responses/Forbidden"
4323
+ },
4324
+ "404": {
4325
+ "$ref": "#/components/responses/NotFound"
4326
+ }
4327
+ },
4328
+ "security": [
4329
+ {
4330
+ "builderSession": []
4331
+ }
4332
+ ]
4333
+ },
4284
4334
  "post": {
4285
4335
  "operationId": "post_goals_id_requests",
4286
4336
  "tags": [
@@ -4415,6 +4465,67 @@
4415
4465
  ]
4416
4466
  }
4417
4467
  },
4468
+ "/goals/{id}/requests/{reqId}/withdraw": {
4469
+ "post": {
4470
+ "operationId": "post_goals_id_requests_reqId_withdraw",
4471
+ "tags": [
4472
+ "goals"
4473
+ ],
4474
+ "summary": "POST /goals/:id/requests/:reqId/withdraw",
4475
+ "description": "POST /goals/:id/requests/:reqId/withdraw — the requester cancels their OWN pending join-request (task 1953): the symmetric self-served mirror of a manager's deny. Sets status='cancelled' (kept as the audit trail, like a deny's 'rejected'); never touches an invitation row. rank: any-builder (requireBuilder) + the in-handler authorizeWithdrawJoinRequest.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4476
+ "x-rank": "any-builder",
4477
+ "x-source": "modules/lifecycle/routes/goals.js",
4478
+ "parameters": [
4479
+ {
4480
+ "name": "id",
4481
+ "in": "path",
4482
+ "required": true,
4483
+ "schema": {
4484
+ "type": "string"
4485
+ },
4486
+ "description": "Path parameter `id`."
4487
+ },
4488
+ {
4489
+ "name": "reqId",
4490
+ "in": "path",
4491
+ "required": true,
4492
+ "schema": {
4493
+ "type": "string"
4494
+ },
4495
+ "description": "Path parameter `reqId`."
4496
+ }
4497
+ ],
4498
+ "responses": {
4499
+ "200": {
4500
+ "description": "Success.",
4501
+ "content": {
4502
+ "application/json": {
4503
+ "schema": {
4504
+ "$ref": "#/components/schemas/PostGoalsIdRequestsReqIdWithdrawResponse"
4505
+ }
4506
+ }
4507
+ }
4508
+ },
4509
+ "400": {
4510
+ "$ref": "#/components/responses/BadRequest"
4511
+ },
4512
+ "401": {
4513
+ "$ref": "#/components/responses/Unauthorized"
4514
+ },
4515
+ "403": {
4516
+ "$ref": "#/components/responses/Forbidden"
4517
+ },
4518
+ "404": {
4519
+ "$ref": "#/components/responses/NotFound"
4520
+ }
4521
+ },
4522
+ "security": [
4523
+ {
4524
+ "builderSession": []
4525
+ }
4526
+ ]
4527
+ }
4528
+ },
4418
4529
  "/goals/{id}/scope": {
4419
4530
  "post": {
4420
4531
  "operationId": "post_goals_id_scope",
@@ -6586,6 +6697,44 @@
6586
6697
  ]
6587
6698
  }
6588
6699
  },
6700
+ "/modules/submissions": {
6701
+ "get": {
6702
+ "operationId": "get_modules_submissions",
6703
+ "tags": [
6704
+ "modules"
6705
+ ],
6706
+ "summary": "GET /modules/submissions",
6707
+ "description": "GET /api/gds/modules/submissions?status=&module_key= — the upstreaming review queue (task 1771 reads this). Metadata only — no file contents (a future GET .../:id can add a with-files fetch if the review UI needs it). rank: metic+archon — the review queue, same rank as filing into it.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).",
6708
+ "x-rank": "metic+archon",
6709
+ "x-source": "src/bongos/routes/modules.js",
6710
+ "responses": {
6711
+ "200": {
6712
+ "description": "Success.",
6713
+ "content": {
6714
+ "application/json": {
6715
+ "schema": {
6716
+ "$ref": "#/components/schemas/GetModulesSubmissionsResponse"
6717
+ }
6718
+ }
6719
+ }
6720
+ },
6721
+ "400": {
6722
+ "$ref": "#/components/responses/BadRequest"
6723
+ },
6724
+ "401": {
6725
+ "$ref": "#/components/responses/Unauthorized"
6726
+ },
6727
+ "403": {
6728
+ "$ref": "#/components/responses/Forbidden"
6729
+ }
6730
+ },
6731
+ "security": [
6732
+ {
6733
+ "builderSession": []
6734
+ }
6735
+ ]
6736
+ }
6737
+ },
6589
6738
  "/modules/{key}/enable": {
6590
6739
  "post": {
6591
6740
  "operationId": "post_modules_key_enable",
@@ -6656,7 +6805,7 @@
6656
6805
  "modules"
6657
6806
  ],
6658
6807
  "summary": "POST /modules/:key/submit",
6659
- "description": "the \"submit this module for review\" front door (501 until the submit pipeline, task 1770, ships).\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).",
6808
+ "description": "POST /api/gds/modules/:key/submit — ADR 0107 §1 upstreaming submission. task 1770. Body: { signed_by?: \"Name <email>\" }. Re-runs the §4 AGPL/publish pre-check + requires a DCO-style sign-off against THIS box's OWN on-disk copy of modules/:key (the authoritative check — a local `bongos module check` pass on a builder's box is a courtesy, not proof, if the module's changes aren't committed + shipped + deployed here yet). signed_by records a NEW sign-off only if none is on file; an existing .upstream-signoff.json is reused as-is (not overwritten). rank: metic+archon — files into a shared review queue, not just a toggle for the caller.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).",
6660
6809
  "x-rank": "metic+archon",
6661
6810
  "x-source": "src/bongos/routes/modules.js",
6662
6811
  "parameters": [
@@ -6670,12 +6819,30 @@
6670
6819
  "description": "Path parameter `key`."
6671
6820
  }
6672
6821
  ],
6822
+ "requestBody": {
6823
+ "required": false,
6824
+ "content": {
6825
+ "application/json": {
6826
+ "schema": {
6827
+ "$ref": "#/components/schemas/PostModulesKeySubmitRequest"
6828
+ }
6829
+ }
6830
+ },
6831
+ "x-validated": true
6832
+ },
6673
6833
  "responses": {
6674
6834
  "200": {
6675
- "description": "Success."
6835
+ "description": "Success.",
6836
+ "content": {
6837
+ "application/json": {
6838
+ "schema": {
6839
+ "$ref": "#/components/schemas/PostModulesKeySubmitResponse"
6840
+ }
6841
+ }
6842
+ }
6676
6843
  },
6677
6844
  "400": {
6678
- "$ref": "#/components/responses/BadRequest"
6845
+ "$ref": "#/components/responses/ValidationFailed"
6679
6846
  },
6680
6847
  "401": {
6681
6848
  "$ref": "#/components/responses/Unauthorized"
@@ -6878,6 +7045,34 @@
6878
7045
  "security": []
6879
7046
  }
6880
7047
  },
7048
+ "/provisioning/github-app/status": {
7049
+ "get": {
7050
+ "operationId": "get_provisioning_github_app_status",
7051
+ "tags": [
7052
+ "provisioning"
7053
+ ],
7054
+ "summary": "GET /provisioning/github-app/status",
7055
+ "description": "GET /provisioning/github-app/status?state=<> — the PUBLIC progress read the onboarding callback page polls (task 2096) to know when setup is done + where to send the owner. Same public-by-state model as the callback: the unguessable, single-use `state` token is the only key, and the response reveals only the manifest lifecycle status + the instance's own (already-public) domain — never a secret. Per-IP rate-limited because the page polls it every ~3s. `ready` is true iff the manifest reached 'done' (creds placed + /healthz verified) — the page then auto-redirects to https://<domain>. rank: public — no session, no mutation, no secret; an unknown state is a 404 no-op.\n\n**Rank:** `public` — No authentication — any caller.",
7056
+ "x-rank": "public",
7057
+ "x-source": "modules/provisioning/routes/provisioning.js",
7058
+ "responses": {
7059
+ "200": {
7060
+ "description": "Success.",
7061
+ "content": {
7062
+ "application/json": {
7063
+ "schema": {
7064
+ "$ref": "#/components/schemas/GetProvisioningGithubAppStatusResponse"
7065
+ }
7066
+ }
7067
+ }
7068
+ },
7069
+ "400": {
7070
+ "$ref": "#/components/responses/BadRequest"
7071
+ }
7072
+ },
7073
+ "security": []
7074
+ }
7075
+ },
6881
7076
  "/provisioning/health": {
6882
7077
  "get": {
6883
7078
  "operationId": "get_provisioning_health",
@@ -7203,6 +7398,34 @@
7203
7398
  ]
7204
7399
  }
7205
7400
  },
7401
+ "/provisioning/onboard-plan": {
7402
+ "get": {
7403
+ "operationId": "get_provisioning_onboard_plan",
7404
+ "tags": [
7405
+ "provisioning"
7406
+ ],
7407
+ "summary": "GET /provisioning/onboard-plan",
7408
+ "description": "GET /provisioning/onboard-plan?mode=greenfield|adopt — the CANONICAL onboarding step sequence (task 2085; goal 35 / criterion 165: \"the canonical step sequence is the source of truth; skill/CLI/hall are forms over it\"). The branded /create page + the hall wizard fetch it so their human-steps checklist can't drift from the CLI's (scripts/gds/onboard.js reads the same modules/provisioning/onboard-plan.js). rank: public — the signed-out /create landing page reads it; it is the same public runbook the /new-project skill documents (no write, no secret).\n\n**Rank:** `public` — No authentication — any caller.",
7409
+ "x-rank": "public",
7410
+ "x-source": "modules/provisioning/routes/provisioning.js",
7411
+ "responses": {
7412
+ "200": {
7413
+ "description": "Success.",
7414
+ "content": {
7415
+ "application/json": {
7416
+ "schema": {
7417
+ "$ref": "#/components/schemas/GetProvisioningOnboardPlanResponse"
7418
+ }
7419
+ }
7420
+ }
7421
+ },
7422
+ "400": {
7423
+ "$ref": "#/components/responses/BadRequest"
7424
+ }
7425
+ },
7426
+ "security": []
7427
+ }
7428
+ },
7206
7429
  "/provisioning/tls-check": {
7207
7430
  "get": {
7208
7431
  "operationId": "get_provisioning_tls_check",
@@ -10250,6 +10473,15 @@
10250
10473
  "cross_goals_considered"
10251
10474
  ]
10252
10475
  },
10476
+ "GetGoalsIdRequestsResponse": {
10477
+ "type": "object",
10478
+ "properties": {
10479
+ "requests": {}
10480
+ },
10481
+ "required": [
10482
+ "requests"
10483
+ ]
10484
+ },
10253
10485
  "GetGoalsIdResponse": {
10254
10486
  "type": "object",
10255
10487
  "properties": {
@@ -10530,6 +10762,15 @@
10530
10762
  "submit_pipeline_live"
10531
10763
  ]
10532
10764
  },
10765
+ "GetModulesSubmissionsResponse": {
10766
+ "type": "object",
10767
+ "properties": {
10768
+ "submissions": {}
10769
+ },
10770
+ "required": [
10771
+ "submissions"
10772
+ ]
10773
+ },
10533
10774
  "GetOverrideRequestsResponse": {
10534
10775
  "type": "object",
10535
10776
  "properties": {
@@ -10548,6 +10789,27 @@
10548
10789
  "instances"
10549
10790
  ]
10550
10791
  },
10792
+ "GetProvisioningGithubAppStatusResponse": {
10793
+ "type": "object",
10794
+ "properties": {
10795
+ "ok": {
10796
+ "type": "boolean"
10797
+ },
10798
+ "status": {},
10799
+ "ready": {},
10800
+ "terminal": {},
10801
+ "domain": {},
10802
+ "instance_status": {}
10803
+ },
10804
+ "required": [
10805
+ "ok",
10806
+ "status",
10807
+ "ready",
10808
+ "terminal",
10809
+ "domain",
10810
+ "instance_status"
10811
+ ]
10812
+ },
10551
10813
  "GetProvisioningHealthResponse": {
10552
10814
  "type": "object",
10553
10815
  "properties": {
@@ -10583,6 +10845,17 @@
10583
10845
  "instances"
10584
10846
  ]
10585
10847
  },
10848
+ "GetProvisioningOnboardPlanResponse": {
10849
+ "type": "object",
10850
+ "properties": {
10851
+ "mode": {},
10852
+ "steps": {}
10853
+ },
10854
+ "required": [
10855
+ "mode",
10856
+ "steps"
10857
+ ]
10858
+ },
10586
10859
  "GetPublicBlockersIdResponse": {
10587
10860
  "type": "object",
10588
10861
  "properties": {
@@ -12305,6 +12578,19 @@
12305
12578
  "request"
12306
12579
  ]
12307
12580
  },
12581
+ "PostGoalsIdRequestsReqIdWithdrawResponse": {
12582
+ "type": "object",
12583
+ "properties": {
12584
+ "ok": {
12585
+ "type": "boolean"
12586
+ },
12587
+ "request": {}
12588
+ },
12589
+ "required": [
12590
+ "ok",
12591
+ "request"
12592
+ ]
12593
+ },
12308
12594
  "PostGoalsIdRequestsRequest": {
12309
12595
  "type": "object",
12310
12596
  "properties": {
@@ -12807,6 +13093,29 @@
12807
13093
  "note"
12808
13094
  ]
12809
13095
  },
13096
+ "PostModulesKeySubmitRequest": {
13097
+ "type": "object",
13098
+ "properties": {
13099
+ "signed_by": {
13100
+ "type": "string",
13101
+ "maxLength": 200
13102
+ }
13103
+ },
13104
+ "additionalProperties": false
13105
+ },
13106
+ "PostModulesKeySubmitResponse": {
13107
+ "type": "object",
13108
+ "properties": {
13109
+ "ok": {
13110
+ "type": "boolean"
13111
+ },
13112
+ "submission": {}
13113
+ },
13114
+ "required": [
13115
+ "ok",
13116
+ "submission"
13117
+ ]
13118
+ },
12810
13119
  "PostOverrideRequestsIdDecideRequest": {
12811
13120
  "type": "object",
12812
13121
  "properties": {
@@ -13712,9 +14021,9 @@
13712
14021
  "description": "A required dependency/feature is not configured or is temporarily down."
13713
14022
  }
13714
14023
  },
13715
- "x-endpoint-count": 224,
13716
- "x-schema-count": 243,
14024
+ "x-endpoint-count": 229,
14025
+ "x-schema-count": 250,
13717
14026
  "x-undocumented-bodies": 8,
13718
- "x-response-schemas": 164,
14027
+ "x-response-schemas": 170,
13719
14028
  "x-generated-by": "scripts/gds/gen-api-docs.js"
13720
14029
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # GDS API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 224 endpoints across 38 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 229 endpoints across 38 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/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -181,7 +181,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
181
181
  | GET | `/api/bongos/gate-approvals` | `archon` | — | GET /gate-approvals — open PRs awaiting owner approval (gate-review red), with the verdict + per-file reasons + changed files + diff link. |
182
182
  | POST | `/api/bongos/gate-approvals/:pr/approve` | `archon` | — | POST /gate-approvals/:pr/approve — record owner approval for a stuck gate PR and re-run the gate-review check so it clears. |
183
183
 
184
- ## `goals` (21)
184
+ ## `goals` (23)
185
185
 
186
186
  | Method | Path | Rank | Body | Description |
187
187
  |---|---|---|---|---|
@@ -198,8 +198,10 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
198
198
  | POST | `/api/bongos/goals/:id/members` | `any-builder` | `role`, `builder_id` | POST /goals/:id/members — the goal's own authority (owner \| manager \| Archon) invites a builder to the goal (task 1762: widened from Arch… |
199
199
  | PATCH | `/api/bongos/goals/:id/members/:builderId` | `any-builder` | `role` | PATCH /goals/:id/members/:builderId — role management by the goal's own authority (task 1735): the owner, a manager, or an Archon promote… |
200
200
  | POST | `/api/bongos/goals/:id/reopen` | `metic+archon` | — | POST /goals/:id/reopen — bring an archived goal back to open (ADR 0086 §6 / BV1.R64). |
201
+ | GET | `/api/bongos/goals/:id/requests` | `any-builder` | — | GET /goals/:id/requests — the goal's own pending invite/join-request queue (task 1953): every pending row on THIS goal, both kinds — outs… |
201
202
  | POST | `/api/bongos/goals/:id/requests` | `any-builder` | `note` | POST /goals/:id/requests — a builder asks to join a (private or protected) goal (task 1952 / ADR 0112). |
202
203
  | POST | `/api/bongos/goals/:id/requests/:reqId/respond` | `any-builder` | `action` | POST /goals/:id/requests/:reqId/respond { action: approve\|deny } — an owner\| manager\|Archon resolves a pending join-request (task 1952). |
204
+ | POST | `/api/bongos/goals/:id/requests/:reqId/withdraw` | `any-builder` | — | POST /goals/:id/requests/:reqId/withdraw — the requester cancels their OWN pending join-request (task 1953): the symmetric self-served mi… |
203
205
  | POST | `/api/bongos/goals/:id/scope` | `metic+archon` | `add` | POST /goals/:id/scope — "ask to widen": add module(s) to a goal's scope_modules (ADR 0086 §4 / BV1.R64). |
204
206
  | POST | `/api/bongos/goals/:id/tasks` | `any-builder` | `title`, `description`, `touches`, `est_minutes`, `priority`, `kind`, `discipline`, `value_summary`, `parent_task_id` | POST /goals/:id/tasks — bounded task authoring within a goal's scope (BV1.R60 / ADR 0086 §3). |
205
207
  | POST | `/api/bongos/goals/:id/transfer` | `any-builder` | `builder_id` | POST /goals/:id/transfer — hand the goal to a new owner (task 1735). |
@@ -303,13 +305,14 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
303
305
  | GET | `/api/bongos/memory/files` | `any-builder` | — | GET /memory/files — list the AUTHENTICATED builder's memory files (metadata only, no content). |
304
306
  | POST | `/api/bongos/memory/sync` | `any-builder` | `files` | POST /memory/sync — push a builder's local memory files to the server. |
305
307
 
306
- ## `modules` (3)
308
+ ## `modules` (4)
307
309
 
308
310
  | Method | Path | Rank | Body | Description |
309
311
  |---|---|---|---|---|
310
312
  | GET | `/api/bongos/modules` | `any-builder` | — | list every on-disk module with attribution + provenance (same read gate as the atlas/primer pages). |
311
313
  | POST | `/api/bongos/modules/:key/enable` | `metic+archon` | `enabled` | toggling a module changes running behavior for the whole instance, not just the caller. |
312
- | POST | `/api/bongos/modules/:key/submit` | `metic+archon` | — | the "submit this module for review" front door (501 until the submit pipeline, task 1770, ships). |
314
+ | POST | `/api/bongos/modules/:key/submit` | `metic+archon` | `signed_by` | POST /api/gds/modules/:key/submit — ADR 0107 §1 upstreaming submission. |
315
+ | GET | `/api/bongos/modules/submissions` | `metic+archon` | — | GET /api/gds/modules/submissions?status=&module_key= — the upstreaming review queue (task 1771 reads this). |
313
316
 
314
317
  ## `override-requests` (2)
315
318
 
@@ -318,13 +321,14 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
318
321
  | GET | `/api/bongos/override-requests` | `archon` | — | GET /override-requests?status=open — Archon queue. |
319
322
  | POST | `/api/bongos/override-requests/:id/decide` | `archon` | `decision`, `note` | POST /override-requests/:id/decide — body: { decision: 'approve'\|'deny', note? } On approve, atomically flips the task completed→confirme… |
320
323
 
321
- ## `provisioning` (11)
324
+ ## `provisioning` (13)
322
325
 
323
326
  | Method | Path | Rank | Body | Description |
324
327
  |---|---|---|---|---|
325
328
  | GET | `/api/bongos/provisioning/fleet` | `archon` | — | GET /provisioning/fleet — the full instance roster across all owners. |
326
329
  | GET | `/api/bongos/provisioning/fleet/cost-ledger` | `archon` | — | GET /provisioning/fleet/cost-ledger — per-instance monthly estimate + total. |
327
330
  | GET | `/api/bongos/provisioning/github-app/callback` | `public` | — | GET /provisioning/github-app/callback?code=&state= — GitHub redirects the owner's BROWSER here after they approve the App Manifest (task … |
331
+ | GET | `/api/bongos/provisioning/github-app/status` | `public` | — | GET /provisioning/github-app/status?state=<> — the PUBLIC progress read the onboarding callback page polls (task 2096) to know when setup… |
328
332
  | GET | `/api/bongos/provisioning/health` | `public` | — | GET /provisioning/health — liveness + the core version this module mounted against. |
329
333
  | GET | `/api/bongos/provisioning/instances` | `any-builder` | — | GET /provisioning/instances — the caller's own instances + each open intent. |
330
334
  | POST | `/api/bongos/provisioning/instances` | `any-builder` | `slug`, `target_ref`, `hosting_shape`, `domain`, `tier` | POST /provisioning/instances — request a new instance. |
@@ -332,6 +336,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
332
336
  | POST | `/api/bongos/provisioning/instances/:id/force-teardown` | `archon` | — | POST /provisioning/instances/:id/force-teardown — Archon tears down ANY instance. |
333
337
  | POST | `/api/bongos/provisioning/instances/:id/github-app` | `any-builder` | `account` | POST /provisioning/instances/:id/github-app — mint a GitHub-App-Manifest onboarding link for the caller's OWN instance (task 2080, ADR 01… |
334
338
  | POST | `/api/bongos/provisioning/instances/:id/teardown` | `any-builder` | — | POST /provisioning/instances/:id/teardown — request teardown of the caller's OWN instance. |
339
+ | GET | `/api/bongos/provisioning/onboard-plan` | `public` | — | GET /provisioning/onboard-plan?mode=greenfield\|adopt — the CANONICAL onboarding step sequence (task 2085; goal 35 / criterion 165: "the c… |
335
340
  | GET | `/api/bongos/provisioning/tls-check` | `public` | — | GET /provisioning/tls-check?domain=<host> — the Caddy on-demand-TLS ALLOW-LIST (ADR 0111 §4, task P4 task 1945). |
336
341
 
337
342
  ## `public` (18)
@@ -69,7 +69,7 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
69
69
  - **Post-merge branch cleanup (standard practice):** Every feature branch that lands on main via `--no-ff` merge gets deleted on origin once the deploy succeeds. The merge commit itself preserves the branch's history in main, so the named ref isn't carrying any signal — keeping it just clutters GitHub's branch list and tricks the UI into offering empty PRs against zero-diff branches. The auto-merge in [`scripts/gds/ship.js`](../scripts/gds/ship.js) does this automatically after `~/deploy.sh` returns 0; the manual [`/merge-mode`](../.claude/skills/merge-mode/SKILL.md) flow follows the same step 5b. Local refs and worktree directories stay — only the origin branch and the local tracking ref (cleaned on next `git fetch --prune`) go.
70
70
  - **Local dev machine:** Lars's MacBook Air (Apple Silicon, macOS Sequoia). Tooling installed via Homebrew at `/opt/homebrew/`. Node v26.0.0 locally; `package.json` declares `"engines": { "node": ">=22" }`. Single ed25519 SSH key (`~/.ssh/id_ed25519`) authenticates to GitHub and droplet.
71
71
  - **Smoke tests:** lightweight scripts in `/tmp/colyseus-*-smoketest.js` verify joinOrCreate, move protocol, interact, identity, queue. Run any after deploy with `node /tmp/colyseus-<name>-smoketest.js`.
72
- - **Repo topology today vs. the configurable-root future ([ADR 0108](adr/<redacted>.md)):** everything above describes the current **single checkout** — `git reset --hard` deploy, `resolveCoreRoot()`/`resolveInstanceRoot()` ([`src/instance-config.js`](../src/instance-config.js)) both resolving to this same repo root. ADR 0108 lands (Mercury-first, then Example last) a model where Example instead installs a versioned `@cloudbongos/core` npm package and deploy becomes `git pull` (the instance repo) → `npm ci` (the pinned core) → migrate → restart — no more `git reset --hard` on a shared checkout. This section gets rewritten for the new topology once Example actually splits (ADR 0108 §6, task 1884/W4); until then it is unchanged and accurate.
72
+ - **Repo topology today vs. the configurable-root future ([ADR 0108](adr/<redacted>.md)):** everything above describes the current **single checkout** — `git reset --hard` deploy, `resolveCoreRoot()`/`resolveInstanceRoot()` ([`src/instance-config.js`](../src/instance-config.js)) both resolving to this same repo root. ADR 0108 lands (Mercury-first, then Example last) a model where Example instead installs a versioned `@bongos/core` npm package and deploy becomes `git pull` (the instance repo) → `npm ci` (the pinned core) → migrate → restart — no more `git reset --hard` on a shared checkout. This section gets rewritten for the new topology once Example actually splits (ADR 0108 §6, task 1884/W4); until then it is unchanged and accurate.
73
73
 
74
74
  **Database (`example` on Postgres 16, peer auth as `lars`):**
75
75
 
package/docs/file-map.md CHANGED
@@ -147,7 +147,7 @@
147
147
  │ ├── gen-file-map.js ← ADR 0066 ([#1276](https://example.com/builders#/task/1276)): generates the `.claude/skills/` + `.claude/scheduled-tasks/` sections of docs/file-map.md from disk; per-entry notes come from docs/file-map.notes.json; `--check` fails on drift OR a skill/routine with no note (CI gate via fitness.js); regenerated on deploy by ship.js regenerateFileMap()
148
148
  │ ├── fitness.js ← Path C (ADR 0062 §9, [#1225](https://example.com/builders#/task/1225)): architecture fitness functions — core↔host import boundary (zero grandfathered exceptions as of R52/#1191), CLAUDE.md budget + nested-doc presence (ADR 0061), no route bypasses rank checks (reuses route-rank-check), repo-map freshness. Enforced in CI via tests/fitness.mjs (the `unit` gate). `node scripts/gds/fitness.js`
149
149
  │ ├── ship.js ← resolve claim as shipped, award credits (`/builder-ship`); also uploads a secret-scrubbed session digest to the corpus (6D.1, ADR 0027); on a dev box runs the sandbox-first review gate before resolving (#927, ADR 0046)
150
- │ ├── package-core.js ← package the core as a versioned, installable artifact + pin manifest (`bongos package-core`; R84, ADR 0100 §1, [#1688](https://example.com/builders#/task/1688)): isPublishable() selection + mirror redaction + fail-closed no-leak gate → dist/cloudbongos-core-<version>.{tgz,manifest.json}; version = src/module-api CORE_VERSION. Recipe: docs/recipes/packaging-the-core.md
150
+ │ ├── package-core.js ← package the core as a versioned, installable artifact + pin manifest (`bongos package-core`; R84, ADR 0100 §1, [#1688](https://example.com/builders#/task/1688)): isPublishable() selection + mirror redaction + fail-closed no-leak gate → dist/bongos-core-<version>.{tgz,manifest.json}; version = src/module-api CORE_VERSION. Recipe: docs/recipes/packaging-the-core.md
151
151
  │ ├── sandbox-stage.js ← stage the working tree on the live game preview (box OR local) for browser review before ship; resolvePreviewContext picks the context (`/builder-stage`; #927, ADR 0046; local: task 1056)
152
152
  │ ├── local-preview.js ← builder CLI for the LOCAL sandbox: start/stop/status/restart/logs/url of the game-only preview at http://localhost:3100 (`npm run preview`; task 1056)
153
153
  │ ├── local-preview-lib.js ← core of the local sandbox launcher (detached `node src/preview-server.js`, pid/health/port mgmt); shared by local-preview.js + sandbox-stage.js (task 1056)
@@ -170,7 +170,7 @@
170
170
  │ ├── gen-api-docs.js ← ADR 0109: generates `docs/api/openapi.json` + `docs/api-reference.md` from the live route files via `route-rank-check.js` introspection, so the API reference cannot drift from what the server actually mounts
171
171
  │ ├── architect-audit.js ← MAS Phase 5 (ADR 0024): the Architect's bounded first-principles `--scope`/`--paths` audit CLI → `docs/audits/`
172
172
  │ ├── module.js ← `bongos module new <key>` scaffolder + module CLI utilities (ADR 0083)
173
- │ ├── upgrade.js ← `bongos upgrade` — bump the installed `@cloudbongos/core` package version with doorway/coreVersion pre-checks (ADR 0108)
173
+ │ ├── upgrade.js ← `bongos upgrade` — bump the installed `@bongos/core` package version with doorway/coreVersion pre-checks (ADR 0108)
174
174
  │ └── newcomer-floor.js ← deterministic on-claim replenisher for the evergreen newcomer chores (engineer/artist/ideator floor); no cron, restocks when one is claimed (task 1168)
175
175
  │
176
176
  ├── src/
@@ -105,6 +105,8 @@ An unknown key throws at validate time — typos fail loud (top-level attributio
105
105
 
106
106
  **`bongos module check <key> [--sign-off "Name <email>"]`** ([ADR 0107](adr/<redacted>.md) §4) is the submit-time pre-check a module must clear before it can be upstreamed. It reuses (never re-types) the public-mirror publish denylist (`scripts/gds/publish-manifest.js`'s `matchesDeny`) to reject content that cannot ship under AGPL (game content, pixel art, copyrighted reference material) — deliberately the DENY half only, since a brand-new module is never on the publish ALLOWLIST until it's accepted into core (§6). It also requires `module.json`'s `license` to be AGPL-3.0 (inbound = outbound). On a pass, `--sign-off` records a lightweight DCO-style affirmation (own work, licensed AGPL-3.0 — never a copyright-assignment CLA) to `modules/<key>/.upstream-signoff.json`.
107
107
 
108
+ **`bongos module submit <key> [--sign-off "Name <email>"]`** ([ADR 0107](adr/<redacted>.md) §1) re-runs the §4 pre-check + requires a sign-off, then packages the module (manifest + a full file snapshot + the sign-off) and files it into the rank-gated (metic+archon) upstreaming review queue via `POST /modules/:key/submit` — the same route the hall "Modules" tab's submit button calls. Refuses (exit 1) if the pre-check fails or no sign-off can be found/recorded. The queue currently lives in **this instance's own DB**, not a live call to the extracted core repo — see [ADR 0135](adr/<redacted>.md) for why, and `GET /modules/submissions` to read it back.
109
+
108
110
  ---
109
111
 
110
112
  ## The loader — `src/module-loader/loader.js`
@@ -1,12 +1,12 @@
1
1
  # Recipe — deploying a Cloud Bongos instance on a pinned core (`git reset` → `npm ci`)
2
2
 
3
- > ADR [0108](../adr/<redacted>.md) §4 (configurable-root W4, task [#1884](https://example.com/builders#/task/1884)). How a **consumer instance** — one that installs `@cloudbongos/core` as a versioned npm dependency rather than living in the monorepo — deploys. This is the target the live droplet deploy converts to; the reference implementation is [`scripts/deploy/deploy-instance.sh`](../../scripts/deploy/deploy-instance.sh).
3
+ > ADR [0108](../adr/<redacted>.md) §4 (configurable-root W4, task [#1884](https://example.com/builders#/task/1884)). How a **consumer instance** — one that installs `@bongos/core` as a versioned npm dependency rather than living in the monorepo — deploys. This is the target the live droplet deploy converts to; the reference implementation is [`scripts/deploy/deploy-instance.sh`](../../scripts/deploy/deploy-instance.sh).
4
4
 
5
5
  ## The two models
6
6
 
7
7
  | | Pre-split (today, `example`) | Post-split (consumer instance) |
8
8
  |---|---|---|
9
- | Core code | in-tree (the monorepo) | `node_modules/@cloudbongos/core` (a pinned version) |
9
+ | Core code | in-tree (the monorepo) | `node_modules/@bongos/core` (a pinned version) |
10
10
  | Deploy | [`deploy-prod.sh`](../../scripts/deploy/deploy-prod.sh): `git reset --hard origin/main` on a shared checkout | [`deploy-instance.sh`](../../scripts/deploy/deploy-instance.sh): `git pull` the instance repo → `npm ci` → migrate → restart |
11
11
  | Upgrade the core | (n/a — one tree) | bump the pin in `package.json` → `npm ci` → migrate → restart (ADR 0108 §4; the R86 channel, task [#1690](https://example.com/builders#/task/1690)) |
12
12
  | `cloudbongos.com` | a 2nd service on the **same** checkout (why it ran stale) | its **own** consumer repo + its own `deploy-instance.sh` |
@@ -14,7 +14,7 @@
14
14
  ## The flow (`deploy-instance.sh`)
15
15
 
16
16
  1. **`git pull --ff-only origin main`** the *instance* repo — host content only: `config/`, `migrations/instance/`, and the pinned core version in `package.json`.
17
- 2. **`npm ci --omit=dev`** — installs the pinned `@cloudbongos/core` + instance deps. This is what replaces `git reset --hard`: the core is a dependency, so an upgrade is a pin bump + `npm ci`, not a source merge.
17
+ 2. **`npm ci --omit=dev`** — installs the pinned `@bongos/core` + instance deps. This is what replaces `git reset --hard`: the core is a dependency, so an upgrade is a pin bump + `npm ci`, not a source merge.
18
18
  3. **`bash <core>/scripts/migrate.sh`** — the core's **three-root** migrate (W5 / ADR 0108 §5) merges `<core>/migrations` + `<instance>/migrations/instance` + each enabled module's migrations, keyed by namespaced filename stems (`core_NNN_`, `<key>_NNN_`, bare instance) so the two repos never collide. It resolves core-root vs instance-root via `src/instance-config.js`.
19
19
  4. **restart the platform** — a systemd unit runs `node <core>/src/platform-server.js` (GDS-only) with `WorkingDirectory` = the instance root (so `resolveInstanceRoot()` resolves to the instance) + `PORT`/`HOST` env; then poll `/healthz`.
20
20
 
@@ -32,6 +32,6 @@
32
32
  ## Wiring it on a consumer host (R85/R89)
33
33
 
34
34
  1. Install the script as the droplet's `~/deploy.sh` (the CI deploy key is forced-command-locked to `~/deploy.sh` — ADR 0043 — so it stays hand-installed, like `deploy-prod.sh`).
35
- 2. Create a systemd unit for the instance: `ExecStart=/usr/bin/node <instanceRoot>/node_modules/@cloudbongos/core/src/platform-server.js`, `WorkingDirectory=<instanceRoot>`, `Environment=PORT=… HOST=127.0.0.1 <PREFIX>_INSTANCE_ROOT=<instanceRoot>`.
35
+ 2. Create a systemd unit for the instance: `ExecStart=/usr/bin/node <instanceRoot>/node_modules/@bongos/core/src/platform-server.js`, `WorkingDirectory=<instanceRoot>`, `Environment=PORT=… HOST=127.0.0.1 <PREFIX>_INSTANCE_ROOT=<instanceRoot>`.
36
36
  3. Set `INSTANCE_SERVICE=<unit>` + `PORT=<port>` in the deploy environment.
37
37
  4. Front it with TLS and point the origins at the real domain (see [self-host.md](self-host.md)).
@@ -0,0 +1,51 @@
1
+ # First run: clone → working instance
2
+
3
+ > The one-shot path from `git clone` of a **standalone Cloud Bongos instance repo**
4
+ > (ADR 0108 — a repo that pins `@cloudbongos/core` as a dependency, e.g. `example-owner/demo`)
5
+ > to a session that can actually claim + ship work. This is for a **builder joining an
6
+ > existing instance**; standing up a *new* instance is `/new-project` (`bongos onboard`).
7
+
8
+ ## Why this recipe exists
9
+
10
+ A cloned instance repo ships `config/` + `package.json` + a vendored core tarball, but
11
+ **not** the installed engine. Until you install it there is no `bongos` binary and no
12
+ `scripts/gds/…`, so every `/builder-*` skill fails. An agent that presses on in that
13
+ state has no tools of its own and can fall back on whatever *other* Cloud Bongos instance
14
+ the machine is signed in to — which is how a `demo` clone once offered to write a task
15
+ into the wrong live backlog (2026-07-08). The session-start hook now prints these same
16
+ steps when it detects an uninstalled instance (task 2105); the wrong-instance write it
17
+ used to risk is refused outright (task 2102).
18
+
19
+ ## The steps
20
+
21
+ From the repo root, in order:
22
+
23
+ ```bash
24
+ # 1. Install the engine (the vendored core → node_modules + the `bongos` bin).
25
+ # No registry auth needed: the dependency is a local file: tarball.
26
+ npm install
27
+
28
+ # 2. Sign in to THIS instance (one browser click — no code to paste).
29
+ # Use the instance's own origin — the one in config/branding.json → domains.publicOrigin.
30
+ npx bongos login https://<this-instance-origin>
31
+
32
+ # 3. Confirm you're wired up: this lists what you can claim right now.
33
+ npx bongos start
34
+ ```
35
+
36
+ That's it — `bongos claim <id>` / `bongos ship` now work, scoped to this instance.
37
+
38
+ ## Notes
39
+
40
+ - **Sign in to the RIGHT instance.** `bongos login <url>` writes a per-instance session
41
+ (`session.api_base`), and the CLI **refuses to act** if the session it would use belongs
42
+ to a different instance than this repo is configured for (task 2102). If you see that
43
+ refusal, re-run `bongos login` with *this* instance's origin.
44
+ - **Which origin?** `config/branding.json` → `domains.publicOrigin`. `GET <origin>/api/bongos`
45
+ also re-advertises an instance's own hall/status/docs origins (the docs-discovery contract,
46
+ ADR 0114).
47
+ - **Invite-only by default.** A brand-new GitHub account isn't admitted until an Archon
48
+ approves it; `bongos login` files the request and waits, then finishes sign-in.
49
+ - **The engine lives in the package, not the repo.** `bongos` resolves the heavy CLI inside
50
+ `node_modules/@cloudbongos/core`; that's why step 1 must come first. On a machine with the
51
+ core installed globally you can drop the `npx`.