@bongos/core 1.25.20 → 1.25.22

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 (99) hide show
  1. package/.bongos-core.json +213 -78
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +18 -0
  4. package/clients/bongos-client/index.cjs +18 -0
  5. package/clients/bongos-client/index.d.ts +34 -8
  6. package/clients/bongos-client/index.mjs +18 -0
  7. package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +18 -0
  8. package/docs/adr/0407-a-project-grant-is-made-by-the-owner-not-witnessed-at-sign-in.md +3 -1
  9. package/docs/api/openapi.json +693 -125
  10. package/docs/api-reference.md +13 -4
  11. package/docs/copy-inventory.md +432 -427
  12. package/docs/copy-registry.json +571 -526
  13. package/docs/file-map.md +1 -0
  14. package/docs/module-api-changelog.md +4 -0
  15. package/docs/page-readings.json +350 -344
  16. package/modules/government/board.js +8 -7
  17. package/modules/government/charter-advice.js +10 -3
  18. package/modules/government/charter.js +88 -4
  19. package/modules/government/migrations/government_039_vote_cast_via_filed.sql +22 -0
  20. package/modules/government/routes/government.js +12 -12
  21. package/modules/government/sole-member.js +75 -0
  22. package/modules/hall-ui/public/genesis-home.js +12 -5
  23. package/modules/lifecycle/kickoff-checklist.js +1 -1
  24. package/modules/lifecycle/routes/pay-type-gates.js +7 -2
  25. package/modules/onboarding/genesis-home.js +14 -2
  26. package/modules/onboarding/project-facts.js +318 -0
  27. package/modules/onboarding/routes/genesis-work.js +16 -0
  28. package/modules/platform-identity/module.json +1 -1
  29. package/modules/platform-identity/project-standing.js +49 -0
  30. package/modules/platform-identity/routes/my-projects.js +8 -0
  31. package/modules/provisioning/grants.js +126 -0
  32. package/modules/provisioning/migrations/provisioning_038_render_promote.sql +43 -0
  33. package/modules/provisioning/migrations/provisioning_039_project_grants.sql +40 -0
  34. package/modules/provisioning/module.json +2 -1
  35. package/modules/provisioning/project-facts.js +55 -0
  36. package/modules/provisioning/project-refusal.js +107 -0
  37. package/modules/provisioning/provisioning.js +6 -3
  38. package/modules/provisioning/render-lookup.js +36 -1
  39. package/modules/provisioning/render-promote.js +80 -0
  40. package/modules/provisioning/render-sandbox.js +6 -0
  41. package/modules/provisioning/route-helpers.js +70 -16
  42. package/modules/provisioning/routes/env-manifest.js +21 -5
  43. package/modules/provisioning/routes/grants.js +141 -0
  44. package/modules/provisioning/routes/provisioning.js +8 -7
  45. package/modules/provisioning/routes/render-standup.js +82 -3
  46. package/modules/public-landing/public/projects.html +290 -32
  47. package/package-lock.json +2 -2
  48. package/package.json +2 -1
  49. package/release-notes.json +32 -0
  50. package/scripts/bongos/genesis.js +49 -3
  51. package/scripts/bongos/government-walk-sole.js +41 -0
  52. package/scripts/bongos/government-walk.js +15 -16
  53. package/scripts/bongos/init.js +13 -0
  54. package/scripts/bongos/package-core.js +2 -0
  55. package/scripts/bongos/provision-render-common.js +48 -0
  56. package/scripts/bongos/provision-render-promote.js +93 -0
  57. package/scripts/bongos/provision-render-sandbox.js +19 -3
  58. package/scripts/bongos/provision-render.js +4 -36
  59. package/scripts/bongos/provision.js +1 -0
  60. package/scripts/bongos/render-api.js +17 -2
  61. package/scripts/bongos/render-payload.js +5 -2
  62. package/scripts/gds/government-walk-sole.js +6 -0
  63. package/scripts/gds/provision-render-common.js +6 -0
  64. package/scripts/gds/provision-render-promote.js +6 -0
  65. package/src/bongos/folder-upload.js +243 -0
  66. package/src/bongos/routes/github.js +109 -16
  67. package/src/bongos/routes.js +3 -0
  68. package/src/branding.js +4 -0
  69. package/src/module-api.js +1 -1
  70. package/src/sandbox/gate.js +164 -0
  71. package/src/sandbox/index.js +144 -0
  72. package/tests/fleet_cost_view.mjs +2 -0
  73. package/tests/folder_upload_project.mjs +396 -0
  74. package/tests/genesis_government.mjs +5 -1
  75. package/tests/genesis_home.mjs +17 -0
  76. package/tests/genesis_work_routes.mjs +25 -1
  77. package/tests/government_charter_advice.mjs +49 -0
  78. package/tests/government_charter_forms.mjs +14 -3
  79. package/tests/government_seed.mjs +1 -0
  80. package/tests/government_sole_member.mjs +153 -0
  81. package/tests/project_catalog_routes.mjs +2 -0
  82. package/tests/project_facts.mjs +158 -0
  83. package/tests/projects_hub.mjs +1 -1
  84. package/tests/provision_settings_apply.mjs +2 -1
  85. package/tests/provisioning_env_manifest.mjs +4 -0
  86. package/tests/provisioning_env_manifest_edit_delete.mjs +2 -0
  87. package/tests/provisioning_project_grants.mjs +458 -0
  88. package/tests/provisioning_project_owner_gate.mjs +3 -1
  89. package/tests/provisioning_project_refusal.mjs +316 -0
  90. package/tests/provisioning_render_route.mjs +1 -1
  91. package/tests/provisioning_restart.mjs +2 -0
  92. package/tests/provisioning_settings.mjs +2 -0
  93. package/tests/provisioning_settings_apply.mjs +1 -1
  94. package/tests/provisioning_settings_env.mjs +2 -2
  95. package/tests/provisioning_teardown_intent.mjs +2 -2
  96. package/tests/public_landing_projects.mjs +27 -5
  97. package/tests/render_promote.mjs +309 -0
  98. package/tests/render_sandbox.mjs +16 -8
  99. package/tests/sandbox_gate.mjs +182 -0
