@bongos/core 1.18.3 → 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 (469) hide show
  1. package/.bongos-core.json +1575 -285
  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 +4 -2
  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 +6 -1
  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/0144-devbox-rehome-onto-cloudbongos-plane.md +41 -0
  27. package/docs/adr/0144-federated-single-logout-backchannel.md +42 -0
  28. package/docs/adr/0145-devbox-app-branding-driven-module.md +44 -0
  29. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +62 -0
  30. package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +53 -0
  31. package/docs/adr/0147-standalone-live-docs-regen.md +39 -0
  32. package/docs/adr/0148-task-scoped-box-source-access.md +48 -0
  33. package/docs/adr/0149-bongos-dev-local-launcher.md +57 -0
  34. package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +68 -0
  35. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +229 -0
  36. package/docs/adr/0152-landing-gate-served-by-the-core-app.md +92 -0
  37. package/docs/adr/0152-metic-task-abandonment.md +67 -0
  38. package/docs/adr/0153-sequential-chain-runner.md +51 -0
  39. package/docs/adr/0154-goal-owner-criterion-authoring.md +86 -0
  40. package/docs/adr/README.md +10 -0
  41. package/docs/api/openapi.json +843 -17
  42. package/docs/api-reference.md +23 -10
  43. package/docs/architecture.md +4 -2
  44. package/docs/branding-contract.md +3 -1
  45. package/docs/canonical-permissions.md +21 -8
  46. package/docs/file-map.md +8 -0
  47. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +2 -2
  48. package/docs/onboarding/diagrams/02-rank-ladder.mmd +3 -1
  49. package/docs/onboarding/diagrams/05-versioning.mmd +1 -3
  50. package/docs/onboarding/diagrams/assertions.json +4 -7
  51. package/docs/onboarding/drachmae-and-karma.md +3 -3
  52. package/docs/onboarding/primer.md +17 -16
  53. package/docs/onboarding/slash-commands.md +124 -0
  54. package/docs/recipes/builder-box-lifecycle.md +23 -0
  55. package/docs/recipes/devbox-app-release.md +14 -4
  56. package/docs/recipes/instance-first-run.md +16 -0
  57. package/docs/recipes/local-dev.md +81 -0
  58. package/docs/recipes/ops-gotchas.md +19 -1
  59. package/docs/recipes/overnight-builder.md +1 -1
  60. package/docs/recipes/parallel-goal-waves.md +174 -0
  61. package/docs/recipes/ship-and-regrade.md +2 -2
  62. package/docs/recipes/standalone-live-docs.md +48 -0
  63. package/docs/recipes/work-on-a-task-from-your-dev-box.md +108 -0
  64. package/migrations/003_pms.sql +6 -7
  65. package/migrations/006_pms_v2.sql +3 -31
  66. package/migrations/core_193_task_needs_rebase.sql +28 -0
  67. package/migrations/core_194_confirmed_backlog_clawback.sql +63 -0
  68. package/migrations/core_195_idea_triage_provenance.sql +57 -0
  69. package/migrations/core_196_session_reward_topup.sql +69 -0
  70. package/modules/autonomy/pollers/routine-timers.js +9 -8
  71. package/modules/builder-settings/wandering-prefs.js +61 -18
  72. package/modules/dev-box/app/README.md +73 -0
  73. package/modules/dev-box/app/assets/tray/mac-alertTemplate.png +0 -0
  74. package/modules/dev-box/app/assets/tray/mac-alertTemplate@2x.png +0 -0
  75. package/modules/dev-box/app/assets/tray/mac-busyTemplate.png +0 -0
  76. package/modules/dev-box/app/assets/tray/mac-busyTemplate@2x.png +0 -0
  77. package/modules/dev-box/app/assets/tray/mac-offTemplate.png +0 -0
  78. package/modules/dev-box/app/assets/tray/mac-offTemplate@2x.png +0 -0
  79. package/modules/dev-box/app/assets/tray/mac-onTemplate.png +0 -0
  80. package/modules/dev-box/app/assets/tray/mac-onTemplate@2x.png +0 -0
  81. package/modules/dev-box/app/assets/tray/win-alert.png +0 -0
  82. package/modules/dev-box/app/assets/tray/win-busy.png +0 -0
  83. package/modules/dev-box/app/assets/tray/win-off.png +0 -0
  84. package/modules/dev-box/app/assets/tray/win-on.png +0 -0
  85. package/modules/dev-box/app/build-resources/dmg-background.png +0 -0
  86. package/modules/dev-box/app/build-resources/dmg-background@2x.png +0 -0
  87. package/modules/dev-box/app/build-resources/icon.png +0 -0
  88. package/modules/dev-box/app/electron-builder.tmpl.yml +95 -0
  89. package/modules/dev-box/app/electron-builder.yml +95 -0
  90. package/modules/dev-box/app/package-lock.json +5291 -0
  91. package/modules/dev-box/app/package.json +30 -0
  92. package/modules/dev-box/app/renderer/app.js +319 -0
  93. package/modules/dev-box/app/renderer/index.html +45 -0
  94. package/modules/dev-box/app/renderer/styles.css +246 -0
  95. package/modules/dev-box/app/renderer/theme.generated.css +16 -0
  96. package/modules/dev-box/app/scripts/apply-dmg-backdrop.sh +82 -0
  97. package/modules/dev-box/app/scripts/dmgbuild-settings.py +39 -0
  98. package/modules/dev-box/app/scripts/gen-brand.js +138 -0
  99. package/modules/dev-box/app/scripts/gen-dmg-backdrop.py +323 -0
  100. package/modules/dev-box/app/scripts/gen-icons.js +286 -0
  101. package/modules/dev-box/app/scripts/vendor-client.js +23 -0
  102. package/modules/dev-box/app/src/box-controller.js +287 -0
  103. package/modules/dev-box/app/src/brand.generated.json +13 -0
  104. package/modules/dev-box/app/src/brand.js +16 -0
  105. package/modules/dev-box/app/src/config.js +19 -0
  106. package/modules/dev-box/app/src/gds-client.js +90 -0
  107. package/modules/dev-box/app/src/main.js +610 -0
  108. package/modules/dev-box/app/src/pairing.js +57 -0
  109. package/modules/dev-box/app/src/preload.js +29 -0
  110. package/modules/dev-box/app/src/session-store.js +58 -0
  111. package/modules/dev-box/app/src/ssh-setup.js +569 -0
  112. package/modules/dev-box/app/src/task-picker.js +70 -0
  113. package/modules/dev-box/app/src/tray.js +99 -0
  114. package/modules/dev-box/app/src/updater.js +55 -0
  115. package/modules/dev-box/app/src/vendor/bongos-client.cjs +698 -0
  116. package/modules/dev-box/app/test/unit.mjs +526 -0
  117. package/modules/dev-box/box-access.js +121 -4
  118. package/modules/dev-box/boxes.js +20 -0
  119. package/modules/dev-box/module.json +1 -1
  120. package/modules/dev-box/routes/box.js +87 -3
  121. package/modules/economy/credits.js +116 -25
  122. package/modules/economy/reward.js +8 -0
  123. package/modules/economy/streak.js +2 -1
  124. package/modules/governance/CLAUDE.md +15 -0
  125. package/modules/governance/catalog.js +419 -0
  126. package/modules/governance/config.js +174 -0
  127. package/modules/governance/db.js +125 -0
  128. package/modules/governance/migrations/governance_001_tables.sql +81 -0
  129. package/modules/governance/migrations/governance_002_seed_and_backfill.sql +103 -0
  130. package/modules/governance/migrations/governance_003_task_abandon_metic.sql +28 -0
  131. package/modules/governance/migrations/governance_004_criterion_create.sql +39 -0
  132. package/modules/governance/migrations/governance_005_resync_builder_rank_roles.sql +56 -0
  133. package/modules/governance/module.json +10 -0
  134. package/modules/governance/protected-surfaces.js +88 -0
  135. package/modules/governance/protected-surfaces.json +80 -0
  136. package/modules/governance/rank-roles.js +83 -0
  137. package/modules/governance/resolver.js +221 -0
  138. package/modules/governance/routes/governance.js +89 -0
  139. package/modules/governance/routes/role-sync.js +49 -0
  140. package/modules/governance/session-scopes.js +127 -0
  141. package/modules/governance/session-scopes.json +38 -0
  142. package/modules/hall-ui/public/atlas.css +117 -0
  143. package/modules/hall-ui/public/atlas.html +3 -114
  144. package/modules/hall-ui/public/brand-apply.js +34 -6
  145. package/modules/hall-ui/public/builders.js +187 -219
  146. package/modules/hall-ui/public/diagrams.html +2 -0
  147. package/modules/hall-ui/public/dom-utils.js +27 -0
  148. package/modules/hall-ui/public/drachmae.html +2 -0
  149. package/modules/hall-ui/public/drachmae.js +54 -1
  150. package/modules/hall-ui/public/gate.css +98 -0
  151. package/modules/hall-ui/public/gate.html +3 -95
  152. package/modules/hall-ui/public/goal-inbox.js +4 -1
  153. package/modules/hall-ui/public/goals-page.js +626 -114
  154. package/modules/hall-ui/public/goals.css +79 -1
  155. package/modules/hall-ui/public/goals.html +38 -11
  156. package/modules/hall-ui/public/hall-widgets.js +62 -52
  157. package/modules/hall-ui/public/harbor.css +123 -0
  158. package/modules/hall-ui/public/harbor.html +3 -120
  159. package/modules/hall-ui/public/index.html +11 -4
  160. package/modules/hall-ui/public/instances-panel.js +4 -1
  161. package/modules/hall-ui/public/modules.css +63 -0
  162. package/modules/hall-ui/public/modules.html +3 -60
  163. package/modules/hall-ui/public/new-project-wizard.js +7 -3
  164. package/modules/hall-ui/public/not-ready.html +2 -0
  165. package/modules/hall-ui/public/pair.css +73 -0
  166. package/modules/hall-ui/public/pair.html +3 -70
  167. package/modules/hall-ui/public/palette.js +302 -0
  168. package/modules/hall-ui/public/primer.css +13 -0
  169. package/modules/hall-ui/public/primer.html +2 -0
  170. package/modules/hall-ui/public/profile.html +2 -0
  171. package/modules/hall-ui/public/ranks.html +2 -0
  172. package/modules/hall-ui/public/roadmap.css +179 -0
  173. package/modules/hall-ui/public/roadmap.html +9 -172
  174. package/modules/hall-ui/public/roadmap.js +329 -316
  175. package/modules/hall-ui/public/sessions.css +16 -0
  176. package/modules/hall-ui/public/sessions.html +3 -13
  177. package/modules/hall-ui/public/settings.html +2 -0
  178. package/modules/hall-ui/public/settings.js +4 -4
  179. package/modules/hall-ui/public/shell.js +143 -18
  180. package/modules/hall-ui/public/style.css +231 -39
  181. package/modules/hall-ui/public/task-detail.js +347 -26
  182. package/modules/hall-ui/public/task.html +6 -1
  183. package/modules/hall-ui/public/watch.html +2 -0
  184. package/modules/hall-ui/public/work.html +8 -6
  185. package/modules/hall-ui/public/work.js +1 -1
  186. package/modules/ideas/inbox.js +61 -11
  187. package/modules/ideas/routes/inbox.js +23 -0
  188. package/modules/lifecycle/claim-eligibility.js +72 -0
  189. package/modules/lifecycle/db.js +519 -139
  190. package/modules/lifecycle/done-when.js +18 -3
  191. package/modules/lifecycle/github-push.js +19 -2
  192. package/modules/lifecycle/goal-advisory.js +114 -0
  193. package/modules/lifecycle/goal-authz.js +62 -0
  194. package/modules/lifecycle/lifecycle.js +9 -0
  195. package/modules/lifecycle/publish-reconciler.js +109 -6
  196. package/modules/lifecycle/routes/claims.js +68 -23
  197. package/modules/lifecycle/routes/done-when.js +110 -15
  198. package/modules/lifecycle/routes/goals.js +8 -38
  199. package/modules/lifecycle/routes/tasks.js +38 -6
  200. package/modules/lifecycle/ship-card.js +6 -0
  201. package/modules/onboarding/onboarding-state.js +1 -1
  202. package/modules/platform-identity/CLAUDE.md +15 -0
  203. package/modules/platform-identity/hub-device.js +147 -0
  204. package/modules/platform-identity/hub-keys.js +151 -0
  205. package/modules/platform-identity/migrations/platform_identity_001_tables.sql +114 -0
  206. package/modules/platform-identity/migrations/platform_identity_002_client_origin_index.sql +18 -0
  207. package/modules/platform-identity/migrations/platform_identity_003_project_memberships.sql +42 -0
  208. package/modules/platform-identity/migrations/platform_identity_004_projects.sql +44 -0
  209. package/modules/platform-identity/migrations/platform_identity_005_builder_activity.sql +42 -0
  210. package/modules/platform-identity/module.json +18 -0
  211. package/modules/platform-identity/platform-identity.js +531 -0
  212. package/modules/platform-identity/pollers/code-sweep.js +43 -0
  213. package/modules/platform-identity/routes/my-projects.js +140 -0
  214. package/modules/platform-identity/routes/projects.js +107 -0
  215. package/modules/platform-identity/routes/scouting.js +35 -0
  216. package/modules/platform-identity/routes/sso.js +402 -0
  217. package/modules/platform-identity/tests/platform-identity.mjs +388 -0
  218. package/modules/platform-identity/ui/.gitkeep +0 -0
  219. package/modules/security/routes/reports.js +10 -0
  220. package/modules/sessions/db.js +166 -21
  221. package/modules/sessions/module.json +1 -1
  222. package/modules/sessions/pollers/session-reward-reconcile.js +78 -0
  223. package/modules/sessions/routes/sessions.js +33 -0
  224. package/package-lock.json +2 -2
  225. package/package.json +1 -1
  226. package/public-landing/assets/anim/idle/frame_00.webp +0 -0
  227. package/public-landing/assets/anim/idle/frame_01.webp +0 -0
  228. package/public-landing/assets/anim/idle/frame_02.webp +0 -0
  229. package/public-landing/assets/anim/idle/frame_03.webp +0 -0
  230. package/public-landing/assets/anim/idle/frame_04.webp +0 -0
  231. package/public-landing/assets/anim/idle/frame_05.webp +0 -0
  232. package/public-landing/assets/anim/idle/frame_06.webp +0 -0
  233. package/public-landing/assets/anim/idle/frame_07.webp +0 -0
  234. package/public-landing/assets/anim/idle/frame_08.webp +0 -0
  235. package/public-landing/assets/anim/idle/frame_09.webp +0 -0
  236. package/public-landing/assets/anim/idle/frame_10.webp +0 -0
  237. package/public-landing/assets/anim/idle/frame_11.webp +0 -0
  238. package/public-landing/assets/anim/idle/frame_12.webp +0 -0
  239. package/public-landing/assets/anim/idle/frame_13.webp +0 -0
  240. package/public-landing/assets/anim/idle/frame_14.webp +0 -0
  241. package/public-landing/assets/anim/idle/frame_15.webp +0 -0
  242. package/public-landing/assets/anim/idle/frame_16.webp +0 -0
  243. package/public-landing/assets/anim/idle/frame_17.webp +0 -0
  244. package/public-landing/assets/anim/idle/frame_18.webp +0 -0
  245. package/public-landing/assets/anim/idle/frame_19.webp +0 -0
  246. package/public-landing/assets/anim/idle/frame_20.webp +0 -0
  247. package/public-landing/assets/anim/idle/frame_21.webp +0 -0
  248. package/public-landing/assets/anim/idle/frame_22.webp +0 -0
  249. package/public-landing/assets/anim/idle/frame_23.webp +0 -0
  250. package/public-landing/assets/anim/idle/frame_24.webp +0 -0
  251. package/public-landing/assets/anim/idle/frame_25.webp +0 -0
  252. package/public-landing/assets/anim/idle/frame_26.webp +0 -0
  253. package/public-landing/assets/anim/idle/frame_27.webp +0 -0
  254. package/public-landing/assets/anim/idle/frame_28.webp +0 -0
  255. package/public-landing/assets/anim/idle/frame_29.webp +0 -0
  256. package/public-landing/assets/anim/idle/frame_30.webp +0 -0
  257. package/public-landing/assets/anim/idle/frame_31.webp +0 -0
  258. package/public-landing/assets/anim/idle/frame_32.webp +0 -0
  259. package/public-landing/assets/anim/idle/frame_33.webp +0 -0
  260. package/public-landing/assets/anim/idle/frame_34.webp +0 -0
  261. package/public-landing/assets/anim/idle/frame_35.webp +0 -0
  262. package/public-landing/assets/anim/idle/frame_36.webp +0 -0
  263. package/public-landing/assets/anim/idle/frame_37.webp +0 -0
  264. package/public-landing/assets/anim/idle/frame_38.webp +0 -0
  265. package/public-landing/assets/anim/idle/frame_39.webp +0 -0
  266. package/public-landing/assets/anim/idle/frame_40.webp +0 -0
  267. package/public-landing/assets/anim/idle/frame_41.webp +0 -0
  268. package/public-landing/assets/anim/idle/frame_42.webp +0 -0
  269. package/public-landing/assets/anim/idle/frame_43.webp +0 -0
  270. package/public-landing/create.html +51 -58
  271. package/public-landing/gate/README.md +137 -0
  272. package/public-landing/gate/dispmaps/bar.png +0 -0
  273. package/public-landing/gate/dispmaps/flat.png +0 -0
  274. package/public-landing/gate/dispmaps/key.png +0 -0
  275. package/public-landing/gate/index.html +587 -0
  276. package/public-landing/gate/previews/cloud-bongos.jpg +0 -0
  277. package/public-landing/gate/previews/off-the-boats.jpg +0 -0
  278. package/public-landing/gate/space.css +799 -0
  279. package/public-landing/gate/space.js +1826 -0
  280. package/public-landing/gate/sprites/enter.png +0 -0
  281. package/public-landing/gate/sprites/search.png +0 -0
  282. package/public-landing/gate/sprites/terminal-blank.png +0 -0
  283. package/public-landing/gate/sprites/tile.png +0 -0
  284. package/public-landing/world/assets/clouds/cloud-island-large.png +0 -0
  285. package/public-landing/world/assets/clouds/cloud-puff.png +0 -0
  286. package/public-landing/world/assets/creatures/creature-whale-cargo.png +0 -0
  287. package/public-landing/world/assets/creatures/creature-whale-glide.png +0 -0
  288. package/public-landing/world/assets/plates/plate-clouds-near.png +0 -0
  289. package/public-landing/world/assets/plates/scene-establishing.png +0 -0
  290. package/scripts/gds/abandon.js +6 -4
  291. package/scripts/gds/api.js +10 -5
  292. package/scripts/gds/api.ps1 +26 -0
  293. package/scripts/gds/api.sh +6 -0
  294. package/scripts/gds/audit-ships.js +7 -1
  295. package/scripts/gds/backfill-sessions.js +78 -18
  296. package/scripts/gds/backup.js +23 -1
  297. package/scripts/gds/box-connect-lib.js +124 -31
  298. package/scripts/gds/box-sync.js +66 -0
  299. package/scripts/gds/box.js +225 -53
  300. package/scripts/gds/cf-tunnel.js +145 -6
  301. package/scripts/gds/claim.js +34 -3
  302. package/scripts/gds/cli-lib.js +161 -27
  303. package/scripts/gds/code.js +6 -2
  304. package/scripts/gds/deploy-divergence.js +209 -0
  305. package/scripts/gds/dev-lib.js +309 -0
  306. package/scripts/gds/dev.js +322 -0
  307. package/scripts/gds/doctor.js +90 -61
  308. package/scripts/gds/fetch-art-key.js +1 -1
  309. package/scripts/gds/fetch-sound-prefs.js +2 -2
  310. package/scripts/gds/fitness.js +228 -12
  311. package/scripts/gds/gds-db-backup.service +16 -1
  312. package/scripts/gds/gds-db-offsite.service +9 -1
  313. package/scripts/gds/gen-api-client.js +1 -1
  314. package/scripts/gds/gen-api-docs.js +36 -14
  315. package/scripts/gds/gen-diagrams.js +45 -28
  316. package/scripts/gds/gen-file-map.js +2 -1
  317. package/scripts/gds/gen-freshness.js +32 -0
  318. package/scripts/gds/gen-repo-map.js +3 -2
  319. package/scripts/gds/gen-session-index.js +14 -5
  320. package/scripts/gds/hooks/pre-push.js +2 -2
  321. package/scripts/gds/init.js +60 -3
  322. package/scripts/gds/install-git-hooks.js +1 -1
  323. package/scripts/gds/key-card.js +15 -6
  324. package/scripts/gds/key-status.js +1 -1
  325. package/scripts/gds/linkify-refs.js +35 -9
  326. package/scripts/gds/login.js +16 -1
  327. package/scripts/gds/paste-token.js +7 -1
  328. package/scripts/gds/preflight.js +126 -0
  329. package/scripts/gds/provision.js +123 -12
  330. package/scripts/gds/publish-manifest.js +7 -1
  331. package/scripts/gds/reauth.js +7 -3
  332. package/scripts/gds/regen-instance-docs.js +47 -0
  333. package/scripts/gds/run-unit-tests.js +4 -2
  334. package/scripts/gds/seed-bongos-v1-seo-tasks.js +104 -0
  335. package/scripts/gds/seed-bv1-profiles-tasks.js +126 -0
  336. package/scripts/gds/sequence.js +425 -0
  337. package/scripts/gds/session-cost.js +10 -1
  338. package/scripts/gds/setup.js +31 -5
  339. package/scripts/gds/shell.js +5 -3
  340. package/scripts/gds/ship.js +319 -29
  341. package/scripts/gds/smoke-gds.js +139 -8
  342. package/scripts/gds/start.js +171 -22
  343. package/scripts/gds/status.js +1 -1
  344. package/scripts/gds/triage.js +10 -9
  345. package/scripts/gds/upgrade.js +124 -2
  346. package/scripts/status-mirror-sync.js +114 -84
  347. package/src/bongos/api-errors.js +1 -0
  348. package/src/bongos/auth.js +447 -102
  349. package/src/bongos/db-kernel.js +27 -0
  350. package/src/bongos/db.js +39 -0
  351. package/src/bongos/module-scope-map.js +27 -1
  352. package/src/bongos/permission-path-check.js +136 -102
  353. package/src/bongos/repo-info.js +47 -11
  354. package/src/bongos/route-rank-check.js +429 -46
  355. package/src/bongos/routes/_helpers.js +12 -1
  356. package/src/bongos/routes/auth.js +219 -2
  357. package/src/bongos/routes/backup.js +58 -2
  358. package/src/bongos/routes/me.js +35 -1
  359. package/src/bongos/serve-internal.js +84 -15
  360. package/src/branding.js +32 -0
  361. package/src/instance-config.js +30 -0
  362. package/src/module-api.js +112 -1
  363. package/src/platform-server.js +86 -9
  364. package/tests/abandon_task.mjs +59 -3
  365. package/tests/api_cli_flags.mjs +53 -0
  366. package/tests/auth_page_gate.mjs +13 -0
  367. package/tests/backfill_sessions.mjs +127 -1
  368. package/tests/backup_cli.mjs +54 -0
  369. package/tests/bongos_box_connect.mjs +77 -0
  370. package/tests/box_access.mjs +130 -1
  371. package/tests/box_credential.mjs +125 -0
  372. package/tests/box_host_keys.mjs +24 -0
  373. package/tests/box_infra_resolve.mjs +149 -0
  374. package/tests/box_scope_session.mjs +6 -2
  375. package/tests/box_sync.mjs +55 -0
  376. package/tests/box_task_scope.mjs +99 -0
  377. package/tests/branding.mjs +12 -0
  378. package/tests/cf_ruleset_preflight.mjs +142 -0
  379. package/tests/cf_tunnel.mjs +37 -0
  380. package/tests/claim_gate_rebase.mjs +98 -0
  381. package/tests/clawback_confirmed_backlog.mjs +103 -0
  382. package/tests/cli_lib_formatters.mjs +20 -0
  383. package/tests/confirm_attribution.mjs +30 -46
  384. package/tests/credit_grant.mjs +198 -10
  385. package/tests/criterion_authoring_gate.mjs +272 -0
  386. package/tests/criterion_progress.mjs +33 -1
  387. package/tests/dev_lib.mjs +253 -0
  388. package/tests/devbox_artifact_gate.mjs +75 -0
  389. package/tests/devbox_dmg_backdrop.mjs +137 -0
  390. package/tests/devbox_icons.mjs +304 -0
  391. package/tests/devbox_installer_brand.mjs +232 -0
  392. package/tests/devbox_key_register.mjs +234 -0
  393. package/tests/docs_openapi_route.mjs +110 -0
  394. package/tests/doctor_hooks.mjs +141 -0
  395. package/tests/extract_json.mjs +140 -0
  396. package/tests/fitness.mjs +89 -0
  397. package/tests/gen_freshness.mjs +96 -0
  398. package/tests/goal_advisory.mjs +251 -0
  399. package/tests/goal_criterion_confirm_ui.mjs +269 -0
  400. package/tests/goal_routes.mjs +59 -4
  401. package/tests/goal_tier.mjs +12 -3
  402. package/tests/governance_catalog.mjs +129 -0
  403. package/tests/governance_claim_eligibility.mjs +262 -0
  404. package/tests/governance_config.mjs +187 -0
  405. package/tests/governance_ownership_scope.mjs +410 -0
  406. package/tests/governance_page_gates.mjs +324 -0
  407. package/tests/governance_parity.mjs +336 -0
  408. package/tests/governance_principals.mjs +232 -0
  409. package/tests/governance_protected_surfaces.mjs +208 -0
  410. package/tests/governance_require_permission.mjs +223 -0
  411. package/tests/governance_resolver.mjs +84 -0
  412. package/tests/governance_role_sync.mjs +231 -0
  413. package/tests/governance_seed.mjs +127 -0
  414. package/tests/governance_session_scope.mjs +434 -0
  415. package/tests/governance_vanilla_boot.mjs +203 -0
  416. package/tests/grade_attribution.mjs +7 -7
  417. package/tests/hall_audit.mjs +223 -0
  418. package/tests/hall_nav.mjs +191 -0
  419. package/tests/hall_palette.mjs +206 -0
  420. package/tests/hall_signout.mjs +124 -0
  421. package/tests/hook_user_agents.mjs +10 -0
  422. package/tests/idea_triage.mjs +162 -0
  423. package/tests/idp_device_exchange.mjs +93 -0
  424. package/tests/init.mjs +51 -0
  425. package/tests/instance_config.mjs +65 -0
  426. package/tests/instance_mismatch_guard.mjs +23 -6
  427. package/tests/instance_release_config.mjs +104 -0
  428. package/tests/linkify_refs.mjs +15 -2
  429. package/tests/module_contributions.mjs +55 -0
  430. package/tests/module_loader.mjs +10 -5
  431. package/tests/module_scope_active_claims.mjs +94 -0
  432. package/tests/needs_rebase.mjs +92 -0
  433. package/tests/one_active_claim_per_session.mjs +76 -0
  434. package/tests/override_attribution.mjs +10 -8
  435. package/tests/override_request_ownership.mjs +8 -4
  436. package/tests/parse_cookie_decode.mjs +42 -0
  437. package/tests/pay_on_land.mjs +129 -0
  438. package/tests/platform_boot.mjs +100 -1
  439. package/tests/post_login_landing.mjs +42 -0
  440. package/tests/preflight_checks.mjs +72 -0
  441. package/tests/provision.mjs +132 -7
  442. package/tests/publish_branch_route.mjs +53 -0
  443. package/tests/publish_reconciler.mjs +187 -2
  444. package/tests/repo_info_binding.mjs +248 -0
  445. package/tests/reward_gate.mjs +11 -2
  446. package/tests/reward_mode_cost_plus_only.mjs +116 -0
  447. package/tests/reward_mode_surfacing.mjs +168 -0
  448. package/tests/route_permission_check.mjs +301 -0
  449. package/tests/route_rank_check.mjs +254 -12
  450. package/tests/route_validation.mjs +30 -0
  451. package/tests/sequence.mjs +267 -0
  452. package/tests/session_digest.mjs +44 -0
  453. package/tests/session_index.mjs +18 -6
  454. package/tests/session_records.mjs +39 -1
  455. package/tests/session_reward_on_land.mjs +381 -0
  456. package/tests/session_reward_reconcile.mjs +229 -0
  457. package/tests/ship_api_client_pathspec.mjs +100 -0
  458. package/tests/ship_base_flag.mjs +93 -0
  459. package/tests/ship_ci_deploy.mjs +80 -3
  460. package/tests/ship_upstream_deletion.mjs +57 -0
  461. package/tests/smoke_target.mjs +233 -0
  462. package/tests/start_env_guard.mjs +87 -0
  463. package/tests/start_rebase_warning.mjs +103 -0
  464. package/tests/status_mirror_sync.mjs +122 -0
  465. package/tests/stop_refcheck.mjs +19 -1
  466. package/tests/task_goal_link.mjs +15 -6
  467. package/tests/upgrade.mjs +139 -0
  468. package/tests/web_admission_status.mjs +162 -0
  469. package/tests/write_validation_gaps.mjs +110 -0
