@bongos/core 1.17.0
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 +5727 -0
- package/.claude/skills/blocker-review/SKILL.md +91 -0
- package/.claude/skills/blocker-solve/SKILL.md +96 -0
- package/.claude/skills/builder-backup/SKILL.md +54 -0
- package/.claude/skills/builder-box/SKILL.md +45 -0
- package/.claude/skills/builder-claim/SKILL.md +76 -0
- package/.claude/skills/builder-connect/SKILL.md +59 -0
- package/.claude/skills/builder-cost/SKILL.md +47 -0
- package/.claude/skills/builder-end/SKILL.md +81 -0
- package/.claude/skills/builder-exit/SKILL.md +88 -0
- package/.claude/skills/builder-key/SKILL.md +40 -0
- package/.claude/skills/builder-reauth/SKILL.md +50 -0
- package/.claude/skills/builder-redteam/SKILL.md +109 -0
- package/.claude/skills/builder-release/SKILL.md +41 -0
- package/.claude/skills/builder-setup/SKILL.md +62 -0
- package/.claude/skills/builder-ship/SKILL.md +79 -0
- package/.claude/skills/builder-stage/SKILL.md +51 -0
- package/.claude/skills/builder-start/SKILL.md +46 -0
- package/.claude/skills/close-box/SKILL.md +43 -0
- package/.claude/skills/design-sync/SKILL.md +69 -0
- package/.claude/skills/dev/SKILL.md +49 -0
- package/.claude/skills/feedback/SKILL.md +32 -0
- package/.claude/skills/figma-design-sync/SKILL.md +74 -0
- package/.claude/skills/goal-review/SKILL.md +89 -0
- package/.claude/skills/idea-triage/SKILL.md +144 -0
- package/.claude/skills/ideate/SKILL.md +82 -0
- package/.claude/skills/merge-mode/SKILL.md +169 -0
- package/.claude/skills/new-project/SKILL.md +108 -0
- package/.claude/skills/otb-character-review/SKILL.md +71 -0
- package/.claude/skills/otb-design-review/SKILL.md +47 -0
- package/.claude/skills/otb-feedback-capture/SKILL.md +45 -0
- package/.claude/skills/otb-figma-sync/SKILL.md +54 -0
- package/.claude/skills/otb-tile-generate/SKILL.md +45 -0
- package/.claude/skills/paint/SKILL.md +70 -0
- package/.claude/skills/planning-session/SKILL.md +299 -0
- package/.claude/skills/priority-session/SKILL.md +134 -0
- package/.claude/skills/read-session-export/SKILL.md +58 -0
- package/.claude/skills/recall/SKILL.md +52 -0
- package/.claude/skills/session-handoff/SKILL.md +46 -0
- package/.claude/skills/status/SKILL.md +33 -0
- package/.devcontainer/Dockerfile +69 -0
- package/.devcontainer/README.md +73 -0
- package/.devcontainer/devcontainer-lock.json +19 -0
- package/.devcontainer/devcontainer.json +93 -0
- package/.devcontainer/healthcheck.sh +84 -0
- package/.devcontainer/init-firewall.sh +198 -0
- package/.devcontainer/post-create.sh +153 -0
- package/.dockerignore +36 -0
- package/.env.local.example +32 -0
- package/.gitattributes +83 -0
- package/.gitignore +91 -0
- package/CLAUDE.md +242 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/CONTRIBUTING.md +51 -0
- package/Dockerfile +46 -0
- package/GOVERNANCE.md +44 -0
- package/LICENSE +661 -0
- package/README.md +88 -0
- package/bin/bongos.js +222 -0
- package/clients/bongos-client/README.md +48 -0
- package/clients/bongos-client/bongos-client.global.js +617 -0
- package/clients/bongos-client/examples/hello-world.mjs +62 -0
- package/clients/bongos-client/index.cjs +619 -0
- package/clients/bongos-client/index.d.ts +793 -0
- package/clients/bongos-client/index.mjs +614 -0
- package/clients/bongos-client/package.json +32 -0
- package/config/branding.neutral.json +60 -0
- package/config/design-tokens.neutral.json +51 -0
- package/config/design-tokens.schema.json +96 -0
- package/config/modules.neutral.json +9 -0
- package/docker-compose.yml +52 -0
- package/docker-entrypoint.sh +30 -0
- package/docs/adr/0001-stack-choice-single-vps.md +45 -0
- package/docs/adr/0002-digitalocean-over-hetzner.md +27 -0
- package/docs/adr/0003-cloudflare-origin-cert-over-letsencrypt.md +35 -0
- package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +45 -0
- package/docs/adr/0005-invisible-other-players-in-v1.md +37 -0
- package/docs/adr/0006-singleton-worldroom-plus-queueroom.md +30 -0
- package/docs/adr/0007-persistent-identity-via-localstorage-uuid.md +31 -0
- package/docs/adr/0008-family-based-tile-generation.md +86 -0
- package/docs/adr/0008-google-chat-oauth-user-auth.md +37 -0
- package/docs/adr/0009-autotile-architecture.md +181 -0
- package/docs/adr/0010-pms-architecture.md +70 -0
- package/docs/adr/0011-terrain-id-rendering-model.md +174 -0
- package/docs/adr/0012-ground-object-cell-split.md +208 -0
- package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +158 -0
- package/docs/adr/0014-families-canonical-over-vocabulary.md +103 -0
- package/docs/adr/0015-task-dependencies-and-auto-promotion.md +125 -0
- package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +132 -0
- package/docs/adr/0017-code-simplification-and-repo-cleanliness.md +74 -0
- package/docs/adr/0018-three-rank-model-goes-live.md +97 -0
- package/docs/adr/0019-red-team-bounty-payout-table.md +52 -0
- package/docs/adr/0020-security-model-public-stub.md +70 -0
- package/docs/adr/0021-per-builder-skill-model-preferences.md +99 -0
- package/docs/adr/0022-secrets-policy.md +124 -0
- package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +118 -0
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +277 -0
- package/docs/adr/0024-multi-agent-system-architecture.md +125 -0
- package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +59 -0
- package/docs/adr/0025-structured-criterion-task-link.md +44 -0
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +117 -0
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +170 -0
- package/docs/adr/0028-honest-llm-spend-accounting.md +109 -0
- package/docs/adr/0029-status-page-outage-resilience.md +59 -0
- package/docs/adr/0030-builders-hall-live-updates.md +59 -0
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +222 -0
- package/docs/adr/0032-discord-mirror-of-gds.md +50 -0
- package/docs/adr/0033-discord-bot-service-principal.md +82 -0
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +53 -0
- package/docs/adr/0035-builder-onboarding-three-paths.md +128 -0
- package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +40 -0
- package/docs/adr/0037-discord-channel-management.md +51 -0
- package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +111 -0
- package/docs/adr/0039-setup-first-onboarding-ux.md +49 -0
- package/docs/adr/0040-remote-control-default-browser-onramp.md +47 -0
- package/docs/adr/0041-temporary-grader-bypass-killswitch.md +40 -0
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +82 -0
- package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +74 -0
- package/docs/adr/0044-mediterranean-palette-replacement.md +73 -0
- package/docs/adr/0044-per-box-live-game-preview.md +57 -0
- package/docs/adr/0045-devbox-desktop-app.md +133 -0
- package/docs/adr/0046-sandbox-first-review-gate.md +72 -0
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +36 -0
- package/docs/adr/0048-works-in-progress-ia-split.md +32 -0
- package/docs/adr/0049-split-parallel-safety-contract.md +46 -0
- package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +43 -0
- package/docs/adr/0051-full-session-transcript-corpus.md +57 -0
- package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +70 -0
- package/docs/adr/0053-scoped-dev-box-session.md +55 -0
- package/docs/adr/0054-session-token-reward-cost-plus.md +63 -0
- package/docs/adr/0055-server-mediated-branch-publish.md +47 -0
- package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +62 -0
- package/docs/adr/0057-container-cost-ledger.md +28 -0
- package/docs/adr/0057-discord-archon-approval-channels.md +64 -0
- package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +64 -0
- package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +37 -0
- package/docs/adr/0060-gds-retrieval-layer.md +97 -0
- package/docs/adr/0061-context-layer-decomposition.md +61 -0
- package/docs/adr/0062-medusa-instance-model-decoupling.md +107 -0
- package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +44 -0
- package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +49 -0
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +69 -0
- package/docs/adr/0066-generated-file-map-sections.md +51 -0
- package/docs/adr/0067-session-start-fast-forward-pull.md +43 -0
- package/docs/adr/0068-shared-art-key-for-newcomers.md +38 -0
- package/docs/adr/0069-hall-live-channel-sse-decouple.md +35 -0
- package/docs/adr/0070-deterministic-session-card-delivery.md +44 -0
- package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +59 -0
- package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +35 -0
- package/docs/adr/0072-dev-box-code-staleness-visibility.md +39 -0
- package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +64 -0
- package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +37 -0
- package/docs/adr/0074-memory-map-stays-light.md +32 -0
- package/docs/adr/0075-per-system-cost-attribution.md +37 -0
- package/docs/adr/0076-in-session-deterministic-compaction.md +58 -0
- package/docs/adr/0077-content-addressed-llm-cache.md +32 -0
- package/docs/adr/0078-deterministic-first-cron.md +48 -0
- package/docs/adr/0079-value-gated-autonomous-engagement.md +39 -0
- package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +46 -0
- package/docs/adr/0081-tool-agnostic-design-layer.md +62 -0
- package/docs/adr/0082-productized-key-storage-provisioning.md +32 -0
- package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +55 -0
- package/docs/adr/0083-modular-architecture-strangler-build-plan.md +143 -0
- package/docs/adr/0084-auto-derived-per-task-rank-floor.md +86 -0
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +39 -0
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +123 -0
- package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +49 -0
- package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +65 -0
- package/docs/adr/0088-consistent-character-generative-animation.md +169 -0
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +179 -0
- package/docs/adr/0090-metic-task-authoring.md +73 -0
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +106 -0
- package/docs/adr/0092-hosting-module-and-on-prem-target.md +117 -0
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +72 -0
- package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +49 -0
- package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +65 -0
- package/docs/adr/0095-cross-agent-context-management.md +58 -0
- package/docs/adr/0096-require-reward-before-workable.md +209 -0
- package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +46 -0
- package/docs/adr/0097-retroactive-reward-backfill.md +124 -0
- package/docs/adr/0098-public-mirror-publish-manifest.md +92 -0
- package/docs/adr/0099-delayed-redacted-mirror-export.md +55 -0
- package/docs/adr/0100-two-repo-instance-model.md +60 -0
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +90 -0
- package/docs/adr/0102-finish-bounding-the-kernel.md +36 -0
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +70 -0
- package/docs/adr/0103-gdsv4-bongos-consolidation.md +28 -0
- package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +42 -0
- package/docs/adr/0105-instance-seed-migrations-out-of-core.md +47 -0
- package/docs/adr/0106-goal-owner-manager-authority.md +84 -0
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +83 -0
- package/docs/adr/0108-instance-composition-configurable-root.md +87 -0
- package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +44 -0
- package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +49 -0
- package/docs/adr/0111-instance-hosting-provisioning-module.md +135 -0
- package/docs/adr/0112-private-goals-invitations-join-requests.md +72 -0
- package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +41 -0
- package/docs/adr/0114-instance-docs-discovery-contract.md +32 -0
- package/docs/adr/0115-scheduled-routines-portability.md +31 -0
- package/docs/adr/0116-api-error-envelope-and-code-taxonomy.md +62 -0
- package/docs/adr/0117-api-versioning-and-deprecation-policy.md +50 -0
- package/docs/adr/0118-api-contract-source-of-truth-code-first.md +47 -0
- package/docs/adr/0119-api-pagination-contract.md +34 -0
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +108 -0
- package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +97 -0
- package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +43 -0
- package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +36 -0
- package/docs/adr/0124-typed-api-response-bodies.md +37 -0
- package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +36 -0
- package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +30 -0
- package/docs/adr/0127-cross-box-fleet-observability.md +64 -0
- package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +46 -0
- package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +34 -0
- package/docs/adr/0130-provision-remote-exec-over-ssh.md +61 -0
- package/docs/adr/0131-rank-scoped-skill-visibility.md +47 -0
- package/docs/adr/0132-cohost-fleet-control-plane-migration.md +54 -0
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +42 -0
- package/docs/adr/0134-private-first-npm-distribution.md +38 -0
- package/docs/adr/README.md +208 -0
- package/docs/api/openapi.json +13720 -0
- package/docs/api-reference.md +437 -0
- package/docs/architecture.md +244 -0
- package/docs/branding-contract.md +66 -0
- package/docs/branding-fill-prompt.md +25 -0
- package/docs/canonical-permissions.md +241 -0
- package/docs/design/container-exterior-tiles.md +49 -0
- package/docs/design/container-exterior.md +81 -0
- package/docs/design/container-interior.md +77 -0
- package/docs/design/modular-architecture/00-research-report.md +107 -0
- package/docs/design/modular-architecture/01-architecture.md +125 -0
- package/docs/design/modular-architecture/02-module-map.md +116 -0
- package/docs/design/modular-architecture/03-builder-flows.md +104 -0
- package/docs/design/modular-architecture/04-module-lifecycle.md +62 -0
- package/docs/design/modular-architecture/README.md +27 -0
- package/docs/design/vanilla-hall-ui-redesign-scope.md +284 -0
- package/docs/design/world-map-scroll.md +41 -0
- package/docs/design-contract.md +320 -0
- package/docs/file-map.md +418 -0
- package/docs/handoff-template.md +92 -0
- package/docs/modules-contract.md +293 -0
- package/docs/onboarding/browser-terminal-guide.md +73 -0
- package/docs/onboarding/diagrams/01-task-lifecycle.mmd +28 -0
- package/docs/onboarding/diagrams/02-rank-ladder.mmd +54 -0
- package/docs/onboarding/diagrams/03-drachmae-karma.mmd +37 -0
- package/docs/onboarding/diagrams/04-architecture.mmd +51 -0
- package/docs/onboarding/diagrams/05-versioning.mmd +29 -0
- package/docs/onboarding/diagrams/README.md +94 -0
- package/docs/onboarding/diagrams/assertions.json +170 -0
- package/docs/onboarding/diagrams/puppeteer-config.json +1 -0
- package/docs/onboarding/diagrams/render-config.json +9 -0
- package/docs/onboarding/drachmae-and-karma.md +178 -0
- package/docs/onboarding/primer.md +202 -0
- package/docs/project-context.template.md +67 -0
- package/docs/recipes/README.md +35 -0
- package/docs/recipes/audit-replay.md +100 -0
- package/docs/recipes/bongos-cli-release.md +66 -0
- package/docs/recipes/builder-box-lifecycle.md +152 -0
- package/docs/recipes/claude-design-loop.md +143 -0
- package/docs/recipes/claude-gemini-bongos-doors.md +155 -0
- package/docs/recipes/cloudbongos-staging-gate.md +139 -0
- package/docs/recipes/cloudbongos-standup.md +111 -0
- package/docs/recipes/devbox-app-release.md +93 -0
- package/docs/recipes/devbox-app-windows-test.md +128 -0
- package/docs/recipes/failed-ship-recovery-proof.md +102 -0
- package/docs/recipes/figma-design-loop.md +129 -0
- package/docs/recipes/gds-db-backup.md +255 -0
- package/docs/recipes/instance-deploy.md +37 -0
- package/docs/recipes/managed-settings-remote-control.md +416 -0
- package/docs/recipes/memory-backup.md +71 -0
- package/docs/recipes/memory-sync-conflicts.md +98 -0
- package/docs/recipes/multi-builder-merge.md +78 -0
- package/docs/recipes/ops-gotchas.md +212 -0
- package/docs/recipes/overnight-builder.md +53 -0
- package/docs/recipes/packaging-the-core.md +49 -0
- package/docs/recipes/parallel-load-results-2026-05-30.md +63 -0
- package/docs/recipes/parallel-load-test.md +32 -0
- package/docs/recipes/pixel-art-pipeline.md +411 -0
- package/docs/recipes/private-npm-distribution.md +79 -0
- package/docs/recipes/search-index-ingestion.md +67 -0
- package/docs/recipes/self-host.md +60 -0
- package/docs/recipes/ship-and-regrade.md +72 -0
- package/docs/recipes/staging-data.md +50 -0
- package/docs/recipes/staging-environment.md +215 -0
- package/docs/recipes/upgrading-the-core.md +58 -0
- package/docs/research/cursor-competitive-analysis.md +255 -0
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +227 -0
- package/migrations/003_pms.sql +284 -0
- package/migrations/004_pms_cost_idempotency.sql +13 -0
- package/migrations/005_pms_smoke_filter.sql +44 -0
- package/migrations/006_pms_v2.sql +378 -0
- package/migrations/007_pms_v2_hierarchy_trigger.sql +59 -0
- package/migrations/008_pms_v2_migration_allocator.sql +27 -0
- package/migrations/009_pms_v2_blockers_table.sql +68 -0
- package/migrations/010_uptime.sql +29 -0
- package/migrations/011_backfill_v2_v3_done_when.sql +20 -0
- package/migrations/012_pms_v2_task_lifecycle_states.sql +82 -0
- package/migrations/013_claim_locking.sql +22 -0
- package/migrations/014_pms_task_discipline.sql +86 -0
- package/migrations/015_pms_estimation_calibration.sql +140 -0
- package/migrations/016_pms_task_grades.sql +60 -0
- package/migrations/017_version_progress_exclude_abandoned.sql +49 -0
- package/migrations/019_rename_pms_v3_to_gds_v3.sql +65 -0
- package/migrations/020_task_dependencies.sql +99 -0
- package/migrations/021_v3_renumber_and_deps.sql +224 -0
- package/migrations/022_v3_reconcile_dep_gated_status.sql +41 -0
- package/migrations/023_pms_rank.sql +30 -0
- package/migrations/025_builder_exit_status.sql +15 -0
- package/migrations/027_builders_preferred_disciplines.sql +46 -0
- package/migrations/028_tasks_parallel_safe.sql +71 -0
- package/migrations/029_rank_three_live.sql +32 -0
- package/migrations/030_vulnerability_reports.sql +61 -0
- package/migrations/031_reward_simplification.sql +57 -0
- package/migrations/032_repo_health_snapshots.sql +56 -0
- package/migrations/033_audit_log.sql +64 -0
- package/migrations/034_lifecycle_breakdown_leaf_only.sql +62 -0
- package/migrations/035_auth_token_hygiene.sql +66 -0
- package/migrations/037_builder_skill_model_prefs.sql +44 -0
- package/migrations/038_task_override_requests.sql +51 -0
- package/migrations/039_newcomer_friendly_column.sql +124 -0
- package/migrations/040_builder_karma.sql +58 -0
- package/migrations/041_kind_multipliers_and_idea_bonus.sql +42 -0
- package/migrations/042_criterion_proposal_workflow.sql +78 -0
- package/migrations/043_builder_onboarding_observability.sql +66 -0
- package/migrations/044_tasks_requires_rank.sql +97 -0
- package/migrations/045_builder_onboarding_state.sql +147 -0
- package/migrations/046_cost_log_builder_attribution.sql +42 -0
- package/migrations/054_builder_memory.sql +108 -0
- package/migrations/055_task_criteria.sql +90 -0
- package/migrations/058_peer_votes.sql +41 -0
- package/migrations/059_onboarding_pick_disciplines.sql +59 -0
- package/migrations/060_access_requests.sql +46 -0
- package/migrations/061_backfill_override_ship_attribution.sql +29 -0
- package/migrations/062_session_records.sql +34 -0
- package/migrations/063_session_records_tool_errors_idx.sql +11 -0
- package/migrations/064_grade_attempts.sql +18 -0
- package/migrations/065_bfg_principal.sql +58 -0
- package/migrations/066_live_notify_triggers.sql +69 -0
- package/migrations/067_builder_boxes.sql +117 -0
- package/migrations/067_discord_bot_foundation.sql +69 -0
- package/migrations/068_thetes_requires_rank.sql +27 -0
- package/migrations/069_builder_ssh_keys.sql +66 -0
- package/migrations/070_box_intents.sql +101 -0
- package/migrations/071_box_first_provision_approval.sql +46 -0
- package/migrations/072_onboarding_ship_three_remove_primer.sql +80 -0
- package/migrations/073_box_terminal_access.sql +46 -0
- package/migrations/075_builder_sound_prefs.sql +28 -0
- package/migrations/078_box_claude_active.sql +22 -0
- package/migrations/079_box_first_connected_at.sql +20 -0
- package/migrations/081_tasks_needs_migration.sql +34 -0
- package/migrations/084_tasks_security_sensitive.sql +24 -0
- package/migrations/085_security_engagement_docs.sql +34 -0
- package/migrations/086_rename_disciplines.sql +125 -0
- package/migrations/088_builders_anthropic_link.sql +28 -0
- package/migrations/089_builders_monthly_budget.sql +19 -0
- package/migrations/090_box_scoped_sessions.sql +38 -0
- package/migrations/091_session_token_reward.sql +44 -0
- package/migrations/093_tasks_sandbox_review.sql +22 -0
- package/migrations/102_remove_box_first_provision_approval.sql +58 -0
- package/migrations/103_search_chunks.sql +90 -0
- package/migrations/104_builder_box_blocked.sql +34 -0
- package/migrations/105_box_host_keys.sql +35 -0
- package/migrations/111_medusa_customer0_framing.sql +35 -0
- package/migrations/112_drop_track_check.sql +25 -0
- package/migrations/113_merge_lease.sql +16 -0
- package/migrations/114_cloudbongos_rename_live_strings.sql +32 -0
- package/migrations/118_currency_label_decoupling.sql +23 -0
- package/migrations/119_builder_behavior_prefs.sql +31 -0
- package/migrations/121_box_code_version.sql +37 -0
- package/migrations/122_builder_gemini_key.sql +30 -0
- package/migrations/123_cost_log_tiers.sql +33 -0
- package/migrations/124_cost_baseline.sql +45 -0
- package/migrations/125_llm_cache.sql +54 -0
- package/migrations/126_autonomy_runs.sql +33 -0
- package/migrations/143_cost_calibration.sql +63 -0
- package/migrations/145_backfill_task_requires_rank.sql +84 -0
- package/migrations/160_goal_tier.sql +88 -0
- package/migrations/163_polymorphic_dependencies.sql +187 -0
- package/migrations/164_event_sound_prefs.sql +20 -0
- package/migrations/165_task_module_key.sql +15 -0
- package/migrations/171_claims_published_head_sha.sql +24 -0
- package/migrations/174_close_orphaned_claims_on_terminal_tasks.sql +30 -0
- package/migrations/175_task_grades_diff_hash.sql +9 -0
- package/migrations/176_promotion_respects_open_blockers.sql +58 -0
- package/migrations/176_ui_discipline.sql +40 -0
- package/migrations/177_require_reward_before_workable.sql +76 -0
- package/migrations/178_reward_gate_auto_assign_revert_autopromote.sql +61 -0
- package/migrations/179_search_chunk_usefulness.sql +33 -0
- package/migrations/180_one_active_claim_per_session.sql +54 -0
- package/migrations/181_cost_log_skill_name.sql +33 -0
- package/migrations/184_claim_release_requested.sql +25 -0
- package/migrations/185_module_upstreaming_goal_wiring.sql +59 -0
- package/migrations/187_goal_sort_order.sql +30 -0
- package/migrations/187_tasks_kind_check_add_verify.sql +21 -0
- package/migrations/README.md +88 -0
- package/migrations/core_188_goal_visibility_and_membership_requests.sql +71 -0
- package/migrations/core_189_core_upgrades_ledger.sql +37 -0
- package/migrations/core_189_credit_log_task_id_index.sql +19 -0
- package/migrations/core_190_rebuild_claimable_task_views.sql +71 -0
- package/migrations/instance/018_pms_v3_planning_seed.sql +131 -0
- package/migrations/instance/080_gds_v4_planning_seed.sql +75 -0
- package/migrations/instance/110_medusa_planning_seed.sql +70 -0
- package/migrations/instance/120_bongos_v1_planning_seed.sql +69 -0
- package/migrations/instance/144_bongos_v1_module_system_criterion.sql +26 -0
- package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +29 -0
- package/migrations/instance/172_v2_world_planning_seed.sql +163 -0
- package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +33 -0
- package/migrations/instance/182_gdsv4_bongos_consolidation.sql +132 -0
- package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +116 -0
- package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +69 -0
- package/modules/autonomy/CLAUDE.md +49 -0
- package/modules/autonomy/db.js +50 -0
- package/modules/autonomy/module.json +13 -0
- package/modules/autonomy/pollers/routine-timers.js +146 -0
- package/modules/autonomy/routes/autonomy.js +37 -0
- package/modules/builder-settings/CLAUDE.md +58 -0
- package/modules/builder-settings/builder-needs.js +115 -0
- package/modules/builder-settings/db.js +168 -0
- package/modules/builder-settings/display-name.js +84 -0
- package/modules/builder-settings/event-sound-prefs.js +169 -0
- package/modules/builder-settings/interaction-prefs.js +201 -0
- package/modules/builder-settings/model-alloc-prefs.js +147 -0
- package/modules/builder-settings/module.json +10 -0
- package/modules/builder-settings/render-prefs.js +103 -0
- package/modules/builder-settings/routes/settings.js +417 -0
- package/modules/builder-settings/settings.js +52 -0
- package/modules/builder-settings/skill-prefs.js +196 -0
- package/modules/builder-settings/sound-prefs.js +178 -0
- package/modules/builder-settings/wandering-prefs.js +282 -0
- package/modules/dev-box/CLAUDE.md +38 -0
- package/modules/dev-box/box-access.js +275 -0
- package/modules/dev-box/box-credential.js +94 -0
- package/modules/dev-box/box-onboard.js +486 -0
- package/modules/dev-box/boxes.js +842 -0
- package/modules/dev-box/db.js +39 -0
- package/modules/dev-box/module.json +14 -0
- package/modules/dev-box/routes/box.js +977 -0
- package/modules/discord/CLAUDE.md +50 -0
- package/modules/discord/auth.js +54 -0
- package/modules/discord/bug-attachments.js +210 -0
- package/modules/discord/db.js +96 -0
- package/modules/discord/discord-approvals.js +145 -0
- package/modules/discord/discord-audit.js +29 -0
- package/modules/discord/discord-bot.js +545 -0
- package/modules/discord/discord-bugs.js +257 -0
- package/modules/discord/discord-channels.js +412 -0
- package/modules/discord/discord-inbound.js +147 -0
- package/modules/discord/discord-message-buffer.js +54 -0
- package/modules/discord/discord-reaction.js +186 -0
- package/modules/discord/discord-role-sync.js +318 -0
- package/modules/discord/module.json +14 -0
- package/modules/discord/pollers/discord-bot.js +19 -0
- package/modules/discord/routes/bug-attachments.js +44 -0
- package/modules/discord/routes/discord.js +102 -0
- package/modules/discord/ship-broadcast.js +78 -0
- package/modules/discord/webhook.js +74 -0
- package/modules/economy/CLAUDE.md +48 -0
- package/modules/economy/achievements.js +594 -0
- package/modules/economy/cost-classify.js +331 -0
- package/modules/economy/cost-summary-shape.js +90 -0
- package/modules/economy/cost.js +438 -0
- package/modules/economy/credits.js +430 -0
- package/modules/economy/migrations/economy_001_fix_gds_shipper_description.sql +91 -0
- package/modules/economy/module.json +10 -0
- package/modules/economy/reward.js +61 -0
- package/modules/economy/routes/cost.js +97 -0
- package/modules/economy/routes/leaderboard.js +26 -0
- package/modules/economy/routes/reward.js +42 -0
- package/modules/economy/streak.js +285 -0
- package/modules/grading/CLAUDE.md +42 -0
- package/modules/grading/db.js +39 -0
- package/modules/grading/grader-rubric.json +151 -0
- package/modules/grading/grader-workers/efficiency.js +213 -0
- package/modules/grading/grader-workers/extract-json.js +80 -0
- package/modules/grading/grader-workers/fence.js +100 -0
- package/modules/grading/grader-workers/hacker.js +239 -0
- package/modules/grading/grader-workers/index.js +183 -0
- package/modules/grading/grader-workers/narc.js +207 -0
- package/modules/grading/grader-workers/quality.js +198 -0
- package/modules/grading/grader-workers/rubric.js +20 -0
- package/modules/grading/grader-workers/worker-prompt.js +89 -0
- package/modules/grading/grader-workers/worker-verdict.js +50 -0
- package/modules/grading/grader.js +1790 -0
- package/modules/grading/module.json +12 -0
- package/modules/grading/routes/grade.js +51 -0
- package/modules/hall-ui/CLAUDE.md +61 -0
- package/modules/hall-ui/module.json +14 -0
- package/modules/hall-ui/public/atlas.html +180 -0
- package/modules/hall-ui/public/atlas.js +336 -0
- package/modules/hall-ui/public/box-panel.js +423 -0
- package/modules/hall-ui/public/brand-apply.js +117 -0
- package/modules/hall-ui/public/builders.js +3028 -0
- package/modules/hall-ui/public/chime.wav +0 -0
- package/modules/hall-ui/public/copy-on-click.js +174 -0
- package/modules/hall-ui/public/cursors/arrow.png +0 -0
- package/modules/hall-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier-out.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier.png +0 -0
- package/modules/hall-ui/public/diagram-viewer.css +125 -0
- package/modules/hall-ui/public/diagram-viewer.js +330 -0
- package/modules/hall-ui/public/diagrams.html +113 -0
- package/modules/hall-ui/public/dom-utils.js +212 -0
- package/modules/hall-ui/public/drachmae.html +68 -0
- package/modules/hall-ui/public/drachmae.js +136 -0
- package/modules/hall-ui/public/gate.html +143 -0
- package/modules/hall-ui/public/gate.js +228 -0
- package/modules/hall-ui/public/goals-page.js +1297 -0
- package/modules/hall-ui/public/goals.html +376 -0
- package/modules/hall-ui/public/goals.js +119 -0
- package/modules/hall-ui/public/hall-widgets.js +189 -0
- package/modules/hall-ui/public/harbor.html +167 -0
- package/modules/hall-ui/public/harbor.js +335 -0
- package/modules/hall-ui/public/index.html +116 -0
- package/modules/hall-ui/public/instances-panel.js +172 -0
- package/modules/hall-ui/public/md-reader.js +234 -0
- package/modules/hall-ui/public/modules.html +119 -0
- package/modules/hall-ui/public/modules.js +154 -0
- package/modules/hall-ui/public/new-project-wizard.js +186 -0
- package/modules/hall-ui/public/not-ready.html +48 -0
- package/modules/hall-ui/public/pair.html +119 -0
- package/modules/hall-ui/public/pair.js +132 -0
- package/modules/hall-ui/public/primer.css +404 -0
- package/modules/hall-ui/public/primer.html +85 -0
- package/modules/hall-ui/public/primer.js +641 -0
- package/modules/hall-ui/public/profile.html +85 -0
- package/modules/hall-ui/public/profile.js +236 -0
- package/modules/hall-ui/public/ranks.html +69 -0
- package/modules/hall-ui/public/ranks.js +206 -0
- package/modules/hall-ui/public/roadmap.html +209 -0
- package/modules/hall-ui/public/roadmap.js +375 -0
- package/modules/hall-ui/public/sessions.html +92 -0
- package/modules/hall-ui/public/sessions.js +222 -0
- package/modules/hall-ui/public/settings.html +640 -0
- package/modules/hall-ui/public/settings.js +1219 -0
- package/modules/hall-ui/public/shell.js +495 -0
- package/modules/hall-ui/public/style.css +1748 -0
- package/modules/hall-ui/public/task-detail.js +253 -0
- package/modules/hall-ui/public/task.html +83 -0
- package/modules/hall-ui/public/task.js +326 -0
- package/modules/hall-ui/public/watch.html +333 -0
- package/modules/hall-ui/public/watch.js +859 -0
- package/modules/hall-ui/public/work.html +469 -0
- package/modules/hall-ui/public/work.js +1292 -0
- package/modules/ideas/CLAUDE.md +37 -0
- package/modules/ideas/blockers.js +100 -0
- package/modules/ideas/inbox.js +459 -0
- package/modules/ideas/module.json +10 -0
- package/modules/ideas/routes/blockers.js +120 -0
- package/modules/ideas/routes/inbox.js +230 -0
- package/modules/lifecycle/CLAUDE.md +63 -0
- package/modules/lifecycle/conflict-resolve.js +436 -0
- package/modules/lifecycle/db.js +4970 -0
- package/modules/lifecycle/done-when.js +355 -0
- package/modules/lifecycle/github-push.js +969 -0
- package/modules/lifecycle/goal-conflicts.js +133 -0
- package/modules/lifecycle/hierarchy.js +104 -0
- package/modules/lifecycle/lifecycle.js +58 -0
- package/modules/lifecycle/merge-lock.js +261 -0
- package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +28 -0
- package/modules/lifecycle/migrations/lifecycle_002_backfill_orphan_task_goals.sql +36 -0
- package/modules/lifecycle/module.json +13 -0
- package/modules/lifecycle/pollers/publish-reconciler.js +20 -0
- package/modules/lifecycle/publish-reconciler.js +418 -0
- package/modules/lifecycle/routes/analytics.js +63 -0
- package/modules/lifecycle/routes/claims.js +506 -0
- package/modules/lifecycle/routes/dependencies.js +82 -0
- package/modules/lifecycle/routes/done-when.js +136 -0
- package/modules/lifecycle/routes/gate-approvals.js +197 -0
- package/modules/lifecycle/routes/goals.js +1419 -0
- package/modules/lifecycle/routes/lifecycle.js +43 -0
- package/modules/lifecycle/routes/tasks.js +1703 -0
- package/modules/lifecycle/routes/versions.js +128 -0
- package/modules/lifecycle/ship-card.js +505 -0
- package/modules/lifecycle/ship-preflight.js +225 -0
- package/modules/lifecycle/task-classifier.js +512 -0
- package/modules/lifecycle/version-close.js +106 -0
- package/modules/memory/CLAUDE.md +40 -0
- package/modules/memory/learnings.js +275 -0
- package/modules/memory/memory.js +572 -0
- package/modules/memory/module.json +12 -0
- package/modules/memory/routes/learnings.js +90 -0
- package/modules/memory/routes/memory.js +916 -0
- package/modules/memory/routes/search.js +188 -0
- package/modules/memory/search-chunker.js +252 -0
- package/modules/memory/search.js +320 -0
- package/modules/onboarding/CLAUDE.md +55 -0
- package/modules/onboarding/approval-broadcast.js +59 -0
- package/modules/onboarding/db.js +54 -0
- package/modules/onboarding/module.json +10 -0
- package/modules/onboarding/newcomer-restock.js +212 -0
- package/modules/onboarding/onboarding-state.js +532 -0
- package/modules/onboarding/onboarding.js +508 -0
- package/modules/onboarding/port.js +63 -0
- package/modules/onboarding/routes/access-requests.js +208 -0
- package/modules/onboarding/routes/onboarding.js +54 -0
- package/modules/security/CLAUDE.md +44 -0
- package/modules/security/module.json +10 -0
- package/modules/security/routes/reports.js +251 -0
- package/modules/security/secret-scrub.js +201 -0
- package/modules/security/security.js +294 -0
- package/modules/sessions/CLAUDE.md +39 -0
- package/modules/sessions/bfg.js +357 -0
- package/modules/sessions/db.js +326 -0
- package/modules/sessions/module.json +10 -0
- package/modules/sessions/pulse.js +149 -0
- package/modules/sessions/routes/sessions.js +331 -0
- package/modules/status-ui/CLAUDE.md +47 -0
- package/modules/status-ui/module.json +14 -0
- package/modules/status-ui/public/README.md +29 -0
- package/modules/status-ui/public/cursors/arrow.png +0 -0
- package/modules/status-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/status-ui/public/index.html +363 -0
- package/modules/status-ui/public/snapshots/.gitkeep +0 -0
- package/modules/status-ui/public/status.js +1375 -0
- package/modules/status-ui/public/style.css +1342 -0
- package/package-lock.json +975 -0
- package/package.json +28 -0
- package/public-docs/index.html +35 -0
- package/public-docs/redoc.standalone.js +1838 -0
- package/public-docs/redoc.standalone.js.LICENSE.txt +102 -0
- package/public-landing/buddha.png +0 -0
- package/public-landing/create.html +868 -0
- package/public-landing/index.html +168 -0
- package/scripts/bongos-mcp.js +28 -0
- package/scripts/cron/style_guide_audit.sh +134 -0
- package/scripts/discord/README.md +52 -0
- package/scripts/discord/lib.js +80 -0
- package/scripts/discord/post.js +51 -0
- package/scripts/gds/CLAUDE.md +144 -0
- package/scripts/gds/abandon.js +58 -0
- package/scripts/gds/adopt-detect.js +123 -0
- package/scripts/gds/adopt-import.js +111 -0
- package/scripts/gds/adopt-preflight.js +121 -0
- package/scripts/gds/api.js +78 -0
- package/scripts/gds/architect-audit.js +288 -0
- package/scripts/gds/art-stage.js +152 -0
- package/scripts/gds/audit-authorship.sh +243 -0
- package/scripts/gds/audit-deps.js +121 -0
- package/scripts/gds/audit-exports.js +128 -0
- package/scripts/gds/audit-replay.sh +161 -0
- package/scripts/gds/audit-ships.js +251 -0
- package/scripts/gds/autonomy-gate.js +135 -0
- package/scripts/gds/backfill-cost.js +165 -0
- package/scripts/gds/backfill-sessions.js +351 -0
- package/scripts/gds/backfill-task-rewards.js +408 -0
- package/scripts/gds/backup.js +94 -0
- package/scripts/gds/bfg-principal-token.js +65 -0
- package/scripts/gds/box-auth-check.js +160 -0
- package/scripts/gds/box-connect-lib.js +453 -0
- package/scripts/gds/box.js +1258 -0
- package/scripts/gds/build-bongos.js +94 -0
- package/scripts/gds/capture.js +123 -0
- package/scripts/gds/cf-tunnel.js +419 -0
- package/scripts/gds/ci-grade.js +82 -0
- package/scripts/gds/claim-recall.js +112 -0
- package/scripts/gds/claim.js +333 -0
- package/scripts/gds/classify-discipline.js +153 -0
- package/scripts/gds/claude-materialize.js +176 -0
- package/scripts/gds/cleanup-orphans.js +74 -0
- package/scripts/gds/cli-lib.js +518 -0
- package/scripts/gds/code.js +101 -0
- package/scripts/gds/codemod-rename-src-gds.js +145 -0
- package/scripts/gds/conductor-dispatch.js +426 -0
- package/scripts/gds/context-pack.js +228 -0
- package/scripts/gds/coreB-carve-proof.sh +716 -0
- package/scripts/gds/cost.js +47 -0
- package/scripts/gds/db-backup-nightly.sh +160 -0
- package/scripts/gds/db-backup-offsite.sh +152 -0
- package/scripts/gds/demote.js +40 -0
- package/scripts/gds/design-sync.js +62 -0
- package/scripts/gds/diagnose-achievements.js +118 -0
- package/scripts/gds/diagram-facts.js +319 -0
- package/scripts/gds/discipline-modes.json +25 -0
- package/scripts/gds/discord-channels.js +66 -0
- package/scripts/gds/do-api.js +176 -0
- package/scripts/gds/docs-entropy.js +403 -0
- package/scripts/gds/doctor.js +389 -0
- package/scripts/gds/feedback-latest.js +94 -0
- package/scripts/gds/fetch-art-key.js +106 -0
- package/scripts/gds/fetch-sound-prefs.js +88 -0
- package/scripts/gds/figma-design-sync.js +61 -0
- package/scripts/gds/fitness.js +1446 -0
- package/scripts/gds/gate-review.js +322 -0
- package/scripts/gds/gating.js +325 -0
- package/scripts/gds/gds-db-backup.service +24 -0
- package/scripts/gds/gds-db-backup.timer +20 -0
- package/scripts/gds/gds-db-offsite.service +29 -0
- package/scripts/gds/gds-db-offsite.timer +18 -0
- package/scripts/gds/gen-api-client.js +508 -0
- package/scripts/gds/gen-api-docs.js +1037 -0
- package/scripts/gds/gen-atlas.js +366 -0
- package/scripts/gds/gen-diagrams.js +608 -0
- package/scripts/gds/gen-file-map.js +196 -0
- package/scripts/gds/gen-repo-map.js +519 -0
- package/scripts/gds/gen-session-index.js +210 -0
- package/scripts/gds/git-merge-regen.js +147 -0
- package/scripts/gds/grade-smoke.js +205 -0
- package/scripts/gds/hooks/pre-push.js +169 -0
- package/scripts/gds/http-api-client.js +88 -0
- package/scripts/gds/init.js +903 -0
- package/scripts/gds/install-git-hooks.js +114 -0
- package/scripts/gds/key-card.js +213 -0
- package/scripts/gds/key-status.js +126 -0
- package/scripts/gds/land-watch.js +168 -0
- package/scripts/gds/learning-capture.js +145 -0
- package/scripts/gds/lib.sh +44 -0
- package/scripts/gds/linkify-refs.js +473 -0
- package/scripts/gds/local-preview-lib.js +159 -0
- package/scripts/gds/local-preview.js +95 -0
- package/scripts/gds/login.js +225 -0
- package/scripts/gds/main-audit.js +279 -0
- package/scripts/gds/me.js +88 -0
- package/scripts/gds/memory-map.js +174 -0
- package/scripts/gds/merge-lock.js +71 -0
- package/scripts/gds/migration-namespace.js +200 -0
- package/scripts/gds/mirror-lineage-check.js +319 -0
- package/scripts/gds/mirror-redact.js +305 -0
- package/scripts/gds/module.js +482 -0
- package/scripts/gds/newcomer-floor.config.json +13 -0
- package/scripts/gds/newcomer-floor.js +415 -0
- package/scripts/gds/newcomer-floor.templates.json +86 -0
- package/scripts/gds/newcomer-floor.test.js +235 -0
- package/scripts/gds/next-number.js +163 -0
- package/scripts/gds/oauth-secret.js +197 -0
- package/scripts/gds/onboard.js +217 -0
- package/scripts/gds/onboarding-analyze.js +226 -0
- package/scripts/gds/onboarding-config.js +178 -0
- package/scripts/gds/onboarding-ship.js +92 -0
- package/scripts/gds/package-core.js +684 -0
- package/scripts/gds/paste-token.js +131 -0
- package/scripts/gds/portability-smoke-art.sh +85 -0
- package/scripts/gds/portability-smoke-memory.sh +147 -0
- package/scripts/gds/provision.js +1324 -0
- package/scripts/gds/publish-manifest.js +307 -0
- package/scripts/gds/pulse.js +309 -0
- package/scripts/gds/push-main.js +45 -0
- package/scripts/gds/read-session-export.js +359 -0
- package/scripts/gds/reauth.js +149 -0
- package/scripts/gds/recall.js +135 -0
- package/scripts/gds/release.js +71 -0
- package/scripts/gds/render-ideas.js +173 -0
- package/scripts/gds/repo-metrics.js +363 -0
- package/scripts/gds/resolve-skill-model.js +57 -0
- package/scripts/gds/run-routine.js +197 -0
- package/scripts/gds/run-unit-tests.js +178 -0
- package/scripts/gds/sandbox-stage.js +653 -0
- package/scripts/gds/search-ingest-db.js +209 -0
- package/scripts/gds/search-ingest-md.js +225 -0
- package/scripts/gds/security-baseline-check.sh +180 -0
- package/scripts/gds/seed-adopt-tasks.js +75 -0
- package/scripts/gds/seed-api-contract-goal-tasks.js +141 -0
- package/scripts/gds/seed-bongos-app-tasks.js +294 -0
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +81 -0
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +100 -0
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +307 -0
- package/scripts/gds/seed-bongos-module-system-tasks.js +346 -0
- package/scripts/gds/seed-bongos-tasks.js +214 -0
- package/scripts/gds/seed-gds-v4-tasks.js +624 -0
- package/scripts/gds/seed-governance-tasks.js +340 -0
- package/scripts/gds/seed-medusa-tasks.js +440 -0
- package/scripts/gds/seed-module-upstreaming.js +219 -0
- package/scripts/gds/seed-productization-tasks.js +235 -0
- package/scripts/gds/seed-provisioning-tasks.js +83 -0
- package/scripts/gds/seed-staging.sh +104 -0
- package/scripts/gds/seed-v2-world-tasks.js +283 -0
- package/scripts/gds/seed-v3-tasks.js +1981 -0
- package/scripts/gds/session-cost.js +393 -0
- package/scripts/gds/session-digest.js +179 -0
- package/scripts/gds/session-eval.js +576 -0
- package/scripts/gds/session.js +404 -0
- package/scripts/gds/setup.js +504 -0
- package/scripts/gds/shell.js +100 -0
- package/scripts/gds/ship.js +3618 -0
- package/scripts/gds/smoke-batch-claim.sh +213 -0
- package/scripts/gds/smoke-batch-release.sh +296 -0
- package/scripts/gds/smoke-box.sh +150 -0
- package/scripts/gds/smoke-claim-consistency.sh +212 -0
- package/scripts/gds/smoke-dependencies.sh +84 -0
- package/scripts/gds/smoke-gds.js +125 -0
- package/scripts/gds/smoke-write.sh +168 -0
- package/scripts/gds/start.js +782 -0
- package/scripts/gds/status.js +365 -0
- package/scripts/gds/triage.js +366 -0
- package/scripts/gds/upgrade.js +421 -0
- package/scripts/gds/validate-design.js +254 -0
- package/scripts/gds/version-close.js +549 -0
- package/scripts/migrate.sh +183 -0
- package/scripts/migrate_cost_ledger.sh +178 -0
- package/scripts/public-mirror-export.js +291 -0
- package/scripts/render-diagrams.sh +88 -0
- package/scripts/security/dep-audit.js +276 -0
- package/scripts/setup-builder.js +274 -0
- package/scripts/setup-builder.sh +28 -0
- package/scripts/snapshots/backfill-history.mjs +292 -0
- package/scripts/snapshots/maybe-render-on-deploy.sh +66 -0
- package/scripts/snapshots/render-pre-art-eras.mjs +329 -0
- package/scripts/snapshots/render-world.mjs +322 -0
- package/scripts/status-mirror-sync.js +192 -0
- package/scripts/status-probe.mjs +185 -0
- package/server.js +212 -0
- package/src/asset-version.js +71 -0
- package/src/bongos/CLAUDE.md +64 -0
- package/src/bongos/api-errors.js +281 -0
- package/src/bongos/api-path-404.js +67 -0
- package/src/bongos/api-prefix.js +38 -0
- package/src/bongos/app-pair.js +172 -0
- package/src/bongos/auth.js +979 -0
- package/src/bongos/cascade-dispatch.js +123 -0
- package/src/bongos/db-kernel.js +252 -0
- package/src/bongos/db.js +911 -0
- package/src/bongos/goal-scope-check.js +120 -0
- package/src/bongos/hierarchy-config.js +189 -0
- package/src/bongos/live-channel.js +145 -0
- package/src/bongos/llm-cache.js +260 -0
- package/src/bongos/llm-pricing.js +220 -0
- package/src/bongos/metrics.js +286 -0
- package/src/bongos/middleware/audit.js +274 -0
- package/src/bongos/middleware/error-envelope.js +93 -0
- package/src/bongos/middleware/rate-limit.js +195 -0
- package/src/bongos/module-scope-map.js +271 -0
- package/src/bongos/optimizer.js +166 -0
- package/src/bongos/path-match.js +47 -0
- package/src/bongos/permission-path-check.js +248 -0
- package/src/bongos/pool.js +55 -0
- package/src/bongos/repo-info.js +91 -0
- package/src/bongos/route-rank-check.js +420 -0
- package/src/bongos/routes/CLAUDE.md +43 -0
- package/src/bongos/routes/_helpers.js +369 -0
- package/src/bongos/routes/audit-log.js +59 -0
- package/src/bongos/routes/auth.js +755 -0
- package/src/bongos/routes/backup.js +104 -0
- package/src/bongos/routes/builders.js +526 -0
- package/src/bongos/routes/healthz.js +16 -0
- package/src/bongos/routes/instance.js +129 -0
- package/src/bongos/routes/live.js +125 -0
- package/src/bongos/routes/llm-cache.js +119 -0
- package/src/bongos/routes/me.js +380 -0
- package/src/bongos/routes/modules.js +131 -0
- package/src/bongos/routes/optimizer.js +54 -0
- package/src/bongos/routes/public.js +476 -0
- package/src/bongos/routes/security.js +207 -0
- package/src/bongos/routes.js +166 -0
- package/src/bongos/secret-box.js +177 -0
- package/src/bongos/sensitive-surfaces.js +30 -0
- package/src/bongos/serve-internal.js +889 -0
- package/src/bongos/uptime-poller.js +90 -0
- package/src/bongos-downloads.js +70 -0
- package/src/branding.js +182 -0
- package/src/build-info.js +77 -0
- package/src/devbox-downloads.js +67 -0
- package/src/instance-config.js +200 -0
- package/src/module-api.js +366 -0
- package/src/module-loader/loader.js +268 -0
- package/src/module-loader/manifest-schema.js +140 -0
- package/src/module-loader/provenance.js +28 -0
- package/src/module-loader/semver.js +100 -0
- package/src/module-seams.js +291 -0
- package/src/modules.js +254 -0
- package/src/platform-server.js +135 -0
- package/src/ui/adapters/claude-design/index.js +333 -0
- package/src/ui/adapters/figma/index.js +328 -0
- package/tests/abandon_task.mjs +138 -0
- package/tests/achievements_reconcile.mjs +167 -0
- package/tests/adopt_detect.mjs +141 -0
- package/tests/adopt_import.mjs +132 -0
- package/tests/adopt_preflight.mjs +105 -0
- package/tests/anti_grid.mjs +89 -0
- package/tests/api_client.mjs +231 -0
- package/tests/api_docs.mjs +283 -0
- package/tests/api_error_envelope_buildcheck.mjs +56 -0
- package/tests/api_error_envelope_middleware.mjs +99 -0
- package/tests/api_error_registry.mjs +108 -0
- package/tests/api_pagination_contract.mjs +51 -0
- package/tests/api_path_404.mjs +96 -0
- package/tests/app_pair.mjs +168 -0
- package/tests/architect.mjs +140 -0
- package/tests/art_key.mjs +121 -0
- package/tests/art_stage.mjs +121 -0
- package/tests/asset_version.mjs +94 -0
- package/tests/atlas.mjs +69 -0
- package/tests/audit_deps.mjs +74 -0
- package/tests/audit_middleware.mjs +385 -0
- package/tests/auth_admission_gate.mjs +164 -0
- package/tests/auth_anthropic_identity.mjs +95 -0
- package/tests/auth_duplicate_cookie.mjs +56 -0
- package/tests/auth_error_brand.mjs +77 -0
- package/tests/auth_flow_slice1.mjs +223 -0
- package/tests/auth_inactive_builder.mjs +94 -0
- package/tests/auth_page_gate.mjs +92 -0
- package/tests/auth_session_ttl.mjs +155 -0
- package/tests/autonomous_fit_protected_paths.mjs +115 -0
- package/tests/autonomy_gate.mjs +85 -0
- package/tests/autotile_variants.mjs +256 -0
- package/tests/autotile_xverify.mjs +133 -0
- package/tests/backfill_sessions.mjs +101 -0
- package/tests/backfill_task_rewards.mjs +152 -0
- package/tests/backup_cli.mjs +104 -0
- package/tests/bfg.mjs +327 -0
- package/tests/bfg_write.mjs +423 -0
- package/tests/bongos_box_connect.mjs +89 -0
- package/tests/bongos_dispatch.mjs +74 -0
- package/tests/bongos_downloads.mjs +118 -0
- package/tests/bongos_login.mjs +34 -0
- package/tests/box_access.mjs +186 -0
- package/tests/box_auth_check.mjs +114 -0
- package/tests/box_code_staleness.mjs +116 -0
- package/tests/box_connect_e2e.mjs +196 -0
- package/tests/box_cost.mjs +70 -0
- package/tests/box_dns_repoint.mjs +151 -0
- package/tests/box_host_keys.mjs +102 -0
- package/tests/box_onboard.mjs +317 -0
- package/tests/box_scope_session.mjs +115 -0
- package/tests/box_ship_permissions.mjs +71 -0
- package/tests/box_terminal_ssrf.mjs +90 -0
- package/tests/boxes.mjs +1255 -0
- package/tests/branding.mjs +88 -0
- package/tests/bug_attachments.mjs +189 -0
- package/tests/build_info.mjs +88 -0
- package/tests/builder_needs.mjs +99 -0
- package/tests/cap_newcomer_tasks.mjs +114 -0
- package/tests/cascade-dispatch.mjs +95 -0
- package/tests/cf_tunnel.mjs +459 -0
- package/tests/claim_recall.mjs +150 -0
- package/tests/claims_bind_session.mjs +47 -0
- package/tests/claude_materialize.mjs +148 -0
- package/tests/cli_box_scope.mjs +52 -0
- package/tests/cli_lib_formatters.mjs +87 -0
- package/tests/cli_token_reissue.mjs +147 -0
- package/tests/client_bundle_route.mjs +47 -0
- package/tests/cloud_bongos_pack.mjs +85 -0
- package/tests/conductor.mjs +496 -0
- package/tests/confirm_attribution.mjs +156 -0
- package/tests/conflict_resolve.mjs +462 -0
- package/tests/context_pack.mjs +240 -0
- package/tests/cost.mjs +94 -0
- package/tests/cost_audit.mjs +122 -0
- package/tests/cost_budget_status.mjs +78 -0
- package/tests/cost_reconcile.mjs +102 -0
- package/tests/cost_summary_shape.mjs +94 -0
- package/tests/credit_grant.mjs +376 -0
- package/tests/criterion_progress.mjs +220 -0
- package/tests/criterion_proposal.mjs +109 -0
- package/tests/criterion_ref_parse.mjs +53 -0
- package/tests/currency_label.mjs +119 -0
- package/tests/day_cycle.mjs +197 -0
- package/tests/dependencies_migration.mjs +77 -0
- package/tests/dependencies_polymorphic.mjs +212 -0
- package/tests/deploy_instance.mjs +78 -0
- package/tests/devbox_downloads.mjs +122 -0
- package/tests/diff_derived_signals.mjs +115 -0
- package/tests/discord_approvals.mjs +174 -0
- package/tests/discord_autojoin.mjs +158 -0
- package/tests/discord_bot.mjs +94 -0
- package/tests/discord_bugs.mjs +297 -0
- package/tests/discord_channels.mjs +337 -0
- package/tests/discord_foundation.mjs +76 -0
- package/tests/discord_inbound.mjs +190 -0
- package/tests/discord_message_buffer.mjs +87 -0
- package/tests/discord_oauth.mjs +55 -0
- package/tests/discord_reaction.mjs +170 -0
- package/tests/discord_role_sync.mjs +151 -0
- package/tests/display_name.mjs +123 -0
- package/tests/dns_preflight.mjs +74 -0
- package/tests/event_sound_prefs.mjs +194 -0
- package/tests/eviction_policy.mjs +279 -0
- package/tests/figma_adapter.mjs +199 -0
- package/tests/file_map.mjs +91 -0
- package/tests/first_admin_bootstrap.mjs +40 -0
- package/tests/fitness.mjs +435 -0
- package/tests/fitness_two_root.mjs +104 -0
- package/tests/fixtures/session-506-digest.json +34 -0
- package/tests/gate_approvals.mjs +451 -0
- package/tests/gate_review.mjs +152 -0
- package/tests/git_merge_regen.mjs +151 -0
- package/tests/github_push_ancestry.mjs +119 -0
- package/tests/github_push_land_proof.mjs +127 -0
- package/tests/github_push_merge_driver.mjs +175 -0
- package/tests/goal_abuse_matrix.mjs +187 -0
- package/tests/goal_achievement.mjs +146 -0
- package/tests/goal_conflicts.mjs +305 -0
- package/tests/goal_dependencies_read.mjs +73 -0
- package/tests/goal_member_roles.mjs +420 -0
- package/tests/goal_membership_requests.mjs +332 -0
- package/tests/goal_routes.mjs +203 -0
- package/tests/goal_scope_check.mjs +167 -0
- package/tests/goal_tier.mjs +312 -0
- package/tests/goal_wall_proof.mjs +112 -0
- package/tests/grade_attempts.mjs +73 -0
- package/tests/grade_attribution.mjs +117 -0
- package/tests/grade_diff_hash.mjs +191 -0
- package/tests/grade_server_authoritative.mjs +305 -0
- package/tests/grade_unavailable_display.mjs +66 -0
- package/tests/grader.mjs +1960 -0
- package/tests/grader_bypass.mjs +57 -0
- package/tests/grader_panel.mjs +252 -0
- package/tests/grader_prompt_fencing.mjs +192 -0
- package/tests/helpers.mjs +52 -0
- package/tests/hierarchy-config.mjs +81 -0
- package/tests/init.mjs +463 -0
- package/tests/instance_config.mjs +76 -0
- package/tests/instance_manifest.mjs +110 -0
- package/tests/interaction_prefs.mjs +72 -0
- package/tests/key-card.mjs +110 -0
- package/tests/key-status.mjs +45 -0
- package/tests/land_watch.mjs +115 -0
- package/tests/lifecycle-card.mjs +145 -0
- package/tests/lifecycle_breakdown_view.mjs +236 -0
- package/tests/linkify_refs.mjs +264 -0
- package/tests/live_channel.mjs +128 -0
- package/tests/live_sse.mjs +122 -0
- package/tests/llm-cache-route.mjs +110 -0
- package/tests/llm-cache.mjs +140 -0
- package/tests/llm-pricing.mjs +152 -0
- package/tests/local_preview.mjs +136 -0
- package/tests/main_audit.mjs +137 -0
- package/tests/memory_isolation.mjs +431 -0
- package/tests/memory_map.mjs +107 -0
- package/tests/memory_pull.mjs +429 -0
- package/tests/merge_lease.mjs +100 -0
- package/tests/merge_lock.mjs +312 -0
- package/tests/metrics.mjs +147 -0
- package/tests/migration_allocation.mjs +146 -0
- package/tests/migration_namespace.mjs +185 -0
- package/tests/migrations_fresh_replay_guard.mjs +38 -0
- package/tests/mirror_lineage_fulltree.mjs +45 -0
- package/tests/mirror_lineage_proof.mjs +72 -0
- package/tests/mirror_redact.mjs +193 -0
- package/tests/model_alloc_prefs.mjs +63 -0
- package/tests/module-scope-map.mjs +88 -0
- package/tests/module_api.mjs +110 -0
- package/tests/module_cli.mjs +292 -0
- package/tests/module_contributions.mjs +148 -0
- package/tests/module_loader.mjs +286 -0
- package/tests/module_manifest.mjs +194 -0
- package/tests/module_owned_tests.mjs +105 -0
- package/tests/module_provenance.mjs +34 -0
- package/tests/module_route_rank.mjs +147 -0
- package/tests/module_seams.mjs +68 -0
- package/tests/modules.mjs +156 -0
- package/tests/modules_route.mjs +38 -0
- package/tests/newcomer_floor.mjs +17 -0
- package/tests/newcomer_restock.mjs +80 -0
- package/tests/next_number.mjs +154 -0
- package/tests/oauth_secret.mjs +60 -0
- package/tests/onboard.mjs +70 -0
- package/tests/onboarding_gate.mjs +267 -0
- package/tests/onboarding_observability.mjs +344 -0
- package/tests/onboarding_route_signals.mjs +175 -0
- package/tests/onboarding_state.mjs +346 -0
- package/tests/one_active_claim_per_session.mjs +111 -0
- package/tests/orphaned_claim_ship.mjs +135 -0
- package/tests/override_attribution.mjs +142 -0
- package/tests/override_request_ownership.mjs +235 -0
- package/tests/package_core.mjs +435 -0
- package/tests/parallel-load.mjs +402 -0
- package/tests/path_match.mjs +62 -0
- package/tests/permission_path.mjs +151 -0
- package/tests/platform_boot.mjs +167 -0
- package/tests/pre_compact.mjs +60 -0
- package/tests/preview_server.mjs +127 -0
- package/tests/profile_route.mjs +197 -0
- package/tests/provision.mjs +805 -0
- package/tests/provisioning_github_app_routes.mjs +98 -0
- package/tests/public_mirror_export.mjs +124 -0
- package/tests/public_task_resolver.mjs +112 -0
- package/tests/publish_branch_route.mjs +422 -0
- package/tests/publish_manifest.mjs +184 -0
- package/tests/publish_reconciler.mjs +728 -0
- package/tests/rank_gate.mjs +463 -0
- package/tests/rate_limit_public.mjs +217 -0
- package/tests/read_session_export.mjs +89 -0
- package/tests/recall_cli.mjs +82 -0
- package/tests/recall_hints.mjs +119 -0
- package/tests/recent_shipped_window.mjs +80 -0
- package/tests/regrade_eligibility.mjs +202 -0
- package/tests/render_prefs.mjs +122 -0
- package/tests/repo_map.mjs +92 -0
- package/tests/reward_gate.mjs +284 -0
- package/tests/route_rank_check.mjs +243 -0
- package/tests/route_validation.mjs +490 -0
- package/tests/routine_timers.mjs +72 -0
- package/tests/rubric_fixtures.mjs +140 -0
- package/tests/run_routine.mjs +69 -0
- package/tests/sandbox_stage.mjs +582 -0
- package/tests/scrubber_corpus.mjs +257 -0
- package/tests/search_chunker.mjs +209 -0
- package/tests/search_ingest.mjs +96 -0
- package/tests/search_ingest_db.mjs +88 -0
- package/tests/search_isolation.mjs +204 -0
- package/tests/search_route.mjs +95 -0
- package/tests/secret_box.mjs +189 -0
- package/tests/security_docs.mjs +186 -0
- package/tests/security_route.mjs +108 -0
- package/tests/served_paths_shipped.mjs +118 -0
- package/tests/session-cards.mjs +142 -0
- package/tests/session_506_regression.mjs +69 -0
- package/tests/session_caps.mjs +238 -0
- package/tests/session_cost.mjs +133 -0
- package/tests/session_digest.mjs +73 -0
- package/tests/session_eval.mjs +386 -0
- package/tests/session_index.mjs +105 -0
- package/tests/session_records.mjs +369 -0
- package/tests/session_search.mjs +78 -0
- package/tests/session_start_freshness.mjs +123 -0
- package/tests/setup_smoke.mjs +154 -0
- package/tests/ship_autolinkify.mjs +60 -0
- package/tests/ship_automerge_injection.mjs +174 -0
- package/tests/ship_broadcast_routing.mjs +125 -0
- package/tests/ship_broadcast_server.mjs +175 -0
- package/tests/ship_card.mjs +280 -0
- package/tests/ship_ci_deploy.mjs +374 -0
- package/tests/ship_preflight.mjs +368 -0
- package/tests/ship_premerge.mjs +75 -0
- package/tests/ship_resume.mjs +129 -0
- package/tests/ship_upload_skip.mjs +89 -0
- package/tests/ship_zero_commit.mjs +60 -0
- package/tests/single_host_hall.mjs +98 -0
- package/tests/skill_prefs.mjs +150 -0
- package/tests/smoke_preflight.mjs +66 -0
- package/tests/snapshot_picker.mjs +233 -0
- package/tests/sound_prefs.mjs +198 -0
- package/tests/sprite_facing.mjs +35 -0
- package/tests/status-probe.mjs +89 -0
- package/tests/status_backfill.mjs +94 -0
- package/tests/stop_refcheck.mjs +127 -0
- package/tests/streak.mjs +175 -0
- package/tests/subdomain_auth.mjs +58 -0
- package/tests/task_classifier_vocab.mjs +41 -0
- package/tests/task_create_idempotency.mjs +96 -0
- package/tests/task_goal_link.mjs +93 -0
- package/tests/task_ownership_gate.mjs +125 -0
- package/tests/terrain_picker.mjs +298 -0
- package/tests/touches_overlap.mjs +75 -0
- package/tests/triage_development.mjs +140 -0
- package/tests/turn_in_place.mjs +280 -0
- package/tests/upgrade.mjs +357 -0
- package/tests/verify_task_guard.mjs +64 -0
- package/tests/version_close.mjs +76 -0
- package/tests/versions_route.mjs +93 -0
- package/tests/walkability.mjs +188 -0
- package/tests/wandering_prefs.mjs +176 -0
- package/tests/worktree_disambiguation.mjs +105 -0
- package/tests/worktree_guard.mjs +90 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/build-bongos.js — compile the standalone `bongos` CLI binaries
|
|
3
|
+
// (GDS-V4 · V4.R81 · task 1248). CI (.github/workflows/build-bongos-cli.yml) runs
|
|
4
|
+
// this; a maintainer can run it locally too.
|
|
5
|
+
//
|
|
6
|
+
// Uses `bun build --compile`, which CROSS-compiles every target from a single
|
|
7
|
+
// host (mac arm64/x64, linux x64/arm64, windows x64) — no per-OS runner matrix.
|
|
8
|
+
// The binary is fully self-contained: no Node, no repo needed at runtime. The
|
|
9
|
+
// on-ramp verbs (login/box/shell/code/init/reauth) are bundled + dispatched
|
|
10
|
+
// in-process by bin/bongos.js (its COMPILED branch); work verbs print how to get
|
|
11
|
+
// a real environment.
|
|
12
|
+
//
|
|
13
|
+
// node scripts/gds/build-bongos.js # all targets → dist/
|
|
14
|
+
// node scripts/gds/build-bongos.js --target mac-arm64
|
|
15
|
+
// node scripts/gds/build-bongos.js --outdir /tmp/out
|
|
16
|
+
//
|
|
17
|
+
// Output filenames match config/bongos-cli.json's `assets` exactly (so the
|
|
18
|
+
// /downloads/bongos redirects resolve after `gh release create`). Version comes
|
|
19
|
+
// from that same config — the single source of truth for a release.
|
|
20
|
+
|
|
21
|
+
'use strict';
|
|
22
|
+
|
|
23
|
+
const fs = require('node:fs');
|
|
24
|
+
const path = require('node:path');
|
|
25
|
+
const { spawnSync } = require('node:child_process');
|
|
26
|
+
const { arg } = require('./cli-lib');
|
|
27
|
+
|
|
28
|
+
const REPO_ROOT = path.join(__dirname, '..', '..');
|
|
29
|
+
const ENTRY = path.join(REPO_ROOT, 'bin', 'bongos.js');
|
|
30
|
+
const cfg = require(path.join(REPO_ROOT, 'config', 'bongos-cli.json'));
|
|
31
|
+
const VERSION = cfg.version;
|
|
32
|
+
|
|
33
|
+
// target key (matches config assets) → { bunTarget, asset filename }
|
|
34
|
+
const TARGETS = {
|
|
35
|
+
'mac-arm64': { bun: 'bun-darwin-arm64', file: cfg.assets['mac-arm64'] },
|
|
36
|
+
'mac-x64': { bun: 'bun-darwin-x64', file: cfg.assets['mac-x64'] },
|
|
37
|
+
'linux-x64': { bun: 'bun-linux-x64', file: cfg.assets['linux-x64'] },
|
|
38
|
+
'linux-arm64': { bun: 'bun-linux-arm64', file: cfg.assets['linux-arm64'] },
|
|
39
|
+
'win-x64': { bun: 'bun-windows-x64', file: cfg.assets['win-x64'] },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function bunPresent() {
|
|
43
|
+
const r = spawnSync('bun', ['--version'], { encoding: 'utf8', shell: process.platform === 'win32' });
|
|
44
|
+
return !!r && !r.error && r.status === 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function build(one, outDir) {
|
|
48
|
+
const t = TARGETS[one];
|
|
49
|
+
if (!t) throw new Error(`unknown target "${one}" (known: ${Object.keys(TARGETS).join(', ')})`);
|
|
50
|
+
if (!t.file) throw new Error(`config/bongos-cli.json has no asset for target "${one}"`);
|
|
51
|
+
const outfile = path.join(outDir, t.file);
|
|
52
|
+
console.log(` building ${one} → ${path.relative(REPO_ROOT, outfile)} (${t.bun})`);
|
|
53
|
+
const r = spawnSync(
|
|
54
|
+
'bun',
|
|
55
|
+
['build', '--compile', `--target=${t.bun}`, ENTRY, '--outfile', outfile],
|
|
56
|
+
{ stdio: 'inherit', cwd: REPO_ROOT, shell: process.platform === 'win32' }
|
|
57
|
+
);
|
|
58
|
+
if (!r || r.error || r.status !== 0) {
|
|
59
|
+
throw new Error(`bun build failed for ${one}${r && r.error ? `: ${r.error.message}` : ` (exit ${r ? r.status : '?'})`}`);
|
|
60
|
+
}
|
|
61
|
+
return outfile;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function main() {
|
|
65
|
+
if (!bunPresent()) {
|
|
66
|
+
console.error('✖ `bun` is required to compile the standalone binary but was not found.');
|
|
67
|
+
console.error(' Install it (https://bun.sh) — e.g. `curl -fsSL https://bun.sh/install | bash` —');
|
|
68
|
+
console.error(' or in CI use the oven-sh/setup-bun action. Then re-run.');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const outDir = arg('--outdir') || path.join(REPO_ROOT, 'dist');
|
|
72
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
73
|
+
const only = arg('--target');
|
|
74
|
+
const targets = only ? [only] : Object.keys(TARGETS);
|
|
75
|
+
|
|
76
|
+
console.log(`bongos build — version ${VERSION}, ${targets.length} target(s) → ${path.relative(REPO_ROOT, outDir) || '.'}`);
|
|
77
|
+
const built = [];
|
|
78
|
+
for (const t of targets) built.push(build(t, outDir));
|
|
79
|
+
|
|
80
|
+
console.log(`\n✓ Built ${built.length} binary(ies):`);
|
|
81
|
+
for (const f of built) {
|
|
82
|
+
let size = '';
|
|
83
|
+
try { size = ` (${(fs.statSync(f).size / 1e6).toFixed(1)} MB)`; } catch { /* ignore */ }
|
|
84
|
+
console.log(` ${path.relative(REPO_ROOT, f)}${size}`);
|
|
85
|
+
}
|
|
86
|
+
console.log('\nNext: publish these as assets on a `v' + VERSION + '` release of the public releases repo');
|
|
87
|
+
console.log('(config/bongos-cli.json → releases_repo). See docs/recipes/bongos-cli-release.md.');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (require.main === module) {
|
|
91
|
+
try { main(); } catch (e) { console.error(`✖ ${e.message}`); process.exit(1); }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { TARGETS, VERSION };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Capture an idea into idea_inbox (the structured replacement for
|
|
3
|
+
// generative-ideas.md).
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// node scripts/gds/capture.js "title" \
|
|
7
|
+
// [--kind feature] \
|
|
8
|
+
// [--body-file path] \
|
|
9
|
+
// [--version V1|PMS-V2|GDS-V3] \
|
|
10
|
+
// [--priority N]
|
|
11
|
+
//
|
|
12
|
+
// Defaults:
|
|
13
|
+
// --kind → server auto-classifies from title+body (keyword heuristics
|
|
14
|
+
// today; replaced by the real classifier when task B1 ships)
|
|
15
|
+
// --version → most recent version with status='building' (queried from
|
|
16
|
+
// /api/gds/versions); leave null if there isn't one
|
|
17
|
+
// --priority → null (set later at triage time)
|
|
18
|
+
//
|
|
19
|
+
// Exit codes:
|
|
20
|
+
// 0 captured
|
|
21
|
+
// 1 api / network error
|
|
22
|
+
// 2 bad invocation
|
|
23
|
+
//
|
|
24
|
+
// Acceptance examples (from task #34 spec):
|
|
25
|
+
// $ node scripts/gds/capture.js "we should add a 'last 24 hours' filter to the public dashboard"
|
|
26
|
+
// 📥 Captured idea #12: kind=feature (auto), version=PMS-V2, priority=null
|
|
27
|
+
// Inbox now: 8 open
|
|
28
|
+
|
|
29
|
+
const fs = require('node:fs/promises');
|
|
30
|
+
const { cliClient, requireSession, arg } = require('./cli-lib');
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async function resolveDefaultVersion() {
|
|
34
|
+
const api = await cliClient();
|
|
35
|
+
const r = await api.versions.getVersions();
|
|
36
|
+
if (!r.ok) return null;
|
|
37
|
+
const versions = r.data?.versions ?? [];
|
|
38
|
+
// Most recent building version. Fall back to any building version if
|
|
39
|
+
// started_at is null on all of them.
|
|
40
|
+
const building = versions.filter((v) => v.status === 'building');
|
|
41
|
+
if (building.length === 0) return null;
|
|
42
|
+
building.sort((a, b) => {
|
|
43
|
+
const ta = a.started_at ? new Date(a.started_at).getTime() : 0;
|
|
44
|
+
const tb = b.started_at ? new Date(b.started_at).getTime() : 0;
|
|
45
|
+
return tb - ta;
|
|
46
|
+
});
|
|
47
|
+
return building[0].id;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function main() {
|
|
51
|
+
await requireSession();
|
|
52
|
+
const args = process.argv.slice(2);
|
|
53
|
+
const title = args[0];
|
|
54
|
+
if (!title || title.startsWith('--')) {
|
|
55
|
+
console.error('usage: node scripts/gds/capture.js "title" [--kind feature] [--body-file path] [--version V1|PMS-V2] [--priority N]');
|
|
56
|
+
process.exit(2);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const kindFromArg = arg('--kind', args);
|
|
60
|
+
const bodyFile = arg('--body-file', args);
|
|
61
|
+
const versionFromArg = arg('--version', args);
|
|
62
|
+
const priorityStr = arg('--priority', args);
|
|
63
|
+
|
|
64
|
+
let bodyMd = '';
|
|
65
|
+
if (bodyFile) {
|
|
66
|
+
try {
|
|
67
|
+
bodyMd = await fs.readFile(bodyFile, 'utf8');
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(`failed to read --body-file: ${err.message}`);
|
|
70
|
+
process.exit(2);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let priority = null;
|
|
75
|
+
if (priorityStr != null) {
|
|
76
|
+
const p = Number(priorityStr);
|
|
77
|
+
if (!Number.isInteger(p) || p < 1 || p > 5) {
|
|
78
|
+
console.error(`--priority must be an integer 1..5 (got ${priorityStr})`);
|
|
79
|
+
process.exit(2);
|
|
80
|
+
}
|
|
81
|
+
priority = p;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const version = versionFromArg || (await resolveDefaultVersion());
|
|
85
|
+
|
|
86
|
+
const payload = {
|
|
87
|
+
title,
|
|
88
|
+
body_md: bodyMd,
|
|
89
|
+
suggested_version: version,
|
|
90
|
+
suggested_priority: priority,
|
|
91
|
+
};
|
|
92
|
+
if (kindFromArg) payload.kind = kindFromArg;
|
|
93
|
+
|
|
94
|
+
const api = await cliClient();
|
|
95
|
+
const r = await api.inbox.postInbox({ body: payload });
|
|
96
|
+
if (!r.ok) {
|
|
97
|
+
console.error(`capture failed (${r.status}):`, r.data);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const { idea, open_count, kind_auto } = r.data;
|
|
102
|
+
const kindLabel = kind_auto ? `${idea.kind} (auto)` : idea.kind;
|
|
103
|
+
const versionLabel = idea.suggested_version || 'none';
|
|
104
|
+
const priorityLabel = idea.suggested_priority == null ? 'null' : `P${idea.suggested_priority}`;
|
|
105
|
+
|
|
106
|
+
console.log(
|
|
107
|
+
`Captured idea #${idea.id}: kind=${kindLabel}, version=${versionLabel}, priority=${priorityLabel}`
|
|
108
|
+
);
|
|
109
|
+
console.log(`Inbox now: ${open_count} open`);
|
|
110
|
+
|
|
111
|
+
// Migration detection lives only on the server now (POST /api/gds/tasks sets
|
|
112
|
+
// tasks.needs_migration from the title/description on create — migration 081,
|
|
113
|
+
// task 876). Ideas carry no touches[] and aren't tasks, so the old CLI-side
|
|
114
|
+
// "keep 'migrations/' in touches[]" hint was removed with the sentinel it
|
|
115
|
+
// referred to; promotion to a task re-runs the detection automatically.
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (require.main === module) {
|
|
119
|
+
main().catch((err) => {
|
|
120
|
+
console.error('fatal:', err);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
// scripts/gds/cf-tunnel.js — a thin Cloudflare API client for the box terminal's
|
|
2
|
+
// NAMED tunnel (#771, ADR 0038 Part B). A control-plane (operator-CLI) network
|
|
3
|
+
// client; moved here from modules/dev-box/ alongside do-api.js so the control
|
|
4
|
+
// plane owns the network clients and the shared http-api-client (task #1943).
|
|
5
|
+
//
|
|
6
|
+
// The control-plane half of the "named tunnel" production upgrade. #760 shipped
|
|
7
|
+
// the BOX-side cloudflared-run.sh that already runs a named tunnel when
|
|
8
|
+
// BOX_TUNNEL_TOKEN + BOX_TERMINAL_HOSTNAME are present in /etc/otb/box.env. This
|
|
9
|
+
// module is how scripts/gds/box.js MAKES those exist: it creates (or reuses) a
|
|
10
|
+
// remotely-managed Cloudflare Tunnel per builder, points its ingress at the box's
|
|
11
|
+
// localhost ttyd (127.0.0.1:7681), routes a stable DNS CNAME
|
|
12
|
+
// (term-<login>.amazonprimea.com → <tunnel-id>.cfargotunnel.com), and hands
|
|
13
|
+
// back the connector token to bake into the box. Teardown deletes the tunnel +
|
|
14
|
+
// the DNS record.
|
|
15
|
+
//
|
|
16
|
+
// Design mirrors src/bongos/do-api.js exactly so the box subsystem has ONE shape for
|
|
17
|
+
// every external API:
|
|
18
|
+
// - Injectable transport (`fetchImpl`) so tests assert request shape with a
|
|
19
|
+
// fake fetch and never touch the network.
|
|
20
|
+
// - `dryRun` mode (the CLI DEFAULT): NO request is sent; each method logs what
|
|
21
|
+
// it WOULD do and returns a synthetic `{ dryRun: true, ... }` so box.js's
|
|
22
|
+
// control flow runs end-to-end against a throwaway plan.
|
|
23
|
+
// - Live mode requires a token + accountId; the constructor throws clearly if
|
|
24
|
+
// asked to run live without them — it never silently no-ops a real call.
|
|
25
|
+
//
|
|
26
|
+
// SECURITY: the Cloudflare API token (Account:Cloudflare Tunnel:Edit +
|
|
27
|
+
// Zone:DNS:Edit) lives ONLY on the control plane (the prod droplet's box.env),
|
|
28
|
+
// exactly where DO_API_TOKEN lives — never on the internet-facing web tier. A
|
|
29
|
+
// web-tier compromise can never create or delete a tunnel. The per-builder
|
|
30
|
+
// connector token this returns is baked into the box's cloud-init (same exposure
|
|
31
|
+
// as the SSH keys already baked there) and only authorizes running THAT tunnel,
|
|
32
|
+
// whose only target is the basic-auth-protected localhost ttyd.
|
|
33
|
+
|
|
34
|
+
const { JsonHttpApi, makeApiError } = require('./http-api-client');
|
|
35
|
+
|
|
36
|
+
const CF_API_BASE = 'https://api.cloudflare.com/client/v4';
|
|
37
|
+
const CFARGO_SUFFIX = 'cfargotunnel.com';
|
|
38
|
+
const TTYD_SERVICE = 'http://127.0.0.1:7681';
|
|
39
|
+
// The box's own `node server.js` (ADR 0044). A SECOND ingress route on the same
|
|
40
|
+
// per-builder named tunnel exposes the live game preview at game-<login>.<apex>.
|
|
41
|
+
const GAME_SERVICE = 'http://127.0.0.1:3000';
|
|
42
|
+
|
|
43
|
+
// SECURITY (#919, security_reports SR#11): the apex gds_session cookie
|
|
44
|
+
// (Domain=.amazonprimea.com) is sent by the browser to every subdomain, including
|
|
45
|
+
// the box-fronting term-<login> (ttyd) and sandbox-<login> (game preview) hosts —
|
|
46
|
+
// so the builder's FULL hall bearer rides the tunnel onto the box, which is OUTSIDE
|
|
47
|
+
// the ADR 0016 trust boundary. We must NOT narrow the apex cookie (the #726 SSO
|
|
48
|
+
// across builders.amazonprimea.com needs it), so instead a zone Transform Rule
|
|
49
|
+
// removes the Cookie REQUEST header at the Cloudflare edge — before the request
|
|
50
|
+
// enters the tunnel — for exactly the box subdomains. ttyd uses basic-auth and the
|
|
51
|
+
// sandbox serves the game, so neither needs the cookie. Cloudflare permits REMOVE
|
|
52
|
+
// (not set/modify) of the Cookie request header via Transform Rules.
|
|
53
|
+
const COOKIE_STRIP_PHASE = 'http_request_late_transform';
|
|
54
|
+
const COOKIE_STRIP_RULE_DESC = 'otb-919 strip Cookie on box subdomains (term-*/sandbox-*) — SR#11';
|
|
55
|
+
// Zone-scoped ruleset ⇒ http.host is always within amazonprimea.com, so the prefix
|
|
56
|
+
// match precisely targets the per-builder box hosts and nothing else.
|
|
57
|
+
const COOKIE_STRIP_EXPRESSION = 'starts_with(http.host, "term-") or starts_with(http.host, "sandbox-")';
|
|
58
|
+
|
|
59
|
+
// #1065 — Cloudflare's DEFAULT 4h Browser Cache TTL rewrites the box origin's
|
|
60
|
+
// no-store on the sandbox hosts, serving multi-hour-stale game code. A zone Cache
|
|
61
|
+
// Rule scoped to sandbox-* bypasses the edge cache + respects the origin headers
|
|
62
|
+
// there, WITHOUT touching the zone-wide TTL prod (the apex) relies on. Like the
|
|
63
|
+
// cookie-strip rule, this needs the CF token to carry zone "Cache Rules" (Account
|
|
64
|
+
// Rulesets) edit scope; callers run it best-effort so a missing scope warns.
|
|
65
|
+
const CACHE_BYPASS_PHASE = 'http_request_cache_settings';
|
|
66
|
+
const CACHE_BYPASS_RULE_DESC = 'otb-1065 bypass cache on sandbox preview hosts (sandbox-*) — keep prod cached';
|
|
67
|
+
// Sandbox preview only. NOT term-* (ttyd, not cached) and NEVER the apex.
|
|
68
|
+
const CACHE_BYPASS_EXPRESSION = 'starts_with(http.host, "sandbox-")';
|
|
69
|
+
|
|
70
|
+
// FORCE IPv4 egress. The Cloudflare API token is IP-locked to the control-plane
|
|
71
|
+
// droplet's IPv4 (least privilege, mirroring box-dns-cloudflare.sh's `curl -4`).
|
|
72
|
+
// The droplet ALSO has IPv6 egress, and Node's fetch will happily dial Cloudflare
|
|
73
|
+
// over IPv6 — whose source address is NOT on the token's allow-list, so Cloudflare
|
|
74
|
+
// rejects it as an "Authentication error" (verified live under #771). undici's
|
|
75
|
+
// Agent with connect.family=4 pins IPv4. Memoized; degrades to undefined (default
|
|
76
|
+
// dispatcher) if undici can't be required, so a non-IP-locked token still works.
|
|
77
|
+
let _ipv4Dispatcher;
|
|
78
|
+
let _ipv4Tried = false;
|
|
79
|
+
function ipv4Dispatcher() {
|
|
80
|
+
if (_ipv4Tried) return _ipv4Dispatcher;
|
|
81
|
+
_ipv4Tried = true;
|
|
82
|
+
try {
|
|
83
|
+
// eslint-disable-next-line global-require
|
|
84
|
+
const { Agent } = require('undici');
|
|
85
|
+
_ipv4Dispatcher = new Agent({ connect: { family: 4 } });
|
|
86
|
+
} catch { _ipv4Dispatcher = undefined; }
|
|
87
|
+
return _ipv4Dispatcher;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const CfApiError = makeApiError('CfApiError', 'CF_API_ERROR');
|
|
91
|
+
|
|
92
|
+
// Deterministic per-builder names so teardown can find what provision created
|
|
93
|
+
// WITHOUT persisting an id in the DB (no migration): the tunnel name and the DNS
|
|
94
|
+
// hostname are both pure functions of the login.
|
|
95
|
+
function tunnelName(login) { return `otb-term-${login}`; }
|
|
96
|
+
function terminalHostname(login, zone) { return `term-${login}.${zone}`; }
|
|
97
|
+
// The live game preview host (ADR 0044) — the builder's "sandbox". One label
|
|
98
|
+
// under the apex (same zone as the terminal host) so free Universal SSL covers
|
|
99
|
+
// it — see the #771 lesson that forced an apex one-label host over `dev.*`.
|
|
100
|
+
function previewHostname(login, zone) { return `sandbox-${login}.${zone}`; }
|
|
101
|
+
|
|
102
|
+
class CfTunnelApi extends JsonHttpApi {
|
|
103
|
+
// opts: { token, accountId, dryRun=true, fetchImpl=globalThis.fetch, base, log }
|
|
104
|
+
constructor(opts = {}) {
|
|
105
|
+
super(opts, { base: CF_API_BASE, logTag: 'CF', ErrorClass: CfApiError });
|
|
106
|
+
this.accountId = opts.accountId || null;
|
|
107
|
+
// Pin IPv4 for the live token (see ipv4Dispatcher). Overridable/null-able for
|
|
108
|
+
// tests; a fake fetchImpl simply ignores the extra `dispatcher` option.
|
|
109
|
+
this.dispatcher = opts.dispatcher !== undefined ? opts.dispatcher : ipv4Dispatcher();
|
|
110
|
+
if (!this.dryRun) {
|
|
111
|
+
if (!this.token) {
|
|
112
|
+
throw new CfApiError(
|
|
113
|
+
'live Cloudflare call requested but no API token is set — ' +
|
|
114
|
+
'set CLOUDFLARE_API_TOKEN (Tunnel + DNS scope) or run without --apply (dry-run)'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (!this.accountId) {
|
|
118
|
+
throw new CfApiError('live Cloudflare tunnel call requested but CLOUDFLARE_ACCOUNT_ID is not set');
|
|
119
|
+
}
|
|
120
|
+
if (typeof this.fetchImpl !== 'function') {
|
|
121
|
+
throw new CfApiError('no fetch implementation available for live mode');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// CfTunnelApi pins the IPv4 dispatcher on every live request (its token is
|
|
127
|
+
// IP-locked, #771) and treats the Cloudflare {success:false} envelope as a
|
|
128
|
+
// failure, not just a non-2xx status. The dry-run/live skeleton itself (and the
|
|
129
|
+
// envelope's {result} passthrough) is inherited from JsonHttpApi.
|
|
130
|
+
requestInit() { return { dispatcher: this.dispatcher }; }
|
|
131
|
+
|
|
132
|
+
detectError(res, json) {
|
|
133
|
+
if (!res.ok || (json && json.success === false)) {
|
|
134
|
+
const errs = json && Array.isArray(json.errors) ? json.errors.map((e) => e.message || e.code).join('; ') : '';
|
|
135
|
+
return errs || `HTTP ${res.status}`;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ---- tunnels (account-scoped) ---------------------------------------------
|
|
141
|
+
|
|
142
|
+
// Find a non-deleted tunnel by exact name. Returns the tunnel object or null.
|
|
143
|
+
async findTunnelByName(name) {
|
|
144
|
+
const r = await this._req('GET', `/accounts/${this.accountId}/cfd_tunnel?name=${encodeURIComponent(name)}&is_deleted=false`, null, {
|
|
145
|
+
dryRunResult: { result: [] },
|
|
146
|
+
});
|
|
147
|
+
const list = (r && r.result) || [];
|
|
148
|
+
return list.find((tn) => tn.name === name) || null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Create a remotely-managed tunnel (config_src: 'cloudflare' so the ingress is
|
|
152
|
+
// set via the API, not a config file on the box). Returns the tunnel object.
|
|
153
|
+
async createTunnel(name) {
|
|
154
|
+
const r = await this._req('POST', `/accounts/${this.accountId}/cfd_tunnel`, { name, config_src: 'cloudflare' }, {
|
|
155
|
+
dryRunResult: { result: { id: `dryrun-tunnel-${name}`, name } },
|
|
156
|
+
});
|
|
157
|
+
return (r && r.result) || null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Find-or-create. Idempotent: re-provisioning a builder reuses their tunnel.
|
|
161
|
+
async ensureTunnel(name) {
|
|
162
|
+
const existing = await this.findTunnelByName(name);
|
|
163
|
+
if (existing) { this.log(`reusing tunnel ${existing.id} (${name})`); return { tunnel: existing, created: false }; }
|
|
164
|
+
const tunnel = await this.createTunnel(name);
|
|
165
|
+
this.log(`created tunnel ${tunnel && tunnel.id} (${name})`);
|
|
166
|
+
return { tunnel, created: true };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// The connector token (the BOX_TUNNEL_TOKEN the box runs cloudflared with).
|
|
170
|
+
async getTunnelToken(tunnelId) {
|
|
171
|
+
const r = await this._req('GET', `/accounts/${this.accountId}/cfd_tunnel/${tunnelId}/token`, null, {
|
|
172
|
+
dryRunResult: { result: `dryrun-token-${tunnelId}` },
|
|
173
|
+
});
|
|
174
|
+
return (r && r.result) || null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Point the tunnel's ingress at the box's localhost ttyd, with a 404 catch-all.
|
|
178
|
+
// `extraRoutes` ([{ hostname, service }, ...]) adds further hostname→service
|
|
179
|
+
// rules on the SAME connector — e.g. the ADR 0044 game preview at
|
|
180
|
+
// sandbox-<login>.<apex> → 127.0.0.1:3000 — inserted before the catch-all. A
|
|
181
|
+
// Cloudflare named tunnel routes by hostname, so each route needs its own
|
|
182
|
+
// proxied DNS CNAME (see ensureNamedTunnel).
|
|
183
|
+
async putConfiguration(tunnelId, { hostname, service = TTYD_SERVICE, extraRoutes = [] } = {}) {
|
|
184
|
+
const ingress = [{ hostname, service }, ...extraRoutes, { service: 'http_status:404' }];
|
|
185
|
+
const config = { ingress };
|
|
186
|
+
return this._req('PUT', `/accounts/${this.accountId}/cfd_tunnel/${tunnelId}/configurations`, { config }, {
|
|
187
|
+
dryRunResult: { result: { config } },
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Best-effort: drop any live connector connections so the tunnel can be deleted
|
|
192
|
+
// (CF refuses to delete a tunnel with active connections). The droplet is
|
|
193
|
+
// already gone by teardown time, so this is usually a no-op.
|
|
194
|
+
async cleanupConnections(tunnelId) {
|
|
195
|
+
return this._req('DELETE', `/accounts/${this.accountId}/cfd_tunnel/${tunnelId}/connections`, null, {
|
|
196
|
+
dryRunResult: { result: {} },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async deleteTunnel(tunnelId) {
|
|
201
|
+
return this._req('DELETE', `/accounts/${this.accountId}/cfd_tunnel/${tunnelId}`, null, {
|
|
202
|
+
dryRunResult: { result: { id: tunnelId } },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ---- DNS (zone-scoped) -----------------------------------------------------
|
|
207
|
+
|
|
208
|
+
async getZoneId(zone) {
|
|
209
|
+
const r = await this._req('GET', `/zones?name=${encodeURIComponent(zone)}`, null, {
|
|
210
|
+
dryRunResult: { result: [{ id: `dryrun-zone-${zone}` }] },
|
|
211
|
+
});
|
|
212
|
+
const z = ((r && r.result) || [])[0];
|
|
213
|
+
if (!z || !z.id) throw new CfApiError(`Cloudflare zone '${zone}' not found, or the token lacks access to it`);
|
|
214
|
+
return z.id;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async findDnsRecord(zoneId, name) {
|
|
218
|
+
const r = await this._req('GET', `/zones/${zoneId}/dns_records?type=CNAME&name=${encodeURIComponent(name)}`, null, {
|
|
219
|
+
dryRunResult: { result: [] },
|
|
220
|
+
});
|
|
221
|
+
const lower = name.toLowerCase();
|
|
222
|
+
return (((r && r.result) || []).find((rec) => rec.name.toLowerCase() === lower)) || null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Upsert the proxied CNAME that fronts the tunnel. proxied:true is required for
|
|
226
|
+
// a *.cfargotunnel.com target (the orange-cloud is what routes to the tunnel).
|
|
227
|
+
async upsertDnsRoute({ zoneId, name, tunnelId }) {
|
|
228
|
+
const body = { type: 'CNAME', name, content: `${tunnelId}.${CFARGO_SUFFIX}`, proxied: true, ttl: 1 };
|
|
229
|
+
const existing = await this.findDnsRecord(zoneId, name);
|
|
230
|
+
if (existing) {
|
|
231
|
+
return this._req('PUT', `/zones/${zoneId}/dns_records/${existing.id}`, body, {
|
|
232
|
+
dryRunResult: { result: { id: existing.id, ...body } },
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return this._req('POST', `/zones/${zoneId}/dns_records`, body, {
|
|
236
|
+
dryRunResult: { result: { id: `dryrun-dns-${name}`, ...body } },
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async deleteDnsRoute({ zoneId, name }) {
|
|
241
|
+
const existing = await this.findDnsRecord(zoneId, name);
|
|
242
|
+
if (!existing) return { result: null, missing: true };
|
|
243
|
+
return this._req('DELETE', `/zones/${zoneId}/dns_records/${existing.id}`, null, {
|
|
244
|
+
dryRunResult: { result: { id: existing.id } },
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ---- edge cookie strip (zone-scoped Transform Rule, #919 / SR#11) ----------
|
|
249
|
+
|
|
250
|
+
// Ensure the zone's request-header Transform Rule that REMOVES the Cookie header
|
|
251
|
+
// on the box subdomains (term-*/sandbox-*). Idempotent and NON-DESTRUCTIVE: it
|
|
252
|
+
// reads the phase entrypoint ruleset, preserves every OTHER transform rule, drops
|
|
253
|
+
// any prior copy of ours (matched by description), and PUTs the merged set. One
|
|
254
|
+
// wildcard-prefix rule covers every builder's box, so this only needs to land
|
|
255
|
+
// ONCE — but re-running on each provision self-heals a deleted rule. Requires the
|
|
256
|
+
// CF token to carry zone "Transform Rules" (Account Rulesets) edit scope; callers
|
|
257
|
+
// run it best-effort so a missing scope warns but never blocks box provisioning.
|
|
258
|
+
async ensureCookieStripRule({ zone }) {
|
|
259
|
+
const zoneId = await this.getZoneId(zone);
|
|
260
|
+
const phasePath = `/zones/${zoneId}/rulesets/phases/${COOKIE_STRIP_PHASE}/entrypoint`;
|
|
261
|
+
// Read the current entrypoint ruleset. A zone with no transform rules yet has
|
|
262
|
+
// no entrypoint (404) — fine, the PUT below creates it.
|
|
263
|
+
let existing = [];
|
|
264
|
+
try {
|
|
265
|
+
const got = await this._req('GET', phasePath, null, { dryRunResult: { result: { rules: [] } } });
|
|
266
|
+
const rules = got && got.result && got.result.rules;
|
|
267
|
+
existing = Array.isArray(rules) ? rules : [];
|
|
268
|
+
} catch (e) {
|
|
269
|
+
if (e.status && e.status !== 404) throw e;
|
|
270
|
+
}
|
|
271
|
+
const ourRule = {
|
|
272
|
+
action: 'rewrite',
|
|
273
|
+
action_parameters: { headers: { Cookie: { operation: 'remove' } } },
|
|
274
|
+
expression: COOKIE_STRIP_EXPRESSION,
|
|
275
|
+
description: COOKIE_STRIP_RULE_DESC,
|
|
276
|
+
enabled: true,
|
|
277
|
+
};
|
|
278
|
+
// Preserve other rules, dropping CF-managed read-only fields (id/version/
|
|
279
|
+
// last_updated) that a PUT rejects; keep a caller-set `ref` if present.
|
|
280
|
+
const preserved = existing
|
|
281
|
+
.filter((r) => r && r.description !== COOKIE_STRIP_RULE_DESC)
|
|
282
|
+
.map((r) => ({
|
|
283
|
+
action: r.action,
|
|
284
|
+
action_parameters: r.action_parameters,
|
|
285
|
+
expression: r.expression,
|
|
286
|
+
description: r.description,
|
|
287
|
+
enabled: r.enabled !== false,
|
|
288
|
+
...(r.ref ? { ref: r.ref } : {}),
|
|
289
|
+
}));
|
|
290
|
+
const rules = [...preserved, ourRule];
|
|
291
|
+
return this._req('PUT', phasePath, { rules }, { dryRunResult: { result: { rules } } });
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ---- edge cache bypass on the sandbox hosts (zone Cache Rule, #1065) --------
|
|
295
|
+
|
|
296
|
+
// Ensure the zone Cache Rule that BYPASSES Cloudflare caching for the sandbox
|
|
297
|
+
// preview hosts (sandbox-*), so the box origin's no-store (#1065 part 1) is
|
|
298
|
+
// honored and the 4h Browser Cache TTL stops serving stale game code. Idempotent
|
|
299
|
+
// + NON-DESTRUCTIVE (mirrors ensureCookieStripRule): read the cache-phase
|
|
300
|
+
// entrypoint ruleset, preserve every OTHER cache rule, drop any prior copy of
|
|
301
|
+
// ours by description, PUT the merged set. Scoped strictly to sandbox-* via the
|
|
302
|
+
// host expression so prod (the apex) caching is UNTOUCHED. Requires the CF token
|
|
303
|
+
// to carry zone "Cache Rules" (Account Rulesets) edit scope; callers run it
|
|
304
|
+
// best-effort so a missing scope warns but never blocks provisioning.
|
|
305
|
+
async ensureCacheBypassRule({ zone }) {
|
|
306
|
+
const zoneId = await this.getZoneId(zone);
|
|
307
|
+
const phasePath = `/zones/${zoneId}/rulesets/phases/${CACHE_BYPASS_PHASE}/entrypoint`;
|
|
308
|
+
let existing = [];
|
|
309
|
+
try {
|
|
310
|
+
const got = await this._req('GET', phasePath, null, { dryRunResult: { result: { rules: [] } } });
|
|
311
|
+
const rules = got && got.result && got.result.rules;
|
|
312
|
+
existing = Array.isArray(rules) ? rules : [];
|
|
313
|
+
} catch (e) {
|
|
314
|
+
if (e.status && e.status !== 404) throw e;
|
|
315
|
+
}
|
|
316
|
+
const ourRule = {
|
|
317
|
+
action: 'set_cache_settings',
|
|
318
|
+
action_parameters: {
|
|
319
|
+
cache: false, // do not cache on the edge
|
|
320
|
+
// Even if a future tweak re-enables caching, honor the box origin's
|
|
321
|
+
// no-store and never override its browser TTL.
|
|
322
|
+
browser_ttl: { mode: 'respect_origin' },
|
|
323
|
+
},
|
|
324
|
+
expression: CACHE_BYPASS_EXPRESSION,
|
|
325
|
+
description: CACHE_BYPASS_RULE_DESC,
|
|
326
|
+
enabled: true,
|
|
327
|
+
};
|
|
328
|
+
const preserved = existing
|
|
329
|
+
.filter((r) => r && r.description !== CACHE_BYPASS_RULE_DESC)
|
|
330
|
+
.map((r) => ({
|
|
331
|
+
action: r.action,
|
|
332
|
+
action_parameters: r.action_parameters,
|
|
333
|
+
expression: r.expression,
|
|
334
|
+
description: r.description,
|
|
335
|
+
enabled: r.enabled !== false,
|
|
336
|
+
...(r.ref ? { ref: r.ref } : {}),
|
|
337
|
+
}));
|
|
338
|
+
const rules = [...preserved, ourRule];
|
|
339
|
+
return this._req('PUT', phasePath, { rules }, { dryRunResult: { result: { rules } } });
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ---- high-level compose ----------------------------------------------------
|
|
343
|
+
|
|
344
|
+
// Create-or-reuse everything the box needs for a stable named tunnel and return
|
|
345
|
+
// the values to bake into /etc/otb/box.env. Idempotent end-to-end.
|
|
346
|
+
async ensureNamedTunnel({ login, zone, terminalZone }) {
|
|
347
|
+
const name = tunnelName(login);
|
|
348
|
+
const hostname = terminalHostname(login, terminalZone);
|
|
349
|
+
// The ADR 0044 live game preview rides the SAME tunnel as a second ingress
|
|
350
|
+
// route + its own proxied CNAME.
|
|
351
|
+
const previewHost = previewHostname(login, terminalZone);
|
|
352
|
+
const { tunnel, created } = await this.ensureTunnel(name);
|
|
353
|
+
const tunnelId = tunnel && tunnel.id;
|
|
354
|
+
await this.putConfiguration(tunnelId, {
|
|
355
|
+
hostname,
|
|
356
|
+
extraRoutes: [{ hostname: previewHost, service: GAME_SERVICE }],
|
|
357
|
+
});
|
|
358
|
+
const token = await this.getTunnelToken(tunnelId);
|
|
359
|
+
const zoneId = await this.getZoneId(zone);
|
|
360
|
+
await this.upsertDnsRoute({ zoneId, name: hostname, tunnelId });
|
|
361
|
+
await this.upsertDnsRoute({ zoneId, name: previewHost, tunnelId });
|
|
362
|
+
// SECURITY (#919 / SR#11): strip the apex cookie at the edge for the box
|
|
363
|
+
// subdomains. BEST-EFFORT — a CF token without Transform Rules scope must not
|
|
364
|
+
// block provisioning (the box still works; the rule is defense-in-depth). Warn
|
|
365
|
+
// loudly so the operator adds the scope or applies the rule once by hand.
|
|
366
|
+
try {
|
|
367
|
+
await this.ensureCookieStripRule({ zone });
|
|
368
|
+
} catch (e) {
|
|
369
|
+
this.log(`⚠ #919 cookie-strip Transform Rule NOT applied (${e.message}) — add zone "Transform Rules" scope to CLOUDFLARE_API_TOKEN or apply it once in the CF dashboard (ADR 0053)`);
|
|
370
|
+
}
|
|
371
|
+
// #1065: stop Cloudflare's 4h Browser Cache TTL from serving stale sandbox
|
|
372
|
+
// game code. BEST-EFFORT — a CF token without Cache-Rules scope must not block
|
|
373
|
+
// provisioning. Warn loudly so the operator adds the scope or applies the rule
|
|
374
|
+
// once by hand (operator blocker, like the cookie-strip rule).
|
|
375
|
+
try {
|
|
376
|
+
await this.ensureCacheBypassRule({ zone });
|
|
377
|
+
} catch (e) {
|
|
378
|
+
this.log(`⚠ #1065 sandbox cache-bypass Cache Rule NOT applied (${e.message}) — add zone "Cache Rules" (Account Rulesets) scope to CLOUDFLARE_API_TOKEN or add it once in the CF dashboard`);
|
|
379
|
+
}
|
|
380
|
+
return { tunnelId, token, hostname, previewHostname: previewHost, created };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Tear down the per-builder tunnel + its DNS route. Best-effort: each leg is
|
|
384
|
+
// independent so a missing tunnel still cleans the DNS and vice versa. Returns a
|
|
385
|
+
// summary the caller can log. Never throws (so deprovision always completes).
|
|
386
|
+
async teardownNamedTunnel({ login, zone, terminalZone }) {
|
|
387
|
+
const out = { tunnelDeleted: false, dnsDeleted: false, previewDnsDeleted: false, errors: [] };
|
|
388
|
+
const name = tunnelName(login);
|
|
389
|
+
const hostname = terminalHostname(login, terminalZone);
|
|
390
|
+
const previewHost = previewHostname(login, terminalZone);
|
|
391
|
+
try {
|
|
392
|
+
const zoneId = await this.getZoneId(zone);
|
|
393
|
+
const res = await this.deleteDnsRoute({ zoneId, name: hostname });
|
|
394
|
+
out.dnsDeleted = !(res && res.missing);
|
|
395
|
+
// The ADR 0044 preview CNAME shares the tunnel; drop it too (best-effort,
|
|
396
|
+
// independent leg so a missing record never blocks teardown).
|
|
397
|
+
try {
|
|
398
|
+
const pres = await this.deleteDnsRoute({ zoneId, name: previewHost });
|
|
399
|
+
out.previewDnsDeleted = !(pres && pres.missing);
|
|
400
|
+
} catch (e) { out.errors.push(`preview-dns: ${e.message}`); }
|
|
401
|
+
} catch (e) { out.errors.push(`dns: ${e.message}`); }
|
|
402
|
+
try {
|
|
403
|
+
const tunnel = await this.findTunnelByName(name);
|
|
404
|
+
if (tunnel && tunnel.id) {
|
|
405
|
+
await this.cleanupConnections(tunnel.id).catch(() => {});
|
|
406
|
+
await this.deleteTunnel(tunnel.id);
|
|
407
|
+
out.tunnelDeleted = true;
|
|
408
|
+
}
|
|
409
|
+
} catch (e) { out.errors.push(`tunnel: ${e.message}`); }
|
|
410
|
+
return out;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
module.exports = {
|
|
415
|
+
CfTunnelApi, CfApiError, CF_API_BASE, CFARGO_SUFFIX, TTYD_SERVICE, GAME_SERVICE,
|
|
416
|
+
tunnelName, terminalHostname, previewHostname,
|
|
417
|
+
// #1065: the sandbox edge cache-bypass rule constants, exported for the test.
|
|
418
|
+
CACHE_BYPASS_PHASE, CACHE_BYPASS_RULE_DESC, CACHE_BYPASS_EXPRESSION,
|
|
419
|
+
};
|