@bongos/core 1.18.0 → 1.18.18

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 (553) hide show
  1. package/.bongos-core.json +1740 -640
  2. package/.claude/skills/builder-box/SKILL.md +6 -0
  3. package/.claude/skills/builder-sequence/SKILL.md +97 -0
  4. package/.claude/skills/builder-ship/SKILL.md +8 -2
  5. package/.claude/skills/builder-start/SKILL.md +11 -0
  6. package/.claude/skills/builder-sync/SKILL.md +41 -0
  7. package/.claude/skills/fix-task/SKILL.md +64 -0
  8. package/.claude/skills/goal-create/SKILL.md +158 -0
  9. package/.claude/skills/goal-review/SKILL.md +3 -1
  10. package/.claude/skills/idea-triage/SKILL.md +14 -8
  11. package/.claude/skills/merge-mode/SKILL.md +2 -2
  12. package/.claude/skills/new-project/SKILL.md +1 -0
  13. package/.claude/skills/planning-session/SKILL.md +45 -18
  14. package/.env.local.example +4 -3
  15. package/README.md +5 -3
  16. package/bin/bongos.js +1 -0
  17. package/clients/bongos-client/README.md +2 -2
  18. package/clients/bongos-client/bongos-client.global.js +82 -18
  19. package/clients/bongos-client/index.cjs +82 -18
  20. package/clients/bongos-client/index.d.ts +131 -29
  21. package/clients/bongos-client/index.mjs +82 -18
  22. package/config/branding.neutral.json +11 -2
  23. package/config/governance.neutral.json +21 -0
  24. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +24 -0
  25. package/docs/adr/0090-metic-task-authoring.md +1 -1
  26. package/docs/adr/0142-project-context-is-prose-only.md +41 -0
  27. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  28. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  29. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  30. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  31. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  32. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  33. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  34. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  35. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  36. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  37. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  38. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  39. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  40. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  41. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  42. package/docs/adr/README.md +15 -2
  43. package/docs/api/openapi.json +2648 -483
  44. package/docs/api-reference.md +73 -13
  45. package/docs/architecture.md +4 -2
  46. package/docs/branding-contract.md +3 -1
  47. package/docs/canonical-permissions.md +21 -8
  48. package/docs/file-map.md +15 -7
  49. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  50. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  51. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  52. package/docs/onboarding/diagrams/assertions.json +4 -7
  53. package/docs/onboarding/drachmae-and-karma.md +3 -3
  54. package/docs/onboarding/primer.md +17 -16
  55. package/docs/onboarding/slash-commands.md +124 -0
  56. package/docs/recipes/builder-box-lifecycle.md +23 -0
  57. package/docs/recipes/devbox-app-release.md +14 -4
  58. package/docs/recipes/instance-first-run.md +16 -0
  59. package/docs/recipes/local-dev.md +81 -0
  60. package/docs/recipes/ops-gotchas.md +19 -1
  61. package/docs/recipes/overnight-builder.md +1 -1
  62. package/docs/recipes/packaging-the-core.md +13 -0
  63. package/docs/recipes/parallel-goal-waves.md +174 -0
  64. package/docs/recipes/ship-and-regrade.md +2 -2
  65. package/docs/recipes/standalone-live-docs.md +48 -0
  66. package/docs/recipes/upgrading-the-core.md +5 -2
  67. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  68. package/migrations/003_pms.sql +6 -7
  69. package/migrations/006_pms_v2.sql +3 -31
  70. package/migrations/039_newcomer_friendly_column.sql +5 -0
  71. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  72. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  73. package/migrations/core_193_task_needs_rebase.sql +28 -0
  74. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  75. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  76. package/migrations/core_196_session_reward_topup.sql +69 -0
  77. package/modules/autonomy/pollers/routine-timers.js +9 -8
  78. package/modules/builder-settings/wandering-prefs.js +61 -18
  79. package/modules/dev-box/app/README.md +73 -0
  80. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  81. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  82. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  83. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  84. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  85. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  86. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  87. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  88. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  89. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  90. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  91. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  92. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  93. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  94. package/modules/dev-box/app/build-resources/icon.png +0 -0
  95. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  96. package/modules/dev-box/app/electron-builder.yml +95 -0
  97. package/modules/dev-box/app/package-lock.json +5291 -0
  98. package/modules/dev-box/app/package.json +30 -0
  99. package/modules/dev-box/app/renderer/app.js +319 -0
  100. package/modules/dev-box/app/renderer/index.html +45 -0
  101. package/modules/dev-box/app/renderer/styles.css +246 -0
  102. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  103. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  104. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  105. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  106. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  107. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  108. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  109. package/modules/dev-box/app/src/box-controller.js +287 -0
  110. package/modules/dev-box/app/src/brand.generated.json +13 -0
  111. package/modules/dev-box/app/src/brand.js +16 -0
  112. package/modules/dev-box/app/src/config.js +19 -0
  113. package/modules/dev-box/app/src/gds-client.js +90 -0
  114. package/modules/dev-box/app/src/main.js +610 -0
  115. package/modules/dev-box/app/src/pairing.js +57 -0
  116. package/modules/dev-box/app/src/preload.js +29 -0
  117. package/modules/dev-box/app/src/session-store.js +58 -0
  118. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  119. package/modules/dev-box/app/src/task-picker.js +70 -0
  120. package/modules/dev-box/app/src/tray.js +99 -0
  121. package/modules/dev-box/app/src/updater.js +55 -0
  122. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  123. package/modules/dev-box/app/test/unit.mjs +526 -0
  124. package/modules/dev-box/box-access.js +121 -4
  125. package/modules/dev-box/boxes.js +20 -0
  126. package/modules/dev-box/module.json +1 -1
  127. package/modules/dev-box/routes/box.js +87 -3
  128. package/modules/economy/credits.js +116 -25
  129. package/modules/economy/reward.js +8 -0
  130. package/modules/economy/streak.js +2 -1
  131. package/modules/governance/CLAUDE.md +15 -0
  132. package/modules/governance/catalog.js +419 -0
  133. package/modules/governance/config.js +174 -0
  134. package/modules/governance/db.js +125 -0
  135. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  136. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  137. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  138. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  139. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  140. package/modules/governance/module.json +10 -0
  141. package/modules/governance/protected-surfaces.js +88 -0
  142. package/modules/governance/protected-surfaces.json +80 -0
  143. package/modules/governance/rank-roles.js +83 -0
  144. package/modules/governance/resolver.js +221 -0
  145. package/modules/governance/routes/governance.js +89 -0
  146. package/modules/governance/routes/role-sync.js +49 -0
  147. package/modules/governance/session-scopes.js +127 -0
  148. package/modules/governance/session-scopes.json +38 -0
  149. package/modules/hall-ui/public/atlas.css +117 -0
  150. package/modules/hall-ui/public/atlas.html +3 -114
  151. package/modules/hall-ui/public/brand-apply.js +34 -6
  152. package/modules/hall-ui/public/builders.js +187 -219
  153. package/modules/hall-ui/public/diagrams.html +2 -0
  154. package/modules/hall-ui/public/dom-utils.js +27 -0
  155. package/modules/hall-ui/public/drachmae.html +2 -0
  156. package/modules/hall-ui/public/drachmae.js +54 -1
  157. package/modules/hall-ui/public/gate.css +98 -0
  158. package/modules/hall-ui/public/gate.html +3 -95
  159. package/modules/hall-ui/public/goal-inbox.js +4 -1
  160. package/modules/hall-ui/public/goals-page.js +626 -114
  161. package/modules/hall-ui/public/goals.css +79 -1
  162. package/modules/hall-ui/public/goals.html +38 -11
  163. package/modules/hall-ui/public/hall-widgets.js +62 -52
  164. package/modules/hall-ui/public/harbor.css +123 -0
  165. package/modules/hall-ui/public/harbor.html +3 -120
  166. package/modules/hall-ui/public/index.html +11 -4
  167. package/modules/hall-ui/public/instances-panel.js +4 -1
  168. package/modules/hall-ui/public/modules.css +63 -0
  169. package/modules/hall-ui/public/modules.html +3 -60
  170. package/modules/hall-ui/public/my-projects.html +78 -0
  171. package/modules/hall-ui/public/my-projects.js +142 -0
  172. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  173. package/modules/hall-ui/public/not-ready.html +2 -0
  174. package/modules/hall-ui/public/pair.css +73 -0
  175. package/modules/hall-ui/public/pair.html +3 -70
  176. package/modules/hall-ui/public/palette.js +302 -0
  177. package/modules/hall-ui/public/primer.css +13 -0
  178. package/modules/hall-ui/public/primer.html +2 -0
  179. package/modules/hall-ui/public/profile.html +2 -0
  180. package/modules/hall-ui/public/ranks.html +2 -0
  181. package/modules/hall-ui/public/roadmap.css +179 -0
  182. package/modules/hall-ui/public/roadmap.html +9 -172
  183. package/modules/hall-ui/public/roadmap.js +329 -316
  184. package/modules/hall-ui/public/scouting.html +45 -0
  185. package/modules/hall-ui/public/scouting.js +73 -0
  186. package/modules/hall-ui/public/sessions.css +16 -0
  187. package/modules/hall-ui/public/sessions.html +3 -13
  188. package/modules/hall-ui/public/settings.html +2 -0
  189. package/modules/hall-ui/public/settings.js +4 -4
  190. package/modules/hall-ui/public/shell.js +143 -18
  191. package/modules/hall-ui/public/style.css +231 -39
  192. package/modules/hall-ui/public/task-detail.js +347 -26
  193. package/modules/hall-ui/public/task.html +6 -1
  194. package/modules/hall-ui/public/watch.html +2 -0
  195. package/modules/hall-ui/public/work.html +8 -6
  196. package/modules/hall-ui/public/work.js +1 -1
  197. package/modules/ideas/inbox.js +61 -11
  198. package/modules/ideas/routes/inbox.js +23 -0
  199. package/modules/lifecycle/claim-eligibility.js +72 -0
  200. package/modules/lifecycle/db.js +519 -139
  201. package/modules/lifecycle/done-when.js +18 -3
  202. package/modules/lifecycle/github-push.js +19 -2
  203. package/modules/lifecycle/goal-advisory.js +114 -0
  204. package/modules/lifecycle/goal-authz.js +62 -0
  205. package/modules/lifecycle/lifecycle.js +9 -0
  206. package/modules/lifecycle/publish-reconciler.js +109 -6
  207. package/modules/lifecycle/routes/claims.js +68 -23
  208. package/modules/lifecycle/routes/done-when.js +110 -15
  209. package/modules/lifecycle/routes/goals.js +8 -38
  210. package/modules/lifecycle/routes/tasks.js +38 -6
  211. package/modules/lifecycle/ship-card.js +6 -0
  212. package/modules/onboarding/onboarding-state.js +1 -1
  213. package/modules/platform-identity/CLAUDE.md +15 -0
  214. package/modules/platform-identity/hub-device.js +147 -0
  215. package/modules/platform-identity/hub-keys.js +151 -0
  216. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  217. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  218. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  219. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  220. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  221. package/modules/platform-identity/module.json +18 -0
  222. package/modules/platform-identity/platform-identity.js +531 -0
  223. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  224. package/modules/platform-identity/routes/my-projects.js +140 -0
  225. package/modules/platform-identity/routes/projects.js +107 -0
  226. package/modules/platform-identity/routes/scouting.js +35 -0
  227. package/modules/platform-identity/routes/sso.js +402 -0
  228. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  229. package/modules/platform-identity/ui/.gitkeep +0 -0
  230. package/modules/security/routes/reports.js +10 -0
  231. package/modules/sessions/db.js +166 -21
  232. package/modules/sessions/module.json +1 -1
  233. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  234. package/modules/sessions/routes/sessions.js +33 -0
  235. package/modules/status-ui/public/explore.html +54 -0
  236. package/modules/status-ui/public/explore.js +67 -0
  237. package/package-lock.json +2 -2
  238. package/package.json +1 -1
  239. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  270. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  271. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  272. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  273. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  274. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  275. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  276. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  277. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  278. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  279. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  280. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  281. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  282. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  283. package/public-landing/create.html +252 -62
  284. package/public-landing/gate/README.md +137 -0
  285. package/public-landing/gate/dispmaps/bar.png +0 -0
  286. package/public-landing/gate/dispmaps/flat.png +0 -0
  287. package/public-landing/gate/dispmaps/key.png +0 -0
  288. package/public-landing/gate/index.html +587 -0
  289. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  290. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  291. package/public-landing/gate/space.css +799 -0
  292. package/public-landing/gate/space.js +1826 -0
  293. package/public-landing/gate/sprites/enter.png +0 -0
  294. package/public-landing/gate/sprites/search.png +0 -0
  295. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  296. package/public-landing/gate/sprites/tile.png +0 -0
  297. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  298. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  299. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  300. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  301. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  302. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  303. package/scripts/gds/abandon.js +6 -4
  304. package/scripts/gds/api.js +10 -5
  305. package/scripts/gds/api.ps1 +26 -0
  306. package/scripts/gds/api.sh +6 -0
  307. package/scripts/gds/audit-ships.js +7 -1
  308. package/scripts/gds/backfill-sessions.js +78 -18
  309. package/scripts/gds/backup.js +23 -1
  310. package/scripts/gds/box-connect-lib.js +124 -31
  311. package/scripts/gds/box-sync.js +66 -0
  312. package/scripts/gds/box.js +225 -53
  313. package/scripts/gds/cf-tunnel.js +145 -6
  314. package/scripts/gds/claim.js +34 -3
  315. package/scripts/gds/cli-lib.js +161 -21
  316. package/scripts/gds/code.js +6 -2
  317. package/scripts/gds/deploy-divergence.js +209 -0
  318. package/scripts/gds/dev-lib.js +309 -0
  319. package/scripts/gds/dev.js +322 -0
  320. package/scripts/gds/doctor.js +90 -61
  321. package/scripts/gds/fetch-art-key.js +1 -1
  322. package/scripts/gds/fetch-sound-prefs.js +2 -2
  323. package/scripts/gds/fitness.js +228 -12
  324. package/scripts/gds/gds-db-backup.service +16 -1
  325. package/scripts/gds/gds-db-offsite.service +9 -1
  326. package/scripts/gds/gen-api-client.js +1 -1
  327. package/scripts/gds/gen-api-docs.js +36 -14
  328. package/scripts/gds/gen-diagrams.js +45 -28
  329. package/scripts/gds/gen-file-map.js +2 -1
  330. package/scripts/gds/gen-freshness.js +32 -0
  331. package/scripts/gds/gen-repo-map.js +3 -2
  332. package/scripts/gds/gen-session-index.js +14 -5
  333. package/scripts/gds/hooks/pre-push.js +2 -2
  334. package/scripts/gds/init.js +60 -3
  335. package/scripts/gds/install-git-hooks.js +1 -1
  336. package/scripts/gds/key-card.js +15 -6
  337. package/scripts/gds/key-status.js +1 -1
  338. package/scripts/gds/linkify-refs.js +35 -9
  339. package/scripts/gds/lint-migrations.js +102 -0
  340. package/scripts/gds/login.js +58 -11
  341. package/scripts/gds/mirror-redact.js +5 -0
  342. package/scripts/gds/package-core.js +263 -4
  343. package/scripts/gds/paste-token.js +7 -1
  344. package/scripts/gds/preflight.js +126 -0
  345. package/scripts/gds/provision.js +268 -19
  346. package/scripts/gds/publish-manifest.js +22 -1
  347. package/scripts/gds/reauth.js +7 -3
  348. package/scripts/gds/regen-instance-docs.js +47 -0
  349. package/scripts/gds/run-unit-tests.js +42 -16
  350. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  351. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  352. package/scripts/gds/sequence.js +425 -0
  353. package/scripts/gds/session-cost.js +10 -1
  354. package/scripts/gds/setup.js +72 -5
  355. package/scripts/gds/shell.js +5 -3
  356. package/scripts/gds/ship.js +433 -59
  357. package/scripts/gds/smoke-gds.js +139 -8
  358. package/scripts/gds/start.js +171 -22
  359. package/scripts/gds/status.js +1 -1
  360. package/scripts/gds/triage.js +10 -9
  361. package/scripts/gds/upgrade.js +271 -7
  362. package/scripts/migrate.sh +10 -0
  363. package/scripts/status-mirror-sync.js +114 -84
  364. package/src/bongos/api-errors.js +1 -0
  365. package/src/bongos/auth.js +809 -107
  366. package/src/bongos/db-kernel.js +27 -0
  367. package/src/bongos/db.js +105 -0
  368. package/src/bongos/github-repos.js +93 -0
  369. package/src/bongos/module-scope-map.js +27 -1
  370. package/src/bongos/permission-path-check.js +136 -102
  371. package/src/bongos/repo-info.js +47 -11
  372. package/src/bongos/route-rank-check.js +429 -46
  373. package/src/bongos/routes/_helpers.js +12 -1
  374. package/src/bongos/routes/auth.js +312 -13
  375. package/src/bongos/routes/backup.js +58 -2
  376. package/src/bongos/routes/github.js +90 -0
  377. package/src/bongos/routes/instance.js +15 -3
  378. package/src/bongos/routes/me.js +35 -1
  379. package/src/bongos/routes.js +2 -0
  380. package/src/bongos/serve-internal.js +84 -15
  381. package/src/branding.js +49 -2
  382. package/src/instance-config.js +46 -0
  383. package/src/module-api.js +140 -1
  384. package/src/platform-server.js +86 -9
  385. package/tests/abandon_task.mjs +59 -3
  386. package/tests/api_cli_flags.mjs +53 -0
  387. package/tests/auth_page_gate.mjs +13 -0
  388. package/tests/backfill_sessions.mjs +127 -1
  389. package/tests/backup_cli.mjs +54 -0
  390. package/tests/bongos_box_connect.mjs +77 -0
  391. package/tests/box_access.mjs +130 -1
  392. package/tests/box_credential.mjs +125 -0
  393. package/tests/box_host_keys.mjs +24 -0
  394. package/tests/box_infra_resolve.mjs +149 -0
  395. package/tests/box_scope_session.mjs +6 -2
  396. package/tests/box_sync.mjs +55 -0
  397. package/tests/box_task_scope.mjs +99 -0
  398. package/tests/branding.mjs +41 -23
  399. package/tests/cf_ruleset_preflight.mjs +142 -0
  400. package/tests/cf_tunnel.mjs +37 -0
  401. package/tests/claim_gate_rebase.mjs +98 -0
  402. package/tests/clawback_confirmed_backlog.mjs +103 -0
  403. package/tests/cli_lib_formatters.mjs +20 -0
  404. package/tests/confirm_attribution.mjs +30 -46
  405. package/tests/credit_grant.mjs +198 -10
  406. package/tests/criterion_authoring_gate.mjs +272 -0
  407. package/tests/criterion_progress.mjs +33 -1
  408. package/tests/dev_lib.mjs +253 -0
  409. package/tests/devbox_artifact_gate.mjs +75 -0
  410. package/tests/devbox_dmg_backdrop.mjs +137 -0
  411. package/tests/devbox_icons.mjs +304 -0
  412. package/tests/devbox_installer_brand.mjs +232 -0
  413. package/tests/devbox_key_register.mjs +234 -0
  414. package/tests/docs_openapi_route.mjs +110 -0
  415. package/tests/doctor_hooks.mjs +141 -0
  416. package/tests/extract_json.mjs +140 -0
  417. package/tests/fitness.mjs +89 -0
  418. package/tests/gen_freshness.mjs +96 -0
  419. package/tests/github_repos_helpers.mjs +91 -0
  420. package/tests/github_token_store.mjs +121 -0
  421. package/tests/goal_advisory.mjs +251 -0
  422. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  423. package/tests/goal_routes.mjs +59 -4
  424. package/tests/goal_tier.mjs +12 -3
  425. package/tests/governance_catalog.mjs +129 -0
  426. package/tests/governance_claim_eligibility.mjs +262 -0
  427. package/tests/governance_config.mjs +187 -0
  428. package/tests/governance_ownership_scope.mjs +410 -0
  429. package/tests/governance_page_gates.mjs +324 -0
  430. package/tests/governance_parity.mjs +336 -0
  431. package/tests/governance_principals.mjs +232 -0
  432. package/tests/governance_protected_surfaces.mjs +208 -0
  433. package/tests/governance_require_permission.mjs +223 -0
  434. package/tests/governance_resolver.mjs +84 -0
  435. package/tests/governance_role_sync.mjs +231 -0
  436. package/tests/governance_seed.mjs +127 -0
  437. package/tests/governance_session_scope.mjs +434 -0
  438. package/tests/governance_vanilla_boot.mjs +203 -0
  439. package/tests/grade_attribution.mjs +7 -7
  440. package/tests/hall_audit.mjs +223 -0
  441. package/tests/hall_nav.mjs +191 -0
  442. package/tests/hall_palette.mjs +206 -0
  443. package/tests/hall_signout.mjs +124 -0
  444. package/tests/hook_user_agents.mjs +10 -0
  445. package/tests/idea_triage.mjs +162 -0
  446. package/tests/idp_device_exchange.mjs +198 -0
  447. package/tests/idp_federation.mjs +100 -0
  448. package/tests/init.mjs +51 -0
  449. package/tests/instance_config.mjs +65 -0
  450. package/tests/instance_mismatch_guard.mjs +23 -6
  451. package/tests/instance_release_config.mjs +104 -0
  452. package/tests/linkify_refs.mjs +15 -2
  453. package/tests/migrations_forward_safe.mjs +86 -0
  454. package/tests/module_api.mjs +1 -1
  455. package/tests/module_contributions.mjs +55 -0
  456. package/tests/module_loader.mjs +10 -5
  457. package/tests/module_scope_active_claims.mjs +94 -0
  458. package/tests/needs_rebase.mjs +92 -0
  459. package/tests/one_active_claim_per_session.mjs +76 -0
  460. package/tests/override_attribution.mjs +10 -8
  461. package/tests/override_request_ownership.mjs +8 -4
  462. package/tests/package_core.mjs +246 -1
  463. package/tests/parse_cookie_decode.mjs +42 -0
  464. package/tests/pay_on_land.mjs +129 -0
  465. package/tests/platform_boot.mjs +100 -1
  466. package/tests/post_login_landing.mjs +42 -0
  467. package/tests/preflight_checks.mjs +72 -0
  468. package/tests/provision.mjs +289 -7
  469. package/tests/pruned_lockfile_integrity.mjs +79 -0
  470. package/tests/publish_branch_route.mjs +53 -0
  471. package/tests/publish_reconciler.mjs +187 -2
  472. package/tests/repo_info_binding.mjs +248 -0
  473. package/tests/reward_gate.mjs +11 -2
  474. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  475. package/tests/reward_mode_surfacing.mjs +168 -0
  476. package/tests/route_permission_check.mjs +301 -0
  477. package/tests/route_rank_check.mjs +254 -12
  478. package/tests/route_validation.mjs +30 -0
  479. package/tests/sequence.mjs +267 -0
  480. package/tests/session_digest.mjs +44 -0
  481. package/tests/session_index.mjs +18 -6
  482. package/tests/session_records.mjs +39 -1
  483. package/tests/session_reward_on_land.mjs +381 -0
  484. package/tests/session_reward_reconcile.mjs +229 -0
  485. package/tests/ship_api_client_pathspec.mjs +100 -0
  486. package/tests/ship_base_flag.mjs +93 -0
  487. package/tests/ship_ci_deploy.mjs +140 -3
  488. package/tests/ship_upstream_deletion.mjs +57 -0
  489. package/tests/smoke_target.mjs +233 -0
  490. package/tests/start_env_guard.mjs +87 -0
  491. package/tests/start_rebase_warning.mjs +103 -0
  492. package/tests/status_mirror_sync.mjs +122 -0
  493. package/tests/stop_refcheck.mjs +19 -1
  494. package/tests/task_goal_link.mjs +15 -6
  495. package/tests/upgrade.mjs +393 -5
  496. package/tests/web_admission_status.mjs +162 -0
  497. package/tests/write_validation_gaps.mjs +110 -0
  498. package/.gitignore +0 -91
  499. package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +0 -94
  500. package/docs/adr/0140-cloudbongos-standalone-reprovision.md +0 -43
  501. package/scripts/hall-preview/fixtures/access-requests.json +0 -20
  502. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  503. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  504. package/scripts/hall-preview/fixtures/audit-log.json +0 -68
  505. package/scripts/hall-preview/fixtures/blockers__detail.json +0 -12
  506. package/scripts/hall-preview/fixtures/box__me.json +0 -5
  507. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -69
  508. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  509. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  510. package/scripts/hall-preview/fixtures/builders__roster.json +0 -48
  511. package/scripts/hall-preview/fixtures/goals.json +0 -502
  512. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  513. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  514. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  515. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  516. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  517. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  518. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  519. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  520. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -32
  521. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  522. package/scripts/hall-preview/fixtures/inbox__detail.json +0 -15
  523. package/scripts/hall-preview/fixtures/instance.json +0 -124
  524. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  525. package/scripts/hall-preview/fixtures/me.json +0 -476
  526. package/scripts/hall-preview/fixtures/me__art-key__own.json +0 -6
  527. package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +0 -209
  528. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  529. package/scripts/hall-preview/fixtures/me__render.json +0 -5
  530. package/scripts/hall-preview/fixtures/me__skill-prefs.json +0 -143
  531. package/scripts/hall-preview/fixtures/me__sound-prefs.json +0 -67
  532. package/scripts/hall-preview/fixtures/me__wandering.json +0 -43
  533. package/scripts/hall-preview/fixtures/override-requests.json +0 -15
  534. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  535. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  536. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  537. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  538. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  539. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  540. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  541. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  542. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  543. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  544. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  545. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  546. package/scripts/hall-preview/fixtures/security__docs.json +0 -10
  547. package/scripts/hall-preview/fixtures/security__reports.json +0 -31
  548. package/scripts/hall-preview/fixtures/sessions__search.json +0 -9
  549. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  550. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  551. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  552. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  553. package/scripts/hall-preview/fixtures/versions.json +0 -89
