@bongos/core 1.19.187 → 1.19.188
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.
- package/.bongos-core.json +14 -14
- package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +7 -0
- package/docs/adr/0172-editable-rank-roles-substrate-axis.md +7 -0
- package/docs/adr/README.md +2 -2
- package/docs/architecture.md +1 -1
- package/docs/canonical-permissions.md +9 -9
- package/docs/file-map.md +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/module-api.js +3 -1
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.188",
|
|
6
|
+
"core_contract": "1.19.188",
|
|
7
|
+
"source_commit": "d007613318330a2803d0a0fc1d6111d6e68edd49",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-16T23:
|
|
9
|
+
"built_at": "2026-08-16T23:22:52.135Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 308,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 1611,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "67d041849002f213d0fe7900fc4ffd31daa363a1ebb8e4c79c8dc18a1e8f1c50",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -1222,7 +1222,7 @@
|
|
|
1222
1222
|
{
|
|
1223
1223
|
"path": "docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md",
|
|
1224
1224
|
"mode": "0000644",
|
|
1225
|
-
"sha256": "
|
|
1225
|
+
"sha256": "dc8615b7e8b807ef69852ee4cdfcad7db0ab737a1ed733fc96ca712a4ad18ec2"
|
|
1226
1226
|
},
|
|
1227
1227
|
{
|
|
1228
1228
|
"path": "docs/adr/0152-landing-gate-served-by-the-core-app.md",
|
|
@@ -1337,7 +1337,7 @@
|
|
|
1337
1337
|
{
|
|
1338
1338
|
"path": "docs/adr/0172-editable-rank-roles-substrate-axis.md",
|
|
1339
1339
|
"mode": "0000644",
|
|
1340
|
-
"sha256": "
|
|
1340
|
+
"sha256": "390339e26a5e05fd65c8bd4f9303434a8d799e4747b6c1921c2abcc859a331ae"
|
|
1341
1341
|
},
|
|
1342
1342
|
{
|
|
1343
1343
|
"path": "docs/adr/0172-per-craft-compensation-ideator-credit-lane.md",
|
|
@@ -1357,7 +1357,7 @@
|
|
|
1357
1357
|
{
|
|
1358
1358
|
"path": "docs/adr/README.md",
|
|
1359
1359
|
"mode": "0000644",
|
|
1360
|
-
"sha256": "
|
|
1360
|
+
"sha256": "68c676272ad284adc2dd0c9c05b0c6eb0198577a27dd5f2468257eec9d87faf7"
|
|
1361
1361
|
},
|
|
1362
1362
|
{
|
|
1363
1363
|
"path": "docs/api-reference.md",
|
|
@@ -1372,7 +1372,7 @@
|
|
|
1372
1372
|
{
|
|
1373
1373
|
"path": "docs/architecture.md",
|
|
1374
1374
|
"mode": "0000644",
|
|
1375
|
-
"sha256": "
|
|
1375
|
+
"sha256": "497b1fbf18ec1cf6d7e0f3620669cfba9008bc6a40e1f70e4b5f53d3406bc12e"
|
|
1376
1376
|
},
|
|
1377
1377
|
{
|
|
1378
1378
|
"path": "docs/branding-contract.md",
|
|
@@ -1387,7 +1387,7 @@
|
|
|
1387
1387
|
{
|
|
1388
1388
|
"path": "docs/canonical-permissions.md",
|
|
1389
1389
|
"mode": "0000644",
|
|
1390
|
-
"sha256": "
|
|
1390
|
+
"sha256": "9cd97486edfff51a2175c2e758ce99cd217658caec857fddaca366db338822ad"
|
|
1391
1391
|
},
|
|
1392
1392
|
{
|
|
1393
1393
|
"path": "docs/design-contract.md",
|
|
@@ -1492,7 +1492,7 @@
|
|
|
1492
1492
|
{
|
|
1493
1493
|
"path": "docs/file-map.md",
|
|
1494
1494
|
"mode": "0000644",
|
|
1495
|
-
"sha256": "
|
|
1495
|
+
"sha256": "a045f8b58bb2e52d770a24fe44524c27afaa4a24acd3e886e1a9a55cff24d3ed"
|
|
1496
1496
|
},
|
|
1497
1497
|
{
|
|
1498
1498
|
"path": "docs/handoff-template.md",
|
|
@@ -4257,12 +4257,12 @@
|
|
|
4257
4257
|
{
|
|
4258
4258
|
"path": "package-lock.json",
|
|
4259
4259
|
"mode": "0000644",
|
|
4260
|
-
"sha256": "
|
|
4260
|
+
"sha256": "c9866e8f3a03bb27a37058828216a3417a9801d563f2ba225f0789e4c744faf3"
|
|
4261
4261
|
},
|
|
4262
4262
|
{
|
|
4263
4263
|
"path": "package.json",
|
|
4264
4264
|
"mode": "0000644",
|
|
4265
|
-
"sha256": "
|
|
4265
|
+
"sha256": "c320b8445c25728e9a37ef01af92966969f35efdd5758782245b108fc2badef7"
|
|
4266
4266
|
},
|
|
4267
4267
|
{
|
|
4268
4268
|
"path": "public-docs/index.html",
|
|
@@ -5867,7 +5867,7 @@
|
|
|
5867
5867
|
{
|
|
5868
5868
|
"path": "src/module-api.js",
|
|
5869
5869
|
"mode": "0000644",
|
|
5870
|
-
"sha256": "
|
|
5870
|
+
"sha256": "ba52655bc052427326c93c2501bf8916161d7b81617132f76c973c82b67ff1e0"
|
|
5871
5871
|
},
|
|
5872
5872
|
{
|
|
5873
5873
|
"path": "src/module-loader/catalog.js",
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
> **⚠ VOCABULARY AMENDED by [ADR 0174](<redacted>.md) (owner directive, 2026-08-16) — the DECISION below is unchanged.**
|
|
15
|
+
> What this ADR calls *governance* is now the **government**; what it calls *seeded roles* / *rank-roles* are now simply **ranks**. The word *role* is reserved for the three Cloud Bongos crafts — Artist, Ideator, Builder — and appears nowhere on the government side.
|
|
16
|
+
> Concretely: `governance_roles` → `government_ranks`, `governance_builder_roles` → `government_builder_ranks`, `governance_role_permissions` → `government_rank_permissions`, `role_key` → `rank_key`, `governance.manage` → `government.manage`, `page.view.governance` → `page.view.government`, `/governance/roles/*` → `/government/ranks/*`, and `modules/governance/` → `modules/government/`.
|
|
17
|
+
> **The body below is deliberately left in the old vocabulary.** An ADR records what was decided and why at a point in time; rewriting it to match today's words would erase the evidence that the words changed — which is the one thing a reader who hits "rank-role" in an old session log actually needs. Every decision it makes still holds; only the nouns moved. A `fitness.js` check now enforces the new vocabulary, and excludes this file by construction.
|
|
18
|
+
|
|
19
|
+
|
|
13
20
|
## Context
|
|
14
21
|
|
|
15
22
|
Authority in Cloud Bongos is a **single rank threshold** today. [ADR 0016](<redacted>.md) put authority in one DB column (`builders.rank`), checked server-side per request with no caching; [ADR 0018](<redacted>.md) / [ADR 0034](<redacted>.md) wired the four live ranks into the ordered tier `xenos (1) < thetes (2) < metic (3) < archon (4)`. Every privileged route calls `requireRank(...allowed)`, which admits a builder whose rank sits **at or above** the lowest-authority rank named (a threshold, [#591](https://cloudbongos.com/builders#/task/591)). That design is sound and is **not** being replaced — it is the substrate this ADR builds *on top of*.
|
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
- **Amends:** ADR 0151 §2 (the "four seeded rank-roles are immutable through this API" wall — the GRANT half only)
|
|
7
7
|
- **Related:** ADR 0016 (trust boundary — server-enforced, uncached, per request), 0043 (git/ssh trust boundary + the rank floor on protected paths), 0157 (the archon→metic delegation of nineteen operational keys)
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
> **⚠ VOCABULARY AMENDED by [ADR 0174](<redacted>.md) (owner directive, 2026-08-16) — the DECISIONS below are unchanged.**
|
|
11
|
+
> What this ADR calls *governance* is now the **government**; what it calls *seeded roles* / *rank-roles* are now simply **ranks**. The word *role* is reserved for the three Cloud Bongos crafts — Artist, Ideator, Builder — and appears nowhere on the government side.
|
|
12
|
+
> Concretely: `governance_roles` → `government_ranks`, `governance_builder_roles` → `government_builder_ranks`, `governance_role_permissions` → `government_rank_permissions`, `role_key` → `rank_key`, `governance.manage` → `government.manage`, `page.view.governance` → `page.view.government`, `/governance/roles/*` → `/government/ranks/*`, and `modules/governance/` → `modules/government/`.
|
|
13
|
+
> **The body below is deliberately left in the old vocabulary.** An ADR records what was decided and why at a point in time; rewriting it to match today's words would erase the evidence that the words changed — which is the one thing a reader who hits "rank-role" in an old session log actually needs. Every decision it makes still holds; only the nouns moved. A `fitness.js` check now enforces the new vocabulary, and excludes this file by construction.
|
|
14
|
+
|
|
15
|
+
|
|
9
16
|
## Context
|
|
10
17
|
|
|
11
18
|
The governance tab (BV1.R110/R111) let an Archon build custom roles and toggle their operational permissions, but rendered all four **rank roles** — Newcomer/`xenos`, Contributor/`thetes`, Trusted/`metic`, Owner/`archon` — read-only. The owner asked why, and then asked for them to be editable.
|
package/docs/adr/README.md
CHANGED
|
@@ -220,7 +220,7 @@ This keeps the decision history honest and traceable.
|
|
|
220
220
|
| 0146 | [Configurable reward mode — an instance chooses whether a shipped task pays BOTH reward streams or ONLY the cost-plus one ([task 1002270](https://cloudbongos.com/builders#/task/1002270), goal 1000037; follow-up to [ADR 0120](<redacted>.md)). A shipped task pays two streams onto one balance (the [ADR 0054](<redacted>.md) "two conventions, one ledger" tension): the per-task author ESTIMATE (`credits_reward` × kind multiplier — unitless, [ADR 0023](<redacted>.md)) AND the cost-plus SESSION reward (`round(true_cost_usd × 1.20)`, 1 credit = $1 — ADR 0054). New `branding.reward.mode`: `"cost-plus-and-estimate"` (DEFAULT — pay both, exactly today's behavior; every existing instance unchanged on upgrade) or `"cost-plus-only"` (the cost-plus reward is the SOLE equity reward; the per-task estimate PAYOUT is withheld and its idea-promotion slice cascades to 0). Resolved by a pure `rewardPolicy()`; gated in the single per-task credit writer (`insertMultipliedConfirmCredit`) — entirely inside the economy module, ZERO lifecycle changes. `credits_reward` still rides the task row for display + the no-zero-reward claim gate; only the payout is suppressed. Unknown mode → default (a typo can't silently zero rewards). Cloud Bongos selects `cost-plus-only`; achievements + the net-negative +1 bonus are out of scope. Backward-compatible + reversible — no clawback, no migration.](<redacted><redacted>.md) | GDS / economy |
|
|
221
221
|
| 0149 | [`bongos dev` — a one-command LOCAL launcher for a standalone instance repo (owner ask, 2026-07-19: "we need a better option to stand up the local host"). A freshly-created project's `config/branding.json` points at `http://localhost:<port>` — configured to run on the owner's machine — but the platform shipped no command to START it there; `bongos onboard` provisions a CLOUD server and Docker serves a vanilla brand on `:3000`. Standing it up by hand was a six-part assembly (Postgres → createdb → migrate → PORT/PGDATABASE/PGHOST/OAuth env → server → login) with three silent mismatches: the server reads PORT from env not branding (platform-server.js:44); the pool DB name collapses to the OS user while migrate.sh defaults to `example` (pool.js:47 vs migrate.sh:52) unless PGDATABASE is set for BOTH; and node-pg defaults to the Linux peer socket `/var/run/postgresql` (pool.js:46), absent under Homebrew on a Mac. `bongos dev` does the whole thing idempotently from one source of truth (branding): ensures Postgres, createdb, migrate (`MEDUSA_GDS_ONLY=1`), starts the server on the branding port, and signs in. The background server is MANAGED (pid/log per instance) with `bongos dev stop`/`status` — the fix for the orphaned-server accident (a stale `:3005` answering a new project's login). Pure resolution + process mgmt in `scripts/gds/dev-lib.js` (unit-tested `tests/dev_lib.mjs`); orchestration in `scripts/gds/dev.js`. Alternatives rejected: cloud dev box (needs hosting + cost — kept for remote work), Docker (vanilla brand/wrong port — kept for Windows), recipe-only (leaves the six steps). Not bundled into the standalone on-ramp binary (needs a real checkout).](<redacted>.md) | Cloud Bongos / dev experience |
|
|
222
222
|
| 0150 | [Box first-boot bring-up on vendored instances — resolve `infra/` from the instance root + fail loud on empty user-data (spike BV1.R97, [task 1002385](https://cloudbongos.com/builders#/task/1002385); C2 of goals 1000051/1000052, "make cloudbongos boxes stop coming up bare"). Root cause: `box.js` sets `REPO_ROOT` two dirs up from itself, which on a VENDORED instance is the `@bongos/core` package — but the R89 packaging split kept `infra/` (the DO cloud-init template + inlined `box-source-fetch.sh`/cloudflared/ttyd/heartbeat scripts) as INSTANCE content, not in the core publish-manifest. So `readCloudInit` reads a missing template, its `try/catch` returns `null`, and the caller's only guard (`0 > 64KiB`) passes → the box is created with EMPTY user-data and boots bare Ubuntu (no clone, no toolchain, no terminal); `fileGzB64` is likewise fail-soft (warns, returns `''`) so a partial `infra/` half-wires. Live re-confirmed 2026-07-19: instance-root `infra/` present, vendored-core `infra/` gone (the [ADR 0144](<redacted>.md) node_modules workaround wiped by a reinstall), fleet idle so the bug is latent-but-live (next provision boots bare). Fix (R98, [task 1002386](https://cloudbongos.com/builders#/task/1002386)): a `resolveBoxInfraDir()` locating `infra/` via [ADR 0108](<redacted>.md)'s `resolveInstanceRootExplicit()` (cloudbongos `bongos.config.json` = `{"instanceRoot":"."}`) + an env override + a walk-up-out-of-`node_modules` fallback, AND fail-loud backstops (throw on missing template; abort provision on empty user-data). R99 ([task 1002387](https://cloudbongos.com/builders#/task/1002387)) then ensures the toolchain builds on the box. Reinstall-proof + portable; core-only, no migration/doorway change.](<redacted>.md) | GDS / dev boxes |
|
|
223
|
-
| 0151 | [Governance: **permissions are the atom, ranks become seeded roles** — the foundation of the BONGOS-V1 Governance goal (1000030), spike BV1.R90 ([task 1001838](https://cloudbongos.com/builders#/task/1001838)); settles the model in an ADR before R93–R114 build. Authority stops being an all-or-nothing rank threshold ([ADR 0016](<redacted>.md)/0018/0034) and becomes granular **permissions** (code constants that map 1:1 to real routes/surfaces — a permission no route consumes doesn't exist), bundled into assignable **roles**; the four live ranks become four seeded roles whose grants reproduce today's thresholds EXACTLY (the compat seed — cumulative nested supersets, so the resolver's UNION preserves the at-or-above threshold), and `builders.rank` stays as the identity/graduation column. A per-request **uncached** `resolveBuilderPermissions()` (kernel port, preserving ADR 0016's instant-demotion) + a `requirePermission()` gate that coexists with `requireRank` via the seed → gates migrate route-by-route, no flag day. The **complete authority model** (C3) represents four axes as first-class types, not rank special-cases: rank-seeded roles, machine **principals** (`system_role`=bfg/discord_bot, exact-identity gate, never UI-grantable), **session-scopes** (box tokens, deny-by-default allow-list intersected with the builder's roles), and **ownership-scoped** perms (`X.manage.own` ≠ `.any`; goal owner/manager per [ADR 0106](<redacted>.md)). The safety keystone (C6): every permission carries a **`system` flag** — `system:true` (deploy, protected-path, rank-set, version-close, grade-bypass, cross-tier edges) is **non-grantable** and LOCKED in the tab, so no configurable role can hand out the crown jewels; and the today-hardcoded `PROTECTED_GLOBS`/`EXPECTED_RANKS` map becomes a **governance-owned protected-surface registry** that the OUT-OF-BAND substrate (pre-push hook, grader pre-pass, `main-audit.js`, gate-review — [ADR 0043](<redacted>.md)) READS but never moves in-process: **policy owns / substrate enforces** — the tab can re-map the floor but a forced `system` grant still can't deploy (abuse-matrix + live-demo proofs, R112/R114). Capability in **core** (`modules/governance/`, default:true); role templates are per-instance **config** (`config/governance.json` over `config/governance.neutral.json` over env, mirroring `src/branding.js`), live assignments in the DB. Collapses the ~6 duplicated numeric rank-tier maps (the Builder-25-incident drift class) behind the resolver. Zero day-one behavior change (parity test R103); one deliberate fail-closed divergence (unwired divine ranks map to no role instead of latently inheriting Archon). Includes the full enumerated permission catalog (every key + `system` flag) grounded in the 2026-07-24 authority sweep. No new recurring cost.](<redacted>.md) | governance / permissions / Cloud Bongos |
|
|
223
|
+
| 0151 | [Governance: **permissions are the atom, ranks become seeded roles** — the foundation of the BONGOS-V1 Governance goal (1000030), spike BV1.R90 ([task 1001838](https://cloudbongos.com/builders#/task/1001838)); settles the model in an ADR before R93–R114 build. Authority stops being an all-or-nothing rank threshold ([ADR 0016](<redacted>.md)/0018/0034) and becomes granular **permissions** (code constants that map 1:1 to real routes/surfaces — a permission no route consumes doesn't exist), bundled into assignable **roles**; the four live ranks become four seeded roles whose grants reproduce today's thresholds EXACTLY (the compat seed — cumulative nested supersets, so the resolver's UNION preserves the at-or-above threshold), and `builders.rank` stays as the identity/graduation column. A per-request **uncached** `resolveBuilderPermissions()` (kernel port, preserving ADR 0016's instant-demotion) + a `requirePermission()` gate that coexists with `requireRank` via the seed → gates migrate route-by-route, no flag day. The **complete authority model** (C3) represents four axes as first-class types, not rank special-cases: rank-seeded roles, machine **principals** (`system_role`=bfg/discord_bot, exact-identity gate, never UI-grantable), **session-scopes** (box tokens, deny-by-default allow-list intersected with the builder's roles), and **ownership-scoped** perms (`X.manage.own` ≠ `.any`; goal owner/manager per [ADR 0106](<redacted>.md)). The safety keystone (C6): every permission carries a **`system` flag** — `system:true` (deploy, protected-path, rank-set, version-close, grade-bypass, cross-tier edges) is **non-grantable** and LOCKED in the tab, so no configurable role can hand out the crown jewels; and the today-hardcoded `PROTECTED_GLOBS`/`EXPECTED_RANKS` map becomes a **governance-owned protected-surface registry** that the OUT-OF-BAND substrate (pre-push hook, grader pre-pass, `main-audit.js`, gate-review — [ADR 0043](<redacted>.md)) READS but never moves in-process: **policy owns / substrate enforces** — the tab can re-map the floor but a forced `system` grant still can't deploy (abuse-matrix + live-demo proofs, R112/R114). Capability in **core** (`modules/governance/`, default:true); role templates are per-instance **config** (`config/governance.json` over `config/governance.neutral.json` over env, mirroring `src/branding.js`), live assignments in the DB. Collapses the ~6 duplicated numeric rank-tier maps (the Builder-25-incident drift class) behind the resolver. Zero day-one behavior change (parity test R103); one deliberate fail-closed divergence (unwired divine ranks map to no role instead of latently inheriting Archon). Includes the full enumerated permission catalog (every key + `system` flag) grounded in the 2026-07-24 authority sweep. No new recurring cost. **Vocabulary amended by ADR 0174 (2026-08-16): governance→government, seeded roles→ranks; the decisions are unchanged.**](<redacted>.md) | governance / permissions / Cloud Bongos |
|
|
224
224
|
| 0152 | [The landing gate is served by the **core app**, not by the front proxy — the cutover step of the landing migration ([task 1002411](https://example.com/builders#/task/1002411), L05 of goal 1000035). The reference instance's orb-gate front page was `file_server`'d by Caddy straight out of a checkout of an UNRELATED product repo (`root * <checkout>/brand/cloud-bongos`), so the landing had two sources of truth, no deploy path of its own, and a cross-product coupling the core could not express. [L01](https://example.com/builders#/task/1002407) had already ported the bundle into the core as `public-landing/` and [L02](https://example.com/builders#/task/1002408) had already taught `platform-server.js` to serve it (`/` -> 302 `/gate/`, `/gate/` serves the index raw, `express.static` covers the assets) — so by the time L05 came up, BOTH halves of its original plan ("give the landing (a) its own Caddy config and (b) its own deploy script") had dissolved. **Decision:** the app owns the landing end to end; the proxy drops `root` + `file_server` and keeps exactly three jobs on that surface — TLS, an optional pre-launch `basic_auth` lock, and the `@hidden` guard that keeps `gate/README.md` unreachable. No separate Caddy config to write (the resulting block IS the generic pure-proxy shape `provision.js`'s `caddyBlock()` already emits per instance, [ADR 0111](<redacted>.md) §4; host-specific hostnames/certs stay on the host per [ADR 0062](<redacted>.md) §7) and no separate deploy script to write (the landing ships INSIDE the pinned core package, so it rides the instance's existing pull-deploy — one artifact, one version, one path). Keeps `redir / /gate/ 302` because Caddy orders `redir` before `basic_auth`, so "/" behaves identically before and after, and the app issues the same 302 once the lock is lifted. Cost accepted: the landing now sits in the app's request path (a dead app = a dead front page — but the gate's whole purpose is to reach the app), and a landing tweak now needs a core release. Verified on the live instance: identical status codes across the apex and both vanity doors before/after, relative redirects (no origin leak), and a **severance test** — with the foreign repo's landing folder moved aside entirely the site still served the byte-identical gate, proving the dependency is cut rather than merely unused. Retiring the foreign copy is L06 ([task 1002412](https://example.com/builders#/task/1002412)).](<redacted>.md) | platform serving / instance infra |
|
|
225
225
|
| 0152 | [**Metic gains task abandonment, paired with an un-abandon at the same rank** (owner directive 2026-07-27: "Metics should also be able to abandon tasks"; [task 1002476](https://cloudbongos.com/builders#/task/1002476)). [ADR 0090](<redacted>.md) moved task authoring (create/edit/promote/deps/criteria) down to the trusted working rank but kept `POST /tasks/:id/abandon` Archon-only as "terminal scope removal" — so the rank that runs idea-triage, seeds the tasks, and shapes them still had to hand every duplicate/moot/superseded chore back to the owner to retire. That hand-back is janitorial, not adjudication. The real hazard was never the grant: abandon was **one-way through the API** (`/promote` took only backlog/blocked, `PATCH` refuses `status`), so a mis-retire needed hand-SQL on prod, and an abandoned task is invisible in every claimable list and every version rollup (migration 017 excludes it from `version_progress`) — nobody notices until the work silently doesn't happen. So the gate moves to `requireRank('metic','archon')` **and** `/promote` gains a third source state, `abandoned → backlog` (never straight to ready — a retired task re-enters un-workable and takes a second deliberate promote), backed by `db.restoreTask`, the mirror of `abandonTask`, which clears the `'Abandoned: <reason>'` stamp and only that. Unchanged: the shipped-task and active-claim refusals, idempotency, and the `audit_log` record of who retired what and who brought it back. The `EXPECTED_RANKS` lifecycle pin moves in lockstep (a *further* downgrade stays a hard CI fail); under [ADR 0151](<redacted>.md) the `task.abandon` floor moves archon→metic, landing as `governance_003` because the compat seed is run-once — purely additive, and the drift guard now compares the **union** of grant migrations to the catalog and fails loudly on a future revocation.](<redacted>.md) | GDS / permissions |
|
|
226
226
|
| 0153 | [**Sequential chain execution — one kickoff walks a dependency chain** ([task 1002484](https://cloudbongos.com/builders#/task/1002484)). [ADR 0015](<redacted>.md) made `dependencies[]` load-bearing and auto-promotes a task's dependents `backlog`→`ready` on ship — but nothing *picks the unblocked task up*, so on the live instance **146 of 303 open tasks sit behind a predecessor** and a 24-task planning seed needed 24 separate human kickoffs. The only "sequential" affordance was a clipboard prompt on the Tasks board (`<redacted>`), which is text rather than execution and cannot even select the gated successors, because they are still `backlog`. Requested independently by two builders (ideas 1000461, 1000398). **Decision:** a chain runner with **no schema change** (the polymorphic `dependencies` table + `task_is_fully_unblocked` + the promote-on-ship trigger already encode the order; a `chain_id`/queue column would be a second, drift-prone source of truth) and **no new claim guard** (one-active-claim-per-session is keyed on the *working tree*, so ship-before-next-claim is already the enforced shape — and batch-claiming a chain is impossible anyway, since successors fail `DEPS_NOT_SHIPPED` until their predecessor ships; the ship IS what unblocks the next step). Deterministic plumbing (`scripts/gds/sequence.js` — scope, topological order, halt matrix, all read off the task row) is split from judgement (`.claude/skills/builder-sequence/`, which defers to `/builder-claim` + `/dev` + `/builder-ship`). **Halt, do not skip** (owner decision): on `needs_migration`, `security_sensitive`, `protected_path`, `rank_floor`, `thin_spec`, `judgement_kind`, `not_claimable`, `deps_unmet`, `in_flight`, or `cycle`, the runner stops and reports with the task still claimed — because in a dependency graph a skipped task is a *predecessor*, so skipping strands everything behind it while the run keeps posting apparent progress. Not built: chains as a priced claimable unit on the board (idea 1000398), which is additive.](<redacted>.md) | GDS / methodology |
|
|
@@ -244,7 +244,7 @@ This keeps the decision history honest and traceable.
|
|
|
244
244
|
| 0167 | [**The /create gate trust link defaults to the AGPL-3.0 license text, not the npm package page** ([task 1002705](https://cloudbongos.com/builders#/task/1002705); gap 1 of the project-creation audit). The gate's "open source" link pointed at a nonexistent repo (404); the task brief's suggested default — the npm package page — is ALSO dead for the gate's actual audience (signed-out visitors): `@cloudbongos/core` and `@bongos/core` both 404 anonymously (private scopes, ADR 0134), and the ADR 0099 public mirror stays dormant until ~2026-11. The license text is the one live, instance-neutral artifact behind the claim today. The browsable-code upgrade is the owner's filed choice (idea 1000700): public repo now (forfeits the ADR 0065 §4 redaction window) / public npm package / wait for the mirror. Rejected: the npm link (verified dead), flipping the repo public (not a builder's call), plain unlinked text (less information, same cost).](<redacted>.md) | public landing / governance |
|
|
245
245
|
| 0169 | [**`bongos serve`: the `bongos dev` boot path, on a real host** ([task 1002398](https://cloudbongos.com/builders#/task/1002398), goal 1000052). [ADR 0149](<redacted>.md) gave an owner one command to stand an instance up on their laptop; "now put it on a server" had no equally good answer — Docker serves the *vanilla* brand on `:3000`, `bongos onboard` provisions a whole droplet through the control plane, and [`instance-deploy.md`](../recipes/instance-deploy.md) left the systemd unit as a hand-written prose step. The six steps (deps → Postgres → createdb → migrate → env → server → health) were already right for a host; only four *decisions inside them* were laptop-shaped. So: a `--server` **mode** on the same script (`bongos serve`), never a second boot path, so the two can't drift. (1) **Supervision** — a systemd unit (`Restart=always`, `WantedBy=multi-user.target`) instead of a pid file that dies on reboot, falling back to the pid-managed process where systemd is absent rather than refusing. (2) **Bind address, derived from the origin** — `https://…` means a proxy terminates TLS, so bind `127.0.0.1`; plain `http://` on a public host means nothing is in front, so bind `0.0.0.0`. The common misconfiguration (app publicly reachable on its raw port behind a proxy) becomes impossible by default. (3) **Peer-auth bootstrap** — a fresh `apt-get install postgresql` cluster has only the `postgres` role, so a deploy user's `createdb` fails with `role "deploy" does not exist`; that reads like a broken install and is really an unbootstrapped cluster, so we create the login role as the superuser. (4) **Health means the PUBLIC origin** — the loopback probe proves the app; DNS/proxy/TLS are where a host actually fails, so it probes the advertised origin too and names the missing layer (advisory — DNS may legitimately not be wired). Secrets go to a root-owned `0600` `EnvironmentFile`, never `Environment=` (`systemctl show` leaks those, and the laptop path's `buildEnv()` spreads the caller's whole shell). Every decision is a pure injectable in `dev-lib.js`, proved in `tests/dev_lib.mjs` with no host. Rejected: a separate `deploy.sh` (drift — the point is the *same* six steps), Docker-on-the-host (makes brand+port a compose override), always binding `0.0.0.0` (exposes the raw port), refusing without systemd (breaks containers/BSD).](<redacted>.md) | onboarding / deploy |
|
|
246
246
|
| 0173 | [**The legacy multi-ship reward shortfall is NOT backfilled — it closes as a one-time transition cost** ([task 1002520](https://cloudbongos.com/builders#/task/1002520), goal 1000037). Before `core_196` the cost-plus reward booked ONE row per session, so a multi-ship session (the normal shape — ship, new worktree, claim again) was paid at its first ship's level and never topped up; `core_196`'s watermark accounting `(session_id, reward_basis)` fixed that forward and deferred the retroactive half to an "owner-signed-off backfill, tracked separately". This is that decision, and it is **decline**. Measured live 2026-08-16, both of the task's open questions answered: (1) the task's own premise is wrong — `reward_basis = 0` is the column's DEFAULT, so it means "booked before top-ups existed", not "underpaid", and **over-selects by ~60%** (478 legacy sessions, but 287 are single-ship and were paid in full; only 191 are candidates); (2) re-pricing each candidate's stored `session_records.model_usage` at `round(true_cost_usd × 1.20)` gives **7,697 credits owed** across 119 sessions — example-owner 5,296 (69%), jaxri 2,319, scootermack 82 — with **72 candidates unreconstructable** (empty `model_usage`) and 16 already OVER-paid by 1,131 that nobody proposed clawing back. Declined because it mirrors the ADR 0146 clawback's own logic (the accounting changed; neither side of the boundary reopens), because paying only the 119 that happened to leave a server-side trace is arbitrary against the 38% that did not, and because correcting shortfalls while ignoring overpayment is a policy choice the owner declined to adopt. Consequence recorded plainly: three builders stay permanently short. **Does NOT close task 1002448** — that is the Windows `encodeProjectPath` population, never *recorded* rather than paid at a stale watermark, still recoverable and still owed.](<redacted>.md) | economy / rewards |
|
|
247
|
-
| 0172 | [**The sub-Archon rank roles are owner-editable; the Archon role is not; the substrate keys are non-grantable to everything** ([task 1002961](https://cloudbongos.com/builders#/task/1002961), goal 1000030). Amends ADR 0151 §2's "the four seeded rank-roles are immutable through this API" wall — the GRANT half only. Their grants were always ordinary `governance_role_permissions` rows (the `governance_002` seed writes them); the read-only rendering was route policy, not structure. Three walls now, where there was one: the **Archon** rank-role stays frozen as the LOCKOUT GUARD (it is the only role holding `governance.manage` by seed, so freezing it means no click sequence can revoke the permission needed to reach this tab); the three **sub-Archon** rank-roles become grant-editable, the seven **in-app** Archon powers included (owner's explicit choice, escalation consequence stated); and `substrate` becomes a declared catalog axis — `deploy.push_main`/`path.protected.modify`/`infra.ssh` are non-grantable to EVERY role forever, because ADR 0043 enforces them out of band, so a grant row confers nothing and the toggle would be the UI lying. Grantability goes per-role (`isGrantableTo(key, role)`); `isGrantable(key)` survives as the narrow custom-role question config.js strips against. **Custom roles are deliberately NOT widened** — a rank-role moves only by a rank write, a custom role is assignable by anyone holding `governance.manage`. Assignment stays rank-derived (R95b) untouched. Adds `POST /governance/roles/:roleKey/reset` (one transaction, filtered through `isGrantableTo`, refused on a custom role) because a drifted ~60-row rank has no way back by clicking. Rejected: substrate keys behind a warning (a toggle that succeeds and delegates nothing), an editable Archon role behind a confirm (a confirm is not a guard; real recovery is hand-written SQL on the droplet).](<redacted>.md) | governance / permissions |
|
|
247
|
+
| 0172 | [**The sub-Archon rank roles are owner-editable; the Archon role is not; the substrate keys are non-grantable to everything** ([task 1002961](https://cloudbongos.com/builders#/task/1002961), goal 1000030). Amends ADR 0151 §2's "the four seeded rank-roles are immutable through this API" wall — the GRANT half only. Their grants were always ordinary `governance_role_permissions` rows (the `governance_002` seed writes them); the read-only rendering was route policy, not structure. Three walls now, where there was one: the **Archon** rank-role stays frozen as the LOCKOUT GUARD (it is the only role holding `governance.manage` by seed, so freezing it means no click sequence can revoke the permission needed to reach this tab); the three **sub-Archon** rank-roles become grant-editable, the seven **in-app** Archon powers included (owner's explicit choice, escalation consequence stated); and `substrate` becomes a declared catalog axis — `deploy.push_main`/`path.protected.modify`/`infra.ssh` are non-grantable to EVERY role forever, because ADR 0043 enforces them out of band, so a grant row confers nothing and the toggle would be the UI lying. Grantability goes per-role (`isGrantableTo(key, role)`); `isGrantable(key)` survives as the narrow custom-role question config.js strips against. **Custom roles are deliberately NOT widened** — a rank-role moves only by a rank write, a custom role is assignable by anyone holding `governance.manage`. Assignment stays rank-derived (R95b) untouched. Adds `POST /governance/roles/:roleKey/reset` (one transaction, filtered through `isGrantableTo`, refused on a custom role) because a drifted ~60-row rank has no way back by clicking. Rejected: substrate keys behind a warning (a toggle that succeeds and delegates nothing), an editable Archon role behind a confirm (a confirm is not a guard; real recovery is hand-written SQL on the droplet). **Vocabulary amended by ADR 0174 (2026-08-16): governance→government, seeded roles→ranks; the decisions are unchanged.**](<redacted>.md) | governance / permissions |
|
|
248
248
|
| 0171 | [**Profile ↔ cross-project rollup: the join runs in-process on the hub; consent is fail-closed account state; the hide flag lives on the account, enforced in the read path** ([task 1002277](https://cloudbongos.com/builders#/task/1002277), R01 of goal 1000045). The C1 cross-project profile reads the platform-identity rollup through the module's **declared-but-never-registered `platform-identity.hub` port**: the module registers a real provider and core `GET /builders/:id/profile` `resolveOptional`s it beside `reward` — zero network, `null` (clean degrade) on every non-hub instance. Federated instances **link out** instead of inlining (amends profile-page spec Decision 1: an instance-side copy is either stale-on-hide or a per-view hub call). Consent: `profile_state` on `platform_identity_accounts`, **fail-closed** — `active` iff touched by a hub-session `/sso/authorize` (device-poll/check-in create `provisional`; backfill = all provisional, lazy upgrade; no core-`builders` join — type-unsafe vs `system:*` ids and a module-migration boundary breach), so the P03 owner decision can only ever widen, never claw back. The C2 hide flag is `hide_stats` on the account (NOT per-instance `behavior_prefs`), enforced **inside** the module's read functions — `listScoutingRollup` itself gains the `active AND NOT hide_stats` predicate so the live Metic-floor `/people`+`/scouting` surfaces honor it by construction. Hub profile responses go `no-store` (hide must beat the 60s cache). Publishing is gated on hardening the self-reported rollup (membership-row requirement, rank-vocab validation, disciplines caps, check-in→rollup sequencing). Found + filed: the `LATERAL unnest` fan-out inflating rollup sums (task 1002911), the unreserved `u` slug (task 1002912), the missing platform T&C artifact (task 1002913), criterion amendments (task 1002914). Rejected: instance→hub per-view pull (always-on dependency), hub→instance mirroring (stale-on-hide), storing the flag in builder-settings, backfilling `active` from hub `builders` rows.](<redacted>.md) | platform identity / profiles / privacy |
|
|
249
249
|
| 0170 | [**The featured projection tells time honestly: `created_at` in, `updated_at` out, owner from the project's own archon** ([task 1002778](https://cloudbongos.com/builders#/task/1002778), goal 1000061). The hub card's metadata pass added `created_at` to the public `/projects/featured` projection, labelled **Listed** — it is the moment the hub catalogued the row, never when the project began, and the C6 card test bans the word "Created". Two recorded deviations: (1) the task brief said `updated_at` was ready to add, but the column is bumped by every client re-registration AND the Archon's feature toggle, so as a public "last updated" it would report curation noise as project activity — it may sort, never project, and the test pins the SELECT list itself (`SELECT *` banned: the route is CORS-open rank:public and a star would leak `owner_github_id`/`status`). (2) The owner fact reads the project's OWN leaderboard archon row (login + avatar, type-checked and capped) from the payload project-stats already fetches — zero extra requests, the 2-fetch pin intact, the advisory `owner_github_id` column still unread per the design contract. Multi-archon: top-credits archon is named; a fallen-off-the-page archon renders as no owner shown, never a wrong one. Rejected: projecting `updated_at` as asked (it lies), reading `owner_github_id` (advisory, contract-banned), a third per-origin fetch for activity recency (moves the test pin for a fact nobody asked for yet).](<redacted>.md) | platform identity / public surface |
|
|
250
250
|
| 0174 | [**Governance is renamed government, its positions are ranks, and "role" is reserved for the three crafts** ([task 1003002](https://cloudbongos.com/builders#/task/1003002), R01 of goal 1000068). Owner directive, 2026-08-16. The word **role** named two unrelated things: the permission system's ladder tiers (`governance_roles`, the "rank-roles") and the three crafts (`tasks.discipline` = engineer/artist/ideator) — and goal 1000066 was actively claiming it for the crafts (`three-roles-only`, `users-hold-roles`), putting the two on a collision course. Resolved at full depth rather than as a label pass, because a labels-only fix leaves the UI and the code disagreeing, which is the condition that produced the collision. `modules/governance/` → `modules/government/`; the kernel module key, the config files, `/api/bongos/governance/*` → `/government/*`, and the permission keys `governance.manage` → `government.manage` (~50 sites) + `page.view.governance` → `page.view.government`. **The entity IS the rank — no second noun**: `governance_roles` → `government_ranks`, `role_key` → `rank_key`, `rank-roles.js` → `ranks.js`; "position" stays prose-only, since introducing it as a code term would recreate the qualifier problem "rank-role" already demonstrates. The cross-module kernel port `governance.roleSync` → `government.rankSync` must land atomically across its provider and both consumers (`modules/lifecycle/db.js`, `src/bongos/db.js`) because it is a transaction participant on the rank-write path. Hand-composed bundles stay in the one table as **custom ranks** — the owner's call over splitting them into a separate "appointments" concept, with the objection recorded (a custom bundle is not a ladder position, and ADR 0172 §4 already treats the two kinds as different). Enforced by a `fitness.js` rule, allowlist shipped with reasons. **Discord's server roles keep the word** — that noun belongs to Discord's API. Amends ADR 0151 + ADR 0172 (the editable-rank-roles one) in **vocabulary only**; ladder slugs, `builders.rank`, `requireRank`, and every floor/grant/assignment semantic are untouched. Rejected: renaming the ladder slugs (turns a bounded rename into a trust-boundary migration), a permanent compat shim (both vocabularies stay correct forever).](<redacted>.md) | government / permissions |
|
package/docs/architecture.md
CHANGED
|
@@ -231,7 +231,7 @@ markdown describes, the DB enforces.**
|
|
|
231
231
|
|
|
232
232
|
- **`example.com`** — game (Phaser + Colyseus). Static files from `public/`. `/builders` + `/builders/*` now **301-redirect to `builders.example.com/<rest>`** ([#739](https://example.com/builders#/task/739) then promoted to permanent 301 in [#741](https://example.com/builders#/task/741), ADR 0036 cutover); the apex no longer serves the builder surface directly.
|
|
233
233
|
- **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/<redacted>.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/gds/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected), run automatically by `.github/workflows/sync-status-mirror.yml` (needs the `STATUS_MIRROR_TOKEN` secret) ([#737](https://example.com/builders#/task/737)). **⚠ FOLLOW-UP (R84):** that workflow's path trigger still watches `public-status/**` and must be re-pointed at `modules/status-ui/public/**` by an owner/Archon — the GitHub App can't push `.github/workflows/*` (learning 107), so until then the mirror sync won't auto-fire on future status edits.
|
|
234
|
-
- **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/<redacted>.md) §1): the surface moved from `public-builders/` to `modules/hall-ui/public/` (~13k LOC, the largest module) and is a loader-discovered web-surface module (`contributes.webSurfaces` host `builders.`). UNLIKE the generic status surface it keeps its **dedicated** serving block in `serve-internal.js` (`BUILDERS_DIR = modules/hall-ui/public/`), partitioned out of the generic web-surface loop on the `isBuildersHost` predicate. A thin rewrite shim maps every non-API path onto the existing `/builders/*` tree (so all serving + gating + asset-stamping is reused), serving the hall (`/`), the Metic+ **`/watch`** monitoring page (gated by `
|
|
234
|
+
- **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/<redacted>.md) §1): the surface moved from `public-builders/` to `modules/hall-ui/public/` (~13k LOC, the largest module) and is a loader-discovered web-surface module (`contributes.webSurfaces` host `builders.`). UNLIKE the generic status surface it keeps its **dedicated** serving block in `serve-internal.js` (`BUILDERS_DIR = modules/hall-ui/public/`), partitioned out of the generic web-surface loop on the `isBuildersHost` predicate. A thin rewrite shim maps every non-API path onto the existing `/builders/*` tree (so all serving + gating + asset-stamping is reused), serving the hall (`/`), the Metic+ **`/watch`** monitoring page (gated by `requireGovernmentPage`), **`/settings`** (Voices + Craft prefs), plus ranks/sessions/primer/diagrams. No behavior change — byte-identical (only `window.__MODULES__.enabled` gains `hall-ui:true`). **Additive** — until its DNS A record + cert are live, the whole surface stays reachable at `example.com/builders/*`. No `.github/workflows/*` follow-up: unlike R84, no workflow path-trigger watches `public-builders/**`.
|
|
235
235
|
- **`/downloads/devbox/*`** (every host, mounted right after the API so the builders-host shim can't rewrite it — [#904](https://example.com/builders#/task/904), [ADR 0045](adr/<redacted>.md)): branded download surface for the Dev Box desktop app. `/{mac-arm64,mac-x64,win-x64}` (+ `mac`/`win` aliases) 302 to the release assets on the public releases repo named in [`config/devbox-app.json`](../config/devbox-app.json); `latest.json` feeds the app's update check. Logic in [`src/devbox-downloads.js`](../src/devbox-downloads.js); the installers never ride the git deploy.
|
|
236
236
|
- The `/api/gds/*` surface is reachable from every host. **Cross-subdomain sign-in:** the `gds_session` cookie is scoped to `.example.com` on the production hosts (apex/www/builders/status) and host-only on localhost/staging (no cross-env token bleed); the OAuth handshake runs on the canonical origin with a validated `?return=` (open-redirect-guarded) so the subdomain can land a builder back on itself.
|
|
237
237
|
- Caddy gets a site block per host ([`infra/Caddyfile`](../infra/Caddyfile)), all reverse-proxying to `127.0.0.1:3000`.
|
|
@@ -141,7 +141,7 @@ or missing ranks fail closed.
|
|
|
141
141
|
- **the four escalation keys**, which look operational but are not: `POST /api/gds/tasks/:id/confirm`
|
|
142
142
|
(grader-bypass), `POST /api/gds/gate-approvals/:pr/approve` (CI deploy-gate override), protected-module
|
|
143
143
|
**goal scope** ([ADR 0086](adr/<redacted>.md)), and `government.manage` (the
|
|
144
|
-
|
|
144
|
+
ranks/permissions tab). Delegating any one of them lets a Metic reach Archon in four steps — create a
|
|
145
145
|
protected-scope goal in the permission core, claim a task there (protected paths already floor at
|
|
146
146
|
*metic* per [ADR 0043](adr/<redacted>.md)), confirm
|
|
147
147
|
past the failed grade, approve their own red gate — so keeping rank Archon-only depends on keeping
|
|
@@ -152,17 +152,17 @@ or missing ranks fail closed.
|
|
|
152
152
|
|
|
153
153
|
> **Amended by [ADR 0172](adr/<redacted>.md) (owner decision, 2026-08-16).**
|
|
154
154
|
> The paragraphs above describe the SEEDED ladder, which is still what a fresh instance boots with — but
|
|
155
|
-
> they are no longer a guarantee about a running one. The owner made the three sub-Archon **
|
|
156
|
-
> editable from the
|
|
155
|
+
> they are no longer a guarantee about a running one. The owner made the three sub-Archon **ranks**
|
|
156
|
+
> editable from the Government tab and chose to include the seven in-app Archon powers, `government.manage`
|
|
157
157
|
> and `builder.rank.set` among them. So "no system permission is grantable below archon" now reads:
|
|
158
|
-
> *no system permission is grantable to a CUSTOM
|
|
159
|
-
> nonetheless hand one to a rank
|
|
158
|
+
> *no system permission is grantable to a CUSTOM rank, and none is seeded below archon* — an Archon may
|
|
159
|
+
> nonetheless hand one to a rank deliberately. The four-step escalation chain described above is
|
|
160
160
|
> therefore **open by decision, not by accident**: whoever holds `government.manage` can reach the rest.
|
|
161
|
-
> Two things that did NOT move, and that bound the blast radius: the **Archon** rank
|
|
161
|
+
> Two things that did NOT move, and that bound the blast radius: the **Archon** rank is immutable
|
|
162
162
|
> (nothing clickable revokes the permission needed to reach the tab), and the three **substrate** keys stay
|
|
163
|
-
> non-grantable to every
|
|
163
|
+
> non-grantable to every rank — ADR 0043's enforcers read the rank ladder and never consult this database,
|
|
164
164
|
> so no amount of in-app escalation produces a push to `main`, a protected-path edit, or an ssh session.
|
|
165
|
-
> `builders.rank` remains the only writer of who holds a rank
|
|
165
|
+
> `builders.rank` remains the only writer of who holds a rank (R95b).
|
|
166
166
|
|
|
167
167
|
Earlier one-power delegations that ADR 0157 generalises: **task authoring** — `POST /api/gds/tasks`,
|
|
168
168
|
`PATCH /api/gds/tasks/:id` (incl. the `newcomer_friendly` flag), `POST /api/gds/tasks/:id/promote`, and the
|
|
@@ -192,7 +192,7 @@ or missing ranks fail closed.
|
|
|
192
192
|
|
|
193
193
|
**[ADR 0157](adr/<redacted>.md) added the whole operational block here** —
|
|
194
194
|
20 permissions that had been Archon-gated only by ADR 0016's fail-closed default, never by a decision:
|
|
195
|
-
the
|
|
195
|
+
the government/monitoring **pages** (`/watch`, `/harbor`, `/gate` — `page.view.government`) and
|
|
196
196
|
`GET /api/gds/sessions/search` (whose own `/sessions` page had no server gate at all until
|
|
197
197
|
task 1002710 put it behind `page.view.government` alongside its three group-mates); the
|
|
198
198
|
**dev-box + provisioning fleets** (`GET /boxes[/cost-ledger]`,
|
package/docs/file-map.md
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
├── brand/ ← repo-canonical design system (ADR 0081)
|
|
38
38
|
│ └── cloud-bongos/ ← Cloud Bongos brand: README design guide + tokens.json + regen_*.py + assets/ (mascot, 9 animation states, Docker-homage sky-whale, coin logo + Baloo 2 wordmark, painted code-glyph charms). Built under task 1506 (mascot restyle 1529, code glyphs 1527); illustrations generated via Gemini (modules/art-pipeline/pipeline gen_api).
|
|
39
39
|
│
|
|
40
|
-
├── config/ ← per-instance config packs. Each pair resolves env → `X.json` (this host's, boundary-excluded) → `X.neutral.json` (the portable starter, the twin that publishes with the core): branding (ADR 0062 §3), modules, design-tokens, and
|
|
40
|
+
├── config/ ← per-instance config packs. Each pair resolves env → `X.json` (this host's, boundary-excluded) → `X.neutral.json` (the portable starter, the twin that publishes with the core): branding (ADR 0062 §3), modules, design-tokens, and government rank templates (BV1.R96 — labels/descriptions/custom-rank templates only; live grants + assignments are DB rows).
|
|
41
41
|
│
|
|
42
42
|
├── docs/
|
|
43
43
|
│ ├── adr/ ← Architecture Decision Records
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.188",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.188",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.188",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/src/module-api.js
CHANGED
|
@@ -801,8 +801,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
801
801
|
// landed since 1.19.185 with no explicit bump. run 31977207459. (task 1002620)
|
|
802
802
|
// 1.19.187 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
803
803
|
// landed since 1.19.186 with no explicit bump. run 31978548058. (task 1002620)
|
|
804
|
+
// 1.19.188 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
805
|
+
// landed since 1.19.187 with no explicit bump. run 31978931152. (task 1002620)
|
|
804
806
|
// ---------------------------------------------------------------------------
|
|
805
|
-
const CORE_VERSION = '1.19.
|
|
807
|
+
const CORE_VERSION = '1.19.188'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
806
808
|
|
|
807
809
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
808
810
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|