@@ -0,0 +1,140 @@
1
+ // modules/platform-identity/routes/my-projects.js — the signed-in builder's cross-
2
+ // project "My Projects" view + self-service join / leave (ADR 0141 §3, task #1002112).
3
+ //
4
+ // GET /my-projects — projects this account builds on, owned grouped apart
5
+ // POST /my-projects/join — request to join a project (executed by the project)
6
+ // POST /my-projects/:clientId/leave — self-service offboard (reflected to the hub)
7
+ //
8
+ // All gated on a live HUB session (requireBuilder). Authority stays LOCAL: JOIN only
9
+ // RELAYS an admission request to the target project (which enforces its own gate);
10
+ // the hub never admits anyone on its own. Reaches core only via the doorway (ADR 0083).
11
+ 'use strict';
12
+
13
+ const express = require('express');
14
+ const api = require('../../../src/module-api');
15
+ const pi = require('../platform-identity');
16
+
17
+ const { pool, requireBuilder, validateOrRespond, userAgent } = api;
18
+
19
+ module.exports = function myProjectsRoutes() {
20
+ const router = express.Router();
21
+
22
+ // rank: any-builder — the caller's OWN cross-project memberships (own data).
23
+ router.get('/my-projects', requireBuilder, async (req, res) => {
24
+ try {
25
+ const rows = await pi.listMembershipsForAccount(req.builder.github_id, { pool });
26
+ const owned = [];
27
+ const building = [];
28
+ for (const m of rows) {
29
+ (m.role === 'owner' ? owned : building).push({
30
+ client_id: m.client_id,
31
+ name: m.project_name || m.project_origin || m.client_id,
32
+ origin: m.project_origin || null,
33
+ role: m.role,
34
+ joined_at: m.joined_at,
35
+ last_active: m.last_active,
36
+ });
37
+ }
38
+ res.json({ owned, building });
39
+ } catch (err) {
40
+ console.error('[platform-identity] GET /my-projects', err);
41
+ res.fail('my_projects_failed', { status: 500, message: 'internal error' });
42
+ }
43
+ });
44
+
45
+ // rank: any-builder — request to join a project. The hub RELAYS the request to the
46
+ // target project's own admission surface (it does NOT admit locally — authority
47
+ // stays local). SSRF guard: only relay to an origin that is a REGISTERED, active
48
+ // client — never an arbitrary builder-supplied URL.
49
+ router.post('/my-projects/join', requireBuilder, async (req, res) => {
50
+ if (validateOrRespond(req, res, { origin: { required: true, type: 'string', maxLength: 512 } })) return;
51
+ try {
52
+ const client = await pi.getClientByOrigin(req.body.origin, { pool });
53
+ if (!client || client.status !== 'active' || !client.origin) {
54
+ return res.fail('unknown_project', 404);
55
+ }
56
+ // Relay an access request to the project's OWN (public) admission endpoint —
57
+ // the project decides (open-join, or request/invite per ADR 0112). We post to
58
+ // the registry-trusted origin, never the caller's raw input.
59
+ let relayed = false;
60
+ let alreadyMember = false;
61
+ try {
62
+ const r = await fetch(`${client.origin}/api/gds/access-requests`, {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json', 'User-Agent': userAgent() },
65
+ body: JSON.stringify({ github_login: req.builder.github_login, note: 'via platform My Projects' }),
66
+ });
67
+ alreadyMember = r.status === 409;
68
+ relayed = r.ok || r.status === 200 || r.status === 201 || alreadyMember;
69
+ } catch (e) {
70
+ console.log('[platform-identity] join relay failed (non-fatal):', e.message);
71
+ }
72
+ if (!relayed) return res.fail('join_relay_failed', { status: 502, message: 'the project could not be reached to request access' });
73
+ res.json({
74
+ ok: true,
75
+ status: alreadyMember ? 'already_member' : 'requested',
76
+ project: { name: client.name, origin: client.origin },
77
+ message: alreadyMember
78
+ ? 'You already build on this project — sign in to it to see it here.'
79
+ : 'Requested access. The project’s owner admits new builders; once approved, sign in to enter.',
80
+ });
81
+ } catch (err) {
82
+ console.error('[platform-identity] POST /my-projects/join', err);
83
+ res.fail('join_failed', { status: 500, message: 'internal error' });
84
+ }
85
+ });
86
+
87
+ // rank: any-builder — the caller's OWN pending invitations (ADR 0141 §5).
88
+ router.get('/my-projects/invites', requireBuilder, async (req, res) => {
89
+ try {
90
+ const invites = await pi.listPendingInvitesForAccount(req.builder.github_id, { pool });
91
+ res.json({ invites: invites.map((i) => ({ client_id: i.client_id, name: i.project_name || i.project_origin || i.client_id, origin: i.project_origin || null, invited_at: i.invited_at })) });
92
+ } catch (err) {
93
+ console.error('[platform-identity] GET /my-projects/invites', err);
94
+ res.fail('invites_failed', { status: 500, message: 'internal error' });
95
+ }
96
+ });
97
+
98
+ // rank: any-builder — accept an invite (pending → builder) for the caller's OWN account.
99
+ router.post('/my-projects/invites/:clientId/accept', requireBuilder, async (req, res) => {
100
+ const clientId = String(req.params.clientId || '');
101
+ if (!clientId) return res.fail('bad_client_id', 400);
102
+ try {
103
+ const out = await pi.resolveInvite({ clientId, githubId: req.builder.github_id, accept: true }, { pool });
104
+ if (!out.resolved) return res.fail('no_pending_invite', 404);
105
+ res.json({ ok: true, accepted: true });
106
+ } catch (err) {
107
+ console.error('[platform-identity] accept invite', err);
108
+ res.fail('accept_failed', { status: 500, message: 'internal error' });
109
+ }
110
+ });
111
+
112
+ // rank: any-builder — decline an invite (delete the pending row) for the caller's OWN account.
113
+ router.post('/my-projects/invites/:clientId/decline', requireBuilder, async (req, res) => {
114
+ const clientId = String(req.params.clientId || '');
115
+ if (!clientId) return res.fail('bad_client_id', 400);
116
+ try {
117
+ const out = await pi.resolveInvite({ clientId, githubId: req.builder.github_id, accept: false }, { pool });
118
+ if (!out.resolved) return res.fail('no_pending_invite', 404);
119
+ res.json({ ok: true, accepted: false });
120
+ } catch (err) {
121
+ console.error('[platform-identity] decline invite', err);
122
+ res.fail('decline_failed', { status: 500, message: 'internal error' });
123
+ }
124
+ });
125
+
126
+ // rank: any-builder — leave a project from the caller's OWN membership list.
127
+ router.post('/my-projects/:clientId/leave', requireBuilder, async (req, res) => {
128
+ const clientId = String(req.params.clientId || '');
129
+ if (!clientId) return res.fail('bad_client_id', 400);
130
+ try {
131
+ const removed = await pi.removeMembership(clientId, req.builder.github_id, { pool });
132
+ res.json({ ok: true, left: removed > 0 });
133
+ } catch (err) {
134
+ console.error('[platform-identity] POST /my-projects/:clientId/leave', err);
135
+ res.fail('leave_failed', { status: 500, message: 'internal error' });
136
+ }
137
+ });
138
+
139
+ return router;
140
+ };
@@ -0,0 +1,107 @@
1
+ // modules/platform-identity/routes/projects.js — the hub projects catalog + the
2
+ // curated public Explore showcase (ADR 0141 §5, task #1002110).
3
+ //
4
+ // GET /projects/featured — PUBLIC Explore listing (featured + active only)
5
+ // GET /projects — Archon: full curation list (+ featured flags)
6
+ // POST /projects — Archon: create / update a catalog entry
7
+ // PATCH /projects/:id/featured — Archon: the feature / unfeature control
8
+ //
9
+ // Reaches core only through the doorway (ADR 0083). Archon routes declared first so
10
+ // route-rank-check's look-ahead never misclassifies the trailing public GET.
11
+ 'use strict';
12
+
13
+ const express = require('express');
14
+ const api = require('../../../src/module-api');
15
+ const pi = require('../platform-identity');
16
+
17
+ const { pool, requireBuilder, requireRank, validateOrRespond, parseId, corsPublicGet } = api;
18
+
19
+ module.exports = function projectsRoutes() {
20
+ const router = express.Router();
21
+
22
+ // rank: archon — the full curation list (includes unfeatured + owner attribution).
23
+ router.get('/projects', requireBuilder, requireRank('archon'), async (_req, res) => {
24
+ try {
25
+ res.json({ projects: await pi.listAllProjects({ pool }) });
26
+ } catch (err) {
27
+ console.error('[platform-identity] GET /projects', err);
28
+ res.fail('projects_list_failed', { status: 500, message: 'internal error' });
29
+ }
30
+ });
31
+
32
+ // rank: archon — create / update a catalog entry (manual seed for hand-wired
33
+ // instances; federated projects auto-catalogue at registration).
34
+ router.post('/projects', requireBuilder, requireRank('archon'), async (req, res) => {
35
+ if (validateOrRespond(req, res, {
36
+ origin: { required: true, type: 'string', maxLength: 512 },
37
+ name: { required: true, type: 'string', maxLength: 200 },
38
+ tagline: { type: 'string', maxLength: 400 },
39
+ art_url: { type: 'string', maxLength: 2048 },
40
+ })) return;
41
+ try {
42
+ const project = await pi.upsertProject({
43
+ origin: req.body.origin,
44
+ name: req.body.name,
45
+ tagline: req.body.tagline,
46
+ artUrl: req.body.art_url,
47
+ }, { pool });
48
+ res.status(201).json({ project });
49
+ } catch (err) {
50
+ console.error('[platform-identity] POST /projects', err);
51
+ res.fail('project_upsert_failed', { status: 500, message: 'internal error' });
52
+ }
53
+ });
54
+
55
+ // rank: archon — invite a builder into a project (ADR 0141 §5, task #1002115).
56
+ // Pre-seeds a 'pending' membership the invitee accepts from My Projects. V1 invites
57
+ // by github_login and requires the invitee to already have a platform account (they
58
+ // build on some project); inviting someone entirely new to the platform (GitHub-id
59
+ // resolution) is a follow-up.
60
+ router.post('/projects/invite', requireBuilder, requireRank('archon'), async (req, res) => {
61
+ if (validateOrRespond(req, res, {
62
+ client_id: { required: true, type: 'string', maxLength: 200 },
63
+ github_login: { required: true, type: 'string', maxLength: 200 },
64
+ })) return;
65
+ try {
66
+ const client = await pi.getClient(req.body.client_id, { pool });
67
+ if (!client || client.status !== 'active') return res.fail('unknown_project', 404);
68
+ const account = await pi.getAccountByLogin(req.body.github_login, { pool });
69
+ if (!account) return res.fail('account_not_found', { status: 404, message: 'That builder has no platform account yet — they must sign in somewhere once before they can be invited.' });
70
+ const out = await pi.inviteToProject({ clientId: req.body.client_id, githubId: account.github_id }, { pool });
71
+ res.status(out.invited ? 201 : 200).json(out);
72
+ } catch (err) {
73
+ console.error('[platform-identity] POST /projects/invite', err);
74
+ res.fail('invite_failed', { status: 500, message: 'internal error' });
75
+ }
76
+ });
77
+
78
+ // rank: archon — the feature / unfeature control (the ADR 0141 §5 curation gate).
79
+ router.patch('/projects/:id/featured', requireBuilder, requireRank('archon'), async (req, res) => {
80
+ const id = parseId(req, res, { code: 'bad_project_id', positiveInt: true });
81
+ if (id === null) return;
82
+ if (validateOrRespond(req, res, { featured: { required: true, type: 'boolean' } })) return;
83
+ try {
84
+ const project = await pi.setProjectFeatured(id, req.body.featured, { pool });
85
+ if (!project) return res.fail('project_not_found', 404);
86
+ res.json({ project });
87
+ } catch (err) {
88
+ console.error('[platform-identity] PATCH /projects/:id/featured', err);
89
+ res.fail('feature_toggle_failed', { status: 500, message: 'internal error' });
90
+ }
91
+ });
92
+
93
+ // The PUBLIC Explore showcase — featured + active projects only, public projection.
94
+ // CORS-enabled cross-origin read (a status page / the apex fetches it pre-auth).
95
+ router.use('/projects/featured', corsPublicGet('/projects/featured'));
96
+ // rank: public — a curated public showcase; no auth by design.
97
+ router.get('/projects/featured', async (_req, res) => {
98
+ try {
99
+ res.json({ projects: await pi.listFeaturedProjects({ pool }) });
100
+ } catch (err) {
101
+ console.error('[platform-identity] GET /projects/featured', err);
102
+ res.fail('explore_failed', { status: 500, message: 'internal error' });
103
+ }
104
+ });
105
+
106
+ return router;
107
+ };
@@ -0,0 +1,35 @@
1
+ // modules/platform-identity/routes/scouting.js — the INTERNAL, Archon-only
2
+ // cross-project scouting view (ADR 0141 §4, task #1002114). Ranks builders across
3
+ // ALL hosted projects from platform_identity_builder_project_activity. It is a
4
+ // talent tool for the platform operator — NOT shown to builders, and NOT authority
5
+ // (the rollup is descriptive; authority stays local, ADR 0141 / ADR 0016). Consent
6
+ // for cross-project aggregation is handled by the platform T&C (out of scope here).
7
+ //
8
+ // Reaches core only through the doorway (ADR 0083).
9
+ 'use strict';
10
+
11
+ const express = require('express');
12
+ const api = require('../../../src/module-api');
13
+ const pi = require('../platform-identity');
14
+
15
+ const { pool, requireBuilder, requireRank, parsePagination } = api;
16
+
17
+ module.exports = function scoutingRoutes() {
18
+ const router = express.Router();
19
+
20
+ // rank: archon — the internal talent directory across every project. The Archon
21
+ // gate here is the load-bearing protection ("NOT shown to builders"): a non-Archon
22
+ // is 403'd before any cross-builder data is read.
23
+ router.get('/scouting', requireBuilder, requireRank('archon'), async (req, res) => {
24
+ const { limit } = parsePagination(req, { defaultLimit: 100, maxLimit: 500 });
25
+ try {
26
+ const builders = await pi.listScoutingRollup({ limit, pool });
27
+ res.json({ builders });
28
+ } catch (err) {
29
+ console.error('[platform-identity] GET /scouting', err);
30
+ res.fail('scouting_failed', { status: 500, message: 'internal error' });
31
+ }
32
+ });
33
+
34
+ return router;
35
+ };