@bongos/core 1.19.702 → 1.19.704
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 +27 -17
- package/docs/module-api-changelog.md +4 -0
- package/docs/recipes/windows-builders.md +43 -16
- package/modules/agents/lib/validate.js +56 -0
- package/modules/government/protected-surfaces.json +8 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/agents-sync.js +482 -0
- package/scripts/migrate.sh +23 -0
- package/src/module-api.js +1 -1
- package/tests/agents_sync.mjs +401 -0
- package/tests/agents_validate.mjs +118 -1
- package/tests/government_protected_surfaces.mjs +132 -1
|
@@ -92,7 +92,89 @@ const EXPECTED_GLOBS_BEFORE_R101 = [
|
|
|
92
92
|
// Each entry is { after, glob, why }: `after` is the glob it is inserted
|
|
93
93
|
// directly below, so the expected list is reconstructed in order rather than
|
|
94
94
|
// re-pasted (a re-paste is how the two lists drift apart).
|
|
95
|
-
|
|
95
|
+
// CONSIDERED AND DELIBERATELY NOT ADDED: `.claude/agents/` (task 1002492).
|
|
96
|
+
//
|
|
97
|
+
// It looks like it belongs — an agent definition is local automation that fires
|
|
98
|
+
// on its own and declares its own scope, which is the stated reason
|
|
99
|
+
// `.claude/hooks/` and `.claude/settings.json` sit in the automation group. It
|
|
100
|
+
// was added, and backed out, because protectedness is DERIVED PER MODULE:
|
|
101
|
+
// module-scope-map marks a module protected when ANY of its globs is, and
|
|
102
|
+
// `.claude/agents/` is one of the `agents` module's globs. So the entry silently
|
|
103
|
+
// rank-walls the WHOLE agents module — `modules/agents/` source included — and
|
|
104
|
+
// with it goals 1000038/39/40, changing who may work them. Two guards caught it:
|
|
105
|
+
// module-scope-map's "derived, not hand-set" assertion and publish_manifest's
|
|
106
|
+
// rule that every protected glob be explicitly excluded or publishable.
|
|
107
|
+
//
|
|
108
|
+
// That is a policy decision about a rank floor on three goals. It is NOT the
|
|
109
|
+
// decision task 1002492 was for — "an agent may not scope itself onto the
|
|
110
|
+
// authority surface" — which the scope_paths wall in
|
|
111
|
+
// modules/agents/lib/validate.js now enforces on its own. Protecting the
|
|
112
|
+
// directory would gate who may EDIT a definition; it does nothing about where a
|
|
113
|
+
// definition POINTS.
|
|
114
|
+
//
|
|
115
|
+
// If the owner does want the agents module rank-walled, it needs the entry here,
|
|
116
|
+
// a publish-manifest carve-out, and the module-scope-map roster test updated —
|
|
117
|
+
// three deliberate edits, not a side effect of a scope fix.
|
|
118
|
+
const ADDED_SINCE_R101 = [
|
|
119
|
+
// task 1003366, audit ref MIT1 (2026-08-29 security audit, goal 1000084). The EIGHT
|
|
120
|
+
// execution roots the merge resolver runs out of a cloned branch. The audit named four
|
|
121
|
+
// of them ("the three gen-* scripts and .gitattributes"); modules/lifecycle/executed-
|
|
122
|
+
// closure.js names eight, so the audit's prose was already stale against shipped code.
|
|
123
|
+
// The drift tripwire below is what keeps this list honest from here.
|
|
124
|
+
{
|
|
125
|
+
after: 'scripts/gds/cli-lib.js',
|
|
126
|
+
glob: 'scripts/gds/git-merge-regen.js',
|
|
127
|
+
why: 'the otb-regen MERGE DRIVER. Registered as a relative command with cwd at the '
|
|
128
|
+
+ 'clone root, so git merge runs the BRANCH copy with the live server environment '
|
|
129
|
+
+ 'BEFORE any post-merge step — the earliest execution vector, and the one the '
|
|
130
|
+
+ "audit's \"after the merge\" framing missed.",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
after: 'scripts/gds/git-merge-regen.js',
|
|
134
|
+
glob: 'scripts/gds/gen-repo-map.js',
|
|
135
|
+
why: 'a post-merge generator the resolver runs as execFile(node, [<clone>/...]) — the '
|
|
136
|
+
+ "branch's own copy, inheriting DATABASE_URL and BUILDER_SECRET_KEY.",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
after: 'scripts/gds/gen-repo-map.js',
|
|
140
|
+
glob: 'scripts/gds/gen-file-map.js',
|
|
141
|
+
why: 'a post-merge generator the resolver executes out of the clone, on the same path '
|
|
142
|
+
+ 'as gen-repo-map.js.',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
after: 'scripts/gds/gen-file-map.js',
|
|
146
|
+
glob: 'scripts/gds/gen-session-index.js',
|
|
147
|
+
why: 'a post-merge generator the resolver executes out of the clone, on the same path '
|
|
148
|
+
+ 'as gen-repo-map.js.',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
after: 'scripts/gds/gen-session-index.js',
|
|
152
|
+
glob: 'scripts/gds/copy-inventory.js',
|
|
153
|
+
why: 'a post-merge generator the resolver executes out of the clone. NOT one of the '
|
|
154
|
+
+ "audit's \"gen-* trio\" — it is the first of the four roots that prose omitted, "
|
|
155
|
+
+ 'which is why this registry is pinned to the closure rather than to the audit.',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
after: 'scripts/gds/copy-inventory.js',
|
|
159
|
+
glob: 'scripts/gds/gen-api-docs.js',
|
|
160
|
+
why: 'a post-merge generator the resolver executes out of the clone, and the widest '
|
|
161
|
+
+ 'one: it require()s src/bongos/route-rank-check, api-prefix and routes/_helpers, '
|
|
162
|
+
+ 'which is why a restore scoped to scripts/gds/ was never sufficient.',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
after: 'scripts/gds/gen-api-docs.js',
|
|
166
|
+
glob: 'scripts/gds/gen-api-client.js',
|
|
167
|
+
why: 'a post-merge generator the resolver executes out of the clone, inheriting the '
|
|
168
|
+
+ 'live server environment like its siblings.',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
after: 'scripts/gds/gen-api-client.js',
|
|
172
|
+
glob: '.gitattributes',
|
|
173
|
+
why: 'never require()d, so it is not code — but it NAMES which paths git hands the '
|
|
174
|
+
+ 'otb-regen driver, so editing it changes how much of the tree that driver '
|
|
175
|
+
+ 'rewrites during a merge. executed-closure.js carries it as TRUSTED_NON_CODE.',
|
|
176
|
+
},
|
|
177
|
+
];
|
|
96
178
|
|
|
97
179
|
// Surfaces RENAMED since R101 — still protected, under a new path. Distinct from
|
|
98
180
|
// a removal on purpose: a rename keeps the protection and moves it, a removal
|
|
@@ -172,6 +254,55 @@ test('every glob added since R101 carries a documented reason', () => {
|
|
|
172
254
|
}
|
|
173
255
|
});
|
|
174
256
|
|
|
257
|
+
// ---------- the drift tripwire: every EXECUTION ROOT is a protected surface ----------
|
|
258
|
+
//
|
|
259
|
+
// task 1003366, audit ref MIT1. The audit prescribed "the three gen-* scripts and
|
|
260
|
+
// .gitattributes" — four surfaces. modules/lifecycle/executed-closure.js (task 1003367,
|
|
261
|
+
// ref B1) names SEVEN execution roots plus .gitattributes, because GENERATOR_SCRIPTS grew
|
|
262
|
+
// after the audit was written. Pasting the audit's four names in would therefore have
|
|
263
|
+
// shipped a hand-curated list that was ALREADY stale on the day it landed, leaving
|
|
264
|
+
// git-merge-regen.js — the earliest vector of the three — writable by any rank.
|
|
265
|
+
//
|
|
266
|
+
// So the registry is pinned to the closure's own ENTRYPOINTS, and this test is what makes
|
|
267
|
+
// the pin real: add a generator to GENERATOR_SCRIPTS (executed_closure.mjs already asserts
|
|
268
|
+
// those two lists are identical) and the build reds HERE until the registry grows to match.
|
|
269
|
+
//
|
|
270
|
+
// WHY THE ENTRYPOINTS AND NOT THE WHOLE 81-FILE CLOSURE — two controls, different jobs:
|
|
271
|
+
// - the closure's TRANSITIVE TAIL is enforced by conflict-resolve.js steps 5b/4b, which
|
|
272
|
+
// REFUSE to auto-resolve a branch touching any of the 81. That refusal is substrate:
|
|
273
|
+
// it does not depend on the builder cooperating, and it cannot drift, because it is
|
|
274
|
+
// computed rather than listed.
|
|
275
|
+
// - this registry is COOPERATIVE (pre-push hook, grader pre-pass, main-audit). Its job
|
|
276
|
+
// is the rank floor and the audit trail. The task says so: MIT1 is the interim
|
|
277
|
+
// mitigation, B1 is the close.
|
|
278
|
+
// Listing all 81 here would add no enforcement the refusal does not already provide, while
|
|
279
|
+
// floor-gating ordinary source at Metic — src/bongos/logger.js, src/branding.js and
|
|
280
|
+
// src/build-info.js are all in the closure — and locking newcomers out of routine work.
|
|
281
|
+
// The entrypoints are different in kind: they exist ONLY to be executed by the pipeline,
|
|
282
|
+
// which is exactly what group 'pipeline' already means for ship.js and gate-review.js.
|
|
283
|
+
test('every execution root in the closure is a protected surface (MIT1 drift tripwire)', () => {
|
|
284
|
+
const ec = require(path.join(ROOT, 'modules', 'lifecycle', 'executed-closure.js'));
|
|
285
|
+
// ENTRYPOINTS lists both script-tree spellings across the C-series rename window; only
|
|
286
|
+
// the ones that exist can be executed, so only those must be protected.
|
|
287
|
+
const roots = [
|
|
288
|
+
...ec.ENTRYPOINTS.filter((rel) => fs.existsSync(path.join(ROOT, rel))),
|
|
289
|
+
...ec.TRUSTED_NON_CODE,
|
|
290
|
+
];
|
|
291
|
+
assert.ok(roots.length >= 8,
|
|
292
|
+
'fixture sanity: the closure must declare the execution roots this test checks');
|
|
293
|
+
for (const rel of roots) {
|
|
294
|
+
const surface = ppc.surfaceFor(rel);
|
|
295
|
+
assert.ok(surface,
|
|
296
|
+
`${rel} is an EXECUTION ROOT — the merge resolver runs it out of a cloned branch `
|
|
297
|
+
+ 'with the live server environment — but no protected surface covers it. Add it to '
|
|
298
|
+
+ 'modules/government/protected-surfaces.json (group "pipeline") and declare it in '
|
|
299
|
+
+ 'ADDED_SINCE_R101 above.');
|
|
300
|
+
assert.ok(ppc.RANK_TIER[surface.floor] >= ppc.RANK_TIER.metic,
|
|
301
|
+
`${rel} is an execution root floored at '${surface.floor}' — below Metic it stays `
|
|
302
|
+
+ 'writable by the ranks ADR 0043 keeps out of the pipeline.');
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
175
306
|
// Metic is a FLOOR, not a fixed value (task 1003191). Pinning every surface to
|
|
176
307
|
// exactly 'metic' made the registry's own contract untestable and, worse,
|
|
177
308
|
// illegal: governance owns this data and raising one surface to 'archon' is a
|