@@ -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
- - 731 operations across 88 resource groups
8
+ - 740 operations across 88 resource groups
9
9
 
10
10
  ## Use it from your project
11
11
 
@@ -497,8 +497,14 @@ function createClient(opts = {}) {
497
497
  getFoundingContext: (args) => request("GET", "/founding/context", { hasBody: false }, args),
498
498
  // PUT /founding/enabled — rank: any-builder — PUT /founding/enabled
499
499
  putFoundingEnabled: (args) => request("PUT", "/founding/enabled", { hasBody: true }, args),
500
+ // GET /founding/facts — rank: any-builder — GET /founding/facts
501
+ getFoundingFacts: (args) => request("GET", "/founding/facts", { hasBody: false }, args),
502
+ // PUT /founding/facts — rank: any-builder — PUT /founding/facts
503
+ putFoundingFacts: (args) => request("PUT", "/founding/facts", { hasBody: true }, args),
500
504
  // GET /founding/genesis — rank: any-builder — GET /founding/genesis
501
505
  getFoundingGenesis: (args) => request("GET", "/founding/genesis", { hasBody: false }, args),
506
+ // GET /founding/legalize/options — rank: any-builder — GET /founding/legalize/options
507
+ getFoundingLegalizeOptions: (args) => request("GET", "/founding/legalize/options", { hasBody: false }, args),
502
508
  // POST /founding/plan — rank: any-builder — POST /founding/plan
503
509
  postFoundingPlan: (args) => request("POST", "/founding/plan", { hasBody: true }, args),
504
510
  // POST /founding/skip — rank: any-builder — POST /founding/skip
@@ -563,6 +569,8 @@ function createClient(opts = {}) {
563
569
  getGithubRepos: (args) => request("GET", "/github/repos", { hasBody: false }, args),
564
570
  // POST /github/repos — rank: any-builder — POST /github/repos
565
571
  postGithubRepos: (args) => request("POST", "/github/repos", { hasBody: true }, args),
572
+ // POST /github/repos/upload — rank: any-builder — POST /github/repos/upload
573
+ postGithubReposUpload: (args) => request("POST", "/github/repos/upload", { hasBody: true }, args),
566
574
  },
567
575
  "goalTaskRelevance": {
568
576
  // POST /goal-task-relevance/{id}/decide — rank: metic+archon — POST /goal-task-relevance/:id/decide
@@ -1317,6 +1325,12 @@ function createClient(opts = {}) {
1317
1325
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1318
1326
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1319
1327
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1328
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1329
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1330
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1331
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1332
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1333
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1320
1334
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1321
1335
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1322
1336
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1331,6 +1345,10 @@ function createClient(opts = {}) {
1331
1345
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1332
1346
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1333
1347
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1348
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1349
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1350
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1351
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1334
1352
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1335
1353
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1336
1354
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
@@ -496,8 +496,14 @@ function createClient(opts = {}) {
496
496
  getFoundingContext: (args) => request("GET", "/founding/context", { hasBody: false }, args),
497
497
  // PUT /founding/enabled — rank: any-builder — PUT /founding/enabled
498
498
  putFoundingEnabled: (args) => request("PUT", "/founding/enabled", { hasBody: true }, args),
499
+ // GET /founding/facts — rank: any-builder — GET /founding/facts
500
+ getFoundingFacts: (args) => request("GET", "/founding/facts", { hasBody: false }, args),
501
+ // PUT /founding/facts — rank: any-builder — PUT /founding/facts
502
+ putFoundingFacts: (args) => request("PUT", "/founding/facts", { hasBody: true }, args),
499
503
  // GET /founding/genesis — rank: any-builder — GET /founding/genesis
500
504
  getFoundingGenesis: (args) => request("GET", "/founding/genesis", { hasBody: false }, args),
505
+ // GET /founding/legalize/options — rank: any-builder — GET /founding/legalize/options
506
+ getFoundingLegalizeOptions: (args) => request("GET", "/founding/legalize/options", { hasBody: false }, args),
501
507
  // POST /founding/plan — rank: any-builder — POST /founding/plan
502
508
  postFoundingPlan: (args) => request("POST", "/founding/plan", { hasBody: true }, args),
503
509
  // POST /founding/skip — rank: any-builder — POST /founding/skip
@@ -562,6 +568,8 @@ function createClient(opts = {}) {
562
568
  getGithubRepos: (args) => request("GET", "/github/repos", { hasBody: false }, args),
563
569
  // POST /github/repos — rank: any-builder — POST /github/repos
564
570
  postGithubRepos: (args) => request("POST", "/github/repos", { hasBody: true }, args),
571
+ // POST /github/repos/upload — rank: any-builder — POST /github/repos/upload
572
+ postGithubReposUpload: (args) => request("POST", "/github/repos/upload", { hasBody: true }, args),
565
573
  },
566
574
  "goalTaskRelevance": {
567
575
  // POST /goal-task-relevance/{id}/decide — rank: metic+archon — POST /goal-task-relevance/:id/decide
@@ -1316,6 +1324,12 @@ function createClient(opts = {}) {
1316
1324
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1317
1325
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1318
1326
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1327
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1328
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1329
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1330
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1331
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1332
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1319
1333
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1320
1334
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1321
1335
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1330,6 +1344,10 @@ function createClient(opts = {}) {
1330
1344
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1331
1345
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1332
1346
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1347
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1348
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1349
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1350
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1333
1351
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1334
1352
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1335
1353
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
@@ -24,6 +24,7 @@ export interface DeleteMeSignInMethodsProviderResponse { ok: boolean }
24
24
  export interface DeleteMemoryFileResponse { deleted: boolean; builder_id: unknown; path: unknown }
25
25
  export interface DeleteNotesIdResponse { ok: boolean }
26
26
  export interface DeleteProvisioningInstancesIdEnvManifestVarIdResponse { ok: boolean; removed: boolean; message: unknown }
27
+ export interface DeleteProvisioningInstancesIdGrantsGrantIdResponse { ok: boolean; revoked: boolean }
27
28
  export interface DeleteSpecialitiesIdDocumentsDocIdResponse { ok: boolean }
28
29
  export interface DeleteTasksIdCriteriaCriterionIdResponse { ok: boolean; removed: unknown }
29
30
  export interface DeleteTasksIdDependenciesDepIdResponse { ok: boolean; removed: unknown }
@@ -164,10 +165,10 @@ export interface GetProvisioningGithubAppResumeResponse { ok: boolean; project:
164
165
  export interface GetProvisioningGithubAppStatusResponse { ok: boolean; status: unknown; failure: unknown; ready: unknown; terminal: unknown; domain: unknown; instance_status: unknown; app_slug: unknown; checklist: unknown; install_url: unknown; repo: unknown; verifying: unknown; app_org: unknown; pick_up: unknown }
165
166
  export interface GetProvisioningHealthResponse { module: unknown; ok: boolean; coreVersion: unknown }
166
167
  export interface GetProvisioningInstancesIdEnvManifestResponse { instance: unknown; env_vars: unknown; environments: unknown; values_held: boolean; note: unknown }
168
+ export interface GetProvisioningInstancesIdGrantsResponse { grants: unknown; levels: unknown; limit: unknown }
167
169
  export interface GetProvisioningInstancesIdInviteSuggestionsResponse { suggested: unknown; seeking: unknown; reason: unknown; unavailable?: unknown }
168
170
  export interface GetProvisioningInstancesIdLookResponse { ok: boolean; look: unknown; options: unknown; logo_max_bytes: unknown }
169
- export interface GetProvisioningInstancesIdRenderResponse { ok: boolean; app: unknown; sandbox: unknown; env_vars: unknown; values_held: boolean }
170
- export interface GetProvisioningInstancesIdResponse { instance: unknown; open_intent: unknown; github_app: unknown; github_setup: unknown }
171
+ export interface GetProvisioningInstancesIdRenderResponse { ok: boolean; app: unknown; sandbox: unknown; promote: unknown; env_vars: unknown; values_held: boolean }
171
172
  export interface GetProvisioningInstancesIdSettingsResponse { ok: boolean; settings: unknown; planet: unknown; options: unknown }
172
173
  export interface GetProvisioningInstancesResponse { instances: unknown }
173
174
  export interface GetProvisioningOnboardPlanResponse { mode: unknown; steps: unknown }
@@ -406,6 +407,8 @@ export interface PostGithubRepoVisibilityRequest { repo: string; visibility: "pu
406
407
  export interface PostGithubRepoVisibilityResponse { ok: boolean; repo: unknown; private_deployable: boolean }
407
408
  export interface PostGithubReposRequest { name: string; org?: string }
408
409
  export interface PostGithubReposResponse { repo: unknown }
410
+ export interface PostGithubReposUploadRequest { name?: string; org?: string; into?: string; files?: unknown[] }
411
+ export interface PostGithubReposUploadResponse { repo: unknown; uploaded: unknown }
409
412
  export interface PostGoalTaskRelevanceIdDecideRequest { decision: "confirmed_gaming" | "false_positive"; note?: string }
410
413
  export interface PostGoalTaskRelevanceIdDecideResponse { ok: boolean; flag: unknown }
411
414
  export interface PostGoalsIdArchiveRequest { reason?: string; dispositions?: Record<string, unknown> }
@@ -446,19 +449,19 @@ export interface PostGovernmentAsksMatterIdUnclearRequest { note?: string }
446
449
  export interface PostGovernmentAsksMatterIdUnclearResponse { ok: boolean; matter_id: unknown; flag: unknown }
447
450
  export interface PostGovernmentAssignmentsRequest { builder_id: number; rank_key: string }
448
451
  export interface PostGovernmentBoardCharterRequest { form?: string; franchise?: string; council_rank?: string; pass_rule?: string; window_minutes?: unknown; rationale_md?: string; acknowledge_self_removal?: boolean }
449
- export interface PostGovernmentBoardCharterResponse { ok: boolean; amendment: unknown; item: unknown; reads_as: unknown }
452
+ export interface PostGovernmentBoardCharterResponse { ok: boolean; amendment: unknown; item: unknown; reads_as: unknown; what_happens_next: unknown; decided: unknown }
450
453
  export interface PostGovernmentBoardDecisionRulesRequest { rules: unknown[]; rationale_md?: string }
451
- export interface PostGovernmentBoardDecisionRulesResponse { ok: boolean; amendment: unknown; item: unknown; rules: unknown }
454
+ export interface PostGovernmentBoardDecisionRulesResponse { ok: boolean; amendment: unknown; item: unknown; rules: unknown; decided: unknown }
452
455
  export interface PostGovernmentBoardItemsItemIdVotesRequest { direction: string; reason_md?: string; section_key?: string }
453
456
  export interface PostGovernmentBoardItemsItemIdWithdrawResponse { ok: boolean; item_closed: boolean; outcome: unknown; item: unknown }
454
457
  export interface PostGovernmentBoardItemsRequest { subject_type: string; proposal: Record<string, unknown>; rationale_md?: string; acknowledge_self_removal?: boolean }
455
- export interface PostGovernmentBoardItemsResponse { ok: boolean; amendment: unknown; item: unknown }
458
+ export interface PostGovernmentBoardItemsResponse { ok: boolean; amendment: unknown; item: unknown; decided: unknown }
456
459
  export interface PostGovernmentBoardLawsRequest { enact?: unknown[]; repeal?: unknown[]; rationale_md?: string }
457
- export interface PostGovernmentBoardLawsResponse { ok: boolean; amendment: unknown; item: unknown; proposal: unknown }
460
+ export interface PostGovernmentBoardLawsResponse { ok: boolean; amendment: unknown; item: unknown; proposal: unknown; decided: unknown }
458
461
  export interface PostGovernmentBoardMattersRequest { area: string; title: string; detail_md?: string; action?: Record<string, unknown> }
459
462
  export interface PostGovernmentBoardMattersResponse { ok: boolean; matter: unknown; item: unknown; decided: unknown }
460
463
  export interface PostGovernmentBoardPresetsRequest { preset: string }
461
- export interface PostGovernmentBoardPresetsResponse { ok: boolean; preset: unknown; amendment: unknown; item: unknown; proposal: unknown }
464
+ export interface PostGovernmentBoardPresetsResponse { ok: boolean; preset: unknown; amendment: unknown; item: unknown; proposal: unknown; decided: unknown }
462
465
  export interface PostGovernmentBuildoutsRequest { building: string; capsule: string; name?: string; line?: string }
463
466
  export interface PostGovernmentBuildoutsResponse { ok: boolean; path: unknown; buildout?: unknown; rights: unknown; matter?: unknown; item?: unknown; decided?: unknown }
464
467
  export interface PostGovernmentRankSetsApplyRequest { type?: string; headcount: number }
@@ -611,6 +614,10 @@ export interface PostProvisioningInstancesIdEnvManifestRequest { name: string; d
611
614
  export interface PostProvisioningInstancesIdForceTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
612
615
  export interface PostProvisioningInstancesIdGithubAppRequest { account?: string; org?: string }
613
616
  export interface PostProvisioningInstancesIdGithubAppResponse { state: unknown; account: unknown; post_url: unknown; personal_url: unknown; org_url: unknown; org_login: unknown; manifest: unknown; redirect_url: unknown; expires_at: unknown }
617
+ export interface PostProvisioningInstancesIdGrantsRequest { github_login: string }
618
+ export interface PostProvisioningInstancesIdRenderPromoteLookRequest { key: string }
619
+ export interface PostProvisioningInstancesIdRenderPromoteRequest { key: string; commit_id: string; expect_live_commit?: string }
620
+ export interface PostProvisioningInstancesIdRenderPromoteResponse { ok: boolean; queued: boolean; action: unknown; message: unknown }
614
621
  export interface PostProvisioningInstancesIdRenderRequest { key: string; owner_id: string; mode: string; service_id?: string; web_plan?: string; db_plan?: string; region?: string; runtime?: string; build_command?: string; start_command?: string; database?: boolean }
615
622
  export interface PostProvisioningInstancesIdRenderResponse { ok: boolean; queued: boolean; action: unknown; mode: unknown; with_setup: boolean; message: unknown }
616
623
  export interface PostProvisioningInstancesIdRenderSandboxRequest { key: string }
@@ -736,6 +743,7 @@ export interface PutCopyDeskPagesPageIdDraftResponse { ok: boolean; outcome: unk
736
743
  export interface PutDoneWhenCriterionIdBackendOnlyRequest { backend_only: boolean }
737
744
  export interface PutDoneWhenCriterionIdBackendOnlyResponse { ok: boolean; criterion_id: unknown; backend_only: unknown }
738
745
  export interface PutFoundingEnabledRequest { enabled?: boolean }
746
+ export interface PutFoundingFactsRequest { facts: Record<string, unknown> }
739
747
  export interface PutFoundingWorkStageAnswersQuestionRequest { state?: string; text?: string; origin?: string; if_empty?: boolean }
740
748
  export interface PutFoundingWorkStageDoorRequest { door: string }
741
749
  export interface PutFoundingWorkStageLinkRequest { url?: string }
@@ -1189,8 +1197,14 @@ export interface BongosClient {
1189
1197
  getFoundingContext(args?: RequestArgs): Promise<ApiResponse>;
1190
1198
  /** PUT /founding/enabled — rank: any-builder */
1191
1199
  putFoundingEnabled(args?: RequestArgs & { body?: PutFoundingEnabledRequest }): Promise<ApiResponse>;
1200
+ /** GET /founding/facts — rank: any-builder */
1201
+ getFoundingFacts(args?: RequestArgs): Promise<ApiResponse>;
1202
+ /** PUT /founding/facts — rank: any-builder */
1203
+ putFoundingFacts(args: RequestArgs & { body: PutFoundingFactsRequest }): Promise<ApiResponse>;
1192
1204
  /** GET /founding/genesis — rank: any-builder */
1193
1205
  getFoundingGenesis(args?: RequestArgs): Promise<ApiResponse>;
1206
+ /** GET /founding/legalize/options — rank: any-builder */
1207
+ getFoundingLegalizeOptions(args?: RequestArgs): Promise<ApiResponse>;
1194
1208
  /** POST /founding/plan — rank: any-builder */
1195
1209
  postFoundingPlan(args?: RequestArgs & { body?: PostFoundingPlanRequest }): Promise<ApiResponse>;
1196
1210
  /** POST /founding/skip — rank: any-builder */
@@ -1255,6 +1269,8 @@ export interface BongosClient {
1255
1269
  getGithubRepos(args?: RequestArgs): Promise<GetGithubReposResponse>;
1256
1270
  /** POST /github/repos — rank: any-builder */
1257
1271
  postGithubRepos(args: RequestArgs & { body: PostGithubReposRequest }): Promise<PostGithubReposResponse>;
1272
+ /** POST /github/repos/upload — rank: any-builder */
1273
+ postGithubReposUpload(args?: RequestArgs & { body?: PostGithubReposUploadRequest }): Promise<PostGithubReposUploadResponse>;
1258
1274
  };
1259
1275
  "goalTaskRelevance": {
1260
1276
  /** POST /goal-task-relevance/{id}/decide — rank: metic+archon */
@@ -1982,7 +1998,7 @@ export interface BongosClient {
1982
1998
  /** POST /provisioning/instances — rank: any-builder */
1983
1999
  postProvisioningInstances(args: RequestArgs & { body: PostProvisioningInstancesRequest }): Promise<ApiResponse>;
1984
2000
  /** GET /provisioning/instances/{id} — rank: any-builder */
1985
- getProvisioningInstancesId(args?: RequestArgs): Promise<GetProvisioningInstancesIdResponse>;
2001
+ getProvisioningInstancesId(args?: RequestArgs): Promise<ApiResponse>;
1986
2002
  /** GET /provisioning/instances/{id}/core-upgrade — rank: archon */
1987
2003
  getProvisioningInstancesIdCoreUpgrade(args?: RequestArgs): Promise<ApiResponse>;
1988
2004
  /** POST /provisioning/instances/{id}/core-upgrade — rank: archon */
@@ -2009,6 +2025,12 @@ export interface BongosClient {
2009
2025
  postProvisioningInstancesIdGithubApp(args?: RequestArgs & { body?: PostProvisioningInstancesIdGithubAppRequest }): Promise<PostProvisioningInstancesIdGithubAppResponse>;
2010
2026
  /** POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder */
2011
2027
  postProvisioningInstancesIdGithubAppPickUp(args?: RequestArgs): Promise<ApiResponse>;
2028
+ /** GET /provisioning/instances/{id}/grants — rank: any-builder */
2029
+ getProvisioningInstancesIdGrants(args?: RequestArgs): Promise<GetProvisioningInstancesIdGrantsResponse>;
2030
+ /** POST /provisioning/instances/{id}/grants — rank: any-builder */
2031
+ postProvisioningInstancesIdGrants(args: RequestArgs & { body: PostProvisioningInstancesIdGrantsRequest }): Promise<ApiResponse>;
2032
+ /** DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder */
2033
+ deleteProvisioningInstancesIdGrantsGrantId(args?: RequestArgs): Promise<DeleteProvisioningInstancesIdGrantsGrantIdResponse>;
2012
2034
  /** GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder */
2013
2035
  getProvisioningInstancesIdInviteSuggestions(args?: RequestArgs): Promise<GetProvisioningInstancesIdInviteSuggestionsResponse>;
2014
2036
  /** DELETE /provisioning/instances/{id}/logo — rank: any-builder */
@@ -2023,6 +2045,10 @@ export interface BongosClient {
2023
2045
  getProvisioningInstancesIdRender(args?: RequestArgs): Promise<GetProvisioningInstancesIdRenderResponse>;
2024
2046
  /** POST /provisioning/instances/{id}/render — rank: any-builder */
2025
2047
  postProvisioningInstancesIdRender(args: RequestArgs & { body: PostProvisioningInstancesIdRenderRequest }): Promise<PostProvisioningInstancesIdRenderResponse>;
2048
+ /** POST /provisioning/instances/{id}/render/promote — rank: any-builder */
2049
+ postProvisioningInstancesIdRenderPromote(args: RequestArgs & { body: PostProvisioningInstancesIdRenderPromoteRequest }): Promise<PostProvisioningInstancesIdRenderPromoteResponse>;
2050
+ /** POST /provisioning/instances/{id}/render/promote/look — rank: any-builder */
2051
+ postProvisioningInstancesIdRenderPromoteLook(args: RequestArgs & { body: PostProvisioningInstancesIdRenderPromoteLookRequest }): Promise<ApiResponse>;
2026
2052
  /** POST /provisioning/instances/{id}/render/sandbox — rank: any-builder */
2027
2053
  postProvisioningInstancesIdRenderSandbox(args: RequestArgs & { body: PostProvisioningInstancesIdRenderSandboxRequest }): Promise<PostProvisioningInstancesIdRenderSandboxResponse>;
2028
2054
  /** POST /provisioning/instances/{id}/repo-private — rank: any-builder */
@@ -493,8 +493,14 @@ export function createClient(opts = {}) {
493
493
  getFoundingContext: (args) => request("GET", "/founding/context", { hasBody: false }, args),
494
494
  // PUT /founding/enabled — rank: any-builder — PUT /founding/enabled
495
495
  putFoundingEnabled: (args) => request("PUT", "/founding/enabled", { hasBody: true }, args),
496
+ // GET /founding/facts — rank: any-builder — GET /founding/facts
497
+ getFoundingFacts: (args) => request("GET", "/founding/facts", { hasBody: false }, args),
498
+ // PUT /founding/facts — rank: any-builder — PUT /founding/facts
499
+ putFoundingFacts: (args) => request("PUT", "/founding/facts", { hasBody: true }, args),
496
500
  // GET /founding/genesis — rank: any-builder — GET /founding/genesis
497
501
  getFoundingGenesis: (args) => request("GET", "/founding/genesis", { hasBody: false }, args),
502
+ // GET /founding/legalize/options — rank: any-builder — GET /founding/legalize/options
503
+ getFoundingLegalizeOptions: (args) => request("GET", "/founding/legalize/options", { hasBody: false }, args),
498
504
  // POST /founding/plan — rank: any-builder — POST /founding/plan
499
505
  postFoundingPlan: (args) => request("POST", "/founding/plan", { hasBody: true }, args),
500
506
  // POST /founding/skip — rank: any-builder — POST /founding/skip
@@ -559,6 +565,8 @@ export function createClient(opts = {}) {
559
565
  getGithubRepos: (args) => request("GET", "/github/repos", { hasBody: false }, args),
560
566
  // POST /github/repos — rank: any-builder — POST /github/repos
561
567
  postGithubRepos: (args) => request("POST", "/github/repos", { hasBody: true }, args),
568
+ // POST /github/repos/upload — rank: any-builder — POST /github/repos/upload
569
+ postGithubReposUpload: (args) => request("POST", "/github/repos/upload", { hasBody: true }, args),
562
570
  },
563
571
  "goalTaskRelevance": {
564
572
  // POST /goal-task-relevance/{id}/decide — rank: metic+archon — POST /goal-task-relevance/:id/decide
@@ -1313,6 +1321,12 @@ export function createClient(opts = {}) {
1313
1321
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1314
1322
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1315
1323
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1324
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1325
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1326
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1327
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1328
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1329
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1316
1330
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1317
1331
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1318
1332
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1327,6 +1341,10 @@ export function createClient(opts = {}) {
1327
1341
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1328
1342
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1329
1343
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1344
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1345
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1346
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1347
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1330
1348
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1331
1349
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1332
1350
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
@@ -114,3 +114,21 @@ Each sibling task's description now opens with a dated note, *"Re-read against A
114
114
  - **The live service's switch to manual deploys is left to the promote task** ([task 1005290](https://cloudbongos.com/builders#/task/1005290)), so that live never stops updating before there is a button that moves it.
115
115
  - **Teardown needs the owner's key to remove the sandbox**, typed on the teardown screen and used once. The Render client gains one delete, `deleteSandboxService`, which refuses anything not named `…-sandbox` on the free plan. Without the key the sandbox stays on the owner's account and the owner is told exactly what to remove.
116
116
 
117
+ ## 11. Amendment — how promotion was built (2026-11-13, [task 1005290](https://cloudbongos.com/builders#/task/1005290))
118
+
119
+ - **Where the owner promotes:** the project's own page on the hub, under the sandbox — where the sandbox's address and state already are. Not the hall's deploy page (`modules/render-deploy`): that module is never turned on in a project's hall today, so a promote button there would be unreachable.
120
+ - **Who may promote: the project's owner, decided on the server** (`POST /provisioning/instances/:id/render/promote`). The key and the live app are the owner's, so an archon on someone else's project gets the same 404 as a stranger — the rule every Render route here already follows (ADR 0327).
121
+ - **What waits, and the read it takes.** The owner sees the change the live app runs and every change that has run on the sandbox since, newest first. Reading that needs Render, so **ADR 0348's read-only exception is widened by exactly one look**: `lookupPromotion` in `modules/provisioning/render-lookup.js` may GET the project's two recorded services (live and sandbox) and their deploy lists, on the owner's key held for that one request. GET only, every service asserted to carry the project's workspace, nothing stored or returned.
122
+ - **The press** queues a `render-promote` intent holding the owner's encrypted key (the borrowed-key rule, ADR 0327 §2). The runner (`scripts/bongos/provision-render-promote.js`) checks the change ran on the sandbox and that live still runs what the owner was shown, **writes the promotion to `provisioning_promotions` before sending anything**, switches the live service to manual deploys, and asks Render to deploy exactly that commit (`triggerDeploy` now takes a `commitId`).
123
+ - **When the live app stops following `main`.** As soon as its sandbox is running (the sandbox setup switches it), and again on every promotion. Not before: a project whose sandbox failed keeps deploying every merge, so finished work always has somewhere to land.
124
+ - **Ship mode is untouched.** No ship, in Auto or Manual mode, reaches the promote leg; landing reaches the sandbox only.
125
+ - **What this cannot stop, said plainly.** The owner can still deploy the live service from Render's own dashboard, or turn its automatic deploys back on there. Bongos does not see or record those. "Nothing reaches the main site without a recorded promotion" holds for everything Bongos does, not for what the owner does in Render directly.
126
+
127
+ ## 12. Amendment — the sandbox's safety, as built (2026-11-13, [task 1005291](https://cloudbongos.com/builders#/task/1005291))
128
+
129
+ - **Fake by default, by construction.** The sandbox service is created with only `BONGOS_SANDBOX=1` and its own `DATABASE_URL`; none of the live app's keys are copied to it. A sandbox the owner has not touched holds no real key, so nothing it does can reach a real customer. Test keys and test data are added by the owner or seeded by the app (`isSandbox()`).
130
+ - **The gate ships in the core package** as `@bongos/core/sandbox` (`src/sandbox/`). One line at the top of a Node app — `require('@bongos/core/sandbox').install()` — does nothing on the live site and, under `BONGOS_SANDBOX=1`, puts the gate in front of `fetch`, `http` and `https`. For each known provider (payments, email, messaging, code hosting and a few data services) a read passes; a send, a charge or a write is refused, never sent, written to the log as `[bongos-sandbox] refused …` (Render shows it), and kept for the owner. A Stripe **test-mode** key is let through, since it cannot move real money.
131
+ - **Visibly a sandbox.** `sandbox.middleware` puts a fixed "Sandbox" band on every HTML page and serves `/__bongos/sandbox`, which tells anyone what a sandbox is and what the gate cannot catch. The refusals and which real keys are lent (by variable name, never value) show only to a visitor carrying the sandbox's page key — a random value the platform sets on the sandbox (`BONGOS_SANDBOX_PAGE_KEY`) and keeps on the project's row, so only the owner's project page links with it. A passer-by on the sandbox's public address learns nothing about the owner's keys.
132
+ - **The starter says how.** The scaffold's README (`bongos init`) carries the one line, and the advice to lend a read-only key.
133
+ - **What it cannot catch, said plainly — here, on the sandbox page, and on the project page.** Only calls the app makes through Node's own web requests, and only to providers in its table. Code that goes around them, an app not written in Node, or an unknown provider is not stopped. A read-only key is the floor; the gate is the second wall. The free plan also blocks outgoing email ports.
134
+
@@ -31,7 +31,7 @@ So no value of `membership_kind` means "the owner trusts this person with the ho
31
31
 
32
32
  ### 1. The grant is its own row, in the provisioning module, with one writer
33
33
 
34
- A new table, `provisioning_project_grants` (migration `<redacted>.sql`, additive, in the module's own namespace):
34
+ A new table, `provisioning_project_grants` (migration `provisioning_039_project_grants.sql`, additive, in the module's own namespace):
35
35
 
36
36
  | Column | Meaning |
37
37
  |---|---|
@@ -99,6 +99,8 @@ The word is documented as "has signed in here" (ADR 0328's amendment already say
99
99
  - **How the row is read.** Through a port, `platform-identity.projectMembershipKind` as ADR 0328 named it, and only after the gate has already refused. If the port is unregistered, throws, or answers an unknown value, the answer is the `404`: on doubt, say less. This read only picks the wording of a refusal and can never admit anyone.
100
100
  - **A grantee on a route without the opt-in** → `403 owner_only`, "Only the project's owner can do this." They already know the project exists.
101
101
 
102
+ **As built (task 1004162), three refinements, none wider than the above:** (1) a `member` or `owner` row on a **private or stealth** project gets the 404, not `project_access_required` — a `member` row comes from any device-flow sign-in, so it is no evidence a person may learn that a closed project's id is real; (2) a person with no row who **applied** inside the 30-day application window is told the owner decides (`project_membership_required`, `apply.state: 'applied'`); (3) a `pending` row is an invitation, so it is told to sign in to the project to accept. The routes that check ownership inline (look, demo, render, repo-private, the GitHub pick-up, core-upgrade) still answer the plain 404.
103
+
102
104
  ## Consequences
103
105
 
104
106
  - A team can share one hosted project's day-to-day running, once task 1004161 lands, without the owner handing over teardown, the address or their own accounts.