@bongos/core 1.19.1073 → 1.19.1075
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 +404 -549
- package/.claude/skills/feedback/SKILL.md +2 -2
- package/bin/bongos.js +1 -3
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -60
- package/clients/bongos-client/index.cjs +4 -60
- package/clients/bongos-client/index.d.ts +5 -90
- package/clients/bongos-client/index.mjs +4 -60
- package/config/branding.neutral.json +1 -5
- package/config/modules.neutral.json +2 -3
- package/config/scheduled-routines.json +0 -2
- package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +1 -0
- package/docs/adr/0285-a-shared-box-holds-about-twelve-projects-per-gb-and-memory-is-the-wall.md +1 -0
- package/docs/adr/0323-hosting-is-three-shapes-and-we-are-not-the-landlord.md +1 -1
- package/docs/adr/0327-a-cloud-host-runs-on-the-owners-account-and-the-key-is-borrowed.md +1 -1
- package/docs/adr/0341-the-page-is-the-unit-of-tweak-mode.md +2 -0
- package/docs/adr/0345-we-host-every-projects-hall-and-its-app-deploys-where-the-owner-chooses.md +94 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +175 -1665
- package/docs/api-reference.md +9 -41
- package/docs/architecture.md +16 -1
- package/docs/branding-contract.md +0 -3
- package/docs/copy-inventory.md +454 -479
- package/docs/copy-registry.json +746 -978
- package/docs/file-map.md +5 -34
- package/docs/module-api-changelog.md +4 -0
- package/docs/modules-contract.md +13 -1
- package/docs/onboarding/diagrams/04-architecture.mmd +11 -22
- package/docs/onboarding/diagrams/README.md +3 -3
- package/docs/onboarding/diagrams/assertions.json +2 -22
- package/docs/onboarding/primer.md +9 -28
- package/docs/page-inventory.json +4 -1
- package/docs/page-readings.json +1032 -1077
- package/docs/recipes/render-pilot.md +29 -10
- package/migrations/core_257_module_store_registry.sql +87 -0
- package/migrations/core_258_drop_dev_box_tables.sql +55 -0
- package/modules/agents/module.json +1 -0
- package/modules/autonomy/module.json +1 -0
- package/modules/builder-settings/module.json +1 -0
- package/modules/builder-settings/render-prefs.js +4 -5
- package/modules/copy-desk/docx.js +78 -5
- package/modules/copy-desk/module.json +1 -0
- package/modules/copy-desk/routes/copy-desk.js +10 -10
- package/modules/copy-desk/tests/copy_docx.mjs +107 -1
- package/modules/copy-desk/tests/fixtures/word-docx.mjs +30 -0
- package/modules/discord/module.json +1 -0
- package/modules/discord/ship-broadcast.js +3 -3
- package/modules/economy/credits.js +2 -2
- package/modules/economy/module.json +1 -0
- package/modules/economy/routes/credits.js +1 -2
- package/modules/government/catalog.js +13 -17
- package/modules/government/migrations/government_019_retire_box_permissions.sql +33 -0
- package/modules/government/module.json +1 -0
- package/modules/government/protected-surfaces.json +3 -11
- package/modules/government/resolver.js +3 -46
- package/modules/government/routes/government.js +0 -2
- package/modules/government/session-scopes.js +43 -83
- package/modules/government/session-scopes.json +8 -18
- package/modules/grading/module.json +1 -0
- package/modules/hall-ui/module.json +1 -0
- package/modules/hall-ui/public/board-lib.js +2 -2
- package/modules/hall-ui/public/builders.js +29 -40
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/collab.js +1 -1
- package/modules/hall-ui/public/diagrams.html +3 -3
- package/modules/hall-ui/public/dom-utils.js +1 -1
- package/modules/hall-ui/public/gate.js +2 -2
- package/modules/hall-ui/public/gate.states.json +1 -1
- package/modules/hall-ui/public/hall-render.js +43 -79
- package/modules/hall-ui/public/index.html +5 -1
- package/modules/hall-ui/public/modules.js +1 -0
- package/modules/hall-ui/public/oversight.css +5 -5
- package/modules/hall-ui/public/palette.js +0 -11
- package/modules/hall-ui/public/primer.js +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings-sessions.js +1 -1
- package/modules/hall-ui/public/settings.css +0 -1
- package/modules/hall-ui/public/settings.html +4 -33
- package/modules/hall-ui/public/settings.js +3 -33
- package/modules/hall-ui/public/settings.states.json +2 -2
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/style.css +10 -13
- package/modules/hall-ui/public/task.html +4 -1
- package/modules/hall-ui/public/task.js +36 -1
- package/modules/hall-ui/public/tweak-editor-lib.js +18 -1
- package/modules/hall-ui/public/tweak-editor.css +16 -0
- package/modules/hall-ui/public/tweak-editor.html +26 -3
- package/modules/hall-ui/public/tweak-editor.js +32 -1
- package/modules/hall-ui/public/work.js +1 -1
- package/modules/hall-ui/records/tweak-editor.md +1 -0
- package/modules/ideas/module.json +1 -0
- package/modules/ideas/projection.js +1 -1
- package/modules/lifecycle/db-claim-reads.js +1 -58
- package/modules/lifecycle/db-ship.js +4 -9
- package/modules/lifecycle/db.js +0 -4
- package/modules/lifecycle/github-push.js +12 -14
- package/modules/lifecycle/kickoff-checklist.js +0 -4
- package/modules/lifecycle/lifecycle.js +0 -8
- package/modules/lifecycle/module.json +1 -0
- package/modules/lifecycle/publish-reconciler.js +10 -10
- package/modules/lifecycle/routes/tasks.js +13 -15
- package/modules/lifecycle/ship-card.js +1 -1
- package/modules/lifecycle/task-visuals.js +2 -2
- package/modules/memory/module.json +1 -0
- package/modules/memory/routes/memory.js +2 -2
- package/modules/npm-release/module.json +1 -0
- package/modules/onboarding/module.json +1 -0
- package/modules/onboarding/onboarding-state.js +17 -36
- package/modules/onboarding/routes/access-requests.js +3 -3
- package/modules/platform-identity/module.json +1 -0
- package/modules/platform-identity/platform-identity.js +13 -5
- package/modules/platform-identity/routes/sso.js +5 -4
- package/modules/platform-identity/tests/platform-identity.mjs +17 -3
- package/modules/provisioning/capacity.js +1 -1
- package/modules/provisioning/module.json +1 -0
- package/modules/provisioning/provisioning.js +6 -5
- package/modules/provisioning/routes/provisioning.js +4 -4
- package/modules/provisioning/starter-bundles.js +5 -25
- package/modules/public-landing/module.json +1 -0
- package/modules/public-landing/public/assets/cosmos.css +1 -1
- package/modules/public-landing/public/contact.html +1 -1
- package/modules/public-landing/public/privacy.html +1 -1
- package/modules/public-landing/public/projects.html +101 -32
- package/modules/public-landing/public/projects.probes.json +2 -2
- package/modules/public-landing/public/projects.states.json +4 -3
- package/modules/public-landing/public/terms.html +1 -1
- package/modules/security/module.json +1 -0
- package/modules/sessions/db.js +1 -1
- package/modules/sessions/module.json +1 -0
- package/modules/specialities/module.json +1 -0
- package/modules/status-ui/module.json +1 -0
- package/modules/ui-design/module.json +1 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +84 -0
- package/scripts/gds/artifact-format.js +203 -0
- package/scripts/gds/artifact-staleness.js +2 -2
- package/scripts/gds/audit-authorship.sh +1 -13
- package/scripts/gds/backfill-task-rewards.js +5 -5
- package/scripts/gds/claim.js +0 -15
- package/scripts/gds/claude-materialize.js +2 -2
- package/scripts/gds/cli-lib.js +15 -15
- package/scripts/gds/codemod-rename-src-gds.js +1 -1
- package/scripts/gds/context-pack.js +5 -7
- package/scripts/gds/diagram-facts.js +12 -23
- package/scripts/gds/do-api.js +13 -80
- package/scripts/gds/doc-cli-guard.js +2 -0
- package/scripts/gds/doctor.js +4 -4
- package/scripts/gds/feedback-latest.js +139 -9
- package/scripts/gds/fitness-checks-identity.js +2 -7
- package/scripts/gds/fitness-checks-packaging.js +4 -4
- package/scripts/gds/fitness-checks-write-validation.js +4 -0
- package/scripts/gds/fitness-ratchets.js +5 -5
- package/scripts/gds/fitness.js +10 -10
- package/scripts/gds/gen-api-client.js +4 -4
- package/scripts/gds/gen-api-docs.js +1 -1
- package/scripts/gds/gen-diagrams.js +49 -71
- package/scripts/gds/gen-repo-map.js +13 -14
- package/scripts/gds/gen-session-index.js +8 -8
- package/scripts/gds/http-api-client.js +12 -19
- package/scripts/gds/init.js +1 -1
- package/scripts/gds/leak-scan-allowlist.js +1 -1
- package/scripts/gds/lint-infra-exec.js +1 -1
- package/scripts/gds/local-preview-lib.js +8 -39
- package/scripts/gds/local-preview.js +2 -15
- package/scripts/gds/migration-namespace.js +3 -3
- package/scripts/gds/module-artifact.js +212 -0
- package/scripts/gds/module.js +95 -6
- package/scripts/gds/package-core.js +5 -116
- package/scripts/gds/plain-cards.js +1 -1
- package/scripts/gds/provision-config.js +2 -2
- package/scripts/gds/provision-net.js +2 -3
- package/scripts/gds/provision.js +9 -9
- package/scripts/gds/publish-manifest.js +1 -2
- package/scripts/gds/push-path-brief.js +10 -10
- package/scripts/gds/regen-instance-docs.js +1 -1
- package/scripts/gds/rename-history-check.js +1 -1
- package/scripts/gds/run-unit-tests.js +2 -16
- package/scripts/gds/sandbox-stage.js +39 -341
- package/scripts/gds/session-digest-build.js +2 -2
- package/scripts/gds/ship-deploy-target.js +13 -13
- package/scripts/gds/ship-flow.js +7 -7
- package/scripts/gds/ship-land.js +9 -10
- package/scripts/gds/ship-merge.js +4 -4
- package/scripts/gds/ship-preflight-steps.js +4 -4
- package/scripts/gds/ship-regen.js +15 -49
- package/scripts/gds/ship.js +13 -33
- package/scripts/gds/skill-preflight.js +9 -8
- package/scripts/gds/start.js +0 -15
- package/scripts/hall-preview/README.md +5 -5
- package/scripts/hall-preview/server.js +6 -6
- package/scripts/render-diagrams.sh +1 -1
- package/src/bongos/api-errors.js +1 -1
- package/src/bongos/api-prefix.js +4 -4
- package/src/bongos/auth-github.js +2 -3
- package/src/bongos/auth.js +51 -126
- package/src/bongos/db-kernel.js +2 -3
- package/src/bongos/db.js +5 -28
- package/src/bongos/module-scope-map.js +14 -29
- package/src/bongos/module-store.js +141 -0
- package/src/bongos/platform-visibility-gate.js +1 -1
- package/src/bongos/route-rank-check.js +3 -16
- package/src/bongos/routes/auth.js +0 -116
- package/src/bongos/routes/builders.js +5 -15
- package/src/bongos/routes/instance.js +8 -14
- package/src/bongos/routes/me.js +7 -23
- package/src/bongos/routes/modules.js +83 -0
- package/src/bongos/routes/security.js +3 -3
- package/src/bongos/routes.js +7 -2
- package/src/bongos/serve-internal.js +5 -6
- package/src/bongos-downloads.js +1 -6
- package/src/branding.js +2 -2
- package/src/build-info.js +4 -6
- package/src/instance-config.js +2 -2
- package/src/module-api.js +13 -6
- package/src/module-loader/catalog.js +3 -0
- package/src/module-loader/loader.js +4 -4
- package/src/module-loader/manifest-schema.js +16 -8
- package/src/module-seams.js +2 -3
- package/src/modules.js +42 -14
- package/tests/agents_spend_guard.mjs +1 -1
- package/tests/api_alias_caller_ratchet.mjs +1 -1
- package/tests/api_alias_exceptions.mjs +1 -1
- package/tests/api_client.mjs +1 -16
- package/tests/api_path_404.mjs +1 -1
- package/tests/auth_page_gate.mjs +10 -10
- package/tests/backfill_task_rewards.mjs +1 -1
- package/tests/canonical_profile_url.mjs +1 -3
- package/tests/claim_action.mjs +4 -1
- package/tests/claim_from_task_and_home.mjs +127 -0
- package/tests/{box_ship_permissions.mjs → cli_allowlist_permissions.mjs} +5 -5
- package/tests/cli_sessions.mjs +1 -1
- package/tests/consumer_layout_boot.mjs +2 -0
- package/tests/context_pack.mjs +13 -13
- package/tests/copy_desk_page_docx.mjs +33 -2
- package/tests/copy_inventory.mjs +7 -7
- package/tests/core_upgrade_runner.mjs +6 -6
- package/tests/credit_grant.mjs +2 -2
- package/tests/criterion_suggest.mjs +1 -1
- package/tests/deploy_divergence_line.mjs +11 -11
- package/tests/design_tokens_sync.mjs +3 -2
- package/tests/diagram_facts_offset.mjs +1 -1
- package/tests/do_api.mjs +106 -0
- package/tests/feedback_latest.mjs +122 -0
- package/tests/fitness.mjs +44 -42
- package/tests/fitness_ratchets.mjs +2 -2
- package/tests/gate_approvals.mjs +0 -1
- package/tests/github_push_land_proof.mjs +1 -1
- package/tests/go_live.mjs +3 -3
- package/tests/goal_advisory.mjs +3 -3
- package/tests/goal_suggest.mjs +3 -3
- package/tests/government_abuse_matrix.mjs +21 -19
- package/tests/government_ownership_scope.mjs +33 -35
- package/tests/government_parity.mjs +2 -2
- package/tests/government_protected_surfaces.mjs +56 -37
- package/tests/government_require_permission.mjs +3 -3
- package/tests/government_seed.mjs +37 -4
- package/tests/government_session_scope.mjs +92 -366
- package/tests/hall_audit.mjs +1 -1
- package/tests/hall_error_envelope.mjs +4 -0
- package/tests/hall_landing_boot.mjs +4 -1
- package/tests/hall_palette.mjs +1 -16
- package/tests/hall_record_world.mjs +6 -0
- package/tests/hall_tweak_editor.mjs +52 -1
- package/tests/helpers.mjs +1 -1
- package/tests/host_topology_skips.mjs +3 -4
- package/tests/html_comment_nesting.mjs +137 -0
- package/tests/infra_exec_paths.mjs +9 -10
- package/tests/init.mjs +4 -5
- package/tests/instance_manifest.mjs +18 -25
- package/tests/kickoff_checklist.mjs +1 -1
- package/tests/lib_sh_resolution.mjs +0 -221
- package/tests/local_preview.mjs +0 -12
- package/tests/migration_namespace.mjs +6 -6
- package/tests/module-scope-map.mjs +9 -9
- package/tests/module_api.mjs +2 -2
- package/tests/module_catalog.mjs +1 -1
- package/tests/module_cli.mjs +20 -20
- package/tests/module_contributions.mjs +6 -6
- package/tests/module_loader.mjs +6 -6
- package/tests/module_manifest.mjs +26 -17
- package/tests/module_route_rank.mjs +2 -2
- package/tests/module_store_publish.mjs +307 -0
- package/tests/module_store_publish_route.mjs +121 -0
- package/tests/module_store_registry_migration.mjs +70 -0
- package/tests/modules.mjs +56 -26
- package/tests/modules_route_wiring.mjs +1 -1
- package/tests/onboarding_route_signals.mjs +21 -31
- package/tests/onboarding_state.mjs +35 -49
- package/tests/paste_token_session_store.mjs +1 -1
- package/tests/permission_path.mjs +0 -3
- package/tests/platform_boot.mjs +1 -2
- package/tests/platform_visibility_gate.mjs +1 -1
- package/tests/profile_route.mjs +1 -6
- package/tests/project_modules_ui.mjs +17 -17
- package/tests/projects_hub.mjs +5 -5
- package/tests/projects_hub_app_step.mjs +138 -0
- package/tests/projects_hub_module_picker.mjs +77 -76
- package/tests/projects_hub_pre_uat.mjs +4 -5
- package/tests/provision.mjs +7 -7
- package/tests/provisioning_capacity.mjs +1 -1
- package/tests/provisioning_recommendations.mjs +2 -1
- package/tests/provisioning_starter_bundles.mjs +0 -22
- package/tests/publish_branch_route.mjs +11 -19
- package/tests/publish_manifest.mjs +2 -3
- package/tests/publish_reconciler.mjs +8 -8
- package/tests/push_path_brief.mjs +10 -9
- package/tests/rank_tier_single_source.mjs +1 -13
- package/tests/regrade_eligibility.mjs +1 -1
- package/tests/rename_history_restraint.mjs +1 -1
- package/tests/repo_map.mjs +12 -13
- package/tests/runner_drift.mjs +3 -21
- package/tests/sandbox_stage.mjs +57 -390
- package/tests/seam_wiring_guard.mjs +11 -11
- package/tests/search_isolation.mjs +3 -3
- package/tests/session_records.mjs +1 -1
- package/tests/session_rename_fallback.mjs +1 -22
- package/tests/session_start_freshness.mjs +3 -3
- package/tests/session_token_hash_db.mjs +1 -1
- package/tests/ship_card.mjs +1 -1
- package/tests/ship_ci_deploy.mjs +17 -17
- package/tests/ship_error_shape.mjs +1 -1
- package/tests/ship_premerge.mjs +1 -1
- package/tests/ship_resume.mjs +1 -1
- package/tests/skill_preflight.mjs +2 -2
- package/tests/skip_is_not_pass.mjs +1 -1
- package/tests/task_visual_slots.mjs +31 -0
- package/tests/terms_acceptance.mjs +2 -2
- package/tests/upgrade.mjs +4 -4
- package/tests/watch_sealed_floor.mjs +0 -1
- package/tests/wizard_draft_resume.mjs +2 -2
- package/tests/wizard_intent_resume.mjs +21 -10
- package/tests/wizard_preselect_why.mjs +18 -18
- package/docs/onboarding/browser-terminal-guide.md +0 -73
- package/docs/recipes/managed-settings-remote-control.md +0 -416
- package/modules/dev-box/CLAUDE.md +0 -15
- package/modules/dev-box/box-access.js +0 -623
- package/modules/dev-box/box-credential.js +0 -94
- package/modules/dev-box/box-onboard.js +0 -486
- package/modules/dev-box/boxes.js +0 -1038
- package/modules/dev-box/db.js +0 -39
- package/modules/dev-box/module.json +0 -19
- package/modules/dev-box/routes/box.js +0 -1223
- package/scripts/gds/box-auth-check.js +0 -160
- package/scripts/gds/box-infra.js +0 -321
- package/scripts/gds/box-sync.js +0 -216
- package/scripts/gds/box.js +0 -1332
- package/scripts/gds/cf-tunnel.js +0 -558
- package/scripts/gds/smoke-box.sh +0 -150
- package/scripts/gds/tree-preflight.js +0 -241
- package/src/bongos/app-pair.js +0 -172
- package/tests/app_pair.mjs +0 -168
- package/tests/box_access.mjs +0 -578
- package/tests/box_auth_check.mjs +0 -114
- package/tests/box_code_staleness.mjs +0 -129
- package/tests/box_connect_e2e.mjs +0 -196
- package/tests/box_cost.mjs +0 -70
- package/tests/box_credential.mjs +0 -125
- package/tests/box_dns_repoint.mjs +0 -153
- package/tests/box_env.mjs +0 -64
- package/tests/box_host_keys.mjs +0 -126
- package/tests/box_infra_resolve.mjs +0 -246
- package/tests/box_onboard.mjs +0 -317
- package/tests/box_scope_session.mjs +0 -119
- package/tests/box_sweep_docs.mjs +0 -119
- package/tests/box_sync.mjs +0 -55
- package/tests/box_sync_scope_report.mjs +0 -126
- package/tests/box_task_scope.mjs +0 -169
- package/tests/box_task_scope_pause.mjs +0 -66
- package/tests/box_terminal_ssrf.mjs +0 -96
- package/tests/boxes.mjs +0 -1585
- package/tests/cf_ruleset_preflight.mjs +0 -142
- package/tests/cf_tunnel.mjs +0 -496
- package/tests/docs_scrubber_damage.mjs +0 -111
- package/tests/module_scope_active_claims.mjs +0 -94
- package/tests/ship_api_client_pathspec.mjs +0 -100
- package/tests/tree_preflight.mjs +0 -243
|
@@ -185,9 +185,11 @@ const ADDED_SINCE_R101 = [
|
|
|
185
185
|
},
|
|
186
186
|
// task 1002891 (from idea 1000692, raised by the grader's hacker worker). Group
|
|
187
187
|
// 'box-access' protected who DECIDES box access but nothing that HOLDS the
|
|
188
|
-
// infrastructure credentials those decisions spend. The
|
|
188
|
+
// infrastructure credentials those decisions spend. The readers below are the
|
|
189
189
|
// COMPUTED set — the credential-reader tripwire further down recomputes it from the
|
|
190
190
|
// tracked tree on every run — plus do-api.js, which the credential is handed to.
|
|
191
|
+
// (Three more readers — the box control plane's box.js, box-infra.js and
|
|
192
|
+
// cf-tunnel.js — were deleted with it in task 1003893, entries and all.)
|
|
191
193
|
{
|
|
192
194
|
after: 'modules/dev-box/box-credential.js',
|
|
193
195
|
glob: 'scripts/gds/provision-config.js',
|
|
@@ -205,29 +207,6 @@ const ADDED_SINCE_R101 = [
|
|
|
205
207
|
},
|
|
206
208
|
{
|
|
207
209
|
after: 'scripts/gds/provision-net.js',
|
|
208
|
-
glob: 'scripts/gds/box-infra.js',
|
|
209
|
-
why: 'reads process.env.CLOUDFLARE_API_TOKEN and process.env.CLOUDFLARE_ACCOUNT_ID '
|
|
210
|
-
+ 'into the Cloudflare config the box plane provisions tunnels and DNS against.',
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
after: 'scripts/gds/box-infra.js',
|
|
214
|
-
glob: 'scripts/gds/cf-tunnel.js',
|
|
215
|
-
why: 'defaults its token parameter to process.env.CLOUDFLARE_API_TOKEN, so it reads '
|
|
216
|
-
+ 'the credential whenever a caller omits one. The recorded decision did not name '
|
|
217
|
-
+ 'this file; the recomputation found it, which is the case for computing the set '
|
|
218
|
-
+ 'rather than transcribing a list.',
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
after: 'scripts/gds/cf-tunnel.js',
|
|
222
|
-
glob: 'scripts/gds/box.js',
|
|
223
|
-
why: 'reads process.env.DO_API_TOKEN — the DigitalOcean control plane for the box '
|
|
224
|
-
+ 'fleet, and also not named by the recorded decision. Adding it widens no module '
|
|
225
|
-
+ 'wall: the dev-box key already lists this path and already derives protected '
|
|
226
|
-
+ 'from the modules/dev-box/ entries, so the derived protected-module set is '
|
|
227
|
-
+ 'unchanged (asserted below).',
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
after: 'scripts/gds/box.js',
|
|
231
210
|
glob: 'scripts/gds/do-api.js',
|
|
232
211
|
why: 'the DigitalOcean API client the token is handed TO. It reads no process.env '
|
|
233
212
|
+ 'value — the token arrives as a parameter and the constructor throws when a live '
|
|
@@ -281,9 +260,6 @@ const ADDED_SINCE_R101 = [
|
|
|
281
260
|
...carve('src/bongos/db.js', ['db-kernel'],
|
|
282
261
|
'the kernel slice carved out of db.js: builder identity and the rank reads the '
|
|
283
262
|
+ 'SEC #863 entry exists for.'),
|
|
284
|
-
...carve('scripts/gds/box.js', ['box-auth-check', 'box-sync'],
|
|
285
|
-
'the box.js family: the dev-box session-start auth gate and the box sync; box-infra.js '
|
|
286
|
-
+ 'was already listed by name.'),
|
|
287
263
|
...carve('modules/grading/grader.js', ['grader-config', 'grader-model', 'grader-no-artifact',
|
|
288
264
|
'grader-prompt', 'grader-score', 'grader-subagent'],
|
|
289
265
|
'the grader.js carve: the deterministic permission-path pre-pass and the server-side '
|
|
@@ -338,8 +314,24 @@ const RENAMED_SINCE_R101 = [
|
|
|
338
314
|
},
|
|
339
315
|
];
|
|
340
316
|
|
|
317
|
+
// Surfaces RETIRED since R101 — the protected FILE itself was deleted from the
|
|
318
|
+
// repo, so there is nothing left to protect. The third shape, and the narrowest: a
|
|
319
|
+
// retirement is accepted only for a path the tracked tree no longer contains (the
|
|
320
|
+
// test below checks the tree, not this prose), so it can never be used to drop
|
|
321
|
+
// protection from code that still runs. Applied LAST, after renames and additions,
|
|
322
|
+
// so an addition anchored on a retired entry still resolves.
|
|
323
|
+
const RETIRED_SINCE_R101 = [
|
|
324
|
+
...['boxes.js', 'box-access.js', 'box-credential.js'].map((f) => ({
|
|
325
|
+
glob: `modules/dev-box/${f}`,
|
|
326
|
+
why: 'task 1003892 (goal 1000120) deleted the dev-box module outright — the rank floor '
|
|
327
|
+
+ 'and source-credential code these entries guarded no longer exists anywhere in '
|
|
328
|
+
+ 'the tree, and the fleet it decided access to was already torn down.',
|
|
329
|
+
})),
|
|
330
|
+
];
|
|
331
|
+
|
|
341
332
|
// The list the registry must produce TODAY: the pre-R101 set with each
|
|
342
|
-
// documented addition spliced in at its declared position
|
|
333
|
+
// documented addition spliced in at its declared position, then each documented
|
|
334
|
+
// retirement removed.
|
|
343
335
|
const EXPECTED_GLOBS = (() => {
|
|
344
336
|
let out = [...EXPECTED_GLOBS_BEFORE_R101];
|
|
345
337
|
for (const r of RENAMED_SINCE_R101) {
|
|
@@ -352,6 +344,11 @@ const EXPECTED_GLOBS = (() => {
|
|
|
352
344
|
assert.notEqual(at, -1, `ADDED_SINCE_R101 anchors on '${a.after}', which is not in the list`);
|
|
353
345
|
out.splice(at + 1, 0, a.glob);
|
|
354
346
|
}
|
|
347
|
+
for (const r of RETIRED_SINCE_R101) {
|
|
348
|
+
const at = out.indexOf(r.glob);
|
|
349
|
+
assert.notEqual(at, -1, `RETIRED_SINCE_R101 retires '${r.glob}', which is not in the list`);
|
|
350
|
+
out.splice(at, 1);
|
|
351
|
+
}
|
|
355
352
|
return out;
|
|
356
353
|
})();
|
|
357
354
|
|
|
@@ -363,8 +360,10 @@ test('nothing protected before R101 has been unprotected since', () => {
|
|
|
363
360
|
// replacement must actually be present — otherwise "it was renamed" becomes a
|
|
364
361
|
// way to unprotect a trust surface with a comment.
|
|
365
362
|
const renamedFrom = new Map(RENAMED_SINCE_R101.map((r) => [r.from, r.to]));
|
|
363
|
+
const retired = new Set(RETIRED_SINCE_R101.map((r) => r.glob));
|
|
366
364
|
for (const glob of EXPECTED_GLOBS_BEFORE_R101) {
|
|
367
365
|
if (registry.PROTECTED_GLOBS.includes(glob)) continue;
|
|
366
|
+
if (retired.has(glob)) continue; // proven gone from the tree by the test below
|
|
368
367
|
const to = renamedFrom.get(glob);
|
|
369
368
|
assert.ok(to,
|
|
370
369
|
`'${glob}' was protected before R101 and is no longer in the registry — `
|
|
@@ -376,6 +375,20 @@ test('nothing protected before R101 has been unprotected since', () => {
|
|
|
376
375
|
}
|
|
377
376
|
});
|
|
378
377
|
|
|
378
|
+
test('a surface is retired only once its path is gone from the tracked tree', () => {
|
|
379
|
+
// The whole guarantee of RETIRED_SINCE_R101: "the file was deleted" is checked
|
|
380
|
+
// against git, so a retirement cannot unprotect a live path with a comment.
|
|
381
|
+
const tracked = execFileSync('git', ['ls-files'], { cwd: ROOT, encoding: 'utf8' })
|
|
382
|
+
.split('\n').map((f) => f.trim()).filter(Boolean);
|
|
383
|
+
for (const r of RETIRED_SINCE_R101) {
|
|
384
|
+
assert.ok(r.why && r.why.length > 40, `${r.glob} must record WHY it was retired`);
|
|
385
|
+
assert.ok(!registry.PROTECTED_GLOBS.includes(r.glob), `${r.glob} is declared retired but is still registered`);
|
|
386
|
+
const prefix = r.glob.endsWith('/') ? r.glob : null;
|
|
387
|
+
const live = tracked.filter((f) => (prefix ? f.startsWith(prefix) : f === r.glob));
|
|
388
|
+
assert.deepEqual(live, [], `${r.glob} is declared retired but the tree still tracks it — a live path cannot be unprotected this way`);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
379
392
|
test('every rename since R101 carries a documented reason', () => {
|
|
380
393
|
for (const r of RENAMED_SINCE_R101) {
|
|
381
394
|
assert.ok(r.why && r.why.length > 40,
|
|
@@ -452,7 +465,8 @@ test('every execution root in the closure is a protected surface (MIT1 drift tri
|
|
|
452
465
|
//
|
|
453
466
|
// task 1004024. Splitting a protected file into `<name>-<phase>.js` siblings is this repo's
|
|
454
467
|
// carve convention, and every carve so far left only the facade registered: ship.js (21
|
|
455
|
-
// files), grader.js (6), auth.js (5), db.js
|
|
468
|
+
// files), grader.js (6), auth.js (5), db.js (and one more family since deleted outright,
|
|
469
|
+
// task 1003893). A require()-graph rule was measured and
|
|
456
470
|
// rejected — from the protected scripts it reaches 52 unprotected files (upgrade.js, login.js,
|
|
457
471
|
// package-core.js…), floor-gating ordinary work. The name rule is the shape a carve leaves.
|
|
458
472
|
function stemSiblings(entry, tracked) {
|
|
@@ -494,7 +508,7 @@ test('every file split out of a protected file is itself protected (1004024 carv
|
|
|
494
508
|
`${rel} is floored at '${surface.floor}', below the ${entry} it was carved from.`);
|
|
495
509
|
}
|
|
496
510
|
}
|
|
497
|
-
assert.ok(checked >= 35, `fixture sanity: expected the
|
|
511
|
+
assert.ok(checked >= 35, `fixture sanity: expected the four known carves (35 files), saw ${checked}`);
|
|
498
512
|
});
|
|
499
513
|
|
|
500
514
|
// ---------- the credential tripwire: every credential READER is a protected surface ----------
|
|
@@ -612,10 +626,13 @@ test('credentialReadsIn does not fire on a near-miss', () => {
|
|
|
612
626
|
|
|
613
627
|
test('every credential reader in the tree is a protected surface (1002891 tripwire)', () => {
|
|
614
628
|
const readers = credentialReaders();
|
|
615
|
-
|
|
629
|
+
// The floor was five from task 1002891 until task 1003893 deleted three of the
|
|
630
|
+
// readers (the box control plane's box.js, box-infra.js and cf-tunnel.js), leaving
|
|
631
|
+
// provision-config.js and provision-net.js.
|
|
632
|
+
assert.ok(readers.length >= 2,
|
|
616
633
|
'fixture sanity: the scan found '
|
|
617
|
-
+ `${readers.length} credential reader(s), and the tree has had at least
|
|
618
|
-
+ 'task
|
|
634
|
+
+ `${readers.length} credential reader(s), and the tree has had at least two since `
|
|
635
|
+
+ 'task 1003893. A scan that finds nothing passes every assertion below without '
|
|
619
636
|
+ 'checking anything — treat this as the scanner being broken, not as good news.');
|
|
620
637
|
for (const rel of readers) {
|
|
621
638
|
const surface = ppc.surfaceFor(rel);
|
|
@@ -623,7 +640,7 @@ test('every credential reader in the tree is a protected surface (1002891 tripwi
|
|
|
623
640
|
`${rel} READS an infrastructure credential off process.env `
|
|
624
641
|
+ `(${credentialReadsIn(fs.readFileSync(path.join(ROOT, rel), 'utf8')).join(', ')}) `
|
|
625
642
|
+ 'but no protected surface covers it. Add it to '
|
|
626
|
-
+ 'modules/government/protected-surfaces.json (group "
|
|
643
|
+
+ 'modules/government/protected-surfaces.json (group "control-plane") and declare it '
|
|
627
644
|
+ 'in ADDED_SINCE_R101 above.');
|
|
628
645
|
assert.ok(ppc.RANK_TIER[surface.floor] >= ppc.RANK_TIER.metic,
|
|
629
646
|
`${rel} holds an infrastructure credential but is floored at '${surface.floor}' — `
|
|
@@ -698,9 +715,11 @@ test('registering the credential readers widened no module wall', () => {
|
|
|
698
715
|
'the provisioning module derived protected:true — a credential-reader entry reached '
|
|
699
716
|
+ 'modules/provisioning/ or scripts/gds/provision.js, which walls goals 1000032, '
|
|
700
717
|
+ '1000046 and 1000059 behind an Archon join. Keep the entries file-level.');
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
718
|
+
// Since task 1003892 the readers are owned by their own control-plane scope, which
|
|
719
|
+
// is protected BY them — that is where the wall belongs, not on provisioning.
|
|
720
|
+
assert.ok(protectedNow.includes('control-plane'),
|
|
721
|
+
'the control-plane scope owns the credential readers and must derive protected:true; '
|
|
722
|
+
+ 'if it does not, a reader lost its registry entry or its owner.');
|
|
704
723
|
});
|
|
705
724
|
|
|
706
725
|
// ---------- the routine-switch tripwire: every SWITCHBOARD is a protected surface ----------
|
|
@@ -255,7 +255,7 @@ test('over the four seeded ranks, requirePermission admits exactly who requireRa
|
|
|
255
255
|
// means a floor moving without an owner decision reds the build, which is the whole
|
|
256
256
|
// point of keeping parity as an assertion instead of prose.
|
|
257
257
|
const DELEGATED_TO_METIC_BY_ADR_0155 = [
|
|
258
|
-
'autonomy.precheck', '
|
|
258
|
+
'autonomy.precheck', 'discord.channels.manage', 'idea.ratify',
|
|
259
259
|
'claim.release.any', 'criterion.unsatisfy', 'goal.reorder', 'task.newcomer_restock',
|
|
260
260
|
'task.peer_votes.tally', 'override_request.decide', 'memory.read.any',
|
|
261
261
|
'project.curate', 'provisioning.fleet.manage', 'security.report.adjudicate',
|
|
@@ -439,7 +439,7 @@ test('every modules/*/routes gate is migrated, bar the one documented holdout',
|
|
|
439
439
|
// the OWNERSHIP axis cannot gate a route (task 1003197 (C))
|
|
440
440
|
// ---------------------------------------------------------------------------
|
|
441
441
|
//
|
|
442
|
-
// `held.has('
|
|
442
|
+
// `held.has('task.abandon.own')` is true for anyone whose rank carries the atom, so a
|
|
443
443
|
// gate mounted on an ownership-scoped key would admit UNCONDITIONALLY — `.own`
|
|
444
444
|
// collapsed into `.any`, the exact degradation the axis exists to prevent, because
|
|
445
445
|
// the gate is never handed the row whose owner is the other half of the question.
|
|
@@ -463,7 +463,7 @@ const OWNED_KEY = catalog.permissionKeys().find((k) => catalog.isOwnershipScoped
|
|
|
463
463
|
|
|
464
464
|
test('the catalog still declares at least one ownership-scoped key', () => {
|
|
465
465
|
// If the axis were ever emptied, the assertions below would pass vacuously.
|
|
466
|
-
assert.ok(OWNED_KEY, 'expected an ownership-scoped atom in the catalog (e.g.
|
|
466
|
+
assert.ok(OWNED_KEY, 'expected an ownership-scoped atom in the catalog (e.g. task.abandon.own)');
|
|
467
467
|
});
|
|
468
468
|
|
|
469
469
|
test('an ownership-scoped key 403s even when the builder HOLDS it', async () => {
|
|
@@ -91,6 +91,13 @@ function grantBlocksForRole(role) {
|
|
|
91
91
|
// not a guard.
|
|
92
92
|
const REVOKE_RE =
|
|
93
93
|
/DELETE\s+FROM\s+govern(?:ance_role|ment_rank)_permissions\s+WHERE\s+(?:rank_key|role_key)\s*=\s*'([^']+)'\s+AND\s+permission_key\s*=\s*'([^']+)'/gi;
|
|
94
|
+
// The EVERY-RANK form (task 1003894): a key RETIRED from the catalog is revoked
|
|
95
|
+
// from every rank at once, custom ranks included, so the statement names no rank:
|
|
96
|
+
// DELETE FROM government_rank_permissions WHERE permission_key IN ('a', 'b');
|
|
97
|
+
// government_019 is the first. Read as "gone from every role" by the fold below.
|
|
98
|
+
const REVOKE_ALL_RE =
|
|
99
|
+
/DELETE\s+FROM\s+govern(?:ance_role|ment_rank)_permissions\s+WHERE\s+permission_key\s+IN\s*\(([^)]*)\)\s*;/gi;
|
|
100
|
+
const keysIn = (list) => [...list.matchAll(/'([^']+)'/g)].map((x) => x[1]);
|
|
94
101
|
|
|
95
102
|
|
|
96
103
|
// The EFFECTIVE grant set: walk the migrations in filename order, adding each
|
|
@@ -109,6 +116,9 @@ function effectiveKeysForRole(role) {
|
|
|
109
116
|
for (const m of code.matchAll(new RegExp(REVOKE_RE.source, 'gi'))) {
|
|
110
117
|
if (m[1] === role) held.delete(RENAMED_KEYS.get(m[2]) || m[2]);
|
|
111
118
|
}
|
|
119
|
+
for (const m of code.matchAll(new RegExp(REVOKE_ALL_RE.source, 'gi'))) {
|
|
120
|
+
for (const k of keysIn(m[1])) held.delete(RENAMED_KEYS.get(k) || k);
|
|
121
|
+
}
|
|
112
122
|
}
|
|
113
123
|
return held;
|
|
114
124
|
}
|
|
@@ -152,14 +162,37 @@ test('every revoking migration is in the shape the union model subtracts', () =>
|
|
|
152
162
|
const deletes = [...code.matchAll(/DELETE\s+FROM\s+(govern(?:ance_role|ment_rank)_permissions)\b/gi)];
|
|
153
163
|
if (deletes.length === 0) continue;
|
|
154
164
|
const parsed = [...code.matchAll(new RegExp(REVOKE_RE.source, 'gi'))];
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
const parsedAll = [...code.matchAll(new RegExp(REVOKE_ALL_RE.source, 'gi'))];
|
|
166
|
+
assert.equal(parsed.length + parsedAll.length, deletes.length,
|
|
167
|
+
`${file}: ${deletes.length} DELETE(s) but only ${parsed.length + parsedAll.length} parseable by REVOKE_RE / REVOKE_ALL_RE — `
|
|
157
168
|
+ 'the union model would silently overstate the grant set. Match the '
|
|
158
|
-
+ "`DELETE FROM government_rank_permissions WHERE rank_key = '…' AND permission_key = '…'` shape
|
|
169
|
+
+ "`DELETE FROM government_rank_permissions WHERE rank_key = '…' AND permission_key = '…'` shape, "
|
|
170
|
+
+ "or `… WHERE permission_key IN ('…')` to revoke from every rank.");
|
|
159
171
|
for (const m of parsed) {
|
|
160
172
|
assert.ok(RANK_ORDER.includes(m[1]), `${file}: revokes from unknown rank '${m[1]}'`);
|
|
161
173
|
}
|
|
174
|
+
for (const m of parsedAll) {
|
|
175
|
+
assert.ok(keysIn(m[1]).length > 0, `${file}: an every-rank revoke names no key`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('an every-rank revocation removes a retired key from EVERY rank', () => {
|
|
181
|
+
// government_019 (task 1003894) retires the three dev-box keys with one statement
|
|
182
|
+
// and no rank predicate. governance_002 granted box.manage.own to all four seeded
|
|
183
|
+
// ranks, so all four must come out without it — and the raw union must still
|
|
184
|
+
// hold it, or the historical grant was edited away rather than superseded.
|
|
185
|
+
for (const role of RANK_ORDER) {
|
|
186
|
+
for (const key of ['box.source.full', 'box.fleet.manage', 'box.manage.own']) {
|
|
187
|
+
assert.equal(effectiveKeysForRole(role).has(key), false, `${role} still holds ${key}`);
|
|
188
|
+
}
|
|
162
189
|
}
|
|
190
|
+
const rawUnion = applyRenames(grantBlocksForRole('xenos').flatMap((b) => b.keys));
|
|
191
|
+
assert.ok(rawUnion.includes('box.manage.own'),
|
|
192
|
+
'the historical grant must remain in governance_002 — migrations are run-once and are never rewritten');
|
|
193
|
+
// The shape the fold reads must be the shape the migration was written in.
|
|
194
|
+
const sql = fs.readFileSync(path.join(MIG_DIR, 'government_019_retire_box_permissions.sql'), 'utf8');
|
|
195
|
+
assert.equal([...stripComments(sql).matchAll(new RegExp(REVOKE_ALL_RE.source, 'gi'))].length, 1);
|
|
163
196
|
});
|
|
164
197
|
|
|
165
198
|
test('a revocation actually removes the key from the effective set', () => {
|
|
@@ -217,7 +250,7 @@ test('later grant migrations are idempotent + transactional', () => {
|
|
|
217
250
|
const code = stripComments(sql);
|
|
218
251
|
const inserts = code.match(/INSERT INTO/g) || [];
|
|
219
252
|
const onConflict = code.match(/ON CONFLICT/g) || [];
|
|
220
|
-
const revokes = [...code.matchAll(new RegExp(REVOKE_RE.source, 'gi'))];
|
|
253
|
+
const revokes = [...code.matchAll(new RegExp(REVOKE_RE.source, 'gi')), ...code.matchAll(new RegExp(REVOKE_ALL_RE.source, 'gi'))];
|
|
221
254
|
// A migration must DO something to the grant set — but since BV1.R21 (task
|
|
222
255
|
// 1003608) "something" includes taking a permission away, not only adding
|
|
223
256
|
// one. A REVOKE-only migration inserts nothing by design and needs no ON
|