@bongos/core 1.18.0 → 1.18.3

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 (113) hide show
  1. package/.bongos-core.json +132 -322
  2. package/README.md +1 -1
  3. package/config/branding.neutral.json +5 -1
  4. package/docs/adr/0142-project-context-is-prose-only.md +41 -0
  5. package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +35 -0
  6. package/docs/adr/README.md +5 -2
  7. package/docs/api/openapi.json +1789 -450
  8. package/docs/api-reference.md +52 -5
  9. package/docs/file-map.md +7 -7
  10. package/docs/recipes/packaging-the-core.md +13 -0
  11. package/docs/recipes/upgrading-the-core.md +5 -2
  12. package/migrations/039_newcomer_friendly_column.sql +5 -0
  13. package/migrations/102_remove_box_first_provision_approval.sql +4 -0
  14. package/migrations/core_192_github_oauth_tokens.sql +33 -0
  15. package/modules/hall-ui/public/my-projects.html +78 -0
  16. package/modules/hall-ui/public/my-projects.js +142 -0
  17. package/modules/hall-ui/public/scouting.html +45 -0
  18. package/modules/hall-ui/public/scouting.js +73 -0
  19. package/modules/status-ui/public/explore.html +54 -0
  20. package/modules/status-ui/public/explore.js +67 -0
  21. package/package-lock.json +2 -2
  22. package/package.json +1 -1
  23. package/public-landing/create.html +211 -14
  24. package/scripts/gds/cli-lib.js +11 -5
  25. package/scripts/gds/lint-migrations.js +102 -0
  26. package/scripts/gds/login.js +42 -10
  27. package/scripts/gds/mirror-redact.js +5 -0
  28. package/scripts/gds/package-core.js +263 -4
  29. package/scripts/gds/provision.js +145 -7
  30. package/scripts/gds/publish-manifest.js +15 -0
  31. package/scripts/gds/run-unit-tests.js +38 -14
  32. package/scripts/gds/setup.js +41 -0
  33. package/scripts/gds/ship.js +115 -31
  34. package/scripts/gds/upgrade.js +147 -5
  35. package/scripts/migrate.sh +10 -0
  36. package/src/bongos/auth.js +362 -5
  37. package/src/bongos/db.js +66 -0
  38. package/src/bongos/github-repos.js +93 -0
  39. package/src/bongos/routes/auth.js +93 -11
  40. package/src/bongos/routes/github.js +90 -0
  41. package/src/bongos/routes/instance.js +15 -3
  42. package/src/bongos/routes.js +2 -0
  43. package/src/branding.js +17 -2
  44. package/src/instance-config.js +16 -0
  45. package/src/module-api.js +29 -1
  46. package/tests/branding.mjs +29 -23
  47. package/tests/github_repos_helpers.mjs +91 -0
  48. package/tests/github_token_store.mjs +121 -0
  49. package/tests/idp_device_exchange.mjs +105 -0
  50. package/tests/idp_federation.mjs +100 -0
  51. package/tests/migrations_forward_safe.mjs +86 -0
  52. package/tests/module_api.mjs +1 -1
  53. package/tests/package_core.mjs +246 -1
  54. package/tests/provision.mjs +157 -0
  55. package/tests/pruned_lockfile_integrity.mjs +79 -0
  56. package/tests/ship_ci_deploy.mjs +60 -0
  57. package/tests/upgrade.mjs +254 -5
  58. package/.gitignore +0 -91
  59. package/docs/adr/0139-platform-history-migration-to-cloudbongos.md +0 -94
  60. package/docs/adr/0140-cloudbongos-standalone-reprovision.md +0 -43
  61. package/scripts/hall-preview/fixtures/access-requests.json +0 -20
  62. package/scripts/hall-preview/fixtures/achievements.json +0 -76
  63. package/scripts/hall-preview/fixtures/analytics__builder.json +0 -251
  64. package/scripts/hall-preview/fixtures/audit-log.json +0 -68
  65. package/scripts/hall-preview/fixtures/blockers__detail.json +0 -12
  66. package/scripts/hall-preview/fixtures/box__me.json +0 -5
  67. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +0 -69
  68. package/scripts/hall-preview/fixtures/builders__active-claims.json +0 -1
  69. package/scripts/hall-preview/fixtures/builders__directory.json +0 -81
  70. package/scripts/hall-preview/fixtures/builders__roster.json +0 -48
  71. package/scripts/hall-preview/fixtures/goals.json +0 -502
  72. package/scripts/hall-preview/fixtures/goals__25.json +0 -96
  73. package/scripts/hall-preview/fixtures/goals__26.json +0 -67
  74. package/scripts/hall-preview/fixtures/goals__3.json +0 -103
  75. package/scripts/hall-preview/fixtures/goals__35.json +0 -49
  76. package/scripts/hall-preview/fixtures/goals__conflicts.json +0 -154
  77. package/scripts/hall-preview/fixtures/goals__detail.json +0 -96
  78. package/scripts/hall-preview/fixtures/goals__inbox.json +0 -5
  79. package/scripts/hall-preview/fixtures/goals__requests.json +0 -3
  80. package/scripts/hall-preview/fixtures/grades__by-builder.json +0 -32
  81. package/scripts/hall-preview/fixtures/inbox.json +0 -330
  82. package/scripts/hall-preview/fixtures/inbox__detail.json +0 -15
  83. package/scripts/hall-preview/fixtures/instance.json +0 -124
  84. package/scripts/hall-preview/fixtures/leaderboard.json +0 -184
  85. package/scripts/hall-preview/fixtures/me.json +0 -476
  86. package/scripts/hall-preview/fixtures/me__art-key__own.json +0 -6
  87. package/scripts/hall-preview/fixtures/me__event-sound-prefs.json +0 -209
  88. package/scripts/hall-preview/fixtures/me__recent-ships.json +0 -304
  89. package/scripts/hall-preview/fixtures/me__render.json +0 -5
  90. package/scripts/hall-preview/fixtures/me__skill-prefs.json +0 -143
  91. package/scripts/hall-preview/fixtures/me__sound-prefs.json +0 -67
  92. package/scripts/hall-preview/fixtures/me__wandering.json +0 -43
  93. package/scripts/hall-preview/fixtures/override-requests.json +0 -15
  94. package/scripts/hall-preview/fixtures/provisioning__fleet.json +0 -1
  95. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +0 -1
  96. package/scripts/hall-preview/fixtures/provisioning__instances.json +0 -1
  97. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +0 -516
  98. package/scripts/hall-preview/fixtures/public__bounty-table.json +0 -37
  99. package/scripts/hall-preview/fixtures/public__cost-summary.json +0 -742
  100. package/scripts/hall-preview/fixtures/public__estimation-drift.json +0 -41
  101. package/scripts/hall-preview/fixtures/public__grades.json +0 -50
  102. package/scripts/hall-preview/fixtures/public__progress.json +0 -124
  103. package/scripts/hall-preview/fixtures/public__recent-shipped.json +0 -426
  104. package/scripts/hall-preview/fixtures/public__repo-health.json +0 -160
  105. package/scripts/hall-preview/fixtures/public__repo-info.json +0 -5
  106. package/scripts/hall-preview/fixtures/security__docs.json +0 -10
  107. package/scripts/hall-preview/fixtures/security__reports.json +0 -31
  108. package/scripts/hall-preview/fixtures/sessions__search.json +0 -9
  109. package/scripts/hall-preview/fixtures/tasks.json +0 -2420
  110. package/scripts/hall-preview/fixtures/tasks__claimable.json +0 -2555
  111. package/scripts/hall-preview/fixtures/tasks__detail.json +0 -111
  112. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +0 -330
  113. package/scripts/hall-preview/fixtures/versions.json +0 -89
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Cloud Bongos is free software under the **GNU AGPL-3.0** (see [`LICENSE`](./LICENSE)), with non-profit, AI-first governance ([`GOVERNANCE.md`](./GOVERNANCE.md)).
6
6
 