@@ -183,6 +183,32 @@ async function hasInvitedAccessRequest(login) {
183
183
  return rows.length > 0;
184
184
  }
185
185
 
186
+ // accessStateByLogin — the three admission-relevant facts about a github login,
187
+ // in ONE round trip: is there already a builder row (member), has an Archon
188
+ // approved them (invited), are they waiting on one (pending). Case-insensitive
189
+ // throughout, matching hasInvitedAccessRequest above.
190
+ //
191
+ // This exists for the "confirming access" waiting page (task 1002097): the page
192
+ // polls a probe that must distinguish "admission is imminent" from "genuine
193
+ // stranger", and doing that with three separate helpers would mean three
194
+ // queries per poll per visitor. It reports FACTS ONLY — the admission DECISION
195
+ // stays in auth.firstTimeAdmissionBlocked, which is the single gate both flows
196
+ // share (SR-19). Nothing here grants access.
197
+ async function accessStateByLogin(login) {
198
+ const { rows } = await pool.query(
199
+ `SELECT
200
+ EXISTS (SELECT 1 FROM builders
201
+ WHERE lower(github_login) = lower($1)) AS member,
202
+ EXISTS (SELECT 1 FROM access_requests
203
+ WHERE lower(github_login) = lower($1) AND status = 'invited') AS invited,
204
+ EXISTS (SELECT 1 FROM access_requests
205
+ WHERE lower(github_login) = lower($1) AND status = 'pending') AS pending`,
206
+ [login]
207
+ );
208
+ const r = rows[0] || {};
209
+ return { member: !!r.member, invited: !!r.invited, pending: !!r.pending };
210
+ }
211
+
186
212
  // --- Auth sessions (kernel: the builder_sessions token store auth.js drives) ----
