@bongos/core 1.19.714 → 1.19.724
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 +488 -413
- package/.claude/skills/backlog-review/SKILL.md +3 -3
- package/.claude/skills/blocker-review/SKILL.md +1 -1
- package/.claude/skills/blocker-solve/SKILL.md +2 -2
- package/.claude/skills/builder-reauth/SKILL.md +1 -1
- package/.claude/skills/builder-redteam/SKILL.md +1 -1
- package/.claude/skills/builder-ship/SKILL.md +1 -1
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/design/SKILL.md +2 -2
- package/.claude/skills/feedback/SKILL.md +1 -1
- package/.claude/skills/goal-create/SKILL.md +1 -1
- package/.claude/skills/goal-review/SKILL.md +2 -2
- package/.claude/skills/idea-triage/SKILL.md +5 -5
- package/.claude/skills/merge-mode/SKILL.md +4 -4
- package/.claude/skills/new-project/SKILL.md +17 -17
- package/.claude/skills/planning-session/SKILL.md +11 -11
- package/.claude/skills/recall/SKILL.md +2 -2
- package/.claude/skills/strand-fix/SKILL.md +1 -1
- package/.devcontainer/README.md +2 -2
- package/CONTRIBUTING.md +2 -2
- package/GOVERNANCE.md +4 -4
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +5 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/config/branding.neutral.json +4 -2
- package/docs/adr/0001-stack-choice-single-vps.md +2 -2
- package/docs/adr/0002-digitalocean-over-hetzner.md +1 -1
- package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
- package/docs/adr/0009-autotile-architecture.md +1 -1
- package/docs/adr/0011-terrain-id-rendering-model.md +3 -3
- package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +1 -1
- package/docs/adr/0014-families-canonical-over-vocabulary.md +1 -1
- package/docs/adr/0015-task-dependencies-and-auto-promotion.md +1 -1
- package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +1 -1
- package/docs/adr/0018-three-rank-model-goes-live.md +3 -3
- package/docs/adr/0020-security-model-public-stub.md +9 -9
- package/docs/adr/0021-per-builder-skill-model-preferences.md +2 -2
- package/docs/adr/0022-secrets-policy.md +5 -5
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +3 -3
- package/docs/adr/0024-multi-agent-system-architecture.md +10 -10
- package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +1 -1
- package/docs/adr/0025-structured-criterion-task-link.md +1 -1
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +13 -13
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +14 -14
- package/docs/adr/0029-status-page-outage-resilience.md +1 -1
- package/docs/adr/0030-builders-hall-live-updates.md +1 -1
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +7 -7
- package/docs/adr/0032-discord-mirror-of-gds.md +3 -3
- package/docs/adr/0033-discord-bot-service-principal.md +4 -4
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
- package/docs/adr/0035-builder-onboarding-three-paths.md +4 -4
- package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +1 -1
- package/docs/adr/0037-discord-channel-management.md +1 -1
- package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +5 -5
- package/docs/adr/0039-setup-first-onboarding-ux.md +6 -6
- package/docs/adr/0040-remote-control-default-browser-onramp.md +3 -3
- package/docs/adr/0041-temporary-grader-bypass-killswitch.md +2 -2
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +5 -5
- package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +2 -2
- package/docs/adr/0044-mediterranean-palette-replacement.md +1 -1
- package/docs/adr/0044-per-box-live-game-preview.md +1 -1
- package/docs/adr/0046-sandbox-first-review-gate.md +1 -1
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +1 -1
- package/docs/adr/0049-split-parallel-safety-contract.md +1 -1
- package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +2 -2
- package/docs/adr/0051-full-session-transcript-corpus.md +2 -2
- package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +1 -1
- package/docs/adr/0053-scoped-dev-box-session.md +1 -1
- package/docs/adr/0054-session-token-reward-cost-plus.md +7 -7
- package/docs/adr/0055-server-mediated-branch-publish.md +2 -2
- package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +3 -3
- package/docs/adr/0057-container-cost-ledger.md +1 -1
- package/docs/adr/0057-discord-archon-approval-channels.md +2 -2
- package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +6 -6
- package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +11 -11
- package/docs/adr/0060-gds-retrieval-layer.md +3 -3
- package/docs/adr/0061-context-layer-decomposition.md +2 -2
- package/docs/adr/0062-medusa-instance-model-decoupling.md +5 -5
- package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +2 -2
- package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +3 -3
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +5 -5
- package/docs/adr/0066-generated-file-map-sections.md +2 -2
- package/docs/adr/0067-session-start-fast-forward-pull.md +1 -1
- package/docs/adr/0068-shared-art-key-for-newcomers.md +1 -1
- package/docs/adr/0069-hall-live-channel-sse-decouple.md +3 -3
- package/docs/adr/0070-deterministic-session-card-delivery.md +1 -1
- package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +2 -2
- package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +2 -2
- package/docs/adr/0072-dev-box-code-staleness-visibility.md +2 -2
- package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +3 -3
- package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +2 -2
- package/docs/adr/0076-in-session-deterministic-compaction.md +2 -2
- package/docs/adr/0077-content-addressed-llm-cache.md +2 -2
- package/docs/adr/0078-deterministic-first-cron.md +3 -3
- package/docs/adr/0079-value-gated-autonomous-engagement.md +2 -2
- package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +3 -3
- package/docs/adr/0081-tool-agnostic-design-layer.md +3 -3
- package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +2 -2
- package/docs/adr/0083-modular-architecture-strangler-build-plan.md +3 -3
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +2 -2
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +15 -15
- package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +5 -5
- package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +1 -1
- package/docs/adr/0088-consistent-character-generative-animation.md +5 -5
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +15 -15
- package/docs/adr/0090-metic-task-authoring.md +8 -8
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +3 -3
- package/docs/adr/0092-hosting-module-and-on-prem-target.md +11 -11
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +5 -5
- package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +1 -1
- package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +6 -6
- package/docs/adr/0095-cross-agent-context-management.md +5 -5
- package/docs/adr/0096-require-reward-before-workable.md +5 -5
- package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +2 -2
- package/docs/adr/0097-retroactive-reward-backfill.md +4 -4
- package/docs/adr/0098-public-mirror-publish-manifest.md +3 -3
- package/docs/adr/0099-delayed-redacted-mirror-export.md +1 -1
- package/docs/adr/0100-two-repo-instance-model.md +6 -6
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +9 -9
- package/docs/adr/0102-finish-bounding-the-kernel.md +1 -1
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +6 -6
- package/docs/adr/0103-gdsv4-bongos-consolidation.md +3 -3
- package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +3 -3
- package/docs/adr/0105-instance-seed-migrations-out-of-core.md +2 -2
- package/docs/adr/0106-goal-owner-manager-authority.md +2 -2
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +6 -6
- package/docs/adr/0108-instance-composition-configurable-root.md +6 -6
- package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +3 -3
- package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +1 -1
- package/docs/adr/0111-instance-hosting-provisioning-module.md +18 -18
- package/docs/adr/0112-private-goals-invitations-join-requests.md +7 -7
- package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +1 -1
- package/docs/adr/0114-instance-docs-discovery-contract.md +4 -4
- package/docs/adr/0115-scheduled-routines-portability.md +1 -1
- package/docs/adr/0117-api-versioning-and-deprecation-policy.md +1 -1
- package/docs/adr/0118-api-contract-source-of-truth-code-first.md +1 -1
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +2 -2
- package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +1 -1
- package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +3 -3
- package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +1 -1
- package/docs/adr/0124-typed-api-response-bodies.md +2 -2
- package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +2 -2
- package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +3 -3
- package/docs/adr/0127-cross-box-fleet-observability.md +1 -1
- package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +3 -3
- package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +4 -4
- package/docs/adr/0130-provision-remote-exec-over-ssh.md +4 -4
- package/docs/adr/0131-rank-scoped-skill-visibility.md +2 -2
- package/docs/adr/0132-cohost-fleet-control-plane-migration.md +2 -2
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +1 -1
- package/docs/adr/0134-private-first-npm-distribution.md +3 -3
- package/docs/adr/0135-module-upstream-submission-interim-queue.md +1 -1
- package/docs/adr/0136-update-channel-subscription-policy.md +2 -2
- package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +6 -6
- package/docs/adr/0138-bundled-module-deps-declared-per-module.md +4 -4
- package/docs/adr/0142-project-context-is-prose-only.md +2 -2
- package/docs/adr/0143-onboarding-repo-picker-oauth-scope.md +2 -2
- package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +2 -2
- package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +2 -2
- package/docs/adr/0146-configurable-reward-mode-cost-plus-only.md +4 -4
- package/docs/adr/0147-standalone-live-docs-regen.md +1 -1
- package/docs/adr/0149-bongos-dev-local-launcher.md +1 -1
- package/docs/adr/0150-box-first-boot-bringup-vendored-instances.md +3 -3
- package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +20 -20
- package/docs/adr/0152-landing-gate-served-by-the-core-app.md +2 -2
- package/docs/adr/0152-metic-task-abandonment.md +7 -7
- package/docs/adr/0153-sequential-chain-runner.md +1 -1
- package/docs/adr/0154-goal-owner-criterion-authoring.md +7 -7
- package/docs/adr/0155-adopt-private-repo-widen-oauth-scope.md +2 -2
- package/docs/adr/0156-user-set-display-name-wins.md +1 -1
- package/docs/adr/0157-archon-is-rank-and-identity-only.md +10 -10
- package/docs/adr/0158-choke-point-verdict-taxonomy.md +1 -1
- package/docs/adr/0159-merge-gate-reconciliation.md +1 -1
- package/docs/adr/0160-main-audit-repo-verifiable-caller.md +1 -1
- package/docs/adr/0161-publish-on-merge.md +2 -2
- package/docs/adr/0163-legacy-display-name-resolution.md +1 -1
- package/docs/adr/0165-instances-hookless-by-default.md +1 -1
- package/docs/adr/0166-module-maintenance-and-deprecation-policy.md +3 -3
- package/docs/adr/0167-gate-trust-link-agpl-default.md +2 -2
- package/docs/adr/0167-module-catalog-source-vs-provenance.md +3 -3
- package/docs/adr/0169-bongos-serve-server-bring-up.md +1 -1
- package/docs/adr/0171-profile-rollup-join-and-consent.md +1 -1
- package/docs/adr/0172-editable-rank-roles-substrate-axis.md +2 -2
- package/docs/adr/0172-per-craft-compensation-ideator-credit-lane.md +4 -4
- package/docs/adr/0173-legacy-multi-ship-shortfall-not-backfilled.md +1 -1
- package/docs/adr/0174-government-terminology-ranks-not-roles.md +1 -1
- package/docs/adr/0177-goal-membership-kind.md +3 -3
- package/docs/adr/0178-the-copy-desk-flag-and-queue.md +1 -1
- package/docs/adr/0179-board-membership-predicate-grammar.md +1 -1
- package/docs/adr/0181-teardown-state-gate-and-address-retention.md +1 -1
- package/docs/adr/0182-project-visibility-two-axes.md +1 -1
- package/docs/adr/0183-criteria-close-themselves.md +1 -1
- package/docs/adr/0184-ship-requires-an-assurance.md +1 -1
- package/docs/adr/0185-spark-handoff-credit-split.md +1 -1
- package/docs/adr/0186-per-project-idea-templates.md +1 -1
- package/docs/adr/0187-collab-four-decisions.md +1 -1
- package/docs/adr/0187-oauth-handshake-cookie-lifetime.md +1 -1
- package/docs/adr/0188-patrol-runs-on-ci-not-the-server.md +2 -2
- package/docs/adr/0189-baseline-floors-and-the-freeze-detector.md +2 -2
- package/docs/adr/0191-majority-and-the-author-who-may-not-decide-alone.md +1 -1
- package/docs/adr/0192-a-category-orients-and-authorises-nothing.md +2 -2
- package/docs/adr/0193-pause-task-scoped-box-slices.md +1 -1
- package/docs/adr/0195-adr-numbers-are-checked-like-migration-numbers.md +2 -2
- package/docs/adr/0196-chrome-world-token-contract-and-the-landing-sheets.md +2 -2
- package/docs/adr/0197-the-ui-design-module.md +1 -1
- package/docs/adr/0198-third-party-skill-vendoring-policy.md +1 -1
- package/docs/adr/0203-doorway-changelog-out-of-module-api.md +2 -2
- package/docs/adr/0204-the-apex-is-dark-only.md +2 -2
- package/docs/adr/0205-federated-checkin-needs-the-hubs-own-signin-witness.md +1 -1
- package/docs/adr/0206-own-scoped-session-revocation-no-absolute-ceiling.md +1 -1
- package/docs/adr/0207-connections-implementation-departures-and-honest-limits.md +1 -1
- package/docs/adr/0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md +2 -2
- package/docs/adr/0209-one-budget-for-the-account-existence-oracle.md +1 -1
- package/docs/adr/0210-scouting-graduates-on-an-instance-asserted-owner-claim.md +1 -1
- package/docs/adr/0212-connections-on-the-profile-surface-and-addressing.md +1 -1
- package/docs/adr/0213-platform-terms-acceptance-is-the-hubs-own-witness.md +2 -2
- package/docs/adr/0215-the-recruiter-sliver-is-a-ceiling-not-a-step.md +6 -6
- package/docs/adr/0216-a-fake-pool-interpreter-must-fail-loudly-not-silently-ignore.md +2 -2
- package/docs/adr/0217-rank-gates-inviting-not-viewing.md +1 -1
- package/docs/adr/0218-the-apex-root-web-surface.md +2 -2
- package/docs/adr/0219-a-look-is-a-branding-pack-the-style-library.md +1 -1
- package/docs/adr/0220-an-in-house-rebuilt-skill-is-a-first-party-skill.md +1 -1
- package/docs/adr/0221-the-impeccable-method-is-one-skill-with-sub-command-playbooks.md +2 -2
- package/docs/adr/0222-the-image-family-under-the-hero-only-rule.md +2 -2
- package/docs/adr/0223-the-detector-is-two-tiers-in-the-kit.md +3 -3
- package/docs/adr/0224-module-skills-reach-the-core-checkout-as-untracked-self-ignored-copies.md +1 -1
- package/docs/adr/0225-privacy-suppresses-cross-project-surfaces-only.md +1 -1
- package/docs/adr/0226-one-stale-timer-reporting-degrades-enforcement-refuses.md +1 -1
- package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
- package/docs/adr/0230-a-look-skill-is-a-composition-grammar-the-palette-is-the-pack.md +1 -1
- package/docs/adr/0231-the-style-session-an-owner-authors-a-look-inside-the-contract.md +2 -2
- package/docs/adr/0232-rot-is-derived-not-swept-and-water-is-the-only-new-verb.md +2 -2
- package/docs/adr/0233-a-copy-proposal-is-a-task-carrying-a-patch.md +2 -2
- package/docs/adr/0234-idea-routing-capture-time-promotion-landing-matrix-homeless-inbox.md +2 -2
- package/docs/adr/0235-a-fix-category-is-kindbug-under-a-goal-no-column-required.md +11 -11
- package/docs/adr/0236-many-ideas-one-task-the-lineage-key-is-the-pair.md +5 -5
- package/docs/adr/0237-a-starter-bundle-is-a-preset-over-the-always-on-core-keyed-by-declared-type.md +5 -5
- package/docs/adr/0238-the-join-door-is-a-provisioning-settings-policy-key.md +1 -1
- package/docs/adr/0239-a-recommendation-is-a-table-that-carries-its-own-reason.md +4 -4
- package/docs/adr/0240-a-skipped-module-picker-stores-nothing-and-resolves-the-bundle-on-read.md +4 -4
- package/docs/adr/0241-the-artist-gate-is-a-per-project-deploy-gate-that-reads-a-state.md +1 -1
- package/docs/adr/0242-a-cascade-is-a-declaration-table-on-the-event-that-already-exists.md +2 -2
- package/docs/adr/0243-a-bundle-adjustment-belongs-to-the-bundle-not-the-advice-about-it.md +4 -4
- package/docs/adr/0244-a-catalog-search-is-a-view-over-the-rows-never-an-edit-to-the-selection.md +3 -3
- package/docs/adr/0245-the-way-back-into-an-optional-step-is-that-step-s-own-answer-route.md +7 -7
- package/docs/adr/0246-catalog-membership-is-a-projection-not-a-federation-side-effect.md +1 -1
- package/docs/adr/0247-the-join-door-is-one-composed-answer-and-dark-matter-has-no-live-verdict-yet.md +2 -2
- package/docs/adr/0248-a-hub-project-s-owner-is-the-provisioning-row-carried-on-a-port.md +3 -3
- package/docs/adr/0249-the-invite-step-is-the-done-panel-s-first-act-not-a-rail-step.md +3 -3
- package/docs/adr/0250-strict-versioning-the-version-boundary-is-the-scope-gate.md +6 -6
- package/docs/adr/0251-a-suggestion-of-who-to-invite-is-a-recruiting-surface-and-owes-the-opt-out.md +5 -5
- package/docs/adr/0252-the-self-hosted-visibility-report-is-a-pull-and-auto-appear-buys-a-retraction-lever.md +19 -19
- package/docs/adr/0253-the-takedown-lever-has-two-writers-and-provenance-is-a-column.md +2 -2
- package/docs/adr/0254-a-relayed-link-is-contained-downward-or-it-is-not-published.md +6 -6
- package/docs/adr/0255-a-public-lists-ordering-is-part-of-its-payload.md +2 -2
- package/docs/adr/0256-the-visibility-ceiling-is-the-sign-in-gate-too-and-the-reader-moves-to-the-composer.md +3 -3
- package/docs/adr/0257-auth-resolves-before-the-hall-mounts-anything.md +1 -1
- package/docs/adr/0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md +1 -1
- package/docs/adr/0259-a-projects-departure-from-the-public-list-is-public.md +7 -7
- package/docs/adr/0260-the-application-is-the-consent-and-the-echo-is-the-gate.md +4 -4
- package/docs/adr/0261-a-preselect-always-carries-a-reason-the-bundle-summary-is-the-floor.md +1 -1
- package/docs/adr/0262-a-bug-never-lands-in-the-inbox.md +1 -1
- package/docs/adr/0263-how-a-version-closes.md +3 -3
- package/docs/adr/0264-the-ten-working-areas.md +3 -3
- package/docs/adr/0265-work-with-no-goal-and-the-order-the-cut-needs.md +5 -5
- package/docs/adr/0266-the-board-room-is-its-own-surface-reachable-by-whoever-may-vote.md +2 -2
- package/docs/adr/0267-unanimity-and-the-revise-and-re-sit-loop.md +1 -1
- package/docs/adr/0268-the-constitution-comes-from-two-roots.md +3 -3
- package/docs/adr/0269-the-cli-session-store-is-host-keyed-at-a-fixed-anchor.md +1 -1
- package/docs/adr/0270-rank-floor-derives-without-a-prediction.md +2 -2
- package/docs/adr/0271-the-ideator-surface-is-two-halves.md +3 -3
- package/docs/adr/0272-a-craft-is-an-identity-not-a-toolchain.md +4 -4
- package/docs/adr/0273-hall-nav-can-gate-on-a-permission.md +1 -1
- package/docs/adr/0274-one-kernel-three-role-packs.md +1 -1
- package/docs/adr/0275-one-source-for-a-written-role-responsibility.md +1 -1
- package/docs/adr/0276-the-skill-listing-budget-cannot-hold-every-trigger.md +1 -1
- package/docs/adr/0277-a-box-is-in-use-only-while-a-human-is-attached.md +1 -1
- package/docs/adr/0278-a-gated-project-still-takes-applications.md +2 -2
- package/docs/adr/0279-an-upgrade-is-proven-by-the-served-version-not-the-health-check.md +1 -1
- package/docs/adr/0280-the-unattended-lane-may-drive-a-co-tenant-because-the-roster-is-the-decision.md +1 -1
- package/docs/adr/0281-an-instance-identity-is-its-own-unix-account-and-pg-role.md +2 -2
- package/docs/adr/README.md +294 -294
- package/docs/api/openapi.json +72 -5
- package/docs/api-reference.md +8 -2
- package/docs/architecture.md +22 -22
- package/docs/branding-contract.md +5 -5
- package/docs/canonical-permissions.md +22 -22
- package/docs/copy-inventory.md +15 -13
- package/docs/copy-registry.json +35 -17
- package/docs/design/hall-direction-v2.md +3 -3
- package/docs/design/landing-page-direction-v2.md +1 -1
- package/docs/design/projects-hub-direction-v2.md +1 -1
- package/docs/file-map.md +3 -1
- package/docs/module-api-changelog.md +36 -1
- package/docs/modules-contract.md +25 -25
- package/docs/onboarding/browser-terminal-guide.md +1 -1
- package/docs/onboarding/diagrams/README.md +3 -3
- package/docs/onboarding/drachmae-and-karma.md +13 -13
- package/docs/onboarding/primer.md +7 -7
- package/docs/packs/artist.md +1 -1
- package/docs/packs/ideator.md +1 -1
- package/docs/project-context.template.md +3 -3
- package/docs/recipes/builder-box-lifecycle.md +5 -5
- package/docs/recipes/claude-design-loop.md +1 -1
- package/docs/recipes/core-release-pipeline.md +55 -14
- package/docs/recipes/figma-design-loop.md +1 -1
- package/docs/recipes/gds-db-backup.md +2 -2
- package/docs/recipes/instance-deploy.md +2 -2
- package/docs/recipes/instance-service-restart.md +3 -3
- package/docs/recipes/local-dev.md +2 -2
- package/docs/recipes/managed-settings-remote-control.md +3 -3
- package/docs/recipes/memory-backup.md +4 -4
- package/docs/recipes/memory-sync-conflicts.md +2 -2
- package/docs/recipes/multi-builder-merge.md +2 -2
- package/docs/recipes/ops-gotchas.md +4 -4
- package/docs/recipes/overnight-builder.md +1 -1
- package/docs/recipes/packaging-the-core.md +6 -6
- package/docs/recipes/private-npm-distribution.md +5 -5
- package/docs/recipes/search-index-ingestion.md +3 -3
- package/docs/recipes/self-host.md +5 -5
- package/docs/recipes/server-bring-up.md +1 -1
- package/docs/recipes/ship-and-regrade.md +2 -2
- package/docs/recipes/standalone-live-docs.md +1 -1
- package/docs/recipes/ui-look-before-you-ship.md +1 -1
- package/docs/recipes/upgrading-the-core.md +2 -2
- package/docs/recipes/work-on-a-task-from-your-dev-box.md +6 -6
- package/docs/research/cursor-competitive-analysis.md +3 -3
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +7 -7
- package/migrations/core_240_artist_gate_indexes.sql +48 -0
- package/migrations/core_240_goal_members_drop_legacy_role.sql +79 -0
- package/modules/dev-box/app/src/vendor/bongos-client.cjs +4 -0
- package/modules/hall-ui/public/watch.css +6 -0
- package/modules/hall-ui/public/watch.js +52 -6
- package/modules/lifecycle/cascade.js +37 -9
- package/modules/lifecycle/db-claims.js +5 -2
- package/modules/lifecycle/db-goals.js +4 -3
- package/modules/lifecycle/db-overrides.js +117 -4
- package/modules/lifecycle/db-tasks.js +63 -0
- package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +12 -4
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/pg-constraint-fail.js +49 -0
- package/modules/lifecycle/routes/artist-gate.js +101 -0
- package/modules/lifecycle/routes/claims.js +13 -1
- package/modules/lifecycle/routes/lifecycle.js +6 -0
- package/modules/lifecycle/routes/task-write-routes.js +7 -0
- package/modules/lifecycle/routes/tasks.js +24 -0
- package/modules/lifecycle/task-classifier.js +10 -1
- package/modules/lifecycle/tests/cascade.mjs +43 -0
- package/modules/provisioning/provisioning.js +79 -3
- package/modules/provisioning/routes/provisioning.js +6 -1
- package/modules/provisioning/tests/provisioning.mjs +8 -8
- package/modules/security/secret-scrub.js +40 -4
- package/modules/status-ui/public/README.md +1 -1
- package/modules/ui-design/docs/design-contract.md +2 -2
- package/modules/ui-design/kit/README.md +1 -1
- package/modules/ui-design/kit/serve.js +1 -0
- package/modules/ui-design/skills/README.md +6 -6
- package/modules/ui-design/skills/brandkit/SKILL.md +1 -1
- package/modules/ui-design/skills/design-taste-frontend/SKILL.md +1 -1
- package/modules/ui-design/skills/design-taste-frontend-v1/SKILL.md +1 -1
- package/modules/ui-design/skills/gpt-taste/SKILL.md +1 -1
- package/modules/ui-design/skills/high-end-visual-design/SKILL.md +1 -1
- package/modules/ui-design/skills/image-to-code/SKILL.md +1 -1
- package/modules/ui-design/skills/imagegen-frontend-mobile/SKILL.md +1 -1
- package/modules/ui-design/skills/imagegen-frontend-web/SKILL.md +1 -1
- package/modules/ui-design/skills/impeccable/SKILL.md +1 -1
- package/modules/ui-design/skills/industrial-brutalist-ui/SKILL.md +1 -1
- package/modules/ui-design/skills/minimalist-ui/SKILL.md +1 -1
- package/modules/ui-design/skills/redesign-existing-projects/SKILL.md +1 -1
- package/modules/ui-design/skills/stitch-design-taste/SKILL.md +1 -1
- package/modules/ui-design/skills/style/SKILL.md +2 -2
- package/modules/ui-design/styles/README.md +3 -3
- package/modules/ui-design/styles/blueprint/DESIGN.md +1 -1
- package/modules/ui-design/styles/chrome-world/DESIGN.md +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/audit-rank-roles.js +172 -0
- package/scripts/gds/backfill-task-rewards.js +9 -4
- package/scripts/gds/build-cli-package.js +1 -0
- package/scripts/gds/claim.js +94 -9
- package/scripts/gds/fitness.js +8 -8
- package/scripts/gds/go-live.js +139 -5
- package/scripts/gds/land-watch.js +13 -5
- package/scripts/gds/mirror-redact.js +13 -2
- package/scripts/gds/package-core.js +11 -3
- package/scripts/gds/release.js +55 -0
- package/scripts/gds/ship-land.js +10 -2
- package/scripts/gds/ship-regen.js +41 -8
- package/scripts/gds/start.js +7 -4
- package/scripts/gds/worktree-claim-guard.js +27 -1
- package/scripts/public-mirror-export.js +17 -4
- package/src/bongos/api-errors.js +9 -0
- package/src/bongos/artist-gate.js +204 -0
- package/src/branding.js +15 -0
- package/src/module-api.js +34 -1
- package/tests/api_path_404.mjs +28 -0
- package/tests/artist_gate.mjs +234 -0
- package/tests/artist_gate_release.mjs +283 -0
- package/tests/artist_gate_route.mjs +174 -0
- package/tests/box_scope_predicate.mjs +117 -0
- package/tests/claim_error_surface.mjs +163 -1
- package/tests/cli_exit_no_abort.mjs +256 -3
- package/tests/credit_log_single_writer.mjs +94 -0
- package/tests/currency_label.mjs +11 -4
- package/tests/go_live.mjs +144 -0
- package/tests/helpers.mjs +8 -0
- package/tests/main_worktree_busy_reason.mjs +167 -0
- package/tests/membership_kind_lockstep.mjs +88 -0
- package/tests/mirror_redact.mjs +14 -0
- package/tests/module_api.mjs +6 -0
- package/tests/provision_settings_apply.mjs +13 -5
- package/tests/provisioning_settings.mjs +11 -7
- package/tests/provisioning_settings_apply.mjs +4 -4
- package/tests/provisioning_settings_env.mjs +59 -7
- package/tests/public_mirror_export.mjs +12 -0
- package/tests/rank_roles_audit.mjs +114 -0
- package/tests/scrubber_corpus.mjs +70 -2
- package/tests/start_rebase_warning.mjs +50 -0
- package/tests/task_field_bounds_match_db.mjs +140 -0
- package/tests/watch_roster_self_row.mjs +289 -0
package/docs/api/openapi.json
CHANGED
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"name": "analytics",
|
|
42
42
|
"description": "Endpoints under `/api/bongos/analytics`."
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
"name": "artist-gate",
|
|
46
|
+
"description": "Endpoints under `/api/bongos/artist-gate`."
|
|
47
|
+
},
|
|
44
48
|
{
|
|
45
49
|
"name": "audit-log",
|
|
46
50
|
"description": "Endpoints under `/api/bongos/audit-log`."
|
|
@@ -1042,6 +1046,44 @@
|
|
|
1042
1046
|
]
|
|
1043
1047
|
}
|
|
1044
1048
|
},
|
|
1049
|
+
"/artist-gate": {
|
|
1050
|
+
"get": {
|
|
1051
|
+
"operationId": "get_artist_gate",
|
|
1052
|
+
"tags": [
|
|
1053
|
+
"artist-gate"
|
|
1054
|
+
],
|
|
1055
|
+
"summary": "GET /artist-gate",
|
|
1056
|
+
"description": "GET /artist-gate — this project's artist strictness and what it is holding. rank: any authenticated builder. The payload is ordinary board state — a policy value the instance already publishes as its own behaviour, and task ids/titles any builder can read on the hall — so a floor above requireBuilder would gate a fact the board already shows. Nothing here is writable. Response: mode 'off' | 'advisory' | 'strict' the project's setting as resolved since ISO string | null when it was last RAISED to strict holds boolean does anything hold a deploy now? truncated boolean `reviews` hit the scan cap — a floor reviews [{ id, created_at }] the open reviews that count halt { code, message, detail } | null the refusal, pre-composed `halt` is composed HERE rather than by the caller on purpose: ADR 0241 §4's second guard is that the refusal must name what holds the deploy and which control releases it, and a sentence assembled independently by each caller is a sentence that eventually says something different. One composer, one wording.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
1057
|
+
"x-rank": "any-builder",
|
|
1058
|
+
"x-source": "modules/lifecycle/routes/artist-gate.js",
|
|
1059
|
+
"responses": {
|
|
1060
|
+
"200": {
|
|
1061
|
+
"description": "Success.",
|
|
1062
|
+
"content": {
|
|
1063
|
+
"application/json": {
|
|
1064
|
+
"schema": {
|
|
1065
|
+
"$ref": "#/components/schemas/GetArtistGateResponse"
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
"400": {
|
|
1071
|
+
"$ref": "#/components/responses/BadRequest"
|
|
1072
|
+
},
|
|
1073
|
+
"401": {
|
|
1074
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
1075
|
+
},
|
|
1076
|
+
"403": {
|
|
1077
|
+
"$ref": "#/components/responses/Forbidden"
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
"security": [
|
|
1081
|
+
{
|
|
1082
|
+
"builderSession": []
|
|
1083
|
+
}
|
|
1084
|
+
]
|
|
1085
|
+
}
|
|
1086
|
+
},
|
|
1045
1087
|
"/audit-log": {
|
|
1046
1088
|
"get": {
|
|
1047
1089
|
"operationId": "get_audit_log",
|
|
@@ -11471,7 +11513,7 @@
|
|
|
11471
11513
|
"override-requests"
|
|
11472
11514
|
],
|
|
11473
11515
|
"summary": "POST /override-requests/:id/decide",
|
|
11474
|
-
"description": "POST /override-requests/:id/decide — body: { decision: 'approve'|'deny', note? } On approve, atomically flips the task completed→confirmed and awards the credits to the original requester (NOT the Archon). On deny, only the row updates; the task stays at completed and the builder must release or re-ship after fixing whatever the grader caught. rank: archon — grader-bypass authority; same gate as POST /tasks/:id/confirm.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `override_request.decide` (all required).",
|
|
11516
|
+
"description": "POST /override-requests/:id/decide — body: { decision: 'approve'|'deny', note? } On approve, atomically flips the task completed→confirmed and awards the credits to the original requester (NOT the Archon). On deny, only the row updates; the task stays at completed and the builder must release or re-ship after fixing whatever the grader caught. rank: archon — grader-bypass authority; same gate as POST /tasks/:id/confirm. ONE EXCEPTION, and it is NARROWER than this gate rather than wider: a request whose target is an unresolved ARTIST REVIEW is a gate release (ADR 0241 §3, db-overrides.js), and only the PROJECT OWNER may decide it. That check lives in decideOverrideRequest, not here, so it cannot be bypassed by a second caller; this route only renders its refusal (403 override_owner_only). Approving one confirms nothing and pays nothing — it stops the review holding the DEPLOY and leaves it open on the board.\n\n**Rank:** `metic+archon` — Metic or Archon rank (review/triage powers).\n\n**Permissions:** `override_request.decide` (all required).",
|
|
11475
11517
|
"x-rank": "metic+archon",
|
|
11476
11518
|
"x-source": "modules/lifecycle/routes/tasks.js",
|
|
11477
11519
|
"x-permissions": [
|
|
@@ -16058,7 +16100,7 @@
|
|
|
16058
16100
|
"tasks"
|
|
16059
16101
|
],
|
|
16060
16102
|
"summary": "POST /tasks/:id/override-request",
|
|
16061
|
-
"description": "POST /tasks/:id/override-request — V3.R74 (task 293). The rare path: a builder whose ship failed the subagent grader believes the grader was wrong and asks an Archon to flip the task to confirmed anyway. Audit-logged via the global write-audit middleware. Open requests surface in the Archon queue. rank: any-builder — opens a request; the decision still rests with Archon.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
16103
|
+
"description": "POST /tasks/:id/override-request — V3.R74 (task 293). The rare path: a builder whose ship failed the subagent grader believes the grader was wrong and asks an Archon to flip the task to confirmed anyway. Audit-logged via the global write-audit middleware. Open requests surface in the Archon queue. rank: any-builder — opens a request; the decision still rests with Archon. The SAME route also opens the artist gate's release (ADR 0241 §3, task 1003575): a request whose target is an unresolved artist review is admitted at ANY status, because such a review sits at `backlog` and a completed-only check would make the one documented escape hatch unusable for the exact case it was written for. Who may DECIDE it is narrower — see the decide route.\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
|
|
16062
16104
|
"x-rank": "any-builder",
|
|
16063
16105
|
"x-source": "modules/lifecycle/routes/tasks.js",
|
|
16064
16106
|
"parameters": [
|
|
@@ -17324,6 +17366,31 @@
|
|
|
17324
17366
|
"vocabulary"
|
|
17325
17367
|
]
|
|
17326
17368
|
},
|
|
17369
|
+
"GetArtistGateResponse": {
|
|
17370
|
+
"type": "object",
|
|
17371
|
+
"properties": {
|
|
17372
|
+
"ok": {
|
|
17373
|
+
"type": "boolean"
|
|
17374
|
+
},
|
|
17375
|
+
"mode": {},
|
|
17376
|
+
"since": {},
|
|
17377
|
+
"holds": {
|
|
17378
|
+
"type": "boolean"
|
|
17379
|
+
},
|
|
17380
|
+
"truncated": {},
|
|
17381
|
+
"reviews": {},
|
|
17382
|
+
"halt": {}
|
|
17383
|
+
},
|
|
17384
|
+
"required": [
|
|
17385
|
+
"ok",
|
|
17386
|
+
"mode",
|
|
17387
|
+
"since",
|
|
17388
|
+
"holds",
|
|
17389
|
+
"truncated",
|
|
17390
|
+
"reviews",
|
|
17391
|
+
"halt"
|
|
17392
|
+
]
|
|
17393
|
+
},
|
|
17327
17394
|
"GetAuditLogResponse": {
|
|
17328
17395
|
"type": "object",
|
|
17329
17396
|
"properties": {
|
|
@@ -23619,9 +23686,9 @@
|
|
|
23619
23686
|
"description": "A required dependency/feature is not configured or is temporarily down."
|
|
23620
23687
|
}
|
|
23621
23688
|
},
|
|
23622
|
-
"x-endpoint-count":
|
|
23623
|
-
"x-schema-count":
|
|
23689
|
+
"x-endpoint-count": 373,
|
|
23690
|
+
"x-schema-count": 412,
|
|
23624
23691
|
"x-undocumented-bodies": 9,
|
|
23625
|
-
"x-response-schemas":
|
|
23692
|
+
"x-response-schemas": 280,
|
|
23626
23693
|
"x-generated-by": "scripts/gds/gen-api-docs.js"
|
|
23627
23694
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# Bongos API reference
|
|
4
4
|
|
|
5
|
-
> **Generated from the live route files** — the route file is authoritative.
|
|
5
|
+
> **Generated from the live route files** — the route file is authoritative. 373 endpoints across 60 route files.
|
|
6
6
|
> Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
|
|
7
7
|
|
|
8
|
-
Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr
|
|
8
|
+
Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/0016-trust-boundary-server-enforced-permissions.md)): `public` < `any-builder` < `metic+archon` < `archon`.
|
|
9
9
|
|
|
10
10
|
## `access-requests` (5)
|
|
11
11
|
|
|
@@ -48,6 +48,12 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
|
|
|
48
48
|
|---|---|---|---|---|
|
|
49
49
|
| GET | `/api/bongos/analytics/builder/:id` | `any-builder` | — | a builder's historical AI dev curve. |
|
|
50
50
|
|
|
51
|
+
## `artist-gate` (1)
|
|
52
|
+
|
|
53
|
+
| Method | Path | Rank | Body | Description |
|
|
54
|
+
|---|---|---|---|---|
|
|
55
|
+
| GET | `/api/bongos/artist-gate` | `any-builder` | — | GET /artist-gate — this project's artist strictness and what it is holding. |
|
|
56
|
+
|
|
51
57
|
## `audit-log` (1)
|
|
52
58
|
|
|
53
59
|
| Method | Path | Rank | Body | Description |
|
package/docs/architecture.md
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
- **Domain:** `example.com` — registered at Cloudflare Registrar. DNS A records (apex + `www`) point to the droplet at `REDACTED_IP`. Cloudflare proxy is **ON (orange cloud)**. CF terminates TLS at the edge; the **Cloudflare Origin Certificate** handles the CF↔origin leg (valid through 2041-05-04). A `status` subdomain is added at PMS-V1 deploy time (see [`docs/pms-v1-deploy.md`](pms-v1-deploy.md)) with the same proxy/cert posture; Origin Cert needs `*.example.com` SAN. Real client IPs come in via `CF-Connecting-IP` / `X-Forwarded-For`, wired into Caddy's `trusted_proxies static` (the Cloudflare IP ranges) in the `infra/Caddyfile` global options block.
|
|
13
13
|
- **Production droplet (co-hosting box):** DigitalOcean, hostname `example`, IPv4 `REDACTED_IP`, IPv6 `REDACTED_IP`. NYC3, Premium Intel 2 GB / 1 vCPU / 60 GB NVMe. Ubuntu 24.04 LTS. ~$14/mo. Hosts the OTB game + co-hosted project instances (`emersonian-circles.`, `staging.`).
|
|
14
|
-
- **Cloud Bongos control-plane droplet (NEW 2026-07-05, [ADR 0126](adr
|
|
14
|
+
- **Cloud Bongos control-plane droplet (NEW 2026-07-05, [ADR 0126](adr/0126-dedicated-cloudbongos-control-plane-droplet.md), task [#2063](https://example.com/builders#/task/2063)):** DigitalOcean, hostname `cloudbongos`, IPv4 `REDACTED_IP`, NYC3, `s-1vcpu-2gb` (2 GB / 1 vCPU), Ubuntu 24.04, ~$12/mo, tag `cloudbongos-control`. Runs **cloudbongos.com + `builders.` + `status.`** (`src/platform-server.js`, Cloud Bongos brand, port 3002, own `cloudbongos` DB, checkout `/home/lars/cloudbongos-instance`, the root subscribed to the nightly core-patch sweep) and is the **sole token-holding control plane** — a SECOND root, `/home/lars/cloudbongos`, survives only to vendor `infra/` (the box cloud-init the core package does not ship, ADR 0150); it is not subscribed, so nothing may resolve core code from it (task 1002738, [ADR 0144](adr/0144-devbox-rehome-onto-cloudbongos-plane.md) follow-up 5) — `/etc/cloudbongos/box.env` holds the account-wide Cloudflare token (IP-locked to this box) + the DigitalOcean token; this is where `provision.js` provisions instance subdomains. **Structurally separate SSH** (own `cloudbongos_ed25519` key). IPv6 egress disabled so the IPv4-locked CF token can't be spuriously rejected. cloudbongos.com was previously a co-tenant on the co-hosting box; that unit was decommissioned at cutover. **Follow-ups:** deploy automation (task [#2064](https://example.com/builders#/task/2064)) + fully stripping cloud tokens off the co-hosting box (task [#2065](https://example.com/builders#/task/2065)).
|
|
15
15
|
- **Server stack:** Node.js 22 LTS · PostgreSQL 16 · Caddy 2.11.2. `example.service` (systemd) runs `node server.js` as user `lars` on `127.0.0.1:3000`; restart-on-failure.
|
|
16
16
|
- **Hardening:** `lars` user with passwordless sudo; SSH key-only (root login disabled, password auth disabled); ufw allows 22/80/443; fail2ban active; unattended-upgrades enabled; timezone `America/New_York`.
|
|
17
|
-
- **TLS:** Origin cert at `/etc/caddy/origin.crt` + `/etc/caddy/origin.key` for the example apexes on the co-hosting box. **cloudbongos.com's apexes moved to the dedicated control-plane droplet** ([ADR 0126](adr
|
|
18
|
-
- **Platform observability (task 2020 stood it up; task 2059 re-homed it cross-project onto the control-plane box; [ADR 0127](adr
|
|
17
|
+
- **TLS:** Origin cert at `/etc/caddy/origin.crt` + `/etc/caddy/origin.key` for the example apexes on the co-hosting box. **cloudbongos.com's apexes moved to the dedicated control-plane droplet** ([ADR 0126](adr/0126-dedicated-cloudbongos-control-plane-droplet.md)) with their own copy of the Cloudflare Origin Cert (SAN `*.cloudbongos.com, cloudbongos.com`) at `/etc/caddy/cloudbongos-origin.{crt,key}` on `REDACTED_IP`. Cloudflare SSL/TLS mode = Full (strict). Renewal is a non-issue for ~15 years. **Provisioned instance hosts use a different, coexisting posture** ([ADR 0111](adr/0111-instance-hosting-provisioning-module.md) §4 / task P4): Caddy **on-demand ACME** (Let's Encrypt) via the global `on_demand_tls { ask … }` block, gated to hostnames the `provisioning` module actually stood up (`/api/bongos/provisioning/tls-check`). Their DNS records are **proxied=false (grey cloud)** so the ACME challenge reaches Caddy — the opposite of the origin-cert apexes; do not enable the proxy on them or renewal breaks silently ([ADR 0003](adr/0003-cloudflare-origin-cert-over-letsencrypt.md)). Per-instance site snippets live in `/etc/caddy/sites/*.caddy` (`import`ed by `infra/Caddyfile`). **Tradeoff (accepted, SEC review of task 1945):** `proxied=false` publishes the box's real origin IP in public DNS for every co-tenant provisioned hostname — defeating, for those names, the Cloudflare-proxy IP-hiding the apexes enjoy (a co-tenant host resolves to the same `REDACTED_IP` that serves the main game). This is inherent to on-demand ACME (the challenge must hit the origin) and acceptable under the budget/trust model; prefer a **dedicated droplet** (its own IP) for any instance expected to draw hostile attention.
|
|
18
|
+
- **Platform observability (task 2020 stood it up; task 2059 re-homed it cross-project onto the control-plane box; [ADR 0127](adr/0127-cross-box-fleet-observability.md)):** this watches the **Bongos API** (`gds_http`/`tasks`/`claims`/`builders`/`auth`), not any one game, so it lives **on the control-plane box** (REDACTED_IP) at **`https://metrics.cloudbongos.com`** and observes the **whole fleet**. **Prometheus** (`127.0.0.1:9090`, loopback-only) scrapes every instance's `/metrics` ([`src/bongos/metrics.js`](../src/bongos/metrics.js)), each tagged with a `project` label ([`infra/prometheus/prometheus.yml`](../infra/prometheus/prometheus.yml)): **cloudbongos** locally (`:3002`); **example + emersonian-circles** on the co-hosting box, reached over the **private VPC** via `socat` forwarders on `10.108.0.2:9101/9102` (→ their loopback `:3000`/`:3004`), ufw-locked to the control-plane box's private IP — raw TCP relays, so the exporter still sees a loopback request and needs no token; nothing is public. **Grafana** (`127.0.0.1:3003`, loopback-only) renders the 4 provisioned-as-code dashboards (folder **Cloud Bongos**: system-overview, error-watch, builder-activity, auth-security), each with a **`project`** template variable for per-instance / fleet views. Reverse-proxied on the `*.cloudbongos.com` origin cert — Archon-only, gated by Caddy `basic_auth` (user `archon`) **and** Grafana's own admin login (both secrets owner-held, never in the repo). Grafana config is a systemd `GF_*` env drop-in (`grafana-server.service.d/override.conf`, `chmod 600`). ~256 MB RAM. A future dedicated-droplet instance is added as a `METRICS_TOKEN` Bearer target instead of a VPC forwarder.
|
|
19
19
|
|
|
20
20
|
**Application stack:**
|
|
21
21
|
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
- **`pg`** Postgres client over Unix socket (`host: '/var/run/postgresql'`).
|
|
26
26
|
- **Auth (planned, not yet wired):** Email + magic link, tied to a Stripe customer record on first purchase.
|
|
27
27
|
|
|
28
|
-
**Module system (core + modules, [ADR 0083](adr
|
|
28
|
+
**Module system (core + modules, [ADR 0083](adr/0083-modular-architecture-strangler-build-plan.md)):**
|
|
29
29
|
|
|
30
|
-
The product is organized as a small kernel (`src/`) + **19 modules** under `modules/<key>/` — the four optional *feature* modules **plus** the carved *core-domain* modules. The four-feature carve (Config A) was only the least-coupled ~26% of the tree; the **core decomposition (Config B = BONGOS-V1 C7 `gds-core-modularized`)** is now done too ([ADR 0091](adr
|
|
30
|
+
The product is organized as a small kernel (`src/`) + **19 modules** under `modules/<key>/` — the four optional *feature* modules **plus** the carved *core-domain* modules. The four-feature carve (Config A) was only the least-coupled ~26% of the tree; the **core decomposition (Config B = BONGOS-V1 C7 `gds-core-modularized`)** is now done too ([ADR 0091](adr/0091-bounding-the-kernel-and-db-carve.md), [ADR 0093](adr/0093-tranche-2-core-carve-sequence.md)). The full, live roster + contract is at [docs/modules-contract.md](modules-contract.md).
|
|
31
31
|
|
|
32
32
|
- **The one-way rule** — a module reaches core only through `src/module-api.js` (the published, semver'd doorway). Core never imports a module. Modules never import each other — they cooperate through `src/module-seams.js` (ports + events). Two CI fitness checks enforce this; a violation is a red build.
|
|
33
33
|
- **The loader** (`src/module-loader/loader.js`) — discovers `modules/*/module.json` at boot, validates manifests, checks `coreVersion` compatibility, and mounts each enabled module's routes behind kernel-composed auth. No core file changes to add or remove a module.
|
|
@@ -38,7 +38,7 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
|
|
|
38
38
|
- `discord` — ship broadcast + inbound bot + role-sync; port: `discord.isLinked`
|
|
39
39
|
- `art-pipeline` — pixel-art generation + artist discipline; port: `art.sharedKeyConfigured`
|
|
40
40
|
- (+ `character-anim`, declaration-only — ADR 0088)
|
|
41
|
-
- **Core-domain modules** (`default: true` — always on unless disabled): `memory`, `grading`, `economy`, `ideas`, `security`, `builder-settings`, `onboarding`, `sessions`, plus `lifecycle` (the task/claim/version state machine), `autonomy` (the MAS), the `hall-ui` + `status-ui` internal surfaces, `public-landing` (the apex front door — [ADR 0218](adr
|
|
41
|
+
- **Core-domain modules** (`default: true` — always on unless disabled): `memory`, `grading`, `economy`, `ideas`, `security`, `builder-settings`, `onboarding`, `sessions`, plus `lifecycle` (the task/claim/version state machine), `autonomy` (the MAS), the `hall-ui` + `status-ui` internal surfaces, `public-landing` (the apex front door — [ADR 0218](adr/0218-the-apex-root-web-surface.md)), `ui-design` (the design contract, its adapters and the `/design` playbook as a platform capability — [ADR 0197](adr/0197-the-ui-design-module.md)), and the `demo` acceptance-proof module. See [docs/modules-contract.md](modules-contract.md) for the live roster and which default on.
|
|
42
42
|
- **Module-owned migrations** — `modules/<key>/migrations/*.sql` applied only when the module is enabled. Stem-keyed so moving a migration never re-runs it.
|
|
43
43
|
- **`bongos module new <key>`** — scaffolds a new module directory in one command.
|
|
44
44
|
- **`bongos upgrade`** — the update-consumption channel a two-repo consumer uses to pull the core from version N→N+1 (task 1690, ADR 0100 §2 / ADR 0103 §4): pre-flight (module-compat + clean tree) → bump the vendored-tarball pin → `npm install` → `npm run migrate` (additive `core_*` migrations) → re-materialize `.claude/` → restart → verify. Run bare (no `--to`) it is still just the module-compat pre-check that exits 1 on mismatch; `--to <version>` runs the real bump. (`scripts/gds/upgrade.js`.)
|
|
@@ -49,7 +49,7 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
|
|
|
49
49
|
- **Sibling `QueueRoom`** — unbounded, FIFO, admits via shared in-process seat bus (`src/seats.js`). Browser-close releases seat automatically (Colyseus `onLeave`).
|
|
50
50
|
- **Move protocol:** client sends `{ dir }` per step. Server validates direction, applies position unless target tile is blocked or out of bounds, always commits facing.
|
|
51
51
|
- **Movement is client-predicted, server-authoritative.** Both sides run identical walkability rules. Walkability lives in `BLOCKING_TERRAINS` (ground impassable — sea) and `BLOCKING_OBJECTS` (object impassable — rocks, container panels) in the shared `terrain.js` module (CJS twin at `src/world/terrain.js`, ESM twin at `public/game/world/terrain.js`); the hardcoded V1 map lives in `src/world/map.js` (server) and `public/game/world/map.js` (client) — **the two map.js + the two terrain.js files must stay in sync** until the world becomes data-driven.
|
|
52
|
-
- **Cell data model ([ADR 0012](adr
|
|
52
|
+
- **Cell data model ([ADR 0012](adr/0012-ground-object-cell-split.md), extends [ADR 0011](adr/0011-terrain-id-rendering-model.md)):** each cell carries TWO independent pieces:
|
|
53
53
|
- **Ground terrain** (always defined) — `GRASS`, `SAND`, `SEA`, `MARBLE_PATH`. Drives the autotile renderer. `INITIAL_MAP.ground[y][x]`.
|
|
54
54
|
- **Object** (optional, sparse) — `ROCK` or one of the 8 `CONTAINER_PANEL_*` (V1). Painted in a second draw pass at depth 1. `INITIAL_MAP.objects[y][x]` (null in most cells).
|
|
55
55
|
The autotile picker sees the ground grid only; objects never affect tile selection. That is the invariant that lets rocks scatter through a meadow without polluting boundary tiles, and lets the container sit cleanly on sand.
|
|
@@ -65,11 +65,11 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
|
|
|
65
65
|
**Code & deploy:**
|
|
66
66
|
|
|
67
67
|
- **Code repo:** [github.com/example-owner/example](https://github.com/example-owner/example) — **private**. Clone URL: `git@github.com:example-owner/example.git`. Default branch: `main`. GitHub user: `example-owner`.
|
|
68
|
-
- **Deploy:** two modes, selected by `config/deploy.json` `mode` (env `OTB_DEPLOY_MODE` overrides), currently **`ci`** (flipped from `laptop` 2026-06-13, [#859](https://example.com/builders#/task/859)) — see [ADR 0042](adr
|
|
68
|
+
- **Deploy:** two modes, selected by `config/deploy.json` `mode` (env `OTB_DEPLOY_MODE` overrides), currently **`ci`** (flipped from `laptop` 2026-06-13, [#859](https://example.com/builders#/task/859)) — see [ADR 0042](adr/0042-builder-self-deploy-ci-auto-merge.md). **`laptop`** (legacy): `git push origin main` from the Mac → `ssh lars@REDACTED_IP ~/deploy.sh`. The droplet has a read-only deploy key at `~/.ssh/github_deploy` registered on the repo. `~/deploy.sh` does: `git fetch + reset --hard origin/main` → `npm ci --omit=dev` if `package-lock.json` changed → `./scripts/migrate.sh` → `sudo systemctl restart example` → `curl /healthz` smoke (**retried up to 15× @ 1s** — `systemctl` reports "active" before the Node process binds the port, so a single curl raced the bind and false-failed healthy deploys: [ADR 0056](adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md) / [#1026](https://example.com/builders#/task/1026)). Droplet checkout: `/home/lars/example/`. `~/deploy.sh` is hand-maintained on the droplet but now has a byte-faithful, reviewable repo mirror at [`scripts/deploy/deploy-prod.sh`](../scripts/deploy/deploy-prod.sh) — **not** auto-installed (the ci deploy key is forced-command-locked, ADR 0042/0043; reinstall by hand on change: `scp scripts/deploy/deploy-prod.sh lars@…:deploy.sh`). **`ci`** (current, armed via [#679](https://example.com/builders#/task/679)): no builder box holds the droplet key — `ship.js` opens a PR + enables GitHub auto-merge, and [`.github/workflows/deploy-prod.yml`](../.github/workflows/deploy-prod.yml) runs the same `~/deploy.sh` from Actions on merge to `main`. Cutover preconditions (incl. a server-recorded **CI grade-gate**) are in ADR 0042.
|
|
69
69
|
- **Post-merge branch cleanup (standard practice):** Every feature branch that lands on main via `--no-ff` merge gets deleted on origin once the deploy succeeds. The merge commit itself preserves the branch's history in main, so the named ref isn't carrying any signal — keeping it just clutters GitHub's branch list and tricks the UI into offering empty PRs against zero-diff branches. The auto-merge in [`scripts/gds/ship.js`](../scripts/gds/ship.js) does this automatically after `~/deploy.sh` returns 0; the manual [`/merge-mode`](../.claude/skills/merge-mode/SKILL.md) flow follows the same step 5b. Local refs and worktree directories stay — only the origin branch and the local tracking ref (cleaned on next `git fetch --prune`) go.
|
|
70
70
|
- **Local dev machine:** Lars's MacBook Air (Apple Silicon, macOS Sequoia). Tooling installed via Homebrew at `/opt/homebrew/`. Node v26.0.0 locally; `package.json` declares `"engines": { "node": ">=22" }`. Single ed25519 SSH key (`~/.ssh/id_ed25519`) authenticates to GitHub and droplet.
|
|
71
71
|
- **Smoke tests:** lightweight scripts in `/tmp/colyseus-*-smoketest.js` verify joinOrCreate, move protocol, interact, identity, queue. Run any after deploy with `node /tmp/colyseus-<name>-smoketest.js`.
|
|
72
|
-
- **Repo topology today vs. the configurable-root future ([ADR 0108](adr
|
|
72
|
+
- **Repo topology today vs. the configurable-root future ([ADR 0108](adr/0108-instance-composition-configurable-root.md)):** everything above describes the current **single checkout** — `git reset --hard` deploy, `resolveCoreRoot()`/`resolveInstanceRoot()` ([`src/instance-config.js`](../src/instance-config.js)) both resolving to this same repo root. ADR 0108 lands (Mercury-first, then Example last) a model where Example instead installs a versioned `@bongos/core` npm package and deploy becomes `git pull` (the instance repo) → `npm ci` (the pinned core) → migrate → restart — no more `git reset --hard` on a shared checkout. This section gets rewritten for the new topology once Example actually splits (ADR 0108 §6, task 1884/W4); until then it is unchanged and accurate.
|
|
73
73
|
|
|
74
74
|
**Database (`example` on Postgres 16, peer auth as `lars`):**
|
|
75
75
|
|
|
@@ -218,23 +218,23 @@ Bongos views: `claimable_tasks` (rebuilt in 006 to use SELECT t.*; rebuilt again
|
|
|
218
218
|
**Bongos API (`/api/gds/*`, mounted in the same Node process):**
|
|
219
219
|
|
|
220
220
|
- **Canonical path is `/api/bongos` (task 1919); `/api/gds` is a PERMANENT alias.** The router + the discovery index are dual-mounted at both by `serve-internal.js`, driven by the single `src/bongos/api-prefix.js` constant (`API_PREFIX` + `LEGACY_API_PREFIXES`). The legacy `/api/gds` alias never goes away — shipped Dev Box binaries, the cached status mirror, and live boxes call it. **Exception:** the GitHub OAuth callback stays pinned to `/api/gds/auth/web/callback` (registered on the OAuth app; `src/bongos/routes/auth.js`). Not yet flipped (still ride the permanent alias): `src/**` internal callers + the deeper internal names (folders, `GDS_*` env, `gds_session` cookie) — the deferred internal-rename pass.
|
|
221
|
-
- **Self-describing (task 1918, [ADR 0109](adr
|
|
221
|
+
- **Self-describing (task 1918, [ADR 0109](adr/0109-self-describing-openapi-and-hosted-docs.md)).** The whole surface is documented in the standard **OpenAPI 3.1** format at [`docs/api/openapi.json`](api/openapi.json), **generated from the live route files** by `scripts/gds/gen-api-docs.js` (reusing the same `route-rank-check.js` introspection the ship-time rank gate uses — so it can't drift; a fitness `--check` + ship-time regen enforce freshness). A rendered docs site (vendored Redoc) is served at **`/docs`** on the apex of every instance (`cloudbongos.com/docs` canonical); `GET /api/gds` returns a machine-discovery index pointing at it. The generated [`docs/api-reference.md`](api-reference.md) supersedes the old hand-maintained `routes-permissions.md`. The mount prefix is the single `src/bongos/api-prefix.js` constant.
|
|
222
222
|
|
|
223
|
-
- Auth: `POST /auth/device/start`, `/poll` (CLI Device Flow); `GET /auth/web/start`, `/web/callback` (browser); `POST /auth/logout`; app pairing for the Dev Box desktop app ([#904](https://example.com/builders#/task/904), [ADR 0045](adr
|
|
224
|
-
- Own-scoped session self-service ([ADR 0206](adr
|
|
225
|
-
- Authenticated CLI/web: `GET /me` (returns `rank`), `GET /versions[/progress]`, `GET /tasks[?version=&status=&kind=&discipline=]`, `GET /tasks/claimable[?version=&discipline=]`, `GET /tasks/:id`, `POST /tasks` (accepts `discipline` + `criterion_ids`; **metic+** — [ADR 0090](adr
|
|
226
|
-
- Criterion rollup + task↔criterion links ([ADR 0025](adr
|
|
227
|
-
- Server-mediated branch publish (ADR 0055 / [#1025](https://example.com/builders#/task/1025) — lets a dev box with no GitHub push credential ship). Owner-gated like ship: `POST /tasks/:id/publish-branch` (`requireBuilder` + `gateTaskOwnership`, **NOT** `allowBoxScope` → a box-scoped session is `403 box_scope`, so the builder must `/builder-reauth` first; own 32 MB json parser for the base64 thin-bundle body, 20 MB decoded cap; the server pushes the branch + opens the PR + auto-merges with a server-side push credential — a **GitHub App** installation token (short-lived, repo-scoped; preferred, [ADR 0055](adr
|
|
223
|
+
- Auth: `POST /auth/device/start`, `/poll` (CLI Device Flow); `GET /auth/web/start`, `/web/callback` (browser); `POST /auth/logout`; app pairing for the Dev Box desktop app ([#904](https://example.com/builders#/task/904), [ADR 0045](adr/0045-devbox-desktop-app.md), store [`src/bongos/app-pair.js`](../src/bongos/app-pair.js) — in-memory, 10-min TTL): `POST /auth/app-pair/start` + `/poll` (public; the secret poll_token is the bearer and the minted token is delivered to it exactly once), `GET /auth/app-pair/info` + `POST /auth/app-pair/approve` (any-builder; approve is **cookie-gated** like `/auth/cli-token/issue` so a leaked bearer can't mint siblings; approving from `/builders/pair?code=…` signs the app in as the approver, `source='cli'`).
|
|
224
|
+
- Own-scoped session self-service ([ADR 0206](adr/0206-own-scoped-session-revocation-no-absolute-ceiling.md), task 1003341), in [`src/bongos/routes/my-sessions.js`](../src/bongos/routes/my-sessions.js): `GET /me/sessions` (every live session on the caller's own account — source, user agent, created/last-used/expires, a `current` flag; the token value is never selected), `POST /me/sessions/revoke` (`{session_id}` — one of your own; a miss answers `revoked: 0` so a stranger's id cannot be probed) and `POST /me/sessions/revoke-all` (sign out everywhere, the requesting session included). All three gate on `requireBuilder` alone and key every statement on `req.builder.id` — an account is never named in the query, body or path. They exist because a bearer refreshes to `now()+24h` on every call, so a leaked one never expires, and the cross-builder pair (`POST /auth/revoke`, `/auth/revoke-all`, both still gated on the admin `auth.session.revoke` atom) needed an Archon the victim might not have. Surfaced in the hall at Settings → Active sessions.
|
|
225
|
+
- Authenticated CLI/web: `GET /me` (returns `rank`), `GET /versions[/progress]`, `GET /tasks[?version=&status=&kind=&discipline=]`, `GET /tasks/claimable[?version=&discipline=]`, `GET /tasks/:id`, `POST /tasks` (accepts `discipline` + `criterion_ids`; **metic+** — [ADR 0090](adr/0090-metic-task-authoring.md)), `PATCH /tasks/:id` (supports `parent_task_id`, `kind`, `discipline`, `goal_id` — (re)assign the task's goal; must be a goal in the task's own version, task 1763; **metic+**), `POST /tasks/:id/promote` (**metic+**), `POST /claims`, `POST /claims/:id/resolve`, `POST /cost`.
|
|
226
|
+
- Criterion rollup + task↔criterion links ([ADR 0025](adr/0025-structured-criterion-task-link.md), [#435](https://example.com/builders#/task/435)/[#438](https://example.com/builders#/task/438)): `GET /versions/:id/progress` rolls up each done-when criterion → its gating tasks (via `task_criteria`) → live status counts + the not-yet-shipped `remaining[]` + `unattributed_tasks` (the read behind the `/status` skill, in `src/bongos/done-when.js criterionProgress`). The link CRUD mirrors the dependency endpoints: `GET /tasks/:id/criteria`, `POST /tasks/:id/criteria` (**metic+** — [ADR 0090](adr/0090-metic-task-authoring.md)) and `DELETE /tasks/:id/criteria/:criterionId` (**metic+**). A criterion ref is a numeric `done_when_criteria.id`, a positional `"Cn"` token, or a `criterion_id` slug, resolved against the task's version (`POST /tasks` links at create time so `/status` counts the task with no backfill).
|
|
227
|
+
- Server-mediated branch publish (ADR 0055 / [#1025](https://example.com/builders#/task/1025) — lets a dev box with no GitHub push credential ship). Owner-gated like ship: `POST /tasks/:id/publish-branch` (`requireBuilder` + `gateTaskOwnership`, **NOT** `allowBoxScope` → a box-scoped session is `403 box_scope`, so the builder must `/builder-reauth` first; own 32 MB json parser for the base64 thin-bundle body, 20 MB decoded cap; the server pushes the branch + opens the PR + auto-merges with a server-side push credential — a **GitHub App** installation token (short-lived, repo-scoped; preferred, [ADR 0055](adr/0055-server-mediated-branch-publish.md) update / task 1028) or the `GITHUB_PUSH_TOKEN` PAT fallback; `503 push_unconfigured` when neither is set; `400 tip_mismatch` if the bundle tip ≠ the claimed `head_sha`) and `GET /tasks/:id/publish-status?branch=…` (polls PR + deploy-prod state derived live from GitHub). `ship.js` uses these in `ci` mode only when `pushVia()` resolves to server (a box, or `OTB_PUSH_VIA_SERVER=1`); a laptop with `gh` keeps the local push path unchanged. Implementation in `src/bongos/github-push.js`.
|
|
228
228
|
- Archon monitoring reads backing the `/watch` page (ADR 0036): `GET /builders/roster`, `GET /grades/by-builder[?days=N]` (**archon-only**, [#726](https://example.com/builders#/task/726) — per-builder grade breakdown for the MARKS section; the project-wide aggregate stays public at `/public/grades`), `GET /audit-log`, `GET /override-requests`, `GET /access-requests`, `GET /security/reports`. Personal-prefs writes backing `/settings`: `GET/PATCH /me/skill-prefs`, `PATCH /me/disciplines`.
|
|
229
|
-
- Per-builder "needs" + own Gemini key ([ADR 0073](adr
|
|
229
|
+
- Per-builder "needs" + own Gemini key ([ADR 0073](adr/0073-builder-needs-signal-and-byok-gemini-key.md), [#1013](https://example.com/builders#/task/1013)): `GET /me` now also carries `needs` ({items, action_needed_count} — the consistent "the system needs an input from you" signal; `modules/builder-settings/builder-needs.js` is the SSOT — carved out in BV1.R80, resolved by `GET /me` via the `builder-settings` kernel port — rendered by the hall Standing card + the CLI `printNeedsNudge`). The own-key (pragmatic BYOK) endpoints, all own-scoped: `GET /me/art-key/own` (masked meta — last4 only), `PUT /me/art-key/own` (validate-on-save via a Google list-models call → encrypt with `src/bongos/secret-box.js` → store; `503 storage_not_configured` until `BUILDER_SECRET_KEY` is set, `422 invalid_key` on a bad key), `DELETE /me/art-key/own`. The existing `GET /me/art-key` (shared-key box-sync delivery) is extended to also deliver the decrypted own key, which `scripts/gds/fetch-art-key.js` syncs into the local `gemini_api_key` slot (own key wins in the `gen_api.py` cascade).
|
|
230
230
|
- Builder memory (ADR 0024 cloneable memory + ADR 0026 BFG). Self-scoped (owner is always `req.builder.id`, never input): `POST /memory/sync` (push own memory; own 64 MB parser, vs the global 64 KB), `GET /memory/files`, `GET /memory/file`, `DELETE /memory/file` (the BFG delete affordance, 6C.2). Cross-builder (input-owner) endpoints — all privileged + audit-logged fail-closed: `GET /memory/builders/:id/files`+`/file` (**archon forensic** read), `GET /memory/bfg/builders/:id/files`+`/file` (**BFG-principal only**, 6B.1 read), and the one cross-builder WRITE `POST /memory/builders/:id/bfg-write` (**BFG-principal only**, kill-switched `BFG_WRITE_ENABLED` default-OFF, namespaced `bfg/`, attributed `author: BFG`, write+audit in one tx — dreams + transparent corrections, 6C.1/6C.2).
|
|
231
231
|
- Session corpus (BFG evaluator — 6D, ADR 0027): `POST /sessions` (upload own session digest; own **4 MB** json parser — capped, vs the global 64 KB — and the digest is per-turn metadata + short scrubbed snippets, never raw transcript content), `GET /sessions/mine` (self-serve), `GET /sessions/search` (cross-builder, **archon-gated** — the BFG-principal stand-in; the principal now exists (6C.1) and the *memory* cross-reads moved to it (6B.1), but these *session* reads still use the archon stand-in pending a retrofit, + audit_log row per read), `GET /sessions/:id` (own self-serve; cross-builder needs archon + audit; non-owner → 404).
|
|
232
232
|
- Public (no auth, `Cache-Control: max-age=60`): `/public/versions`, `/public/progress`, `/public/cost-summary`, `/public/recent-shipped`, `/public/leaderboard`, `/public/grades[?days=N]`, `/public/tasks/:id` ([#604](https://example.com/builders#/task/604) — single-task resolver for `#NNN` doc deep-links; `title`/`value_summary`/`visual_url` returned **only** for `shipped`|`confirmed` work and withheld for in-flight tasks so unshipped/security task names can't leak; the status dashboard renders it at `#/task/:id`), `/public/ref-ids` ([#653](https://example.com/builders#/task/653) — `{tasks:[ids]}`, ids only, token-free; the doc-ref linkifier + its CI gate consult it to decide which bare `#NNN` are real task refs). These power `status.example.com`.
|
|
233
|
-
- Live updates (Server-Sent Events — [#569](https://example.com/builders#/task/569), [ADR 0030](adr
|
|
233
|
+
- Live updates (Server-Sent Events — [#569](https://example.com/builders#/task/569), [ADR 0030](adr/0030-builders-hall-live-updates.md) signal layer, [ADR 0069](adr/0069-hall-live-channel-sse-decouple.md) transport): an SSE stream at `GET /api/gds/live` ([`src/bongos/routes/live.js`](../src/bongos/routes/live.js)), mounted in both entrypoints (`server.js` + `src/platform-server.js`) so the hall stays live on a game-less boot. This **superseded** the original broadcast-only Colyseus `builders_hall` room (R55 / task 1194 — the room and `src/rooms/BuildersHallRoom.js` were deleted because a Bongos-only instance has no Colyseus in the process). The change-signal layer is **unchanged**: a statement-level Postgres `NOTIFY` trigger (migration 066) on `tasks`/`claims`/`builders`/`builder_onboarding_state`/`credit_log`/`karma_log` fires a `gds_live` notification on every write (incl. direct `psql`); one persistent `LISTEN` connection ([`src/bongos/live-channel.js`](../src/bongos/live-channel.js)) relays each notification, and the SSE endpoint emits an **opaque empty nudge** to open hall tabs (the `{table, op}` is kept server-side so internal table names can't leak); the hall re-runs its `loadAll()` (debounced) on any nudge. No row data crosses the channel — access control stays on the per-panel re-fetches.
|
|
234
234
|
|
|
235
235
|
**Builder ranks & the trust boundary:** moved to its own canonical reference —
|
|
236
236
|
[`docs/canonical-permissions.md`](canonical-permissions.md) (rank ladder, live ranks, what's gated,
|
|
237
|
-
failure modes) and [ADR 0016](adr
|
|
237
|
+
failure modes) and [ADR 0016](adr/0016-trust-boundary-server-enforced-permissions.md) (the decision).
|
|
238
238
|
**Authority lives in `builders.rank` on the prod DB, checked server-side per request with no caching;
|
|
239
239
|
markdown describes, the DB enforces.**
|
|
240
240
|
|
|
@@ -242,11 +242,11 @@ markdown describes, the DB enforces.**
|
|
|
242
242
|
|
|
243
243
|
**Multi-host setup (same Node process), routed by `Host` header in [`src/bongos/serve-internal.js`](../src/bongos/serve-internal.js), shared by both entrypoints:**
|
|
244
244
|
|
|
245
|
-
- **the apex root itself** — the public front door (`/`, `/projects`, `/create`, `/privacy`, `/terms`, `/contact`). **Carved to the `public-landing` module in task 1003322** ([ADR 0218](adr
|
|
245
|
+
- **the apex root itself** — the public front door (`/`, `/projects`, `/create`, `/privacy`, `/terms`, `/contact`). **Carved to the `public-landing` module in task 1003322** ([ADR 0218](adr/0218-the-apex-root-web-surface.md)): the surface moved from repo-root `public-landing/` to `modules/public-landing/public/` and is a loader-discovered web-surface module — the THIRD, and the first that is not a subdomain. Where `hall-ui`/`status-ui` declare a Host PREFIX, this one declares `{ apexRoot: true, dir }`, because the apex is whatever host is left once the subdomains are taken (`isApexHost` = `!isStatusHost && !isBuildersHost`); `host: ""` is rejected, since `host.startsWith("")` is true for every host and would swallow the other two surfaces. Like the hall it keeps its **dedicated** serving block — in `src/platform-server.js`, now resolving its root through `moduleWebSurfaces()` by the `apexRoot` predicate rather than a hardcoded path — so the apex-only sentinel strip, the brand-token stamp and the `?v=` content stamp are unchanged. Disable the module and the front door vanishes: every route falls through to the game-less 404 tail. Served bytes are identical across the carve apart from the module's own `window.__MODULES__` entry.
|
|
246
246
|
- **`example.com`** — game (Phaser + Colyseus). Static files from `public/`. `/builders` + `/builders/*` now **301-redirect to `builders.example.com/<rest>`** ([#739](https://example.com/builders#/task/739) then promoted to permanent 301 in [#741](https://example.com/builders#/task/741), ADR 0036 cutover); the apex no longer serves the builder surface directly.
|
|
247
|
-
- **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr
|
|
248
|
-
- **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr
|
|
249
|
-
- **`/downloads/devbox/*`** (every host, mounted right after the API so the builders-host shim can't rewrite it — [#904](https://example.com/builders#/task/904), [ADR 0045](adr
|
|
247
|
+
- **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/gds/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected), run automatically by `.github/workflows/sync-status-mirror.yml` (needs the `STATUS_MIRROR_TOKEN` secret) ([#737](https://example.com/builders#/task/737)). **⚠ FOLLOW-UP (R84):** that workflow's path trigger still watches `public-status/**` and must be re-pointed at `modules/status-ui/public/**` by an owner/Archon — the GitHub App can't push `.github/workflows/*` (learning 107), so until then the mirror sync won't auto-fire on future status edits.
|
|
248
|
+
- **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-builders/` to `modules/hall-ui/public/` (~13k LOC, the largest module) and is a loader-discovered web-surface module (`contributes.webSurfaces` host `builders.`). UNLIKE the generic status surface it keeps its **dedicated** serving block in `serve-internal.js` (`BUILDERS_DIR = modules/hall-ui/public/`), partitioned out of the generic web-surface loop on the `isBuildersHost` predicate. A thin rewrite shim maps every non-API path onto the existing `/builders/*` tree (so all serving + gating + asset-stamping is reused), serving the hall (`/`), the Metic+ **`/watch`** monitoring page (gated by `requireGovernmentPage`), **`/settings`** (Voices + Craft prefs), plus ranks/sessions/primer/diagrams. No behavior change — byte-identical (only `window.__MODULES__.enabled` gains `hall-ui:true`). **Additive** — until its DNS A record + cert are live, the whole surface stays reachable at `example.com/builders/*`. No `.github/workflows/*` follow-up: unlike R84, no workflow path-trigger watches `public-builders/**`.
|
|
249
|
+
- **`/downloads/devbox/*`** (every host, mounted right after the API so the builders-host shim can't rewrite it — [#904](https://example.com/builders#/task/904), [ADR 0045](adr/0045-devbox-desktop-app.md)): branded download surface for the Dev Box desktop app. `/{mac-arm64,mac-x64,win-x64}` (+ `mac`/`win` aliases) 302 to the release assets on the public releases repo named in [`config/devbox-app.json`](../config/devbox-app.json); `latest.json` feeds the app's update check. Logic in [`src/devbox-downloads.js`](../src/devbox-downloads.js); the installers never ride the git deploy.
|
|
250
250
|
- The `/api/gds/*` surface is reachable from every host. **Cross-subdomain sign-in:** the `gds_session` cookie is scoped to `.example.com` on the production hosts (apex/www/builders/status) and host-only on localhost/staging (no cross-env token bleed); the OAuth handshake runs on the canonical origin with a validated `?return=` (open-redirect-guarded) so the subdomain can land a builder back on itself.
|
|
251
251
|
- Caddy gets a site block per host ([`infra/Caddyfile`](../infra/Caddyfile)), all reverse-proxying to `127.0.0.1:3000`.
|
|
252
252
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The branding contract (`config/branding.*`)
|
|
2
2
|
|
|
3
|
-
The branding contract is how a **Cloud Bongos instance** supplies its identity. It is the keystone of the Cloud Bongos decoupling (ADR [0062](adr
|
|
3
|
+
The branding contract is how a **Cloud Bongos instance** supplies its identity. It is the keystone of the Cloud Bongos decoupling (ADR [0062](adr/0062-medusa-instance-model-decoupling.md) §3; task [#1192](https://example.com/builders#/task/1192) / V4.R53). One config, read through one resolver (`src/branding.js`), so brand strings live in **one place** instead of the ~90 hardcoded sites they occupy today.
|
|
4
4
|
|
|
5
5
|
> Generalizes the single-config rule of [ADR 0004](adr/0004-example-name-and-trademark-acceptance.md) (the civ name must be one string, never baked into code) from one string to the whole identity surface. Code reads `branding().identity.worldName`, never `"Example"`.
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ env override → instance config (config/branding.json) → neutral star
|
|
|
12
12
|
|
|
13
13
|
- A fresh instance with **no** `config/branding.json` resolves to the **plain neutral identity** — never to a host's brand (fail-to-vanilla).
|
|
14
14
|
- `config/branding.neutral.json` is **customer 0** (vanilla Cloud Bongos). `config/branding.json` is the host instance — here, **customer 1** (Example / OTB).
|
|
15
|
-
- **Configurable-root ([ADR 0108](adr
|
|
15
|
+
- **Configurable-root ([ADR 0108](adr/0108-instance-composition-configurable-root.md) §1, task 1881/W1 shipped):** `NEUTRAL_PATH` resolves off `resolveCoreRoot()` (the neutral starter ships WITH the core package) and `INSTANCE_PATH` off `resolveInstanceRoot()` (the instance pack is host content) — [`src/instance-config.js`](../src/instance-config.js). Both resolvers return the repo root today, so resolution is unchanged; the split only diverges once a consumer installs the core as a package.
|
|
16
16
|
- Env overrides apply only to the operationally-swapped fields (origins + cookie domain) for dev/staging, keyed `<envPrefix>_<FIELD>` (e.g. `OTB_PUBLIC_ORIGIN`). Everything else comes from the committed pack.
|
|
17
17
|
|
|
18
18
|
## Fields
|
|
@@ -24,7 +24,7 @@ env override → instance config (config/branding.json) → neutral star
|
|
|
24
24
|
| `identity.company` | `{ name, site }` of the operating company (may be empty). |
|
|
25
25
|
| `llmProjectName` | The project name injected into grader / architect / onboarding **LLM prompts**, so a non-OTB instance is graded against its own identity. **Required.** |
|
|
26
26
|
| `domains.publicOrigin` | Public game/app origin. **Required.** |
|
|
27
|
-
| `domains.buildersOrigin` / `statusOrigin` | Hall + status origins. **These three (`publicOrigin`/`buildersOrigin`/`statusOrigin`) are the docs-discovery contract** ([ADR 0114](adr
|
|
27
|
+
| `domains.buildersOrigin` / `statusOrigin` | Hall + status origins. **These three (`publicOrigin`/`buildersOrigin`/`statusOrigin`) are the docs-discovery contract** ([ADR 0114](adr/0114-instance-docs-discovery-contract.md)): the hall is the canonical doc-reading surface, `/docs` on `publicOrigin` renders the API reference, the status page is the outage fallback. `GET <publicOrigin>/api/bongos` re-advertises them (`hall`/`status`/`public`) so an agent resolves the surfaces with no hard-coded host. |
|
|
28
28
|
| `domains.statusDataUrl` | **Optional.** The off-box prober's `status.json` URL that the mirrored status page's availability banner polls (ADR 0029). Read by `scripts/status-mirror-sync.js`; `""` (the neutral default) = this instance publishes no off-box mirror, and the publisher REFUSES rather than shipping a banner that points nowhere. (task [#1002510](https://cloudbongos.com/builders#/task/1002510)) |
|
|
29
29
|
| `domains.cookieDomain` | Session cookie domain (`""` = host-only — the safe default; never widen to a parent domain by accident). |
|
|
30
30
|
| `domains.oauthOrigin` | Canonical sign-in origin. |
|
|
@@ -36,10 +36,10 @@ env override → instance config (config/branding.json) → neutral star
|
|
|
36
36
|
| `repo` | `{ owner, name }` GitHub binding. |
|
|
37
37
|
| `db.database` | DB name Bongos pool connects to when neither `DATABASE_URL` nor `PGHOST`/`PGDATABASE` is set (`src/bongos/pool.js`, ADR 0062 §5). `null` in the neutral starter = **fail loud** rather than silently target a host DB. |
|
|
38
38
|
| `currency` | `{ label, symbol }` — the reward unit label (e.g. "example"). Display only. |
|
|
39
|
-
| `reward` | `{ marginPct, usdPeg, mode }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr
|
|
39
|
+
| `reward` | `{ marginPct, usdPeg, mode }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr/0054-session-token-reward-cost-plus.md) + ADR 0146, tasks 2009/1002270): the cost-plus margin percent (default `20`), the example-per-USD peg (default `1`), and `mode` — `"cost-plus-and-estimate"` (default; pay both the per-task author estimate AND the cost-plus session reward) or `"cost-plus-only"` (suppress the per-task estimate payout; the cost-plus session reward is the sole equity reward). A committed, code-reviewed change — not a live UI knob. Omit ⇒ code defaults (20% margin, 1:1 peg, pay both streams). |
|
|
40
40
|
| `models` | `{ main, subagentDefault, subagentRoutine }` — the per-instance subagent model-allocation DEFAULT the builder-settings module reads (task 2011): the tier for the main session, subagent-default work, and routine plumbing (tiers: `haiku`/`sonnet`/`opus`/`fable`). A per-builder override resolves over this. Omit ⇒ code defaults (`opus`/`opus`/`haiku`). |
|
|
41
41
|
| `tracks` | The configurable version-track set (replaces the hardcoded `product\|internal`). |
|
|
42
|
-
| `theme` | `{ palette, mode, ui }` — palette file ref + theme mode, plus `ui`, the WEB look `themeMarkup()` splices into every served page as a plain `:root` after the page's stylesheet: `colors` (the thirteen contract tokens — **light-mode values**; each stylesheet derives its own dark tier from them at `:root[data-mode="dark"]` + its `prefers-color-scheme` twin, which outrank the pack), `fonts` (`display`, `body`, `links`), `favicon`, and `backdrop` — a `body{background:…}` rule that outranks every sheet in **both** modes, so a dual-mode world sets it to `var(--bg)` (the neutral pack does since [task 1003298](https://cloudbongos.com/builders#/task/1003298), ADR 0196) rather than a literal. The neutral values are the chrome world's; `config/design-tokens.neutral.json` must mirror `colors` + `fonts` key for key (`tests/design_tokens_sync.mjs`), and the world's derived recipes are recorded in `DESIGN.md`. The ui-design module's **style library** (`modules/ui-design/styles/`, [ADR 0219](adr
|
|
42
|
+
| `theme` | `{ palette, mode, ui }` — palette file ref + theme mode, plus `ui`, the WEB look `themeMarkup()` splices into every served page as a plain `:root` after the page's stylesheet: `colors` (the thirteen contract tokens — **light-mode values**; each stylesheet derives its own dark tier from them at `:root[data-mode="dark"]` + its `prefers-color-scheme` twin, which outrank the pack), `fonts` (`display`, `body`, `links`), `favicon`, and `backdrop` — a `body{background:…}` rule that outranks every sheet in **both** modes, so a dual-mode world sets it to `var(--bg)` (the neutral pack does since [task 1003298](https://cloudbongos.com/builders#/task/1003298), ADR 0196) rather than a literal. The neutral values are the chrome world's; `config/design-tokens.neutral.json` must mirror `colors` + `fonts` key for key (`tests/design_tokens_sync.mjs`), and the world's derived recipes are recorded in `DESIGN.md`. The ui-design module's **style library** (`modules/ui-design/styles/`, [ADR 0219](adr/0219-a-look-is-a-branding-pack-the-style-library.md)) ships ready-made `theme.ui` blocks (looks) an instance copies into this field; every served sheet reads only these fifteen, so a look re-themes every surface with no page edit. |
|
|
43
43
|
| `copy` | Instance copy keys (tagline, hallName, notFound, …). Full copy pack adoption = task [#1196](https://example.com/builders#/task/1196). |
|
|
44
44
|
| `landing.postLogin` | Where a successful web sign-in lands when it carried no explicit `?return=` / same-apex `Referer` (`src/bongos/routes/auth.js` `postLoginLanding`). **Portable default `/builders`** — the hall always exists. A platform-home instance points this at its OWN front door so a visitor who signs in from there returns there instead of being auto-redirected into the hall (cloudbongos.com → `/gate/`, the orbs). Validated through the same open-redirect allowlist as `?return=` (a misconfigured value falls back to `/builders`). Env-overridable: `<PREFIX>_POST_LOGIN_LANDING`. (task [#1002240](https://cloudbongos.com/builders#/task/1002240)) |
|
|
45
45
|
| `envPrefix` | Env-var namespace for overrides (`BONGOS` for vanilla, `OTB`, …). Legacy `CLOUDBONGOS_`, `OTB_`, `GDS_` and `PMS_` spellings still resolve, with one deprecation warning per name, until core 1.21 (task 1003703). |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> plus the `requireRank()` middleware on each route. This file *describes* that model so humans
|
|
6
6
|
> and agents can read it in one place; it cannot *grant* anything. If this file and a route ever
|
|
7
7
|
> disagree, **the route is authoritative and the doc is the bug.** See
|
|
8
|
-
> [ADR 0016 — Trust boundary](adr
|
|
8
|
+
> [ADR 0016 — Trust boundary](adr/0016-trust-boundary-server-enforced-permissions.md).
|
|
9
9
|
>
|
|
10
10
|
> Changing the permission model is a code + migration + ADR change, never an edit to this file alone.
|
|
11
11
|
> A builder editing local files (this doc, `CLAUDE.md`, skills, `settings.json`, hooks) cannot
|
|
@@ -56,7 +56,7 @@ forming the ordered claim-gate tier **`xenos` (1) < `thetes` (2) < `metic` (3) <
|
|
|
56
56
|
(`REQUIRES_RANK_TIER` in `src/bongos/db.js`):
|
|
57
57
|
|
|
58
58
|
- **`archon`** — Lars (`github_login = 'example-owner'`, set by migration 023). **Since
|
|
59
|
-
[ADR 0157](adr
|
|
59
|
+
[ADR 0157](adr/0157-archon-is-rank-and-identity-only.md) (2026-08-05) the Archon rank is responsible for
|
|
60
60
|
RANK and IDENTITY, not day-to-day administration.** It is everything a Metic can do, plus: **rank**
|
|
61
61
|
(grant/revoke — the single writer), **identity** (offboard/(de)activate, admit an access request, revoke
|
|
62
62
|
sessions), the **four escalation keys** that would otherwise make that delegation self-reversible
|
|
@@ -64,21 +64,21 @@ forming the ordered claim-gate tier **`xenos` (1) < `thetes` (2) < `metic` (3) <
|
|
|
64
64
|
**version close**, cross-tier dependency edges, and the substrate floors (push `main`, protected paths,
|
|
65
65
|
ssh — ADR 0043). Version-**level** criteria (a `done-when` with no `goal_id`, or one outside an open
|
|
66
66
|
version / outside a goal they own) also stay Archon per
|
|
67
|
-
[ADR 0154](adr
|
|
67
|
+
[ADR 0154](adr/0154-goal-owner-criterion-authoring.md), though that ADR's `done-when/:id/unsatisfy`
|
|
68
68
|
carve-out was superseded — unsatisfy is Metic now. Overrides any claim. The authority that
|
|
69
69
|
stays *exclusively* Archon — never delegated to Metic — is **setting rank** (`PATCH /builders/:id/rank`)
|
|
70
70
|
and **closing versions**.
|
|
71
71
|
- **`metic`** — the Archon-approved **working rank**. Full claim/ship of any ready task (own work),
|
|
72
72
|
plus the review/triage powers criterion C2 assigns: **idea triage** (`PATCH /inbox/:id`), **blocker
|
|
73
|
-
review** (`POST /blockers/:id/{resolve,link}`), and planning/priority sessions. **As of [ADR 0090](adr
|
|
73
|
+
review** (`POST /blockers/:id/{resolve,link}`), and planning/priority sessions. **As of [ADR 0090](adr/0090-metic-task-authoring.md)
|
|
74
74
|
(owner decision 2026-06-26) a Metic may also author + shape tasks**: create (`POST /tasks`), edit
|
|
75
75
|
(`PATCH /tasks/:id`), promote (`POST /tasks/:id/promote`), and wire a task's dependencies + criterion
|
|
76
76
|
links (`/tasks/:id/dependencies`, `/tasks/:id/criteria`) — the reasoning being that a rank trusted to
|
|
77
|
-
*triage* ideas is trusted to *seed* the work they become. **As of [ADR 0152](adr
|
|
77
|
+
*triage* ideas is trusted to *seed* the work they become. **As of [ADR 0152](adr/0152-metic-task-abandonment.md)
|
|
78
78
|
(owner decision 2026-07-27) a Metic may also retire work** — `POST /tasks/:id/abandon` — and undo a
|
|
79
79
|
mis-retire, since `POST /tasks/:id/promote` now also restores `abandoned → backlog`. **Still cannot**
|
|
80
80
|
set rank, close versions, grader-bypass confirm, or author cross-tier `POST /dependencies` / goal-scope edges
|
|
81
|
-
([ADR 0086](adr
|
|
81
|
+
([ADR 0086](adr/0086-goal-scoped-work-hierarchy.md)) — those stay Archon. A builder reaches Metic
|
|
82
82
|
only by deliberate Archon promotion (`PATCH /builders/:id/rank`).
|
|
83
83
|
- **`thetes`** — the **graduated-newcomer rank** (ADR 0034). Claims the **whole general queue** — any
|
|
84
84
|
task whose `requires_rank` is the default `'xenos'` — and is **not** limited to `newcomer_friendly`,
|
|
@@ -132,7 +132,7 @@ index = higher authority). So `requireRank('archon')` admits `archon` **and the
|
|
|
132
132
|
silently *lost* all archon-gated authority — while still denying everything below the floor. Unknown
|
|
133
133
|
or missing ranks fail closed.
|
|
134
134
|
|
|
135
|
-
- **Archon-only** — **rank, identity, and the four escalation keys ([ADR 0157](adr
|
|
135
|
+
- **Archon-only** — **rank, identity, and the four escalation keys ([ADR 0157](adr/0157-archon-is-rank-and-identity-only.md), owner decision 2026-08-05).**
|
|
136
136
|
That ADR narrowed Archon from ~50 route gates to 9 live ones, on the rule *"the Archon rank is
|
|
137
137
|
responsible for rank and identity only"*:
|
|
138
138
|
- **rank** — `PATCH /api/gds/builders/:id/rank` (the single writer).
|
|
@@ -140,17 +140,17 @@ or missing ranks fail closed.
|
|
|
140
140
|
(who is admitted), `POST /api/gds/auth/revoke[-all]` (whose sessions are valid).
|
|
141
141
|
- **the four escalation keys**, which look operational but are not: `POST /api/gds/tasks/:id/confirm`
|
|
142
142
|
(grader-bypass), `POST /api/gds/gate-approvals/:pr/approve` (CI deploy-gate override), protected-module
|
|
143
|
-
**goal scope** ([ADR 0086](adr
|
|
143
|
+
**goal scope** ([ADR 0086](adr/0086-goal-scoped-work-hierarchy.md)), and `government.manage` (the
|
|
144
144
|
ranks/permissions tab). Delegating any one of them lets a Metic reach Archon in four steps — create a
|
|
145
145
|
protected-scope goal in the permission core, claim a task there (protected paths already floor at
|
|
146
|
-
*metic* per [ADR 0043](adr
|
|
146
|
+
*metic* per [ADR 0043](adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md)), confirm
|
|
147
147
|
past the failed grade, approve their own red gate — so keeping rank Archon-only depends on keeping
|
|
148
148
|
these Archon-only too. **Any future delegation must re-check that chain.**
|
|
149
149
|
- plus `version.close` (paired with rank as the powers that never delegate), the cross-tier
|
|
150
150
|
`POST|DELETE /api/gds/dependencies` (`system: true`), and the substrate floors
|
|
151
151
|
(`deploy.push_main` / `path.protected.modify` / `infra.ssh`, ADR 0043).
|
|
152
152
|
|
|
153
|
-
> **Amended by [ADR 0172](adr
|
|
153
|
+
> **Amended by [ADR 0172](adr/0172-editable-rank-roles-substrate-axis.md) (owner decision, 2026-08-16).**
|
|
154
154
|
> The paragraphs above describe the SEEDED ladder, which is still what a fresh instance boots with — but
|
|
155
155
|
> they are no longer a guarantee about a running one. The owner made the three sub-Archon **ranks**
|
|
156
156
|
> editable from the Government tab and chose to include the seven in-app Archon powers, `government.manage`
|
|
@@ -166,11 +166,11 @@ or missing ranks fail closed.
|
|
|
166
166
|
|
|
167
167
|
Earlier one-power delegations that ADR 0157 generalises: **task authoring** — `POST /api/gds/tasks`,
|
|
168
168
|
`PATCH /api/gds/tasks/:id` (incl. the `newcomer_friendly` flag), `POST /api/gds/tasks/:id/promote`, and the
|
|
169
|
-
`tasks/:id/{dependencies,criteria}` CRUD — moved to Metic+ in [ADR 0090](adr
|
|
169
|
+
`tasks/:id/{dependencies,criteria}` CRUD — moved to Metic+ in [ADR 0090](adr/0090-metic-task-authoring.md),
|
|
170
170
|
and **task retirement** — `POST /api/gds/tasks/:id/abandon`, plus the `abandoned → backlog` restore on
|
|
171
|
-
`/promote` — in [ADR 0152](adr
|
|
171
|
+
`/promote` — in [ADR 0152](adr/0152-metic-task-abandonment.md) (see the Metic+Archon bullet).
|
|
172
172
|
`POST /api/gds/done-when/:id/unsatisfy` **was** Archon-only and moved to Metic in ADR 0157, superseding
|
|
173
|
-
[ADR 0154](adr
|
|
173
|
+
[ADR 0154](adr/0154-goal-owner-criterion-authoring.md)'s "the backward ratchet stays Archon" carve-out;
|
|
174
174
|
satisfy and unsatisfy remain separate permissions, so confirming a criterion still never confers
|
|
175
175
|
un-confirming one. **A manual promotion advances exactly
|
|
176
176
|
ONE live rung at a time** (`xenos→thetes→metic→archon`; [#707](https://example.com/builders#/task/707)) — a multi-rung jump (e.g. `xenos→metic`) returns
|
|
@@ -178,21 +178,21 @@ or missing ranks fail closed.
|
|
|
178
178
|
drops straight to `xenos`); the automatic `xenos→thetes` graduation is +1 and unaffected.
|
|
179
179
|
- **Metic + Archon** — the working rank's review/triage powers ([#360](https://example.com/builders#/task/360) / ADR 0018): `PATCH /api/gds/inbox/:id`
|
|
180
180
|
(idea triage), `POST /api/gds/blockers/:id/{resolve,link}` (blocker review) — **plus, since
|
|
181
|
-
[ADR 0090](adr
|
|
181
|
+
[ADR 0090](adr/0090-metic-task-authoring.md), full task authoring**: `POST /api/gds/tasks`,
|
|
182
182
|
`PATCH /api/gds/tasks/:id`, `POST /api/gds/tasks/:id/promote`, the `tasks/:id/dependencies` +
|
|
183
183
|
`tasks/:id/criteria` CRUD, and `POST /api/gds/done-when/:id/satisfy` (criterion confirm,
|
|
184
|
-
[ADR 0086](adr
|
|
185
|
-
[ADR 0154](adr
|
|
184
|
+
[ADR 0086](adr/0086-goal-scoped-work-hierarchy.md)). Since
|
|
185
|
+
[ADR 0154](adr/0154-goal-owner-criterion-authoring.md), also `POST /api/gds/versions/:id/done-when`
|
|
186
186
|
(criterion **create**) — but walled by goal ownership, not by rank alone: a non-Archon must name a
|
|
187
187
|
`goal_id`, on an open (`planning`/`building`) version, in an `open` goal they **own or manage** (the same
|
|
188
188
|
`authorizeGoalManagement` wall as goal visibility/invites/memberships — the membership column is
|
|
189
189
|
`goal_members.membership_kind` ('lead' | 'member') since task 1003013, never `role`, which
|
|
190
|
-
[ADR 0174](adr
|
|
191
|
-
`done-when/:id/unsatisfy` moved here in [ADR 0157](adr
|
|
190
|
+
[ADR 0174](adr/0174-government-terminology-ranks-not-roles.md) reserves for the three crafts). Version-level criteria stay Archon;
|
|
191
|
+
`done-when/:id/unsatisfy` moved here in [ADR 0157](adr/0157-archon-is-rank-and-identity-only.md). The floor here is
|
|
192
192
|
`metic`, so **`thetes` does NOT pass these** — it sits below `metic` on the ladder and inherits none
|
|
193
193
|
of its grants (ADR 0034); `archon` and the divine tiers above it do.
|
|
194
194
|
|
|
195
|
-
**[ADR 0157](adr
|
|
195
|
+
**[ADR 0157](adr/0157-archon-is-rank-and-identity-only.md) added the whole operational block here** —
|
|
196
196
|
20 permissions that had been Archon-gated only by ADR 0016's fail-closed default, never by a decision:
|
|
197
197
|
the government/monitoring **pages** (`/watch`, `/harbor`, `/gate` — `page.view.government`) and
|
|
198
198
|
`GET /api/gds/sessions/search` (whose own `/sessions` page had no server gate at all until
|
|
@@ -237,7 +237,7 @@ nothing set it, so every task sat at the `'xenos'` default and the claim gate ab
|
|
|
237
237
|
- **Derivation (`db.deriveRequiredRank(touches, security_sensitive)`):** a task floors at `metic` when
|
|
238
238
|
it is `security_sensitive` **or** any `touches[]` entry hits the permission-sensitive set — reusing
|
|
239
239
|
the **same** `permission-path-check.matchProtected` matcher the trust boundary uses (so the claim
|
|
240
|
-
floor and the [ADR 0043](adr
|
|
240
|
+
floor and the [ADR 0043](adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md) git-push floor can never disagree). Everything else stays `'xenos'` (the open
|
|
241
241
|
general queue). The rule **never auto-assigns `archon`** — owner-only is a deliberate manual call.
|
|
242
242
|
- **Override is upward-only (`db.highestRank`):** the stored value is `max(derived floor, requested)`.
|
|
243
243
|
An Archon may RAISE a task's floor (incl. to `archon`) on `POST /api/gds/tasks` or
|
|
@@ -285,7 +285,7 @@ pre-merge gate misses, independent of the builder's cooperation:
|
|
|
285
285
|
activated per-clone by `/builder-setup` via `install-git-hooks.js` — inert on a clone that never
|
|
286
286
|
activated it; ADR 0043 §"G-2/G-17 resolution") blocks it. This hook is a CORE-repo control:
|
|
287
287
|
scaffolded standalone instances are hookless by default — deliberate, not a gap
|
|
288
|
-
([ADR 0165](adr
|
|
288
|
+
([ADR 0165](adr/0165-instances-hookless-by-default.md)); the graded
|
|
289
289
|
pipeline pushes only via `scripts/gds/push-main.js` (which carries the `OTB_ALLOW_MAIN_PUSH`
|
|
290
290
|
override). A raw push is caught and reverted by the **post-push main audit**
|
|
291
291
|
(`scripts/gds/main-audit.js`) — nightly and as the `~/deploy.sh` deploy gate — which is the
|
|
@@ -310,7 +310,7 @@ pre-merge gate misses, independent of the builder's cooperation:
|
|
|
310
310
|
A builder who edits their checkout to try to elevate themselves hits the boundary and fails every
|
|
311
311
|
time, in a defined way (`403 rank_forbidden`), because the server never consults anything the
|
|
312
312
|
builder's machine can write. The full enumeration of local-edit attack attempts and their outcomes
|
|
313
|
-
lives in [ADR 0016 §"Failure mode when a builder edits local files"](adr
|
|
313
|
+
lives in [ADR 0016 §"Failure mode when a builder edits local files"](adr/0016-trust-boundary-server-enforced-permissions.md).
|
|
314
314
|
|
|
315
315
|
---
|
|
316
316
|
|