7
- > **Provenance.** This core was extracted with fresh history from **Amazonprimea** — the reference instance, built by Hermeslines, and the first project to run on Cloud Bongos. Amazonprimea now consumes this core as a pinned dependency, the same shape as any other instance. The extraction is a redacted subtree (no instance secrets, IPs, or private identity); the exact pin — `core_version`, `source_commit`, `tree_sha256` — is recorded in [`.cloudbongos-core.json`](./.cloudbongos-core.json).
7
+ > **Provenance.** This core was extracted with fresh history from **Example** — the reference instance, built by Hermeslines, and the first project to run on Cloud Bongos. Example now consumes this core as a pinned dependency, the same shape as any other instance. The extraction is a redacted subtree (no instance secrets, IPs, or private identity); the exact pin — `core_version`, `source_commit`, `tree_sha256` — is recorded in [`.cloudbongos-core.json`](./.cloudbongos-core.json).
8
8
 
9
9
  The durable framing for AI agents — methodology, working rules, session protocol, architecture — lives in [`CLAUDE.md`](./CLAUDE.md). Read it before editing code.
10
10
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "_note": "Cloud Bongos vanilla brand pack — customer 0, the identity Cloud Bongos itself runs on (Amazonprimea is customer 1). The neutral starter every instance resolves over. Light + joyful — 'playing in the clouds', where building software is laying down a beat (ADR 0064). The LOOK ships via theme.ui, injected by src/bongos/serve-internal.js (R57): a Lion-King sunrise backdrop, warm palette, Baloo 2 (display/wordmark) + Quicksand (interface) + Fira Code (code) type, and a bongo-pair favicon. To brand a NEW instance, copy this to config/branding.json and fill it in (docs/branding-fill-prompt.md). Authored by task 1216 / V4.R74. See docs/branding-contract.md.",
2
+ "_note": "Cloud Bongos vanilla brand pack — customer 0, the identity Cloud Bongos itself runs on. The neutral starter every instance resolves over. Light + joyful — 'playing in the clouds', where building software is laying down a beat (ADR 0064). The LOOK ships via theme.ui, injected by src/bongos/serve-internal.js (R57): a Lion-King sunrise backdrop, warm palette, Baloo 2 (display/wordmark) + Quicksand (interface) + Fira Code (code) type, and a bongo-pair favicon. To brand a NEW instance, copy this to config/branding.json and fill it in (docs/branding-fill-prompt.md). Authored by task 1216 / V4.R74. See docs/branding-contract.md.",
3
3
  "identity": {
4
4
  "productName": "Cloud Bongos",
5
5
  "worldName": "Cloud Bongos",
@@ -17,6 +17,10 @@
17
17
  "sandboxPrefix": "sandbox-",
18
18
  "termPrefix": "term-"
19
19
  },
