@bongos/core 1.25.19 → 1.25.21

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 (131) hide show
  1. package/.bongos-core.json +237 -112
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +12 -0
  4. package/clients/bongos-client/index.cjs +12 -0
  5. package/clients/bongos-client/index.d.ts +26 -9
  6. package/clients/bongos-client/index.mjs +12 -0
  7. package/docs/adr/0406-every-project-gets-a-sandbox-that-follows-main-and-live-moves-only-when-a-person-promotes.md +10 -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 +444 -37
  10. package/docs/api-reference.md +11 -5
  11. package/docs/copy-inventory.md +223 -221
  12. package/docs/copy-registry.json +262 -244
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/page-readings.json +348 -347
  15. package/docs/project-context.template.md +1 -1
  16. package/modules/front-door-guide/handoff.js +120 -0
  17. package/modules/front-door-guide/module.json +1 -1
  18. package/modules/front-door-guide/routes/front-door-guide-plan.js +24 -0
  19. package/modules/government/board.js +8 -7
  20. package/modules/government/charter-advice.js +10 -3
  21. package/modules/government/charter.js +88 -4
  22. package/modules/government/migrations/government_039_vote_cast_via_filed.sql +22 -0
  23. package/modules/government/routes/government.js +12 -12
  24. package/modules/government/sole-member.js +75 -0
  25. package/modules/hall-ui/public/ai-studio.html +1 -1
  26. package/modules/hall-ui/public/atlas.html +1 -1
  27. package/modules/hall-ui/public/blockers.html +1 -1
  28. package/modules/hall-ui/public/board-room.html +1 -1
  29. package/modules/hall-ui/public/city.html +1 -1
  30. package/modules/hall-ui/public/collab.html +1 -1
  31. package/modules/hall-ui/public/commands.html +1 -1
  32. package/modules/hall-ui/public/copy-desk.html +1 -1
  33. package/modules/hall-ui/public/deploy.html +1 -1
  34. package/modules/hall-ui/public/genesis-home.js +35 -9
  35. package/modules/hall-ui/public/goal-map.html +1 -1
  36. package/modules/hall-ui/public/goals.html +1 -1
  37. package/modules/hall-ui/public/government.html +1 -1
  38. package/modules/hall-ui/public/home-city-draw.js +14 -1
  39. package/modules/hall-ui/public/idea.html +1 -1
  40. package/modules/hall-ui/public/ideas.html +1 -1
  41. package/modules/hall-ui/public/index.html +1 -1
  42. package/modules/hall-ui/public/market-watch-item.html +1 -1
  43. package/modules/hall-ui/public/market-watch-rules.html +1 -1
  44. package/modules/hall-ui/public/market-watch.html +1 -1
  45. package/modules/hall-ui/public/modules.html +1 -1
  46. package/modules/hall-ui/public/money.html +1 -1
  47. package/modules/hall-ui/public/my-agents.html +1 -1
  48. package/modules/hall-ui/public/primer.html +1 -1
  49. package/modules/hall-ui/public/profile.html +1 -1
  50. package/modules/hall-ui/public/project-settings.html +1 -1
  51. package/modules/hall-ui/public/roster.html +1 -1
  52. package/modules/hall-ui/public/settings.html +1 -1
  53. package/modules/hall-ui/public/shell.js +32 -20
  54. package/modules/hall-ui/public/street.html +1 -1
  55. package/modules/hall-ui/public/studio.html +1 -1
  56. package/modules/hall-ui/public/style.css +9 -4
  57. package/modules/hall-ui/public/task.html +1 -1
  58. package/modules/hall-ui/public/thinking.html +1 -1
  59. package/modules/hall-ui/public/tweak-editor.html +1 -1
  60. package/modules/hall-ui/public/watch.html +1 -1
  61. package/modules/hall-ui/public/work.html +1 -1
  62. package/modules/lifecycle/home-city.js +17 -3
  63. package/modules/onboarding/founding-mode.js +45 -1
  64. package/modules/onboarding/genesis-home.js +16 -2
  65. package/modules/onboarding/guide-handoff.js +109 -0
  66. package/modules/onboarding/routes/genesis-work.js +9 -5
  67. package/modules/platform-identity/module.json +1 -1
  68. package/modules/platform-identity/project-standing.js +49 -0
  69. package/modules/platform-identity/routes/my-projects.js +8 -0
  70. package/modules/provisioning/grants.js +126 -0
  71. package/modules/provisioning/guide-handoff.js +65 -0
  72. package/modules/provisioning/migrations/provisioning_038_render_promote.sql +43 -0
  73. package/modules/provisioning/migrations/provisioning_039_project_grants.sql +40 -0
  74. package/modules/provisioning/module.json +2 -1
  75. package/modules/provisioning/project-refusal.js +107 -0
  76. package/modules/provisioning/provisioning.js +4 -4
  77. package/modules/provisioning/render-lookup.js +36 -1
  78. package/modules/provisioning/render-promote.js +80 -0
  79. package/modules/provisioning/route-helpers.js +70 -16
  80. package/modules/provisioning/routes/env-manifest.js +21 -5
  81. package/modules/provisioning/routes/grants.js +141 -0
  82. package/modules/provisioning/routes/provisioning.js +12 -9
  83. package/modules/provisioning/routes/render-standup.js +82 -3
  84. package/modules/public-landing/public/projects.html +178 -1
  85. package/package-lock.json +2 -2
  86. package/package.json +1 -1
  87. package/release-notes.json +28 -0
  88. package/scripts/bongos/genesis.js +11 -1
  89. package/scripts/bongos/government-walk-sole.js +41 -0
  90. package/scripts/bongos/government-walk.js +15 -16
  91. package/scripts/bongos/provision-render-common.js +48 -0
  92. package/scripts/bongos/provision-render-promote.js +93 -0
  93. package/scripts/bongos/provision-render-sandbox.js +14 -2
  94. package/scripts/bongos/provision-render.js +4 -36
  95. package/scripts/bongos/provision.js +1 -0
  96. package/scripts/bongos/render-api.js +17 -2
  97. package/scripts/gds/government-walk-sole.js +6 -0
  98. package/scripts/gds/provision-render-common.js +6 -0
  99. package/scripts/gds/provision-render-promote.js +6 -0
  100. package/src/bongos/founding-page-gate.js +67 -0
  101. package/src/bongos/serve-internal.js +3 -0
  102. package/src/branding.js +4 -0
  103. package/src/module-api.js +1 -1
  104. package/tests/fleet_cost_view.mjs +2 -0
  105. package/tests/founding_mode.mjs +84 -8
  106. package/tests/founding_page_gate.mjs +105 -0
  107. package/tests/front_door_guide_existing.mjs +1 -0
  108. package/tests/genesis_government.mjs +5 -1
  109. package/tests/genesis_home.mjs +41 -0
  110. package/tests/government_charter_advice.mjs +49 -0
  111. package/tests/government_charter_forms.mjs +14 -3
  112. package/tests/government_seed.mjs +1 -0
  113. package/tests/government_sole_member.mjs +153 -0
  114. package/tests/guide_handoff.mjs +322 -0
  115. package/tests/home_city.mjs +52 -0
  116. package/tests/nav_permission_atoms.mjs +1 -1
  117. package/tests/project_catalog_routes.mjs +2 -0
  118. package/tests/provision_settings_apply.mjs +2 -1
  119. package/tests/provisioning_env_manifest.mjs +4 -0
  120. package/tests/provisioning_env_manifest_edit_delete.mjs +2 -0
  121. package/tests/provisioning_project_grants.mjs +458 -0
  122. package/tests/provisioning_project_owner_gate.mjs +3 -1
  123. package/tests/provisioning_project_refusal.mjs +316 -0
  124. package/tests/provisioning_render_route.mjs +1 -1
  125. package/tests/provisioning_restart.mjs +2 -0
  126. package/tests/provisioning_settings.mjs +2 -0
  127. package/tests/provisioning_settings_apply.mjs +1 -1
  128. package/tests/provisioning_settings_env.mjs +2 -2
  129. package/tests/provisioning_teardown_intent.mjs +2 -2
  130. package/tests/render_promote.mjs +309 -0
  131. package/tests/render_sandbox.mjs +9 -4