187
213
 
188
214
  // SESSION_TTL_MS — session TTL on create/refresh. Centralized so the migration's
@@ -247,6 +273,7 @@ module.exports = {
247
273
  seatFirstAdminIfUnclaimed,
248
274
  getBuilderByGithubId,
249
275
  hasInvitedAccessRequest,
276
+ accessStateByLogin,
250
277
  createSession,
251
278
  lookupSession,
252
279
  };
package/src/bongos/db.js CHANGED
@@ -25,6 +25,7 @@
25
25
  // grade-count SQL runs on both sides of the kernel↔module line — keep in sync.
26
26
 
27
27
  const { pool } = require('./pool');
28
+ const secretBox = require('./secret-box');
28
29
  // Module seam (ADR 0083 / BV1.R43). The rank/status-change paths EMIT
29
30
  // `builder.box-reconcile-needed` AFTER COMMIT (best-effort) so the dev-box module
30
31
  // can reconcile a droplet a demotion/graduation implies — never a direct require
@@ -205,6 +206,68 @@ async function updateBuilderDisciplines(builderId, disciplines) {
205
206
  // { enc: null, ... } when no key is set.
206
207
 
207
208
 
209
+ // ---- GitHub OAuth repo token, encrypted at rest (core_192 / task 1002099) ----
210
+ //
211
+ // The onboarding wizard (public-landing/create.html) opts into `public_repo` at
212
+ // sign-in so it can list + create the user's repos. That user-to-server GitHub
213
+ // token is held here BRIEFLY: encrypted with secret-box (master key in server env
214
+ // only — the plaintext never touches the DB) and given a short TTL (one wizard
215
+ // sitting), read back by the repo picker/creator, then deleted on use. It is the
216
+ // auth system's OWN handshake token (distinct from a feature's third-party key
217
+ // like the art module's Gemini key, ADR 0102), so it lives in core auth. secret-box
218
+ // is the gate: with no master key configured we NEVER store a plaintext token —
219
+ // capture no-ops and the wizard degrades to manual repo entry (ADR 0143).
220
+ const GITHUB_TOKEN_TTL_MS = 60 * 60 * 1000; // 1h — one wizard sitting.
221
+
222
+ // Store (or replace) the builder's GitHub repo token. `token` is the raw
223
+ // user-to-server access token; it is encrypted here so the plaintext never touches
224
+ // the DB. No-ops when secret-box is unconfigured (returns { stored:false }).
225
+ async function upsertGithubToken({ builderId, token, scope = null, ttlMs = GITHUB_TOKEN_TTL_MS, p = pool }) {
226
+ if (!secretBox.isConfigured()) return { stored: false };
227
+ const enc = secretBox.encrypt(token);
228
+ const expiresAt = new Date(Date.now() + ttlMs);
229
+ await p.query(
230
+ `INSERT INTO github_oauth_tokens (builder_id, token_enc, scope, created_at, expires_at)
231
+ VALUES ($1, $2, $3, now(), $4)
232
+ ON CONFLICT (builder_id) DO UPDATE
233
+ SET token_enc = EXCLUDED.token_enc, scope = EXCLUDED.scope,
234
+ created_at = now(), expires_at = EXCLUDED.expires_at`,
235
+ [builderId, enc, scope, expiresAt],
236
+ );
237
+ return { stored: true, expires_at: expiresAt };
238
+ }
239
+
240
+ // Read + decrypt the builder's GitHub token, or null when there is none, it has
241
+ // expired, or secret-box is unconfigured. Lazily deletes an expired row so the
242
+ // table self-cleans without a cron (mirrors the deviceFlows reaping in auth.js).
243
+ // The 503-vs-403 distinction the endpoint needs is made by the endpoint checking
244
+ // secretBox.isConfigured() itself before calling this.
245
+ async function getGithubToken({ builderId, p = pool }) {
246
+ if (!secretBox.isConfigured()) return null;
247
+ const { rows } = await p.query(
248
+ `SELECT token_enc, scope, expires_at FROM github_oauth_tokens WHERE builder_id = $1`,
249
+ [builderId],
250
+ );
251
+ const row = rows[0];
252
+ if (!row) return null;
253
+ if (new Date(row.expires_at).getTime() <= Date.now()) {
254
+ await p.query(`DELETE FROM github_oauth_tokens WHERE builder_id = $1`, [builderId]).catch(() => {});
255
+ return null;
256
+ }
257
+ let token;
258
+ try { token = secretBox.decrypt(row.token_enc); }
259
+ catch { return null; } // a blob that won't decrypt (e.g. rotated master key) reads as "none".
260
+ return { token, scope: row.scope, expires_at: row.expires_at };
261
+ }
262
+
263
+ // Delete the builder's token (called after the wizard's terminal enqueue, and on
264
+ // expiry). Best-effort; safe to call when nothing is stored.
265
+ async function deleteGithubToken({ builderId, p = pool }) {
266
+ await p.query(`DELETE FROM github_oauth_tokens WHERE builder_id = $1`, [builderId]);
267
+ return { deleted: true };
268
+ }
269
+
270
+
208
271
  // leaderboard() carved into modules/economy/credits.js (BV1.R77 / ADR 0093 §1-2).
209
272
  // Core read routes resolve it via the `reward` kernel port.
210
273
 
@@ -235,6 +298,15 @@ async function updateBuilderDisciplines(builderId, disciplines) {
235
298
  // shipped." Pure decision helper is exported so tests/rank_gate.mjs can exercise
236
299
  // the threshold without a DB.
237
300
 
301
+ // REQUIRES_RANK_TIER — the canonical rank → tier (1-based) map: the rank "brain".
302
+ // MUST stay byte-identical to permission-path-check.js RANK_TIER and
303
+ // modules/lifecycle/db.js REQUIRES_RANK_TIER (tests/permission_path.mjs guards the
304
+ // drift; gate-review.js + diagram-facts.js parse this literal by regex, so keep it
305
+ // an inline object literal). Restores the binding the LIVE_RANK_LADDER carve
306
+ // (ADR 0102) left dangling — both singleRungPromotionError below and the
307
+ // db.REQUIRES_RANK_TIER export depend on it.
308
+ const REQUIRES_RANK_TIER = { xenos: 1, thetes: 2, metic: 3, archon: 4 };
309
+
238
310
  function singleRungPromotionError(oldRank, newRank) {
239
311
  const a = REQUIRES_RANK_TIER[oldRank];
240
312
  const b = REQUIRES_RANK_TIER[newRank];
@@ -267,6 +339,24 @@ function singleRungPromotionError(oldRank, newRank) {
267
339
  // has nothing to collide on, so it's returned unchanged. Pure + exported so
268
340
  // tests can exercise it without a DB; claimTask calls it inside the txn.
269
341
 
342
+ // syncGovernanceRankRole — keep governance_builder_roles in step with builders.rank
343
+ // (BV1.R95b, ADR 0151). Resolved through the `governance.roleSync` kernel port and
344
+ // run on the CALLER's transaction client, so the role rotation is atomic with the
345
+ // rank write beside it. Core never requires modules/governance/ (ADR 0083).
346
+ //
347
+ // A missing port means the governance module is disabled, and skipping is the
348
+ // fail-closed answer: the builder then holds no role and resolves to ZERO
349
+ // permissions. Admitting anything here would make disabling a module a privilege
350
+ // escalation — the same call requirePermission() makes on a missing port.
351
+ //
352
+ // TWINNED with modules/lifecycle/db.js (the boundary-forced _applyRankChangeTx
353
+ // duplication, ADR 0091 §2) — keep the two in sync.
354
+ async function syncGovernanceRankRole(client, builderId, rank) {
355
+ const roleSync = seams.resolveOptional('governance.roleSync');
356
+ if (!roleSync || typeof roleSync.syncRankRole !== 'function') return null;
357
+ return roleSync.syncRankRole(client, { builderId, rank });
358
+ }
359
+
270
360
  async function _applyRankChangeTx(client, { builderId, newRank, actorBuilderId, reasonNote = null, enforceSingleRungPromotion = false }) {
271
361
  const { rows } = await client.query(
272
362
  `SELECT id, rank, status FROM builders WHERE id = $1 FOR UPDATE`,
@@ -291,6 +381,17 @@ async function _applyRankChangeTx(client, { builderId, newRank, actorBuilderId,
291
381
  [builderId, newRank]
292
382
  );
293
383
 
384
+ // BV1.R95b — rotate the seeded rank-role IN THIS TRANSACTION. A DEMOTION removes
385
+ // the higher role rather than merely adding the lower one; without that, a demoted
386
+ // Archon keeps resolving Archon permissions (the ADR 0016 freshness promise broken
387
+ // one layer beneath the uncached resolver).
388
+ //
389
+ // Deliberately NOT wrapped in try/catch. If the rotation cannot be written the rank
390
+ // write must roll back with it: a committed rank change whose role rotation failed
391
+ // IS the privilege-retention bug, just with a smaller window. Refusing leaves the
392
+ // builder consistently at their OLD rank, which the actor can retry.
393
+ await syncGovernanceRankRole(client, builderId, newRank);
394
+
294
395
  // V3.R28 / #249 — ceremony delta. Promotion (moving UP the ladder = lower
295
396
  // index in RANKS) earns +5; demotion is audit-only (0).
296
397
  const oldIdx = RANKS.indexOf(oldRank);
@@ -897,6 +998,7 @@ module.exports = {
897
998
  SESSION_TTL_MS,
898
999
  LIVE_RANK_LADDER,
899
1000
  singleRungPromotionError,
1001
+ REQUIRES_RANK_TIER,
900
1002
  recentKarmaForBuilder,
901
1003
  karmaDelta30d,
902
1004
  insertAuditLog,
@@ -908,4 +1010,7 @@ module.exports = {
908
1010
  upsertSecurityDoc,
909
1011
  getSecurityDoc,
910
1012
  listSecurityDocs,
1013
+ upsertGithubToken,
1014
+ getGithubToken,
1015
+ deleteGithubToken,
911
1016
  };
@@ -0,0 +1,93 @@
1
+ // GitHub repo list/create on behalf of the signed-in user — the server half of the
2
+ // onboarding wizard's repo picker (adopt) + auto-create (fresh). Task 1002099 / ADR 0143.
3
+ //
4
+ // Raw `fetch` against GitHub's REST API (the house style — see auth.js
5
+ // fetchGithubUser; no octokit dependency). The user-to-server token these take is
6
+ // the `public_repo`-scoped token the web callback captured and stored (db.js
7
+ // github_oauth_tokens); callers pass the decrypted token in, this module never
8
+ // touches storage. `fetchImpl` is injectable so tests can drive it with a mock and
9
+ // never hit the network.
10
+
11
+ const { userAgent } = require('../branding');
12
+
13
+ const GH_API = 'https://api.github.com';
14
+ const PER_PAGE = 100;
15
+ // Up to 300 most-recently-updated OWNED repos — plenty to back a picker for the vast
16
+ // majority of accounts, and a hard bound so a power user can't make us page forever
17
+ // (v1 cap; the picker filters this set client-and-server-side by substring).
18
+ const MAX_PAGES = 3;
19
+
20
+ class GithubApiError extends Error {
21
+ constructor(message, { status, code } = {}) {
22
+ super(message);
23
+ this.name = 'GithubApiError';
24
+ this.status = status;
25
+ this.code = code;
26
+ }
27
+ }
28
+
29
+ function ghHeaders(token, extra = {}) {
30
+ return {
31
+ Authorization: `Bearer ${token}`,
32
+ 'User-Agent': userAgent(),
33
+ Accept: 'application/vnd.github+json',
34
+ ...extra,
35
+ };
36
+ }
37
+
38
+ // List the signed-in user's OWN repos (affiliation=owner so `full_name` is always
39
+ // `login/repo` and the org-OAuth-policy complexity is out of scope for v1),
40
+ // most-recently-updated first, optionally filtered by a case-insensitive substring
41
+ // `q` on the full name. Returns [{ full_name, name, owner, private }].
42
+ async function listUserRepos(token, { q = '', fetchImpl = fetch } = {}) {
43
+ const out = [];
44
+ for (let page = 1; page <= MAX_PAGES; page++) {
45
+ const url = `${GH_API}/user/repos?per_page=${PER_PAGE}&page=${page}&sort=updated&affiliation=owner`;
46
+ const res = await fetchImpl(url, { headers: ghHeaders(token) });
47
+ if (res.status === 401) {
48
+ throw new GithubApiError('GitHub rejected the stored token', { status: 401, code: 'github_unauthorized' });
49
+ }
50
+ if (!res.ok) {
51
+ throw new GithubApiError(`GitHub /user/repos failed (${res.status})`, { status: res.status, code: 'github_error' });
52
+ }
53
+ const rows = await res.json();
54
+ if (!Array.isArray(rows) || rows.length === 0) break;
55
+ for (const r of rows) {
56
+ out.push({
57
+ full_name: r.full_name,
58
+ name: r.name,
59
+ owner: r.owner && r.owner.login,
60
+ private: !!r.private,
61
+ });
62
+ }
63
+ if (rows.length < PER_PAGE) break;
64
+ }
65
+ const needle = String(q || '').trim().toLowerCase();
66
+ return needle ? out.filter((r) => String(r.full_name).toLowerCase().includes(needle)) : out;
67
+ }
68
+
69
+ // Create an EMPTY repo in the signed-in user's personal account. auto_init:false =
70
+ // no README/first commit (exactly the "leave it completely empty" the manual step
71
+ // demanded); private:false because we hold only `public_repo`. Returns
72
+ // { full_name, html_url }. A 422 (name already exists / invalid) becomes a typed
73
+ // `name_taken` error the route maps to a friendly 409 rather than an opaque 500.
74
+ async function createUserRepo(token, { name, fetchImpl = fetch } = {}) {
75
+ const res = await fetchImpl(`${GH_API}/user/repos`, {
76
+ method: 'POST',
77
+ headers: ghHeaders(token, { 'Content-Type': 'application/json' }),
78
+ body: JSON.stringify({ name, private: false, auto_init: false }),
79
+ });
80
+ if (res.status === 201) {
81
+ const r = await res.json();
82
+ return { full_name: r.full_name, html_url: r.html_url };
83
+ }
84
+ if (res.status === 401) {
85
+ throw new GithubApiError('GitHub rejected the stored token', { status: 401, code: 'github_unauthorized' });
86
+ }
87
+ if (res.status === 422) {
88
+ throw new GithubApiError('A repository with that name already exists on your account', { status: 422, code: 'name_taken' });
89
+ }
90
+ throw new GithubApiError(`GitHub create-repo failed (${res.status})`, { status: res.status, code: 'github_error' });
91
+ }
92
+
93
+ module.exports = { listUserRepos, createUserRepo, GithubApiError, MAX_PAGES };
@@ -166,6 +166,18 @@ const MODULE_GLOBS = {
166
166
  // to the kernel key (02-module-map §5).
167
167
  'modules/security/',
168
168
  ],
169
+ // --- configurable roles & permissions: the permission resolver, catalog, and
170
+ // requirePermission gate (BV1 goal 1000030, ADR 0151). A core default:true
171
+ // module. `protected` DERIVES true — its 'modules/governance/' glob is in
172
+ // PROTECTED_GLOBS (the authz core) — so creating a goal scoped to governance is
173
+ // Archon-only (BV1.R57 / POST /goals). The config globs are the per-instance
174
+ // role templates (R96), listed here as goal territory; the module code lands in
175
+ // R93+ (the carve precedes the feature — ADR 0086 §4). Written as exact paths,
176
+ // not 'config/governance*.json' — the touches convention has no wildcards. ---
177
+ governance: [
178
+ 'modules/governance/',
179
+ 'config/governance.json', 'config/governance.neutral.json',
180
+ ],
169
181
  // --- the two web surfaces ---
170
182
  // BV1.R85: hall-UI graduated to modules/hall-ui/ — public-builders/ moved to
171
183
  // modules/hall-ui/public/ and is now a loader-discovered web-surface module
@@ -194,7 +206,21 @@ const MODULE_GLOBS = {
194
206
  // core/CLI-side under scripts/discord/.
195
207
  'scripts/discord/', 'modules/discord/',
196
208
  ],
197
- 'dev-box': ['modules/dev-box/', 'devbox-app/'],
209
+ // --- per-builder cloud dev boxes (DO droplets + Cloudflare tunnels), the sandbox
210
+ // preview, server-mediated branch publish. First module carved to modules/dev-box/
211
+ // (BV1.R43 — ADR 0083). Like the lifecycle/onboarding CLIs, the dev-box OPERATOR +
212
+ // connect commands travel with the domain but stay under scripts/gds/: box.js (the
213
+ // DO/CF provisioning control plane), box-auth-check, box-connect-lib, and the box
214
+ // smoke test. Listing them here so a `dev-box`-scoped goal's wall covers the box
215
+ // provisioning / bring-up work (BV1.R91, goal 1000051 C2), not just modules/dev-box/.
216
+ // The box BRING-UP scripts (infra/box-*.sh — box-source-fetch, heartbeat, terminal
217
+ // units) are INSTANCE-VENDORED (ADR 0144; not tracked in core), so they are not
218
+ // listed here yet — they come under this key when de-vendored (task 1002243).
219
+ 'dev-box': [
220
+ 'modules/dev-box/', 'devbox-app/',
221
+ 'scripts/gds/box.js', 'scripts/gds/box-auth-check.js', 'scripts/gds/box-connect-lib.js',
222
+ 'scripts/gds/smoke-box.sh',
223
+ ],
198
224
  };
199
225
 
200
226
  // A glob set is protected iff it overlaps the imported PROTECTED_GLOBS — the one