20
+ "auth": {
21
+ "_note": "Cross-site identity (ADR 0141). idp=false → this instance owns its auth outright (its own GitHub app; the default + the self-hosted path). A HOSTED instance sets idp=true and gets its hub origin + client credentials from env (<PREFIX>_HUB_ORIGIN / _HUB_CLIENT_ID / _HUB_CLIENT_SECRET, written by provisioning) so web + CLI sign-in federate through the Cloud Bongos hub with no GitHub app of its own. Identity is federated; authority stays local.",
22
+ "idp": false
23
+ },
20
24
  "repo": { "owner": "", "name": "" },
21
25
  "db": { "database": null },
22
26
  "configDir": "cloudbongos",
@@ -0,0 +1,41 @@
1
+ # 0142 — Project context is prose-only; the structured host contract is branding
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-07-13
5
+ - **Deciders:** Claude (acting builder, autonomous session under goal 1000042); owner to ratify. Presented the fork the audit named — build a structured neutral+instance+resolver for project context (mirroring branding), or keep project context prose-only — and chose prose-only.
6
+ - **Task:** [#1002224](https://example.com/builders#/task/1002224) (BONGOS-V1, goal 1000042 — *Harden the Cloud Bongos update pipeline*). Closes hardening item **H11** / finding **F7** of [`docs/audits/update-pipeline-audit.md`](../audits/update-pipeline-audit.md).
7
+ - **Builds on:** [ADR 0062](<redacted>.md) §7 (the core↔host split — CLAUDE.md is portable methodology; host identity lives beside it), the branding contract ([`docs/branding-contract.md`](../branding-contract.md), [`src/branding.js`](../../src/branding.js)), and the agent-doc stub (task 2121).
8
+
9
+ ## Context
10
+
11
+ The audit's finding F7 asked a fair question: **branding** flows as a *structured* contract — `config/branding.neutral.json` (ships) ⊕ `config/branding.json` (publish-excluded) → a validated resolver ([`src/branding.js`](../../src/branding.js)) with env-override precedence and a client-safe projection — while **project context** flows only as *prose*: [`docs/project-context.template.md`](../project-context.template.md) ships (the scaffold `cloudbongos init` fills), `docs/project-context.md` (the instance's filled-in prose) is publish-excluded, plus the `CLAUDE.md`/`AGENTS.md` brand-free stub (task 2121) so a consumer's `node_modules` can't auto-load core project-memory.
12
+
13
+ So the two match at the **publish-boundary** level (a neutral template ships; the instance's filled-in copy is excluded) but NOT at the **structured-resolution** level: there is no runtime resolver, no required-field validation, and no env override for project context — code never reads a merged "project-context object." F7 framed closing that gap as a decision: introduce a parallel structured resolver, or explicitly document prose-only.
14
+
15
+ ## Decision
16
+
17
+ **Project context stays prose-only. We do NOT build a parallel structured neutral+instance+resolver for it.** The structured, code-read host contract is **branding** (and only branding). Project context is deliberately narrative — written for the *AI agents* who read it (product, vision, world, visual style), not for code to consume as fields.
18
+
19
+ Concretely, the contract is:
20
+
21
+ 1. **Machine-readable host identity → branding.** Every instance-identity string code actually renders or injects (names, domains/origins, currency label, cookie/OAuth/dev-box hosts, theme, track set, the project name injected into LLM prompts) lives in the branding contract: `branding.neutral.json` (ships) ⊕ `branding.json` (excluded) → `resolveBranding()` with env precedence and fail-to-vanilla. If a new host string needs to be *code-read*, it goes in **branding**, not a new project-context resolver.
22
+ 2. **Prose host context → project-context, unstructured.** Vision / world / visual-style narrative for agents lives in `docs/project-context.md` (instance, excluded) scaffolded from `docs/project-context.template.md` (ships). It is read by humans and agents, never parsed by code.
23
+ 3. **The boundary is enforced at the publish layer, which already exists.** `isPublishable()` ships the neutral template and excludes the instance's filled copy ([`scripts/gds/publish-manifest.js`](../../scripts/gds/publish-manifest.js)); the `CLAUDE.md`/`AGENTS.md` stub stops a consumer auto-loading core project-memory. No runtime contract is needed because nothing at runtime consumes project context as data.
24
+
25
+ ## Why prose-only over a structured resolver (the trade-off)
26
+
27
+ - **No consumer → YAGNI.** A structured resolver earns its keep only when *code* must read merged, validated fields with env precedence — exactly branding's job, which already exists. Nothing in the platform reads a "project-context object": it is documentation. Building a second resolver, schema, and validation layer for a thing only agents read is speculative infrastructure against the bootstrapped posture ([CLAUDE.md §4](../../CLAUDE.md)).
28
+ - **It matches the core↔host split as already drawn** ([ADR 0062](<redacted>.md) §7): CLAUDE.md is portable methodology; the host authors identity beside it — the *strings code reads* in branding (structured), the *prose agents read* in project-context (narrative). F7 is not a gap in that split; it is the split working as designed.
29
+ - **Redaction stays simple + correct.** Project-context prose flows through the same doc-redaction + publish-exclusion path as every other doc. A structured project-context file would add another schema the no-leak gate and the `init` flow must understand, for no functional gain.
30
+ - **One place to add a host string.** "Where does a new instance-identity value go?" has a single answer — branding — instead of a judgment call between two parallel contracts.
31
+
32
+ ## When to revisit
33
+
34
+ Revisit if a concrete need appears for **code to read project-context as structured data** — e.g. the product runtime (not just agents) must branch on a world/vision field, or an automated flow must validate that an instance filled in required narrative before it can ship. At that point the value under question would really be a *branding* field (add it there), or a genuinely new structured need would justify its own resolver. Until such a consumer exists, prose-only is correct.
35
+
36
+ ## Consequences
37
+
38
+ - **No new code.** No project-context resolver, schema, or env-override layer is added; `src/branding.js` carries a short pointer comment so the next person who wonders "why isn't there a project-context resolver?" finds this ADR at the natural place they'd add one.
39
+ - **Init unchanged.** `cloudbongos init` keeps scaffolding `docs/project-context.md` from the template as prose; there is nothing to validate at standup beyond the existing branding validation.
40
+ - **Publish boundary unchanged.** The template ships, the filled instance prose is excluded, the agent-doc stub stands — already true, now documented as the deliberate contract rather than an accidental asymmetry.
41
+ - **Audit H11 closed** without expanding the surface the update pipeline must keep neutral (which the sibling PROVE-NO-LEAK work — H4/H5/H6 — is separately hardening).
@@ -0,0 +1,35 @@
1
+ # 0143 — Onboarding repo picker & auto-create: broaden the OAuth scope (not a GitHub App), store a short-lived token
2
+
3
+ - **Status:** Accepted — built in task 1002099.
4
+ - **Date:** 2026-07-13
5
+ - **Deciders:** Lars (owner/Archon) chose the credential approach; Claude designed + built.
6
+ - **Task:** [#1002099](https://cloudbongos.com/builders#/task/1002099) · **Goal:** 35 (greenfield onboarding).
7
+
8
+ ## Context
9
+
10
+ The onboarding wizard at `/create` ([public-landing/create.html](../../public-landing/create.html)) had the visitor **type `owner/repo` by hand** (adopt) and, for a fresh project, do a **manual** "New repository on github.com → leave it empty" step. Owner feedback: make it real — let the signed-in user **pick from their own repos** (adopt) and **auto-create the empty repo** (fresh).
11
+
12
+ Blocker: the wizard's GitHub sign-in requests only `read:user` ([auth.js `SCOPE`](../../src/bongos/auth.js)), which cannot list or create repos, and `completeWebFlow` discarded the OAuth token after reading the username. Two ways forward were weighed:
13
+
14
+ - **(A) Broaden the OAuth scope** and act as the user via their own token.
15
+ - **(B) A central "Cloud Bongos" GitHub App** the user installs (fine-grained `Administration:write` to create, `Metadata:read` to list).
16
+
17
+ The existing per-instance GitHub **App-manifest** flow ([ADR 0133](<redacted>.md)) is *not* reusable here — it builds a sign-in-only App with `default_permissions:{}`, one per provisioned instance, not a central repo-acting App.
18
+
19
+ ## Decision
20
+
21
+ **Take (A) — broaden the scope — per the owner's explicit call**, accepting that it is less least-privilege than a GitHub App, in exchange for no install step and a single sign-in. Within (A):
22
+
23
+ 1. **Scope = `public_repo`, not `repo`.** There is no OAuth scope for "create a repo only"; `repo` grants read/write to *all* the user's code (public **and** private) — a serious liability for a token we now persist on an internet-facing tier. `public_repo` lists/creates **public** repos with a much gentler consent screen and a far smaller blast radius. Cloud Bongos instances are open-source / capture-resistant by design, so public is the norm. **Accepted limitation:** private repos can't be listed/adopted or created; revisit to `repo` only if private support is needed.
24
+ 2. **Opt-in per sign-in.** The scope is requested **only** by the wizard, via `?repos=1` on `/auth/web/start` (a `gds_oauth_repos` intent cookie carried to the callback). The builders'-hall web sign-in and the CLI Device Flow stay `read:user`. A single pure `scopeForWebFlow({repos})` is the one place the scope string is decided (unit-tested).
25
+ 3. **Lazy consent.** The step-0 gate sign-in stays identity-only; repo access is requested at **step 2**, when the user reaches the picker/creator — more private, and the "grant access" path is the well-exercised normal path.
26
+ 4. **Token persistence, contained.** The captured `public_repo` token is stored **encrypted** (secret-box, master key in server env only) in `github_oauth_tokens` (migration `core_192`), keyed to the builder, with a **short TTL (1h = one wizard sitting)** and a lazy expiry sweep on read. This lives in **core auth**, not the provisioning module: it is the auth system's *own* handshake token, not a feature's third-party API key (contrast the art module's Gemini key, [ADR 0102](<redacted>.md)), and the provisioning module's charter forbids holding tokens / calling cloud APIs ([ADR 0111](<redacted>.md) §2 / [ADR 0016](<redacted>.md)). Endpoints `GET/POST /github/repos` ([src/bongos/routes/github.js](../../src/bongos/routes/github.js)) read it back, `requireBuilder` + router-wide rate-limited.
27
+ 5. **v1 = the user's own personal repos** (`affiliation=owner`), so `full_name` is unambiguously `login/repo` and org OAuth-policy complexity (an org can restrict/approve OAuth apps; repos silently omitted) is out of scope. Org/collaborator repos are a later enhancement.
28
+ 6. **Progressive enhancement / graceful degrade.** If secret-box is **unconfigured** (`BUILDER_SECRET_KEY` unset), no token is ever stored: `GET /github/repos` returns `503 github_repos_unavailable` and the wizard **keeps the manual owner/repo inputs + the manual create-repo done-step** as the fallback. Onboarding never regresses.
29
+
30
+ ## Consequences
31
+
32
+ - **New surface:** `scopeForWebFlow` + `captureRepoToken` in auth.js; `?repos=1` handling in the web routes; `github_oauth_tokens` (core_192) + `upsert/get/deleteGithubToken` in db.js; `src/bongos/github-repos.js` (raw-fetch `listUserRepos`/`createUserRepo`); `src/bongos/routes/github.js`; the wizard's picker/auto-create UI.
33
+ - **Security posture:** a stored `public_repo` token is a smaller honeypot than `repo`, and it is encrypted at rest, short-lived, and swept — but it *is* new liability the web tier didn't carry before. The 503-fallback means an instance that doesn't configure secret-box simply doesn't get the feature (no plaintext token is ever written).
34
+ - **Consent friction:** a returning user who signed in months ago has only `read:user`; the picker's `repo_scope_required` (403) prompts a one-click reconnect. The sessionStorage draft round-trips through the OAuth hop (same-tab), so no wizard state is lost.
35
+ - **Reversal path:** switching to `repo` (private support) is a one-line scope change; switching to a GitHub App later would supersede this ADR (append a new one, don't edit).
@@ -209,7 +209,10 @@ This keeps the decision history honest and traceable.
209
209
  | 0137 | [Upstream publish policy: `@bongos/core` patches are published MANUALLY (owner-gated), NOT auto-published on merge (task [#2158](https://example.com/builders#/task/2158), BONGOS-V1, goal 26; the SUPPLY half split out of ADR 0136 §5 / task 2150, builds on ADR 0134). Owner chose manual over auto. Decision: the owner runs `package-core.js --publish --live` to cut a release (optional `core-v<version>` git tag as the auditable marker — triggers no CI); `CORE_VERSION` (src/module-api.js) is bumped by hand in-task with a changelog line (provenance stays in git, not a release-tool side effect); NO npm write-token at rest (preserves ADR 0134 tokenless tooling — owner auths at publish time; only the read token exists); the no-leak/mirror-redact gate is already fail-closed inside `package-core.js`, so `--publish` cannot upload a leaking artifact. The ADR 0136 subscription consumes whatever is published; freshness is owner-paced by design. Rejected: auto-publish-on-merge (needs a standing npm write-token as a CI secret — reverses the tokenless posture for little gain at low, deliberate release volume). Revisit as a tag-triggered CI publish when the managed-fleet epic (task 1948) makes the manual step a real bottleneck. Ritual: docs/recipes/private-npm-distribution.md "Cutting a core release".](<redacted>.md) | distribution / npm |
210
210
  | 0138 | [A core-bundled module's external npm deps are declared per-module; the consumer composes them, core stays lean (task [#2160](https://example.com/builders#/task/2160), BONGOS-V1, goal 26; R89 cutover rehearsal finding F2, builds on ADR 0108 + ADR 0083). The discord module ships inside `@bongos/core` but `package-core.js` declares only express+pg, so a consumer that enables discord crashed at boot on missing `discord.js` (the only such case; discord is `default:false`). Owner chose lean-core over hoisting. Decision: core deps stay express+pg; a bundled module declares its own npm deps in `module.json` `dependencies` (schema-validated in `manifest-schema.js`; discord declares `discord.js`); greenfield `bongos init` composes the ENABLED modules' deps into the instance package.json (`enabledModuleDeps`→`buildInstancePackageJson`, existing pin wins, core always set); the R89 cutover preserves the monolith's existing closure ∪ core. Rejected: hoisting `discord.js` into core `optionalDependencies` (installs for EVERY consumer though discord is opt-in — cuts against ADR 0108 lean-core); `peerDependencies` (optional peers aren't auto-installed → crash remains; required peers = hoisting-with-warnings).](<redacted>.md) | modules / distribution |
211
211
 
212
- | 0139 | [Migrate the platform work-history (tasks/goals/credits/builder identities) from the Off the Boats instance DB to the cloudbongos DB — the DATA half of the CB↔OTB split (companion to the R89 code half). Owner-locked: clean move (platform history leaves OTB), game credits stay, identity keyed by `builders.github_id` (balance surfaces on the existing GitHub sign-in, no federation hub), currency number moves + label adapts, near-empty target = clean load. Needs its own ADR because it deliberately crosses the goal-41 "authority stays per-project" line + ADR 0107 §3's deferral. WS-0 (re-provision cloudbongos.com onto core 1.17.3 first) … WS-7; the mover (WS-2) is bespoke — bigint PK renumber + full FK remap, the polymorphic `dependencies` table per-kind, `credit_log` load-with-triggers-off then rebuild `total_credits` from `SUM(delta)`, preserve the `session.token_reward` idempotency index. EXECUTION is owner-gated (WS-4+); nothing runs against production until greenlit; prove on a throwaway copy first.](<redacted>.md) | platform / migration |
213
- | 0140 | [cloudbongos.com re-provisioned to the ADR 0108 standalone model, DB-PRESERVING — closing ADR 0139's skipped WS-0 (executed 2026-07-12). The site was a lift-and-shift clone of the `amazonprimea` repo frozen on stale code — every `/builders/*` asset 404'd — because its pull-deploy silently no-op'd against the unchanged game repo (`origin` was `lars589/amazonprimea`, not a cloudbongos instance); it had never run the restored code. WS-0's original fresh-DB re-provision would now WIPE the migrated history/balances, so a build-alongside-then-flip variant was used: a dedicated private `cloudbongos/cloudbongos-instance` repo (lean config over the neutral brand + a pinned `@bongos/core@1.17.3`), materialized beside the untouched old checkout, proven on a spare port against the live DB (migrate = clean no-op; leaderboard read migrated balances), then `cloudbongos.service` flipped to the instance + engine and the ADR 0129 pull-timer repointed at the instance repo. Engine source stays authoritative at `lars589/cloud-bongos` (not relocated); verified DB backup + retained old checkout/unit/deploy-script give instant rollback. Enabled org-wide deploy keys on the `cloudbongos` org so the box's read-only deploy key could attach.](<redacted>.md) | infra / Cloud Bongos |
212
+ | 0139 | [Migrate the platform work-history (tasks/goals/credits/builder identities) from the Example instance DB to the cloudbongos DB — the DATA half of the CB↔OTB split (companion to the R89 code half). Owner-locked: clean move (platform history leaves OTB), game credits stay, identity keyed by `builders.github_id` (balance surfaces on the existing GitHub sign-in, no federation hub), currency number moves + label adapts, near-empty target = clean load. Needs its own ADR because it deliberately crosses the goal-41 "authority stays per-project" line + ADR 0107 §3's deferral. WS-0 (re-provision cloudbongos.com onto core 1.17.3 first) … WS-7; the mover (WS-2) is bespoke — bigint PK renumber + full FK remap, the polymorphic `dependencies` table per-kind, `credit_log` load-with-triggers-off then rebuild `total_credits` from `SUM(delta)`, preserve the `session.token_reward` idempotency index. EXECUTION is owner-gated (WS-4+); nothing runs against production until greenlit; prove on a throwaway copy first.](<redacted>.md) | platform / migration |
213
+ | 0143 | [Onboarding repo picker (adopt) + auto-create (fresh): the `/create` wizard's Home step no longer makes the user hand-type `owner/repo` or manually create an empty repo on github.com (task [#1002099](https://cloudbongos.com/builders#/task/1002099), goal 35). Owner chose to **broaden the OAuth scope** over a central GitHub App (no install step, single sign-in), accepting it is less least-privilege. Within that: scope = **`public_repo`, not `repo`** (no OAuth scope is "create-only"; `repo` grants R/W to ALL the user's code and we now PERSIST the token — `public_repo` still lists/creates public repos with a gentler consent + smaller blast radius; can't do private, revisit only if needed); **opt-in per sign-in** via `?repos=1` (a `gds_oauth_repos` intent cookie → `captureRepoToken`; hall + CLI stay `read:user`; one pure `scopeForWebFlow`); **lazy consent** (asked at step 2, not the gate); token stored **encrypted (secret-box), short TTL (1h), lazily swept**, in **core auth** not the provisioning module (it's auth's OWN handshake token, not a feature key à la ADR 0102; provisioning's charter forbids tokens/cloud-API, ADR 0111 §2 / ADR 0016); v1 **`affiliation=owner`** personal repos only (org policy deferred); **graceful degrade** — secret-box unconfigured → `503` → wizard keeps the manual inputs + manual done-step, onboarding never regresses. New: `github_oauth_tokens` (core_192), `src/bongos/github-repos.js`, `src/bongos/routes/github.js` (`GET/POST /github/repos`, requireBuilder + rate-limited). Not the App-manifest flow (ADR 0133 — sign-in-only, per-instance, no repo perms).](<redacted>.md) | onboarding / auth |
214
+ | 0140 | [cloudbongos.com re-provisioned to the ADR 0108 standalone model, DB-PRESERVING — closing ADR 0139's skipped WS-0 (executed 2026-07-12). The site was a lift-and-shift clone of the `example` repo frozen on stale code — every `/builders/*` asset 404'd — because its pull-deploy silently no-op'd against the unchanged game repo (`origin` was `example-owner/example`, not a cloudbongos instance); it had never run the restored code. WS-0's original fresh-DB re-provision would now WIPE the migrated history/balances, so a build-alongside-then-flip variant was used: a dedicated private `cloudbongos/cloudbongos-instance` repo (lean config over the neutral brand + a pinned `@bongos/core@1.17.3`), materialized beside the untouched old checkout, proven on a spare port against the live DB (migrate = clean no-op; leaderboard read migrated balances), then `cloudbongos.service` flipped to the instance + engine and the ADR 0129 pull-timer repointed at the instance repo. Engine source stays authoritative at `example-owner/cloud-bongos` (not relocated); verified DB backup + retained old checkout/unit/deploy-script give instant rollback. Enabled org-wide deploy keys on the `cloudbongos` org so the box's read-only deploy key could attach.](<redacted>.md) | infra / Cloud Bongos |
215
+ | 0141 | [Cross-site identity — cloudbongos.com becomes a federated identity provider (the "hub") so one platform account reaches any hosted project's builders hall, browser AND CLI, with no second GitHub sign-in (Goal 41 design of record; task [#1002082](https://cloudbongos.com/builders#/task/1002082); implemented across [#1002106](https://cloudbongos.com/builders#/task/1002106)–[#1002115](https://cloudbongos.com/builders#/task/1002115)). Core principle: **identity is federated, authority is not** — the hub carries identity ONLY (github_id, login, display name, avatar), never rank/credits/admission, so [ADR 0016](<redacted>.md)'s self-owned-authority boundary is preserved by construction. Federation is opt-in + reversible via a config switch (`auth.idp`): a hosted instance provisioned with `auth.idp` + `<PREFIX>_HUB_*` routes web sign-in through the hub's `/sso/authorize`→`/sso/token` (OAuth authorization-code, single-use 60s codes, server-to-server client-secret redemption) and CLI sign-in through the hub's device flow + an audience-scoped Ed25519-signed assertion verified offline at a new `/auth/device/exchange`; a self-hosted instance leaves `auth.idp` unset and keeps owning its own GitHub app (the direct-GitHub path, unchanged fallback). Adds a hub `platform-identity` module (accounts / sso_clients / sso_authorization_codes / projects / project_memberships / builder_project_activity), a project→hub membership check-in inside upsertBuilder (coarse role, never rank), a My Projects view with project-executed join/leave, a curated public Explore showcase, per-builder cross-project activity rollups, and an Archon-only cross-project scouting view (upgrading the coarse [ADR 0127](<redacted>.md) fleet gauges to a github_id-keyed store). Two credential types by design: per-client hashed secret (instance→hub server-to-server auth) + a hub Ed25519 keypair (CLI assertions, asymmetric so one instance can't forge for another). Was scoped as "ADR 0135"; that number was reassigned, so it lands here as 0141.](<redacted>.md) | auth / Cloud Bongos identity |
216
+ | 0142 | [Project context is prose-only; the structured host-identity contract is branding (audit H11 / finding F7; task [#1002224](https://example.com/builders#/task/1002224), goal 1000042). Branding flows as a structured neutral⊕instance→validated-resolver contract because CODE reads those strings; project context (vision/world/visual-style in `docs/project-context.md`, scaffolded from the shipped `docs/project-context.template.md`) is deliberately narrative — read by AI agents, never parsed by code — so it stays prose-only with no parallel resolver/schema/env layer (YAGNI: no consumer; branding already covers code-read strings; the publish boundary + the CLAUDE.md/AGENTS.md stub already enforce the split at the file level per [ADR 0062](<redacted>.md) §7). A new host value that code must read goes in branding, not a new project-context resolver. Revisit only when code (not agents) must read project context as validated, structured data.](<redacted>.md) | core / host-split |
214
217
 
215
218
  > ⚠️ **Numbering collision (known):** two ADRs share `0008`. The numbers were assigned in parallel sessions before the lock could be enforced. The files are kept under their existing filenames to preserve git history, but the table disambiguates them as `0008-a` / `0008-b`. New ADRs should resume at `0040` to avoid further collisions. (`0024` is also a real on-disk duplicate: the cloneable-repo/local-first-memory ADR and the multi-agent-system-architecture ADR were both numbered `0024` in parallel; both keep their filenames, disambiguated as `0024-a` / `0024-b` like `0008`. Likewise `0025` ended up with two on-disk files — the offsite-backup ADR and the structured-criterion↔task-link ADR — both kept under their existing filenames and disambiguated as `0025-a` / `0025-b`; separately, the BFG ADR had also claimed `0025` on 2026-05-30 and yielded to `0026`. A third happened 2026-06-06: `0036` was claimed in parallel by the builders-subdomain ADR ([#726](https://example.com/builders#/task/726)) and this Discord-channels ADR ([#727](https://example.com/builders#/task/727)); the Discord-channels ADR yielded to `0037`. A fourth landed 2026-06-10: `0044` was claimed in parallel by the palette-replacement ADR and the per-box game-preview ADR ([#897](https://example.com/builders#/task/897)); both keep their filenames, disambiguated as `0044-a` / `0044-b` like `0008`. A fifth was caught pre-land 2026-06-13: `0050` was claimed in parallel by the device-flow-admission ADR ([#1000](https://example.com/builders#/task/1000)) and the sandbox-for-everyone ADR ([#1001](https://example.com/builders#/task/1001)); the latter yielded to `0052` before merging, so there is no `0050` duplicate. A sixth was caught pre-land 2026-06-21: the tool-agnostic-design-layer ADR ([#1375](https://example.com/builders#/task/1375)) first collided at `0079` with the value-gated-autonomous-engagement ADR, then at `0080` with the llm-cache-api-transport ADR (both part of the 0075–0080 LLM-cost-reduction series, landed on `main` in parallel); it yielded to `0081` before merging, so there is no `0079`/`0080` design-layer duplicate. A seventh landed 2026-06-23: `0084` was claimed in parallel by the auto-derived-per-task-rank-floor ADR and the remove-default-spend-cap ADR (task 1499); the rank-floor ADR landed on `main` first, so the spend-cap ADR yielded to `0085`, leaving no `0084` duplicate. An eighth landed 2026-06-27: `0095` was claimed in parallel by the borrowed-memory-and-retrieval-concepts ADR (PR #459, landed first) and the cross-agent-context-management ADR ([#1651](https://example.com/builders#/task/1651), PR #460); both keep their filenames, disambiguated as `0095-a` / `0095-b` like `0008`. These two are companions — `0095-a` adopts the memory/retrieval concepts and explicitly defers the grep-vs-semantic question to `0095-b`.)