@bongos/core 1.19.185 → 1.19.187
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 +90 -85
- package/clients/bongos-client/index.d.ts +2 -2
- package/config/government.neutral.json +6 -6
- package/docs/adr/0172-editable-rank-roles-substrate-axis.md +1 -1
- package/docs/api/openapi.json +12 -12
- package/docs/api-reference.md +7 -7
- package/modules/builder-settings/wandering-prefs.js +13 -13
- package/modules/government/catalog.js +79 -79
- package/modules/government/config.js +43 -33
- package/modules/government/db.js +58 -58
- package/modules/government/protected-surfaces.js +7 -7
- package/modules/government/protected-surfaces.json +4 -4
- package/modules/government/ranks.js +17 -17
- package/modules/government/resolver.js +24 -24
- package/modules/government/routes/government.js +88 -88
- package/modules/government/routes/rank-sync.js +8 -8
- package/modules/government/session-scopes.js +7 -7
- package/modules/government/session-scopes.json +5 -5
- package/modules/hall-ui/public/gate.js +2 -2
- package/modules/hall-ui/public/{governance.css → government.css} +11 -11
- package/modules/hall-ui/public/{governance.html → government.html} +14 -14
- package/modules/hall-ui/public/{governance.js → government.js} +108 -108
- package/modules/hall-ui/public/harbor.js +2 -2
- package/modules/hall-ui/public/shell.js +19 -15
- package/modules/hall-ui/public/watch.js +1 -1
- package/modules/lifecycle/claim-eligibility.js +1 -1
- package/modules/lifecycle/db.js +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/fitness.js +138 -0
- package/scripts/hall-preview/server.js +1 -1
- package/src/bongos/auth.js +11 -11
- package/src/bongos/serve-internal.js +8 -8
- package/src/module-api.js +5 -1
- package/tests/auth_page_gate.mjs +2 -2
- package/tests/auth_resolve_failure.mjs +4 -4
- package/tests/{governance_abuse_matrix.mjs → government_abuse_matrix.mjs} +39 -39
- package/tests/{governance_catalog.mjs → government_catalog.mjs} +11 -11
- package/tests/{governance_claim_eligibility.mjs → government_claim_eligibility.mjs} +2 -2
- package/tests/{governance_config.mjs → government_config.mjs} +54 -54
- package/tests/{governance_fold.mjs → government_fold.mjs} +6 -6
- package/tests/{governance_fold_bench.mjs → government_fold_bench.mjs} +3 -3
- package/tests/{governance_live_proof.mjs → government_live_proof.mjs} +5 -5
- package/tests/{governance_ownership_scope.mjs → government_ownership_scope.mjs} +16 -16
- package/tests/{governance_page_gates.mjs → government_page_gates.mjs} +14 -14
- package/tests/{governance_parity.mjs → government_parity.mjs} +3 -3
- package/tests/{governance_principals.mjs → government_principals.mjs} +14 -14
- package/tests/{governance_protected_surfaces.mjs → government_protected_surfaces.mjs} +1 -1
- package/tests/{governance_role_sync.mjs → government_rank_sync.mjs} +2 -2
- package/tests/{governance_require_permission.mjs → government_require_permission.mjs} +1 -1
- package/tests/{governance_resolver.mjs → government_resolver.mjs} +6 -6
- package/tests/{governance_routes.mjs → government_routes.mjs} +36 -36
- package/tests/{governance_seed.mjs → government_seed.mjs} +8 -8
- package/tests/{governance_session_scope.mjs → government_session_scope.mjs} +10 -10
- package/tests/{governance_vanilla_boot.mjs → government_vanilla_boot.mjs} +26 -26
- package/tests/government_vocabulary.mjs +94 -0
- package/tests/hall_nav.mjs +8 -7
- package/tests/hall_page_gate_map.mjs +9 -9
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// modules/
|
|
3
|
+
// modules/government/session-scopes.js — the SESSION-SCOPE axis (ADR 0151 §3, BV1.R99).
|
|
4
4
|
//
|
|
5
5
|
// The FOURTH axis, and the only one attached to the TOKEN rather than to the
|
|
6
|
-
// builder.
|
|
6
|
+
// builder. Ranks say what a person may do (R95); a principal's identity says what
|
|
7
7
|
// a machine may do (R98); an ownership scope says whose row it may be done to
|
|
8
8
|
// (R100); a SESSION-SCOPE says how much of that authority this particular
|
|
9
9
|
// credential carries. A dev-box session is minted onto a machine OUTSIDE the ADR
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
// A SESSION-SCOPE CAN ONLY EVER NARROW. That is the whole load-bearing property,
|
|
14
14
|
// and it has two halves that fail in opposite directions:
|
|
15
15
|
// • INTERSECTION, never union — the scope may not GRANT a permission the
|
|
16
|
-
// builder's
|
|
16
|
+
// builder's ranks do not already confer, or a box token would escalate;
|
|
17
17
|
// • DENY-BY-DEFAULT — a permission the allow-list does not name is denied, or an
|
|
18
18
|
// unlisted permission leaks through.
|
|
19
19
|
// resolver.narrowToSessionScope() is the one place the two compose, and it is
|
|
20
|
-
// written as a FILTER of the
|
|
20
|
+
// written as a FILTER of the rank answer so widening is not expressible there.
|
|
21
21
|
//
|
|
22
22
|
// EXPLICIT DATA, not `if (source === 'box')`. session-scopes.json (next to this
|
|
23
23
|
// file) is the declaration; this module validates it against the permission
|
|
24
|
-
// catalog at load.
|
|
24
|
+
// catalog at load. GOVERNMENT OWNS THE POLICY, THE KERNEL STAYS THE ENFORCER —
|
|
25
25
|
// the same split R101 draws for the protected-surface registry: src/bongos/auth.js
|
|
26
26
|
// reads the same JSON as DATA (fs, never `require` — ADR 0083's one-way rule) and
|
|
27
27
|
// requireBuilder remains the gate every route composes. Nothing here enforces
|
|
@@ -64,10 +64,10 @@ function validateAgainstCatalog(scopes) {
|
|
|
64
64
|
throw new Error(`${where} allows "${key}", which the permission catalog does not define`);
|
|
65
65
|
}
|
|
66
66
|
// R98's rule, kept structural: a machine principal's capability comes from
|
|
67
|
-
// its exact system_role, never from a
|
|
67
|
+
// its exact system_role, never from a rank — so a box-scoped session
|
|
68
68
|
// carrying one must not be expressible on a scope allow-list either.
|
|
69
69
|
if (catalog.isPrincipalKey(key)) {
|
|
70
|
-
throw new Error(`${where} allows the machine-principal permission "${key}" — a session-scope narrows a builder's
|
|
70
|
+
throw new Error(`${where} allows the machine-principal permission "${key}" — a session-scope narrows a builder's RANK authority and never composes with the identity axis`);
|
|
71
71
|
}
|
|
72
72
|
// A session-scope IS the surface a credential outside the ADR 0016 trust
|
|
73
73
|
// boundary may reach. A trust-boundary permission must never appear on one,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": [
|
|
3
3
|
"The SESSION-SCOPE registry (BV1.R99, ADR 0151 §3; the model behind ADR 0053).",
|
|
4
|
-
"A session's scope is capability attached to the TOKEN, orthogonal to the builder's
|
|
4
|
+
"A session's scope is capability attached to the TOKEN, orthogonal to the builder's ranks.",
|
|
5
5
|
"Each row declares EITHER unscoped:true (the session narrows nothing) OR a deny-by-default",
|
|
6
6
|
"permissions allow-list (unlisted => denied). A scope can only ever NARROW: effective",
|
|
7
|
-
"authority is (the builder's
|
|
8
|
-
"Every key here is validated against modules/
|
|
9
|
-
"modules/
|
|
7
|
+
"authority is (the builder's rank permissions) INTERSECT (this allow-list), never a union.",
|
|
8
|
+
"Every key here is validated against modules/government/catalog.js at load by",
|
|
9
|
+
"modules/government/session-scopes.js — unknown, system:true and principal keys are refused.",
|
|
10
10
|
"Read as DATA by src/bongos/auth.js (fs, never require — ADR 0083's one-way rule)."
|
|
11
11
|
],
|
|
12
12
|
"scopes": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"source": "cli",
|
|
15
15
|
"label": "CLI session",
|
|
16
16
|
"unscoped": true,
|
|
17
|
-
"note": "Device Flow token on a builder's own machine — inside the trust boundary, carries the builder's full
|
|
17
|
+
"note": "Device Flow token on a builder's own machine — inside the trust boundary, carries the builder's full rank authority."
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"source": "web",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// Like The Watch + The Harbor, this reads /api/bongos/me to show a Sealed notice for
|
|
11
11
|
// non-Archons — DEFENCE IN DEPTH only. GET /gate-approvals + POST
|
|
12
12
|
// /gate-approvals/:pr/approve are ALSO archon-gated server-side (ADR 0016), and
|
|
13
|
-
// the page itself is gated by server.js
|
|
13
|
+
// the page itself is gated by server.js requireGovernmentPage. On 401 → web sign-in.
|
|
14
14
|
|
|
15
15
|
(() => {
|
|
16
16
|
'use strict';
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
}
|
|
219
219
|
const rank = (me && (me.builder || me).rank || '').toLowerCase();
|
|
220
220
|
// ADR 0157: the Gate page sits at the `page.view.government` floor (metic). The
|
|
221
|
-
// server's
|
|
221
|
+
// server's requireGovernmentPage is the wall — this only decides whether to render the
|
|
222
222
|
// body or the sealed notice, so it must agree or a Metic sees "sealed" on a page
|
|
223
223
|
// they were just admitted to.
|
|
224
224
|
if (rank !== 'metic' && rank !== 'archon') { showSealed(); return; }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* government.css — Page-local styles for the Government page (ranks /
|
|
2
2
|
permissions / assignments — BV1.R111, ADR 0151). Built on the shared design
|
|
3
3
|
tokens (style.css), mirroring gate.css's card + pill idiom; the ?v= cache-bust
|
|
4
4
|
is stamped from this file's content hash at boot (src/asset-version.js). */
|
|
@@ -6,28 +6,28 @@
|
|
|
6
6
|
.gov-h { color: var(--ink); font-size: 16px; font-weight: 600; margin: 22px 0 8px; }
|
|
7
7
|
.gov-h--minor { font-size: 13px; margin: 18px 0 6px; }
|
|
8
8
|
.gov-grid-note { color: var(--ink-soft); font-size: 12.5px; margin: 0 0 12px; }
|
|
9
|
-
/* Holds the rank
|
|
9
|
+
/* Holds the ladder-rank reset button. Empty for every other rank, so it collapses
|
|
10
10
|
rather than reserving a gap — hence no margin on the empty box itself. */
|
|
11
11
|
.gov-grid-actions:not(:empty) { margin: 0 0 14px; }
|
|
12
12
|
.gov-sealed, .gov-empty { color: var(--ink-soft); padding: 16px 0; }
|
|
13
13
|
|
|
14
|
-
/* Two columns on wide screens:
|
|
14
|
+
/* Two columns on wide screens: rank rail left, permission grid right. */
|
|
15
15
|
.gov-layout { display: grid; grid-template-columns: 260px 1fr; gap: 22px; align-items: start; }
|
|
16
16
|
@media (max-width: 760px) { .gov-layout { grid-template-columns: 1fr; } }
|
|
17
17
|
|
|
18
|
-
/* ----
|
|
19
|
-
.gov-
|
|
20
|
-
.gov-
|
|
18
|
+
/* ---- rank list ---------------------------------------------------------- */
|
|
19
|
+
.gov-rank-list { display: flex; flex-direction: column; gap: 8px; }
|
|
20
|
+
.gov-rank {
|
|
21
21
|
text-align: left; font: inherit; cursor: pointer;
|
|
22
22
|
border: 1px solid var(--border); border-radius: var(--radius-sm);
|
|
23
23
|
background: var(--surface); padding: 10px 12px;
|
|
24
24
|
display: flex; flex-direction: column; gap: 4px;
|
|
25
25
|
}
|
|
26
|
-
.gov-
|
|
27
|
-
.gov-
|
|
28
|
-
.gov-
|
|
29
|
-
.gov-
|
|
30
|
-
.gov-
|
|
26
|
+
.gov-rank:hover { background: var(--surface-2); }
|
|
27
|
+
.gov-rank[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 2px 0 0 var(--accent); }
|
|
28
|
+
.gov-rank__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
29
|
+
.gov-rank__label { font-weight: 600; color: var(--ink); font-size: 13.5px; }
|
|
30
|
+
.gov-rank__meta { color: var(--ink-faint); font-size: 11.5px; }
|
|
31
31
|
|
|
32
32
|
.gov-pill {
|
|
33
33
|
font-size: 10.5px; font-weight: 600;
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>
|
|
7
|
-
<meta name="description" content="
|
|
6
|
+
<title>Government — {{worldName}}</title>
|
|
7
|
+
<meta name="description" content="Ranks and permissions — create a custom rank, grant everyday permissions, assign it to a builder. Trust-boundary powers stay locked.">
|
|
8
8
|
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
|
|
9
9
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
12
12
|
<link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
|
|
13
|
-
<link rel="stylesheet" href="/builders/
|
|
13
|
+
<link rel="stylesheet" href="/builders/government.css">
|
|
14
14
|
</head>
|
|
15
|
-
<body data-page="
|
|
15
|
+
<body data-page="government" data-page-title="Government">
|
|
16
16
|
|
|
17
17
|
<div class="app">
|
|
18
18
|
<aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
|
|
28
28
|
<section id="gov-body" hidden>
|
|
29
29
|
<div class="gov-layout">
|
|
30
|
-
<div class="gov-
|
|
31
|
-
<h2 class="gov-h">
|
|
32
|
-
<div class="gov-
|
|
30
|
+
<div class="gov-ranks-col">
|
|
31
|
+
<h2 class="gov-h">Ranks</h2>
|
|
32
|
+
<div class="gov-rank-list" id="gov-rank-list"></div>
|
|
33
33
|
<form class="gov-create" id="gov-create-form" autocomplete="off">
|
|
34
|
-
<h3 class="gov-h gov-h--minor">New custom
|
|
35
|
-
<input class="gov-input" id="gov-create-key" placeholder="
|
|
34
|
+
<h3 class="gov-h gov-h--minor">New custom rank</h3>
|
|
35
|
+
<input class="gov-input" id="gov-create-key" placeholder="rank-key (kebab-case)" maxlength="64" required>
|
|
36
36
|
<input class="gov-input" id="gov-create-label" placeholder="Label" maxlength="200" required>
|
|
37
37
|
<input class="gov-input" id="gov-create-desc" placeholder="Description (optional)" maxlength="2000">
|
|
38
|
-
<button class="gov-btn" type="submit">Create
|
|
38
|
+
<button class="gov-btn" type="submit">Create rank</button>
|
|
39
39
|
</form>
|
|
40
40
|
</div>
|
|
41
41
|
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
50
|
<h2 class="gov-h">Assignments</h2>
|
|
51
|
-
<p class="gov-grid-note">Hand a custom
|
|
51
|
+
<p class="gov-grid-note">Hand a custom rank to a builder. The four ladder ranks are assigned by rank itself and cannot be granted here.</p>
|
|
52
52
|
<form class="gov-assign" id="gov-assign-form" autocomplete="off">
|
|
53
53
|
<input class="gov-input gov-input--id" id="gov-assign-builder" type="number" min="1" placeholder="Builder id" required>
|
|
54
|
-
<select class="gov-input" id="gov-assign-
|
|
54
|
+
<select class="gov-input" id="gov-assign-rank" required></select>
|
|
55
55
|
<button class="gov-btn" type="submit">Assign</button>
|
|
56
56
|
</form>
|
|
57
57
|
<div id="gov-assignments"></div>
|
|
58
58
|
|
|
59
59
|
<h2 class="gov-h">Machine principals</h2>
|
|
60
|
-
<p class="gov-grid-note">Capabilities held by a machine identity, never by a person or a
|
|
60
|
+
<p class="gov-grid-note">Capabilities held by a machine identity, never by a person or a rank. Shown for completeness — nothing here can be granted.</p>
|
|
61
61
|
<div id="gov-principals"></div>
|
|
62
62
|
</section>
|
|
63
63
|
</main>
|
|
@@ -73,6 +73,6 @@
|
|
|
73
73
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
74
74
|
<script src="/builders/palette.js" defer></script>
|
|
75
75
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
76
|
-
<script src="/builders/
|
|
76
|
+
<script src="/builders/government.js?v=2026-08-16-government"></script>
|
|
77
77
|
</body>
|
|
78
78
|
</html>
|