@@ -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
- - 730 operations across 88 resource groups
8
+ - 736 operations across 88 resource groups
9
9
 
10
10
  ## Use it from your project
11
11
 
@@ -541,6 +541,8 @@ function createClient(opts = {}) {
541
541
  postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
542
542
  // GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
543
543
  getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
544
+ // GET /front-door-guide/mine/handoff.md — rank: any-builder — GET /front-door-guide/mine/handoff.md
545
+ getFrontDoorGuideMineHandoffMd: (args) => request("GET", "/front-door-guide/mine/handoff.md", { hasBody: false }, args),
544
546
  // GET /front-door-guide/status — rank: public — GET /front-door-guide/status
545
547
  getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
546
548
  },
@@ -1315,6 +1317,12 @@ function createClient(opts = {}) {
1315
1317
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1316
1318
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1317
1319
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1320
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1321
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1322
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1323
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1324
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1325
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1318
1326
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1319
1327
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1320
1328
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1329,6 +1337,10 @@ function createClient(opts = {}) {
1329
1337
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1330
1338
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1331
1339
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1340
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1341
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1342
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1343
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1332
1344
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1333
1345
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1334
1346
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
@@ -540,6 +540,8 @@ function createClient(opts = {}) {
540
540
  postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
541
541
  // GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
542
542
  getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
543
+ // GET /front-door-guide/mine/handoff.md — rank: any-builder — GET /front-door-guide/mine/handoff.md
544
+ getFrontDoorGuideMineHandoffMd: (args) => request("GET", "/front-door-guide/mine/handoff.md", { hasBody: false }, args),
543
545
  // GET /front-door-guide/status — rank: public — GET /front-door-guide/status
544
546
  getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
545
547
  },
@@ -1314,6 +1316,12 @@ function createClient(opts = {}) {
1314
1316
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1315
1317
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1316
1318
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1319
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1320
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1321
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1322
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1323
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1324
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1317
1325
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1318
1326
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1319
1327
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1328,6 +1336,10 @@ function createClient(opts = {}) {
1328
1336
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1329
1337
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1330
1338
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1339
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1340
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1341
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1342
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1331
1343
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1332
1344
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1333
1345
  // 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 }
@@ -446,19 +447,19 @@ export interface PostGovernmentAsksMatterIdUnclearRequest { note?: string }
446
447
  export interface PostGovernmentAsksMatterIdUnclearResponse { ok: boolean; matter_id: unknown; flag: unknown }
447
448
  export interface PostGovernmentAssignmentsRequest { builder_id: number; rank_key: string }
448
449
  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 }
450
+ export interface PostGovernmentBoardCharterResponse { ok: boolean; amendment: unknown; item: unknown; reads_as: unknown; what_happens_next: unknown; decided: unknown }
450
451
  export interface PostGovernmentBoardDecisionRulesRequest { rules: unknown[]; rationale_md?: string }
451
- export interface PostGovernmentBoardDecisionRulesResponse { ok: boolean; amendment: unknown; item: unknown; rules: unknown }
452
+ export interface PostGovernmentBoardDecisionRulesResponse { ok: boolean; amendment: unknown; item: unknown; rules: unknown; decided: unknown }
452
453
  export interface PostGovernmentBoardItemsItemIdVotesRequest { direction: string; reason_md?: string; section_key?: string }
453
454
  export interface PostGovernmentBoardItemsItemIdWithdrawResponse { ok: boolean; item_closed: boolean; outcome: unknown; item: unknown }
454
455
  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 }
456
+ export interface PostGovernmentBoardItemsResponse { ok: boolean; amendment: unknown; item: unknown; decided: unknown }
456
457
  export interface PostGovernmentBoardLawsRequest { enact?: unknown[]; repeal?: unknown[]; rationale_md?: string }
457
- export interface PostGovernmentBoardLawsResponse { ok: boolean; amendment: unknown; item: unknown; proposal: unknown }
458
+ export interface PostGovernmentBoardLawsResponse { ok: boolean; amendment: unknown; item: unknown; proposal: unknown; decided: unknown }
458
459
  export interface PostGovernmentBoardMattersRequest { area: string; title: string; detail_md?: string; action?: Record<string, unknown> }
459
460
  export interface PostGovernmentBoardMattersResponse { ok: boolean; matter: unknown; item: unknown; decided: unknown }
460
461
  export interface PostGovernmentBoardPresetsRequest { preset: string }
461
- export interface PostGovernmentBoardPresetsResponse { ok: boolean; preset: unknown; amendment: unknown; item: unknown; proposal: unknown }
462
+ export interface PostGovernmentBoardPresetsResponse { ok: boolean; preset: unknown; amendment: unknown; item: unknown; proposal: unknown; decided: unknown }
462
463
  export interface PostGovernmentBuildoutsRequest { building: string; capsule: string; name?: string; line?: string }
463
464
  export interface PostGovernmentBuildoutsResponse { ok: boolean; path: unknown; buildout?: unknown; rights: unknown; matter?: unknown; item?: unknown; decided?: unknown }
464
465
  export interface PostGovernmentRankSetsApplyRequest { type?: string; headcount: number }
@@ -611,6 +612,10 @@ export interface PostProvisioningInstancesIdEnvManifestRequest { name: string; d
611
612
  export interface PostProvisioningInstancesIdForceTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; message: unknown }
612
613
  export interface PostProvisioningInstancesIdGithubAppRequest { account?: string; org?: string }
613
614
  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 }
615
+ export interface PostProvisioningInstancesIdGrantsRequest { github_login: string }
616
+ export interface PostProvisioningInstancesIdRenderPromoteLookRequest { key: string }
617
+ export interface PostProvisioningInstancesIdRenderPromoteRequest { key: string; commit_id: string; expect_live_commit?: string }
618
+ export interface PostProvisioningInstancesIdRenderPromoteResponse { ok: boolean; queued: boolean; action: unknown; message: unknown }
614
619
  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
620
  export interface PostProvisioningInstancesIdRenderResponse { ok: boolean; queued: boolean; action: unknown; mode: unknown; with_setup: boolean; message: unknown }
616
621
  export interface PostProvisioningInstancesIdRenderSandboxRequest { key: string }
@@ -620,7 +625,7 @@ export interface PostProvisioningInstancesIdRestartResponse { ok: boolean; queue
620
625
  export interface PostProvisioningInstancesIdTeardownResponse { ok: boolean; queued: unknown; action: unknown; status: unknown; superseded: unknown; sandbox_key_lent: unknown; message: unknown }
621
626
  export interface PostProvisioningInstancesIdUpdateSubscriptionRequest { subscribed: boolean }
622
627
  export interface PostProvisioningInstancesIdUpdateSubscriptionResponse { ok: boolean; update_subscribed: unknown; previous: unknown; changed: unknown }
623
- export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; no_address?: boolean; tier?: string; onboard_mode?: string; type?: string; description?: string; detail?: Record<string, unknown>; modules?: string[]; terms_acknowledged?: boolean; demo?: Record<string, unknown>; ship_mode?: "auto" | "manual"; genesis?: boolean; test?: boolean }
628
+ export interface PostProvisioningInstancesRequest { slug: string; target_ref?: string; hosting_shape?: string; domain?: string; no_address?: boolean; tier?: string; onboard_mode?: string; type?: string; description?: string; detail?: Record<string, unknown>; modules?: string[]; terms_acknowledged?: boolean; demo?: Record<string, unknown>; ship_mode?: "auto" | "manual"; genesis?: boolean; test?: boolean; from_guide?: boolean }
624
629
  export interface PostProvisioningPhysicsCheckRequest { description?: string; detail?: Record<string, unknown> }
625
630
  export interface PostProvisioningPhysicsCheckResponse { stop: boolean; message: unknown; soft_limits: unknown }
626
631
  export interface PostProvisioningRenderLookupRequest { key: string; owner_id?: string }
@@ -1233,6 +1238,8 @@ export interface BongosClient {
1233
1238
  postFrontDoorGuideConversationsIdPlan(args: RequestArgs & { body: PostFrontDoorGuideConversationsIdPlanRequest }): Promise<ApiResponse>;
1234
1239
  /** GET /front-door-guide/mine — rank: any-builder */
1235
1240
  getFrontDoorGuideMine(args?: RequestArgs): Promise<GetFrontDoorGuideMineResponse>;
1241
+ /** GET /front-door-guide/mine/handoff.md — rank: any-builder */
1242
+ getFrontDoorGuideMineHandoffMd(args?: RequestArgs): Promise<ApiResponse>;
1236
1243
  /** GET /front-door-guide/status — rank: public */
1237
1244
  getFrontDoorGuideStatus(args?: RequestArgs): Promise<ApiResponse>;
1238
1245
  };
@@ -1980,7 +1987,7 @@ export interface BongosClient {
1980
1987
  /** POST /provisioning/instances — rank: any-builder */
1981
1988
  postProvisioningInstances(args: RequestArgs & { body: PostProvisioningInstancesRequest }): Promise<ApiResponse>;
1982
1989
  /** GET /provisioning/instances/{id} — rank: any-builder */
1983
- getProvisioningInstancesId(args?: RequestArgs): Promise<GetProvisioningInstancesIdResponse>;
1990
+ getProvisioningInstancesId(args?: RequestArgs): Promise<ApiResponse>;
1984
1991
  /** GET /provisioning/instances/{id}/core-upgrade — rank: archon */
1985
1992
  getProvisioningInstancesIdCoreUpgrade(args?: RequestArgs): Promise<ApiResponse>;
1986
1993
  /** POST /provisioning/instances/{id}/core-upgrade — rank: archon */
@@ -2007,6 +2014,12 @@ export interface BongosClient {
2007
2014
  postProvisioningInstancesIdGithubApp(args?: RequestArgs & { body?: PostProvisioningInstancesIdGithubAppRequest }): Promise<PostProvisioningInstancesIdGithubAppResponse>;
2008
2015
  /** POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder */
2009
2016
  postProvisioningInstancesIdGithubAppPickUp(args?: RequestArgs): Promise<ApiResponse>;
2017
+ /** GET /provisioning/instances/{id}/grants — rank: any-builder */
2018
+ getProvisioningInstancesIdGrants(args?: RequestArgs): Promise<GetProvisioningInstancesIdGrantsResponse>;
2019
+ /** POST /provisioning/instances/{id}/grants — rank: any-builder */
2020
+ postProvisioningInstancesIdGrants(args: RequestArgs & { body: PostProvisioningInstancesIdGrantsRequest }): Promise<ApiResponse>;
2021
+ /** DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder */
2022
+ deleteProvisioningInstancesIdGrantsGrantId(args?: RequestArgs): Promise<DeleteProvisioningInstancesIdGrantsGrantIdResponse>;
2010
2023
  /** GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder */
2011
2024
  getProvisioningInstancesIdInviteSuggestions(args?: RequestArgs): Promise<GetProvisioningInstancesIdInviteSuggestionsResponse>;
2012
2025
  /** DELETE /provisioning/instances/{id}/logo — rank: any-builder */
@@ -2021,6 +2034,10 @@ export interface BongosClient {
2021
2034
  getProvisioningInstancesIdRender(args?: RequestArgs): Promise<GetProvisioningInstancesIdRenderResponse>;
2022
2035
  /** POST /provisioning/instances/{id}/render — rank: any-builder */
2023
2036
  postProvisioningInstancesIdRender(args: RequestArgs & { body: PostProvisioningInstancesIdRenderRequest }): Promise<PostProvisioningInstancesIdRenderResponse>;
2037
+ /** POST /provisioning/instances/{id}/render/promote — rank: any-builder */
2038
+ postProvisioningInstancesIdRenderPromote(args: RequestArgs & { body: PostProvisioningInstancesIdRenderPromoteRequest }): Promise<PostProvisioningInstancesIdRenderPromoteResponse>;
2039
+ /** POST /provisioning/instances/{id}/render/promote/look — rank: any-builder */
2040
+ postProvisioningInstancesIdRenderPromoteLook(args: RequestArgs & { body: PostProvisioningInstancesIdRenderPromoteLookRequest }): Promise<ApiResponse>;
2024
2041
  /** POST /provisioning/instances/{id}/render/sandbox — rank: any-builder */
2025
2042
  postProvisioningInstancesIdRenderSandbox(args: RequestArgs & { body: PostProvisioningInstancesIdRenderSandboxRequest }): Promise<PostProvisioningInstancesIdRenderSandboxResponse>;
2026
2043
  /** POST /provisioning/instances/{id}/repo-private — rank: any-builder */
@@ -537,6 +537,8 @@ export function createClient(opts = {}) {
537
537
  postFrontDoorGuideConversationsIdPlan: (args) => request("POST", "/front-door-guide/conversations/{id}/plan", { hasBody: true }, args),
538
538
  // GET /front-door-guide/mine — rank: any-builder — GET /front-door-guide/mine
539
539
  getFrontDoorGuideMine: (args) => request("GET", "/front-door-guide/mine", { hasBody: false }, args),
540
+ // GET /front-door-guide/mine/handoff.md — rank: any-builder — GET /front-door-guide/mine/handoff.md
541
+ getFrontDoorGuideMineHandoffMd: (args) => request("GET", "/front-door-guide/mine/handoff.md", { hasBody: false }, args),
540
542
  // GET /front-door-guide/status — rank: public — GET /front-door-guide/status
541
543
  getFrontDoorGuideStatus: (args) => request("GET", "/front-door-guide/status", { hasBody: false }, args),
542
544
  },
@@ -1311,6 +1313,12 @@ export function createClient(opts = {}) {
1311
1313
  postProvisioningInstancesIdGithubApp: (args) => request("POST", "/provisioning/instances/{id}/github-app", { hasBody: true }, args),
1312
1314
  // POST /provisioning/instances/{id}/github-app/pick-up — rank: any-builder — POST /provisioning/instances/:id/github-app/pick-up
1313
1315
  postProvisioningInstancesIdGithubAppPickUp: (args) => request("POST", "/provisioning/instances/{id}/github-app/pick-up", { hasBody: true }, args),
1316
+ // GET /provisioning/instances/{id}/grants — rank: any-builder — GET /provisioning/instances/:id/grants
1317
+ getProvisioningInstancesIdGrants: (args) => request("GET", "/provisioning/instances/{id}/grants", { hasBody: false }, args),
1318
+ // POST /provisioning/instances/{id}/grants — rank: any-builder — POST /provisioning/instances/:id/grants
1319
+ postProvisioningInstancesIdGrants: (args) => request("POST", "/provisioning/instances/{id}/grants", { hasBody: true }, args),
1320
+ // DELETE /provisioning/instances/{id}/grants/{grantId} — rank: any-builder — DELETE /provisioning/instances/:id/grants/:grantId
1321
+ deleteProvisioningInstancesIdGrantsGrantId: (args) => request("DELETE", "/provisioning/instances/{id}/grants/{grantId}", { hasBody: false }, args),
1314
1322
  // GET /provisioning/instances/{id}/invite-suggestions — rank: any-builder — GET /provisioning/instances/:id/invite-suggestions
1315
1323
  getProvisioningInstancesIdInviteSuggestions: (args) => request("GET", "/provisioning/instances/{id}/invite-suggestions", { hasBody: false }, args),
1316
1324
  // DELETE /provisioning/instances/{id}/logo — rank: any-builder — DELETE /provisioning/instances/:id/logo
@@ -1325,6 +1333,10 @@ export function createClient(opts = {}) {
1325
1333
  getProvisioningInstancesIdRender: (args) => request("GET", "/provisioning/instances/{id}/render", { hasBody: false }, args),
1326
1334
  // POST /provisioning/instances/{id}/render — rank: any-builder — POST /provisioning/instances/:id/render
1327
1335
  postProvisioningInstancesIdRender: (args) => request("POST", "/provisioning/instances/{id}/render", { hasBody: true }, args),
1336
+ // POST /provisioning/instances/{id}/render/promote — rank: any-builder — POST /provisioning/instances/:id/render/promote
1337
+ postProvisioningInstancesIdRenderPromote: (args) => request("POST", "/provisioning/instances/{id}/render/promote", { hasBody: true }, args),
1338
+ // POST /provisioning/instances/{id}/render/promote/look — rank: any-builder — POST /provisioning/instances/:id/render/promote/look
1339
+ postProvisioningInstancesIdRenderPromoteLook: (args) => request("POST", "/provisioning/instances/{id}/render/promote/look", { hasBody: true }, args),
1328
1340
  // POST /provisioning/instances/{id}/render/sandbox — rank: any-builder — POST /provisioning/instances/:id/render/sandbox
1329
1341
  postProvisioningInstancesIdRenderSandbox: (args) => request("POST", "/provisioning/instances/{id}/render/sandbox", { hasBody: true }, args),
1330
1342
  // POST /provisioning/instances/{id}/repo-private — rank: any-builder — POST /provisioning/instances/:id/repo-private
@@ -114,3 +114,13 @@ 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
+
@@ -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.