@bongos/core 1.17.0 → 1.17.2
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 +363 -312
- package/.claude/skills/blocker-review/SKILL.md +1 -1
- package/.claude/skills/builder-claim/SKILL.md +2 -0
- package/.claude/skills/builder-exit/SKILL.md +2 -2
- package/.claude/skills/builder-redteam/SKILL.md +3 -3
- package/.claude/skills/builder-setup/SKILL.md +2 -2
- package/.claude/skills/builder-start/SKILL.md +1 -1
- package/.claude/skills/dev/SKILL.md +1 -1
- package/.claude/skills/idea-triage/SKILL.md +2 -2
- package/.claude/skills/ideate/SKILL.md +1 -1
- package/.claude/skills/merge-mode/SKILL.md +1 -1
- package/.claude/skills/new-project/SKILL.md +3 -0
- package/.claude/skills/paint/SKILL.md +1 -1
- package/CLAUDE.md +11 -238
- package/GOVERNANCE.md +1 -1
- package/README.md +1 -1
- package/bin/bongos.js +1 -0
- package/clients/bongos-client/README.md +4 -4
- package/clients/bongos-client/bongos-client.global.js +14 -1
- package/clients/bongos-client/index.cjs +14 -1
- package/clients/bongos-client/index.d.ts +19 -2
- package/clients/bongos-client/index.mjs +11 -1
- package/clients/bongos-client/package.json +1 -1
- package/docs/adr/0001-stack-choice-single-vps.md +1 -1
- package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
- package/docs/adr/0019-red-team-bounty-payout-table.md +3 -3
- package/docs/adr/0020-security-model-public-stub.md +1 -1
- package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +1 -1
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +1 -1
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +4 -4
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +3 -3
- package/docs/adr/0030-builders-hall-live-updates.md +1 -1
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +4 -4
- package/docs/adr/0032-discord-mirror-of-gds.md +2 -2
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
- 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/0054-session-token-reward-cost-plus.md +10 -10
- package/docs/adr/0057-container-cost-ledger.md +3 -3
- package/docs/adr/0062-medusa-instance-model-decoupling.md +4 -4
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +2 -2
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +1 -1
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +1 -1
- package/docs/adr/0096-require-reward-before-workable.md +9 -9
- package/docs/adr/0097-retroactive-reward-backfill.md +3 -3
- package/docs/adr/0100-two-repo-instance-model.md +1 -1
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +3 -3
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +3 -3
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +1 -1
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +6 -6
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +2 -0
- package/docs/adr/0134-private-first-npm-distribution.md +20 -6
- package/docs/adr/0135-module-upstream-submission-interim-queue.md +34 -0
- package/docs/adr/0136-update-channel-subscription-policy.md +51 -0
- package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +40 -0
- package/docs/adr/0138-bundled-module-deps-declared-per-module.md +45 -0
- package/docs/adr/README.md +14 -10
- package/docs/api/openapi.json +315 -6
- package/docs/api-reference.md +10 -5
- package/docs/architecture.md +3 -3
- package/docs/branding-contract.md +5 -4
- package/docs/canonical-permissions.md +1 -1
- package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
- package/docs/file-map.md +20 -19
- package/docs/handoff-template.md +2 -2
- package/docs/modules-contract.md +8 -1
- package/docs/onboarding/diagrams/README.md +7 -7
- package/docs/onboarding/drachmae-and-karma.md +18 -18
- package/docs/onboarding/primer.md +9 -9
- package/docs/recipes/audit-replay.md +2 -2
- package/docs/recipes/builder-box-lifecycle.md +2 -2
- package/docs/recipes/claude-design-loop.md +1 -1
- package/docs/recipes/instance-deploy.md +4 -4
- package/docs/recipes/instance-first-run.md +51 -0
- package/docs/recipes/ops-gotchas.md +1 -1
- package/docs/recipes/packaging-the-core.md +5 -5
- package/docs/recipes/private-npm-distribution.md +39 -12
- package/docs/recipes/self-host.md +1 -1
- package/docs/recipes/staging-environment.md +1 -1
- package/docs/recipes/upgrading-the-core.md +63 -8
- package/docs/research/cursor-competitive-analysis.md +1 -1
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +1 -1
- package/migrations/core_191_module_submissions.sql +45 -0
- package/modules/autonomy/CLAUDE.md +11 -45
- package/modules/builder-settings/CLAUDE.md +11 -54
- package/modules/dev-box/CLAUDE.md +11 -34
- package/modules/discord/CLAUDE.md +11 -46
- package/modules/discord/module.json +2 -1
- package/modules/economy/CLAUDE.md +11 -44
- package/modules/economy/achievements.js +9 -1
- package/modules/economy/credits.js +10 -1
- package/modules/grading/CLAUDE.md +11 -38
- package/modules/hall-ui/CLAUDE.md +11 -57
- package/modules/hall-ui/public/builders.js +71 -4
- package/modules/hall-ui/public/goal-inbox.js +191 -0
- package/modules/hall-ui/public/goals-page.js +227 -22
- package/modules/hall-ui/public/goals.html +16 -0
- package/modules/hall-ui/public/hall-widgets.js +14 -1
- package/modules/hall-ui/public/index.html +3 -0
- package/modules/hall-ui/public/new-project-wizard.js +6 -4
- package/modules/hall-ui/public/style.css +43 -0
- package/modules/ideas/CLAUDE.md +11 -33
- package/modules/lifecycle/CLAUDE.md +11 -59
- package/modules/lifecycle/routes/goals.js +80 -0
- package/modules/memory/CLAUDE.md +11 -36
- package/modules/onboarding/CLAUDE.md +11 -51
- package/modules/provisioning/CLAUDE.md +15 -0
- package/modules/provisioning/migrations/provisioning_001_tables.sql +160 -0
- package/modules/provisioning/migrations/provisioning_002_standalone_shape.sql +11 -0
- package/modules/provisioning/migrations/provisioning_003_github_app_manifest.sql +95 -0
- package/modules/provisioning/module.json +17 -0
- package/modules/provisioning/onboard-plan.js +37 -0
- package/modules/provisioning/provisioning.js +539 -0
- package/modules/provisioning/rate-limit.js +35 -0
- package/modules/provisioning/routes/provisioning.js +607 -0
- package/modules/provisioning/tests/provisioning.mjs +232 -0
- package/modules/provisioning/ui/.gitkeep +0 -0
- package/modules/security/CLAUDE.md +11 -40
- package/modules/security/secret-scrub.js +10 -0
- package/modules/sessions/CLAUDE.md +11 -35
- package/modules/status-ui/CLAUDE.md +11 -43
- package/package-lock.json +2 -2
- package/package.json +7 -2
- package/public-landing/create.html +58 -12
- package/public-landing/index.html +40 -21
- package/scripts/discord/README.md +1 -1
- package/scripts/gds/CLAUDE.md +11 -140
- package/scripts/gds/claim.js +98 -48
- package/scripts/gds/claude-materialize.js +174 -20
- package/scripts/gds/claude-md-template.js +84 -0
- package/scripts/gds/cli-lib.js +112 -2
- package/scripts/gds/cutover-codemod.js +241 -0
- package/scripts/gds/fitness.js +54 -0
- package/scripts/gds/gen-api-client.js +10 -10
- package/scripts/gds/init.js +112 -16
- package/scripts/gds/lint-infra-exec.js +70 -0
- package/scripts/gds/lint-workflow-exec.js +63 -0
- package/scripts/gds/migration-namespace.js +1 -1
- package/scripts/gds/mirror-lineage-check.js +14 -5
- package/scripts/gds/mirror-redact.js +8 -0
- package/scripts/gds/module.js +118 -4
- package/scripts/gds/npmrc.js +93 -0
- package/scripts/gds/onboard.js +17 -24
- package/scripts/gds/package-core.js +74 -17
- package/scripts/gds/provision.js +102 -17
- package/scripts/gds/publish-manifest.js +60 -2
- package/scripts/gds/run-routine.js +51 -13
- package/scripts/gds/run-unit-tests.js +4 -0
- package/scripts/gds/seed-adopt-tasks.js +1 -1
- package/scripts/gds/status.js +6 -1
- package/scripts/gds/task.js +166 -0
- package/scripts/gds/update-channel.js +186 -0
- package/scripts/gds/upgrade.js +172 -25
- package/src/bongos/CLAUDE.md +11 -60
- package/src/bongos/auth.js +24 -0
- package/src/bongos/module-submissions.js +56 -0
- package/src/bongos/route-rank-check.js +6 -0
- package/src/bongos/routes/CLAUDE.md +11 -39
- package/src/bongos/routes/auth.js +6 -1
- package/src/bongos/routes/modules.js +123 -21
- package/src/bongos/serve-internal.js +10 -1
- package/src/branding.js +1 -0
- package/src/instance-config.js +1 -1
- package/src/module-api.js +24 -1
- package/src/module-loader/loader.js +36 -4
- package/src/module-loader/manifest-schema.js +16 -1
- package/tests/branding.mjs +11 -0
- package/tests/claim_error_surface.mjs +107 -0
- package/tests/claude_materialize.mjs +125 -0
- package/tests/consumer_layout_boot.mjs +302 -0
- package/tests/cutover_codemod.mjs +184 -0
- package/tests/device_flow_start.mjs +96 -0
- package/tests/first_run_engine_check.mjs +79 -0
- package/tests/goal_membership_requests.mjs +33 -3
- package/tests/hook_core_resolve.mjs +125 -0
- package/tests/hook_user_agents.mjs +62 -0
- package/tests/infra_exec_paths.mjs +104 -0
- package/tests/init.mjs +106 -6
- package/tests/instance_mismatch_guard.mjs +101 -0
- package/tests/mirror_lineage_proof.mjs +14 -0
- package/tests/module_cli.mjs +130 -2
- package/tests/module_loader.mjs +42 -0
- package/tests/module_manifest.mjs +19 -0
- package/tests/module_submissions.mjs +135 -0
- package/tests/npmrc.mjs +105 -0
- package/tests/onboard.mjs +62 -0
- package/tests/package_core.mjs +76 -22
- package/tests/platform_boot.mjs +5 -2
- package/tests/provision.mjs +107 -8
- package/tests/provisioning_github_app_routes.mjs +44 -2
- package/tests/publish_manifest.mjs +52 -1
- package/tests/run_routine.mjs +26 -1
- package/tests/run_routine_two_root.mjs +77 -0
- package/tests/scrubber_corpus.mjs +17 -0
- package/tests/served_paths_shipped.mjs +2 -2
- package/tests/task_cli.mjs +99 -0
- package/tests/update_channel.mjs +186 -0
- package/tests/upgrade.mjs +220 -25
- package/tests/workflow_exec_paths.mjs +98 -0
- package/docs/design/container-exterior-tiles.md +0 -49
- package/docs/design/container-exterior.md +0 -81
- package/docs/design/container-interior.md +0 -77
- package/docs/design/world-map-scroll.md +0 -41
- package/docs/recipes/claude-gemini-bongos-doors.md +0 -155
- package/docs/recipes/cloudbongos-staging-gate.md +0 -139
- package/docs/recipes/cloudbongos-standup.md +0 -111
- package/docs/recipes/parallel-load-results-2026-05-30.md +0 -63
- package/docs/recipes/parallel-load-test.md +0 -32
- package/docs/recipes/pixel-art-pipeline.md +0 -411
- package/docs/recipes/staging-data.md +0 -50
- package/migrations/instance/018_pms_v3_planning_seed.sql +0 -131
- package/migrations/instance/080_gds_v4_planning_seed.sql +0 -75
- package/migrations/instance/110_medusa_planning_seed.sql +0 -70
- package/migrations/instance/120_bongos_v1_planning_seed.sql +0 -69
- package/migrations/instance/144_bongos_v1_module_system_criterion.sql +0 -26
- package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +0 -29
- package/migrations/instance/172_v2_world_planning_seed.sql +0 -163
- package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +0 -33
- package/migrations/instance/182_gdsv4_bongos_consolidation.sql +0 -132
- package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +0 -116
- package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +0 -69
- package/scripts/gds/art-stage.js +0 -152
- package/server.js +0 -212
- package/tests/art_key.mjs +0 -121
- package/tests/day_cycle.mjs +0 -197
- package/tests/snapshot_picker.mjs +0 -233
- package/tests/sprite_facing.mjs +0 -35
- package/tests/terrain_picker.mjs +0 -298
- package/tests/turn_in_place.mjs +0 -280
- package/tests/walkability.mjs +0 -188
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
// carries a live credential verbatim, PRODUCE NOTHING — dist/ is never touched. The
|
|
39
39
|
// in-memory pass makes the abort atomic (same discipline as the mirror export).
|
|
40
40
|
// 5. Only when the whole set is clean: write the tree to
|
|
41
|
-
// dist/
|
|
41
|
+
// dist/bongos-core-<version>/, the .tgz, and the pin MANIFEST.
|
|
42
42
|
//
|
|
43
43
|
// THE VERSION STAMP is the platform version — src/module-api.js CORE_VERSION,
|
|
44
44
|
// read via the SAME fail-soft accessor scripts/gds/module.js + bongos upgrade use
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
// [--version <v>] [--droplet-ip <ip>] [--publish [--live]]
|
|
56
56
|
// Defaults: --ref HEAD, --out-dir dist, --version = platform CORE_VERSION.
|
|
57
57
|
// Outputs (nothing is committed — dist/ is gitignored):
|
|
58
|
-
// dist/
|
|
59
|
-
// dist/
|
|
60
|
-
// dist/
|
|
58
|
+
// dist/bongos-core-<version>/ the redacted core tree (inspectable)
|
|
59
|
+
// dist/bongos-core-<version>.tgz the installable unit
|
|
60
|
+
// dist/bongos-core-<version>.manifest.json the PIN (tree hash + per-file hashes)
|
|
61
61
|
// --publish after building, `npm publish` the .tgz as a PRIVATE scoped
|
|
62
62
|
// package (--access restricted). DRY-RUN unless --live is added
|
|
63
63
|
// (task 2089 / ADR 0134). Private publish needs the cloudbongos
|
|
@@ -81,7 +81,7 @@ const { collectEnvSecrets } = require(path.join(REPO_ROOT, 'modules/security/sec
|
|
|
81
81
|
const { redactBlob, parseLsTree } = require(path.join(REPO_ROOT, 'scripts/public-mirror-export.js'));
|
|
82
82
|
|
|
83
83
|
const MANIFEST_SCHEMA = 1;
|
|
84
|
-
const ARTIFACT_NAME = '
|
|
84
|
+
const ARTIFACT_NAME = 'bongos-core';
|
|
85
85
|
// The tar internal root MUST be `package/` — that is the one hardcoded npm
|
|
86
86
|
// convention for an installable tarball (`npm install ./x.tgz` / `npm pack`
|
|
87
87
|
// output both use it; npm does not read the directory name to find package.json,
|
|
@@ -92,7 +92,7 @@ const TAR_ROOT = 'package/';
|
|
|
92
92
|
// The self-describing manifest carried INSIDE the artifact (minus tarball.* — a
|
|
93
93
|
// file cannot contain its own hash). The authoritative PIN is the side-car next
|
|
94
94
|
// to the .tgz, which adds tarball.{sha256,bytes}.
|
|
95
|
-
const INNER_MANIFEST = `${TAR_ROOT}.
|
|
95
|
+
const INNER_MANIFEST = `${TAR_ROOT}.bongos-core.json`;
|
|
96
96
|
|
|
97
97
|
// ---------------------------------------------------------------------------
|
|
98
98
|
// The platform version — read CORE_VERSION via the doorway, lazily + fail-soft,
|
|
@@ -136,6 +136,38 @@ function sha256hex(buf) {
|
|
|
136
136
|
const DOC_RE = /\.(md|markdown)$/i;
|
|
137
137
|
function isDocPath(p) { return DOC_RE.test(String(p || '')); }
|
|
138
138
|
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Agent-doc STUB (task 2121; surfaced by the 2026-07-08 demo task-creation audit).
|
|
141
|
+
// Claude Code AUTO-LOADS the nearest file named CLAUDE.md (or AGENTS.md) into the
|
|
142
|
+
// live session whenever an agent opens a sibling file. In a CONSUMER instance the
|
|
143
|
+
// core installs at node_modules/@bongos/core/, so the core repo's OWN CLAUDE.md tree
|
|
144
|
+
// (root + scripts/gds + src/bongos + every module) would silently inject the
|
|
145
|
+
// platform's project memory — wrong project title, hundreds of lines, dangling links
|
|
146
|
+
// — into the instance's context the moment an agent reads any core file.
|
|
147
|
+
// The PUBLIC MIRROR deliberately publishes CLAUDE.md as the portable methodology
|
|
148
|
+
// (ADR 0065 §4), so this cannot live in the shared publish-manifest — it is a
|
|
149
|
+
// package-core-only transform. We keep the files PRESENT (nothing that probes for
|
|
150
|
+
// them by path breaks) but replace their body with a tiny, brand-free stub, turning
|
|
151
|
+
// the auto-load into a harmless "this doesn't govern you" redirect.
|
|
152
|
+
const AGENT_DOC_RE = /(^|\/)(CLAUDE|AGENTS)\.md$/i;
|
|
153
|
+
function isAgentDoc(p) { return AGENT_DOC_RE.test(String(p || '')); }
|
|
154
|
+
const CORE_AGENT_DOC_STUB = `# @bongos/core — installed platform dependency (not your project's CLAUDE.md)
|
|
155
|
+
|
|
156
|
+
This file is a placeholder shipped inside the **@bongos/core** package. The core's own
|
|
157
|
+
internal agent notes are intentionally omitted from the published artifact so they cannot
|
|
158
|
+
load into your instance's context.
|
|
159
|
+
|
|
160
|
+
**It does not govern this repository.** Your own root \`CLAUDE.md\`, your \`.claude/\`
|
|
161
|
+
directory, and the live Bongos database are the source of truth for how work happens here
|
|
162
|
+
and who may do what.
|
|
163
|
+
|
|
164
|
+
You are seeing this only because an agent opened a file under \`node_modules/@bongos/core/\`.
|
|
165
|
+
Nothing in here needs to be read to use the platform — run \`bongos help\` for commands.
|
|
166
|
+
|
|
167
|
+
_To work ON the platform core itself, use the standalone @bongos/core source repository,
|
|
168
|
+
not this vendored copy._
|
|
169
|
+
`;
|
|
170
|
+
|
|
139
171
|
// Fail-loud gate for a FUNCTIONAL file: only an exact live-credential value (an env-secret
|
|
140
172
|
// VALUE present verbatim, >= 8 chars) is a real leak. The sample is withheld (it's a secret).
|
|
141
173
|
function functionalSecretLeaks(view, envSecrets) {
|
|
@@ -154,6 +186,12 @@ function functionalSecretLeaks(view, envSecrets) {
|
|
|
154
186
|
// `advisories` = brand-identity substrings + public IPs that ship as-is (non-fatal, for
|
|
155
187
|
// human awareness) — REUSES findLeaks so the detector is defined once.
|
|
156
188
|
function processCoreFile({ pathRel, raw, rules, sensitiveLiterals, envSecrets }) {
|
|
189
|
+
// An auto-loaded agent doc (CLAUDE.md/AGENTS.md) → ship a brand-free stub, never the
|
|
190
|
+
// core's own project memory (task 2121). The stub is brand-free by construction, so it
|
|
191
|
+
// needs no redaction and can never leak — it short-circuits ahead of the doc path.
|
|
192
|
+
if (isAgentDoc(pathRel)) {
|
|
193
|
+
return { buf: Buffer.from(CORE_AGENT_DOC_STUB, 'utf8'), leaks: [], advisories: [], kind: 'stub' };
|
|
194
|
+
}
|
|
157
195
|
if (isDocPath(pathRel)) {
|
|
158
196
|
const r = redactBlob({ buf: raw, rules, sensitiveLiterals, envSecrets });
|
|
159
197
|
const leaks = r.leaks.map((l) => ({ label: `doc:${l.label}`, sample: l.sample }));
|
|
@@ -174,7 +212,7 @@ function processCoreFile({ pathRel, raw, rules, sensitiveLiterals, envSecrets })
|
|
|
174
212
|
//
|
|
175
213
|
// The source repo's package.json/package-lock.json (isPublishable() includes
|
|
176
214
|
// both) are GAME-heavy — colyseus/phaser/sharp/discord.js plus the repo's own
|
|
177
|
-
// name/version — and are not what a downstream `npm install @
|
|
215
|
+
// name/version — and are not what a downstream `npm install @bongos/core`
|
|
178
216
|
// should see. These two files are SYNTHESIZED here (never copied verbatim from
|
|
179
217
|
// git) and staged in their place. Everything else still ships through the
|
|
180
218
|
// normal isPublishable()/processCoreFile path.
|
|
@@ -195,27 +233,42 @@ function buildPackageJson({ version, sourceDeps, sourceOverrides }) {
|
|
|
195
233
|
dependencies[name] = range;
|
|
196
234
|
}
|
|
197
235
|
const pkg = {
|
|
198
|
-
name: '@
|
|
236
|
+
name: '@bongos/core',
|
|
199
237
|
version,
|
|
200
238
|
description: 'Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).',
|
|
201
239
|
license: 'AGPL-3.0-or-later',
|
|
202
240
|
main: 'src/platform-server.js',
|
|
203
241
|
bin: { bongos: 'bin/bongos.js' },
|
|
204
242
|
// Named exports a consumer imports directly, alongside the default entry
|
|
205
|
-
// (buildPlatformApp, from `main`)
|
|
206
|
-
//
|
|
207
|
-
// module-api doorway a
|
|
243
|
+
// (buildPlatformApp, from `main`). Two groups:
|
|
244
|
+
// • the platform surface — serve-internal (the shared host-routing surface
|
|
245
|
+
// both server.js and platform-server.js call) + the module-api doorway a
|
|
246
|
+
// module's routes/seams are authored against.
|
|
247
|
+
// • the GAME-HOST KIT (rehearsal F3, task 2161) — the core internals a
|
|
248
|
+
// game-bearing instance's own entrypoint (server.js, kept host per task
|
|
249
|
+
// 2134) wires directly: the API-404 shaping, the uptime poller, the module
|
|
250
|
+
// loader, the enabled-module gate, and the seam registry. A game-less
|
|
251
|
+
// instance boots via `.`/platform-server.js and never imports these; a game
|
|
252
|
+
// instance's server.js requires them, and the cutover codemod
|
|
253
|
+
// (scripts/gds/cutover-codemod.js) rewrites its relative `./src/*` requires
|
|
254
|
+
// to exactly these subpaths. Every subpath the codemod's CORE_INTERNAL_MAP
|
|
255
|
+
// targets MUST appear here or the rewritten require won't resolve.
|
|
208
256
|
exports: {
|
|
209
257
|
'.': './src/platform-server.js',
|
|
210
258
|
'./serve-internal': './src/bongos/serve-internal.js',
|
|
211
259
|
'./module-api': './src/module-api.js',
|
|
260
|
+
'./bongos/api-path-404': './src/bongos/api-path-404.js',
|
|
261
|
+
'./bongos/uptime-poller': './src/bongos/uptime-poller.js',
|
|
262
|
+
'./module-loader/loader': './src/module-loader/loader.js',
|
|
263
|
+
'./modules': './src/modules.js',
|
|
264
|
+
'./module-seams': './src/module-seams.js',
|
|
212
265
|
},
|
|
213
266
|
engines: { node: '>=22' },
|
|
214
267
|
// Pre-launch distribution posture (task 2089 / ADR 0134): publish PRIVATE by
|
|
215
268
|
// default. `access:"restricted"` makes a scoped package private on publish, so a
|
|
216
269
|
// paid npm org can ship it where only members can install — no accidental public
|
|
217
270
|
// leak if someone forgets the CLI flag. Going public at launch is one step:
|
|
218
|
-
// `npm access public @
|
|
271
|
+
// `npm access public @bongos/core` (or flip this to "public"). The name must
|
|
219
272
|
// stay SCOPED to be private at all — unscoped npm names are always public.
|
|
220
273
|
publishConfig: { access: 'restricted' },
|
|
221
274
|
dependencies,
|
|
@@ -481,7 +534,7 @@ function publishTarball({ tgzPath, live }) {
|
|
|
481
534
|
if (!live) {
|
|
482
535
|
console.error(' Dry-run: nothing is uploaded. To publish for real: re-run with --publish --live.');
|
|
483
536
|
console.error(' That is PERMANENT and requires `npm login` + the cloudbongos npm org on a paid plan');
|
|
484
|
-
console.error(' (private scoped publish needs one). Going public later: `npm access public @
|
|
537
|
+
console.error(' (private scoped publish needs one). Going public later: `npm access public @bongos/core`.');
|
|
485
538
|
}
|
|
486
539
|
const r = spawnSync(NPM_BIN, args, { cwd: REPO_ROOT, stdio: ['inherit', process.stderr, 'inherit'] });
|
|
487
540
|
if (r.error || r.status !== 0) {
|
|
@@ -489,7 +542,7 @@ function publishTarball({ tgzPath, live }) {
|
|
|
489
542
|
if (live) console.error(' Common causes: not logged in (`npm login`), the org isn’t on a paid plan (private scoped publish requires one), or 2FA.');
|
|
490
543
|
process.exit(r.status || 1);
|
|
491
544
|
}
|
|
492
|
-
console.error(`[package-core] npm publish ${live ? 'succeeded — @
|
|
545
|
+
console.error(`[package-core] npm publish ${live ? 'succeeded — @bongos/core is live (private).' : 'dry-run OK — the tarball is publishable.'}`);
|
|
493
546
|
}
|
|
494
547
|
|
|
495
548
|
function main() {
|
|
@@ -520,7 +573,7 @@ function main() {
|
|
|
520
573
|
|
|
521
574
|
// 2b. Synthesize the core's own package.json + pruned package-lock.json from the
|
|
522
575
|
// SOURCE files at this ref (never the live working tree, so --ref stays
|
|
523
|
-
// reproducible) — express+pg only, name @
|
|
576
|
+
// reproducible) — express+pg only, name @bongos/core, version = the
|
|
524
577
|
// platform version being packaged.
|
|
525
578
|
const pkgJsonBlob = entries.find((e) => e.path === 'package.json');
|
|
526
579
|
const pkgLockBlob = entries.find((e) => e.path === 'package-lock.json');
|
|
@@ -557,6 +610,7 @@ function main() {
|
|
|
557
610
|
const advisories = []; // { path, label, sample } — non-fatal (brand/IP that ships verbatim)
|
|
558
611
|
let docCount = 0;
|
|
559
612
|
let funcCount = 0;
|
|
613
|
+
let stubCount = 0; // agent docs (CLAUDE.md/AGENTS.md) replaced with the brand-free stub (task 2121)
|
|
560
614
|
for (const e of publishable) {
|
|
561
615
|
let raw;
|
|
562
616
|
try { raw = gitBuf(['cat-file', 'blob', e.sha]); }
|
|
@@ -565,7 +619,7 @@ function main() {
|
|
|
565
619
|
processCoreFile({ pathRel: e.path, raw, rules, sensitiveLiterals, envSecrets });
|
|
566
620
|
for (const l of fileLeaks) leaks.push({ path: e.path, label: l.label, sample: l.sample });
|
|
567
621
|
for (const a of fileAdvisories) advisories.push({ path: e.path, label: a.label, sample: a.sample });
|
|
568
|
-
if (kind === 'doc') docCount++; else funcCount++;
|
|
622
|
+
if (kind === 'doc') docCount++; else if (kind === 'stub') stubCount++; else funcCount++;
|
|
569
623
|
filesMeta.push({ path: e.path, mode: e.mode, sha256: sha256hex(buf) });
|
|
570
624
|
staged.push({ name: TAR_ROOT + e.path, mode: parseInt(normalizeMode(e.mode), 8), buf });
|
|
571
625
|
}
|
|
@@ -593,7 +647,7 @@ function main() {
|
|
|
593
647
|
console.error(' for a live-credential leak, remove the secret at SOURCE (it should never be committed). Then re-run. dist/ was NOT touched.');
|
|
594
648
|
process.exit(1);
|
|
595
649
|
}
|
|
596
|
-
console.error(`[package-core] no-leak gate PASSED — ${staged.length} files clean (${docCount} docs redacted, ${funcCount} functional verbatim).`);
|
|
650
|
+
console.error(`[package-core] no-leak gate PASSED — ${staged.length} files clean (${docCount} docs redacted, ${stubCount} agent-docs stubbed, ${funcCount} functional verbatim).`);
|
|
597
651
|
|
|
598
652
|
// Advisory: brand-identity + public-IP literals that ship VERBATIM inside functional
|
|
599
653
|
// files. Not a leak (these are public, not secrets; a downstream rebrands via config) —
|
|
@@ -614,6 +668,7 @@ function main() {
|
|
|
614
668
|
redaction: {
|
|
615
669
|
model: 'docs-redacted+functional-verbatim', // task 1824
|
|
616
670
|
docs_redacted: docCount,
|
|
671
|
+
agent_docs_stubbed: stubCount, // CLAUDE.md/AGENTS.md → brand-free stub (task 2121)
|
|
617
672
|
functional_verbatim: funcCount,
|
|
618
673
|
rules: rules.length,
|
|
619
674
|
gate_literals: sensitiveLiterals.length,
|
|
@@ -675,6 +730,8 @@ module.exports = {
|
|
|
675
730
|
octal, tarChecksum, ustarHeader, splitUstarName, buildTar,
|
|
676
731
|
// task 1824 — the consumer-core file-classification layer (pure; unit-tested)
|
|
677
732
|
isDocPath, functionalSecretLeaks, processCoreFile,
|
|
733
|
+
// task 2121 — agent-doc (CLAUDE.md/AGENTS.md) stub so a consumer's node_modules can't auto-load core memory
|
|
734
|
+
isAgentDoc, CORE_AGENT_DOC_STUB,
|
|
678
735
|
// task 1882 (ADR 0108 §2) — the real installable npm package
|
|
679
736
|
CORE_DEP_NAMES, buildPackageJson, resolveLockDep, lockfileClosure, prunePackageLock,
|
|
680
737
|
// task 2089 (ADR 0134) — private-by-default npm publish
|
package/scripts/gds/provision.js
CHANGED
|
@@ -56,6 +56,12 @@ const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
|
56
56
|
// plain require (its require.main guard means importing it runs no CLI).
|
|
57
57
|
const oauthSecret = require('./oauth-secret');
|
|
58
58
|
|
|
59
|
+
// The registry-install gates + env-fed .npmrc (ADR 0134, task 2090). Lets the
|
|
60
|
+
// standalone scaffold OPT IN to pulling the PRIVATE @bongos/core from the npm
|
|
61
|
+
// registry (PROVISION_CORE_FROM_REGISTRY=1) instead of vendoring a tarball, with a
|
|
62
|
+
// fail-soft fallback to the vendored path when no NPM_TOKEN is present.
|
|
63
|
+
const { registryCoreRequested, hasNpmToken } = require('./npmrc');
|
|
64
|
+
|
|
59
65
|
// The HTTP User-Agent the manifest conversion stamps its GitHub call with (GitHub
|
|
60
66
|
// requires a UA). Overridable so a fork can identify itself; not secret.
|
|
61
67
|
const MANIFEST_UA = process.env.PROVISION_GITHUB_UA || 'cloudbongos-provisioner';
|
|
@@ -118,7 +124,7 @@ const CONFIG = {
|
|
|
118
124
|
// since the control plane and the run box are then the same machine.
|
|
119
125
|
controlPlaneIp: process.env.PROVISION_CONTROL_PLANE_IP || null,
|
|
120
126
|
// Parent dir for a STANDALONE instance's OWN repo checkout (hosting_shape='standalone',
|
|
121
|
-
// ADR 0108): each lives at <standaloneBase>/<slug> with @
|
|
127
|
+
// ADR 0108): each lives at <standaloneBase>/<slug> with @bongos/core installed as
|
|
122
128
|
// an npm dep. Distinct from co-tenant (which shares THIS control-plane checkout).
|
|
123
129
|
standaloneBase: process.env.PROVISION_STANDALONE_BASE || '/srv/cloudbongos',
|
|
124
130
|
// ── Privilege escalation (task 2066, ADR 0128) ───────────────────────────
|
|
@@ -207,13 +213,45 @@ function migrateCmd(inst, { privileged = false } = {}) {
|
|
|
207
213
|
: `PGDATABASE=${dbName(inst)} MEDUSA_GDS_ONLY=1 ./scripts/migrate.sh`;
|
|
208
214
|
}
|
|
209
215
|
|
|
216
|
+
// Seed the instance's FIRST version so it can take tasks from minute one (task 2119,
|
|
217
|
+
// goal 35). A freshly-migrated instance DB comes up with an EMPTY versions table —
|
|
218
|
+
// migrate runs instance-seeds-off (ADR 0105) and `bongos init` ran --no-seed — yet
|
|
219
|
+
// every task requires a version (tasks.version_id NOT NULL) and POST /versions is
|
|
220
|
+
// Archon-only (no Archon exists until first sign-in). Without a seed here, a brand-new
|
|
221
|
+
// project has NOWHERE to file a task. This runs on the box's DB path (no rank gate),
|
|
222
|
+
// ONLY IF the versions table is empty: idempotent, safe to re-run, and it never
|
|
223
|
+
// disturbs a project that already has versions. Mirrors seedViaApi's shape — V1
|
|
224
|
+
// (status 'building') + one done-when criterion so /status has a finish line from day
|
|
225
|
+
// one. `track` is set EXPLICITLY: versions.track is NOT NULL with no default (mig 112
|
|
226
|
+
// dropped the CHECK), and 'product' matches the canonical V1 seed in 003_pms.sql.
|
|
227
|
+
//
|
|
228
|
+
// The id/name/done_when come from instanceInitSpec so the starter version has ONE
|
|
229
|
+
// source of truth (the same spec the greenfield `bongos init` seed uses). SQL string
|
|
230
|
+
// literals are DOLLAR-QUOTED ($v$…$v$) so the whole -c argument is single-quoted —
|
|
231
|
+
// the one form that is safe UNCHANGED across all three executors: inline (/bin/sh),
|
|
232
|
+
// over SSH (bash -s), AND embedded in a dedicated droplet's cloud-init (bash -lc "…"),
|
|
233
|
+
// with no nested-quote or $-expansion hazard.
|
|
234
|
+
function seedFirstVersionCmd(inst, { privileged = false } = {}) {
|
|
235
|
+
const v = instanceInitSpec(inst).version;
|
|
236
|
+
const q = (s) => `$v$${s}$v$`; // dollar-quoted literal (no value contains a single quote or $)
|
|
237
|
+
const sql =
|
|
238
|
+
`INSERT INTO versions (id, name, track, status, done_when) ` +
|
|
239
|
+
`SELECT ${q(v.id)}, ${q(v.name)}, $v$product$v$, $v$building$v$, ${q(v.done_when)} ` +
|
|
240
|
+
`WHERE NOT EXISTS (SELECT 1 FROM versions); ` +
|
|
241
|
+
`INSERT INTO done_when_criteria (version_id, criterion_id, criterion_md, sort_order) ` +
|
|
242
|
+
`SELECT ${q(v.id)}, $v$first-goal$v$, ${q(v.done_when)}, 10 ` +
|
|
243
|
+
`WHERE EXISTS (SELECT 1 FROM versions WHERE id = ${q(v.id)}) ` +
|
|
244
|
+
`AND NOT EXISTS (SELECT 1 FROM done_when_criteria WHERE version_id = ${q(v.id)} AND criterion_id = $v$first-goal$v$);`;
|
|
245
|
+
return asPostgres(`psql -v ON_ERROR_STOP=1 -d ${dbName(inst)} -c '${sql}'`, privileged);
|
|
246
|
+
}
|
|
247
|
+
|
|
210
248
|
// ── STANDALONE shape (hosting_shape='standalone', ADR 0108, task 1978) ────────
|
|
211
249
|
// A standalone instance runs from its OWN repo checkout (host content: config/,
|
|
212
|
-
// migrations/instance/, the core PIN in package.json) with @
|
|
250
|
+
// migrations/instance/, the core PIN in package.json) with @bongos/core installed
|
|
213
251
|
// as an npm DEPENDENCY — NOT the shared control-plane checkout the co-tenant shape uses.
|
|
214
252
|
// It is the ADR 0108 DESTINATION model; these generators make provision.js drive the
|
|
215
253
|
// scripts/deploy/deploy-instance.sh runbook API-driven instead of by hand.
|
|
216
|
-
const CORE_PKG_DIR = 'node_modules/@
|
|
254
|
+
const CORE_PKG_DIR = 'node_modules/@bongos/core';
|
|
217
255
|
function standaloneRoot(inst, { base = CONFIG.standaloneBase } = {}) { return path.posix.join(base, inst.slug); }
|
|
218
256
|
// Sync the instance's own repo (host content + the core pin). Mirrors deploy-instance.sh
|
|
219
257
|
// step 1 — assumes the repo is already cloned at standaloneRoot (initial clone is a
|
|
@@ -281,7 +319,7 @@ function instanceInitSpec(inst, { ownerLogin } = {}) {
|
|
|
281
319
|
const INSTANCE_GITIGNORE = ['node_modules/', 'dist/', '.env', '.env.local', '*.log', ''].join('\n');
|
|
282
320
|
|
|
283
321
|
// Clone the (empty) target_ref → standaloneRoot → materialize config/ + .claude/ + a
|
|
284
|
-
// file:-pinned @
|
|
322
|
+
// file:-pinned @bongos/core + lockfile (via `bongos init --vendor-core`, task 2053)
|
|
285
323
|
// → commit + push. Idempotent (skips once the repo carries a package.json) and dry-run
|
|
286
324
|
// safe (every mutation goes through the injected exec/writeFile). ADR 0108 / 0125.
|
|
287
325
|
async function scaffoldStandaloneRepo(inst, deps) {
|
|
@@ -327,23 +365,44 @@ async function scaffoldStandaloneRepo(inst, deps) {
|
|
|
327
365
|
}
|
|
328
366
|
exec(`git -C ${root} checkout -B main`);
|
|
329
367
|
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
|
|
368
|
+
// Core-install path (ADR 0134, task 2090). DEFAULT = vendor a tarball built from THIS
|
|
369
|
+
// control-plane checkout (offline, proven — task 2053). OPT-IN = pull the PRIVATE
|
|
370
|
+
// @bongos/core from the npm registry (PROVISION_CORE_FROM_REGISTRY=1). The registry
|
|
371
|
+
// path needs NPM_TOKEN at `npm ci` time; if the flag is set but no token is present we
|
|
372
|
+
// FAIL SOFT to the vendored path so a tokenless standup still works (never a broken
|
|
373
|
+
// instance). The env is injectable for tests; the runner falls back to process.env.
|
|
374
|
+
const env = deps.env || process.env;
|
|
375
|
+
const wantRegistry = registryCoreRequested(env);
|
|
376
|
+
const useRegistry = wantRegistry && hasNpmToken(env);
|
|
377
|
+
if (wantRegistry && !useRegistry) {
|
|
378
|
+
log(' [scaffold] PROVISION_CORE_FROM_REGISTRY set but no NPM_TOKEN in env — falling back to the vendored-tarball core (ADR 0134 fail-soft).');
|
|
379
|
+
}
|
|
333
380
|
|
|
334
|
-
//
|
|
335
|
-
//
|
|
381
|
+
// materialize config/ + .claude/ + a pinned package.json + lockfile via `bongos init`.
|
|
382
|
+
// --no-seed: the instance's own DB is seeded by migrate, not here. Two mutually
|
|
383
|
+
// exclusive core-resolution shapes:
|
|
384
|
+
// registry (--registry-core): caret pin + env-fed .npmrc; `npm ci` pulls from the
|
|
385
|
+
// registry. init generates the lockfile (NPM_TOKEN is present — we gated on it).
|
|
386
|
+
// vendored (--vendor-core, default): a tarball built from this checkout, file:-pinned.
|
|
336
387
|
const spec = instanceInitSpec(inst, { ownerLogin });
|
|
337
388
|
const specPath = path.join(os.tmpdir(), `bongos-init-${inst.slug}.json`);
|
|
338
389
|
writeFile(specPath, JSON.stringify(spec, null, 2));
|
|
339
|
-
|
|
390
|
+
if (useRegistry) {
|
|
391
|
+
log(` [scaffold] core install: registry — PRIVATE @bongos/core@${coreV} via env-fed NPM_TOKEN (ADR 0134)`);
|
|
392
|
+
exec(`node scripts/gds/init.js --from ${specPath} --dir ${root} --no-seed --force --registry-core`);
|
|
393
|
+
} else {
|
|
394
|
+
log(` [scaffold] core install: vendored tarball (offline default)`);
|
|
395
|
+
exec(`node scripts/gds/package-core.js`); // cwd = REPO_ROOT → dist/bongos-core-<v>.tgz
|
|
396
|
+
const tgz = path.join(REPO_ROOT, 'dist', `bongos-core-${coreV}.tgz`);
|
|
397
|
+
exec(`node scripts/gds/init.js --from ${specPath} --dir ${root} --no-seed --force --vendor-core ${tgz}`);
|
|
398
|
+
}
|
|
340
399
|
|
|
341
400
|
// 4. commit + push the scaffold to the instance's own main (keep node_modules out).
|
|
342
401
|
writeFile(path.join(root, '.gitignore'), INSTANCE_GITIGNORE);
|
|
343
402
|
exec(`git -C ${root} config user.name "Cloud Bongos"`);
|
|
344
403
|
exec(`git -C ${root} config user.email "bot@cloudbongos.com"`);
|
|
345
404
|
exec(`git -C ${root} add -A`);
|
|
346
|
-
exec(`git -C ${root} commit -m "chore: scaffold ${inst.slug} on a pinned @
|
|
405
|
+
exec(`git -C ${root} commit -m "chore: scaffold ${inst.slug} on a pinned @bongos/core ${coreV} (provision.js, ADR 0108)"`, { allowFail: true });
|
|
347
406
|
exec(`git -C ${root} push -u origin main`);
|
|
348
407
|
log(` [scaffold] pushed initial scaffold to ${repo.owner}/${repo.name}@main`);
|
|
349
408
|
return { ok: true, scaffolded: true };
|
|
@@ -446,11 +505,25 @@ ${prefix}_OAUTH_ORIGIN=${origin}
|
|
|
446
505
|
# GitHub App Manifest flow (ADR 0133) — the owner clicked one link; no secret was pasted.`
|
|
447
506
|
: `# Provisioned by scripts/gds/provision.js (ADR 0111). Fill the OAuth app creds via the
|
|
448
507
|
# one-click GitHub App Manifest flow (ADR 0133), or manually (oauth-secret.js place):`;
|
|
508
|
+
// The founding owner (firstAdmin): the GitHub login src/bongos/auth.js seats as the
|
|
509
|
+
// instance's first Archon on first sign-in (maybeSeatFirstAdmin checks
|
|
510
|
+
// <prefix>_FIRST_ADMIN before branding.firstAdmin). WITHOUT it a provisioned instance
|
|
511
|
+
// has NO owner — first sign-in is refused / lands rankless and the owner can never
|
|
512
|
+
// claim their own instance (goal 35 / criterion 165 regression, caught live 2026-07-07:
|
|
513
|
+
// demo had every origin override but no FIRST_ADMIN, so lars589 could not be seated).
|
|
514
|
+
// Derived from the instance repo owner (target_ref = "<owner>/<repo>"), the SAME source
|
|
515
|
+
// instanceInitSpec uses for the scaffold's branding.firstAdmin — so this env override and
|
|
516
|
+
// the scaffolded config/branding.json agree. (Org-owned repo: the org login is not a
|
|
517
|
+
// sign-in identity, so it is left unset; the owner sets <prefix>_FIRST_ADMIN by hand.)
|
|
518
|
+
const ownerRepo = parseTargetRef(inst.target_ref);
|
|
519
|
+
const firstAdminLine = ownerRepo && ownerRepo.owner
|
|
520
|
+
? `${prefix}_FIRST_ADMIN=${ownerRepo.owner}\n`
|
|
521
|
+
: '';
|
|
449
522
|
return `# /etc/${inst.slug}/web.env — per-instance secrets (chmod 600, OUTSIDE the repo).
|
|
450
523
|
${credComment}
|
|
451
524
|
${prefix}_GITHUB_CLIENT_ID=${clientId || ''}
|
|
452
525
|
${prefix}_GITHUB_CLIENT_SECRET=${clientSecret || ''}
|
|
453
|
-
GDS_BRANDING_FILE=${PROVISIONED_BRANDING_FILE}
|
|
526
|
+
${firstAdminLine}GDS_BRANDING_FILE=${PROVISIONED_BRANDING_FILE}
|
|
454
527
|
${originLines}PORT=${inst.port}
|
|
455
528
|
PGDATABASE=${dbName(inst)}
|
|
456
529
|
`;
|
|
@@ -808,7 +881,7 @@ async function provisionInstance(inst, deps) {
|
|
|
808
881
|
// Co-tenant OR standalone: a process bound to an allocated port on the box it runs
|
|
809
882
|
// on. Co-tenant shares that box's checkout ($0, cloudbongos.com model — under
|
|
810
883
|
// remote-exec, the co-hosting box); standalone (ADR 0108) runs from its OWN repo
|
|
811
|
-
// dir with a pinned @
|
|
884
|
+
// dir with a pinned @bongos/core (synced in step 2) on the CONTROL PLANE.
|
|
812
885
|
// Allocate against the ports of whichever box it runs on (boxExec: remote for a
|
|
813
886
|
// co-tenant, local for a standalone — task 2074), then run the rest there.
|
|
814
887
|
if (!inst.port) {
|
|
@@ -838,11 +911,16 @@ async function provisionInstance(inst, deps) {
|
|
|
838
911
|
// ── step 2: code sync (standalone) + database ─────────────────────────────
|
|
839
912
|
if (local && standalone) {
|
|
840
913
|
// Standalone (ADR 0108 / deploy-instance.sh steps 1-2): sync the instance's own
|
|
841
|
-
// repo + install the pinned @
|
|
914
|
+
// repo + install the pinned @bongos/core, so the migrate + service below run
|
|
842
915
|
// from the INSTANCE root, not this control-plane checkout. cwd = standaloneRoot.
|
|
843
916
|
// boxExec = the control plane (where scaffoldStandaloneRepo just created the dir).
|
|
917
|
+
// REGISTRY CORE (ADR 0134): when the scaffold pinned the registry core, the committed
|
|
918
|
+
// .npmrc reads `_authToken=${NPM_TOKEN}` — so `npm ci` resolves the PRIVATE package
|
|
919
|
+
// only if NPM_TOKEN is in this runner's env (makeExec inherits process.env). The
|
|
920
|
+
// scaffold already gated on the token, so it is present; the VENDORED default needs
|
|
921
|
+
// no token (the tarball is committed). A tokenless registry `npm ci` 404s cleanly.
|
|
844
922
|
const root = standaloneRoot(inst);
|
|
845
|
-
log(' [code] standalone — pull instance repo + npm ci (pinned @
|
|
923
|
+
log(' [code] standalone — pull instance repo + npm ci (pinned @bongos/core)');
|
|
846
924
|
boxExec(standalonePullCmd(), { cwd: root });
|
|
847
925
|
boxExec(standaloneInstallCmd(), { cwd: root });
|
|
848
926
|
}
|
|
@@ -851,7 +929,13 @@ async function provisionInstance(inst, deps) {
|
|
|
851
929
|
boxExec(dbCreateCmd(inst, { privileged }), { allowFail: true }); // "already exists" is fine
|
|
852
930
|
if (standalone) boxExec(standaloneMigrateCmd(inst, { privileged }), { cwd: standaloneRoot(inst) }); // instance-root migrate
|
|
853
931
|
else boxExec(migrateCmd(inst, { privileged }));
|
|
854
|
-
|
|
932
|
+
// Seed the first version so the instance can take tasks from minute one (task 2119,
|
|
933
|
+
// goal 35). Only fires if the versions table is empty — idempotent, never disturbs an
|
|
934
|
+
// existing project. NOT allowFail: a re-run is a clean 0-row no-op, so a real failure
|
|
935
|
+
// here should surface. Dedicated bakes the same step into cloud-init (dedicatedUserData).
|
|
936
|
+
log(' [seed] first version (only if versions is empty)');
|
|
937
|
+
boxExec(seedFirstVersionCmd(inst, { privileged }));
|
|
938
|
+
} else { log(' (db create + migrate + first-version seed run via cloud-init on the droplet)'); }
|
|
855
939
|
|
|
856
940
|
// ── step 3: config + per-instance secrets ─────────────────────────────────
|
|
857
941
|
log(' [config] per-instance web.env');
|
|
@@ -929,6 +1013,7 @@ function dedicatedUserData(inst) {
|
|
|
929
1013
|
runcmd:
|
|
930
1014
|
- [ bash, -lc, "${dbCreateCmd(i)} || true" ]
|
|
931
1015
|
- [ bash, -lc, "cd ${REPO_ROOT} && ${migrateCmd(i)}" ]
|
|
1016
|
+
- [ bash, -lc, "${seedFirstVersionCmd(i)}" ]
|
|
932
1017
|
- [ bash, -lc, "systemctl daemon-reload && systemctl enable --now ${i.slug}" ]
|
|
933
1018
|
`;
|
|
934
1019
|
}
|
|
@@ -1310,7 +1395,7 @@ if (require.main === module) main();
|
|
|
1310
1395
|
module.exports = {
|
|
1311
1396
|
CONFIG, MAX_INTENT_ATTEMPTS,
|
|
1312
1397
|
// pure step generators (tested directly)
|
|
1313
|
-
dbName, dbCreateCmd, migrateCmd, serviceUnit, serviceUnitPath, webEnvBody, webEnvPath,
|
|
1398
|
+
dbName, dbCreateCmd, migrateCmd, seedFirstVersionCmd, serviceUnit, serviceUnitPath, webEnvBody, webEnvPath,
|
|
1314
1399
|
standaloneRoot, standalonePullCmd, standaloneInstallCmd, standaloneMigrateCmd,
|
|
1315
1400
|
// standalone scaffold (ADR 0108 / 0125, task 2055)
|
|
1316
1401
|
parseTargetRef, instanceRepoRemote, instanceInitSpec, scaffoldStandaloneRepo, coreVersionSafe,
|
|
@@ -44,7 +44,9 @@ const PUBLISH_ALLOWLIST = [
|
|
|
44
44
|
'src/', // platform engine + GDS core (the game residue is denied below)
|
|
45
45
|
'scripts/', // build + methodology tooling (deploy is denied below)
|
|
46
46
|
'bin/', // the `cloudbongos`/`bongos` CLI entrypoint
|
|
47
|
-
|
|
47
|
+
// NB: repo-root server.js is the GAME+platform entry (top-level require('colyseus'),
|
|
48
|
+
// a pruned core dep) — HOST-excluded in CONTENT_EXCLUDE below; the core boots
|
|
49
|
+
// game-less via src/platform-server.js (package-core sets that as `main`). task 2134.
|
|
48
50
|
// --- the build system's shared schema + its tests ---
|
|
49
51
|
'migrations/',
|
|
50
52
|
'tests/',
|
|
@@ -63,6 +65,7 @@ const PUBLISH_ALLOWLIST = [
|
|
|
63
65
|
'modules/status-ui/',
|
|
64
66
|
'modules/dev-box/',
|
|
65
67
|
'modules/discord/',
|
|
68
|
+
'modules/provisioning/', // instance-hosting control plane — CORE like its sibling dev-box (same do-api/cf-tunnel toolchain, all core). Reclassified IN so the core CLI scripts/gds/provision.js resolves it from the core package post-split, not a MODULE_NOT_FOUND (task 2135). default:false — shipped ≠ enabled.
|
|
66
69
|
// --- neutral (customer-0) config starters + their schemas (the filled-in *.json twins are denied) ---
|
|
67
70
|
'config/branding.neutral.json',
|
|
68
71
|
'config/modules.neutral.json',
|
|
@@ -77,7 +80,7 @@ const PUBLISH_ALLOWLIST = [
|
|
|
77
80
|
'CONTRIBUTING.md',
|
|
78
81
|
'CODE_OF_CONDUCT.md',
|
|
79
82
|
'docs/adr/', // sanitized — ADR 0065 §4 "docs/ADRs (sanitized)"
|
|
80
|
-
'docs/recipes/',
|
|
83
|
+
'docs/recipes/', // portable METHODOLOGY recipes only; project-specific ones (art/staging/load-test/standup/decouple) are denied below — task 2153
|
|
81
84
|
'docs/design/',
|
|
82
85
|
'docs/research/',
|
|
83
86
|
'docs/architecture.md',
|
|
@@ -85,6 +88,11 @@ const PUBLISH_ALLOWLIST = [
|
|
|
85
88
|
// renders broken onboarding + API-reference pages (task 2078). Redacted like the
|
|
86
89
|
// rest of this docs section; the diagrams' .png/.svg regenerate on the box.
|
|
87
90
|
'docs/onboarding/', // primer.md + drachmae-and-karma.md + diagram sources (/builders/primer · /drachmae · /diagrams)
|
|
91
|
+
// API artifacts (classification settled, task 2141): CORE-shipped STARTERS so a fresh
|
|
92
|
+
// hall/docs render before first regen — but per-instance GENERATED. init + `bongos
|
|
93
|
+
// upgrade` regenerate them INTO the instance; the instance-root fitness gate
|
|
94
|
+
// (gen-api-docs --check) + tests/api_client.mjs guard drift. They ship; they are not a
|
|
95
|
+
// monolith-only artifact.
|
|
88
96
|
'docs/api/openapi.json', // the generated OpenAPI 3.1 spec served at /docs/openapi.json
|
|
89
97
|
'docs/api-reference.md', // the markdown API reference
|
|
90
98
|
'docs/modules-contract.md',
|
|
@@ -161,12 +169,33 @@ const CONTENT_EXCLUDE = [
|
|
|
161
169
|
'src/world/',
|
|
162
170
|
'src/rooms/',
|
|
163
171
|
'src/preview-server.js',
|
|
172
|
+
'server.js', // repo-root game+platform entry: top-level require('colyseus') (a pruned core dep) → un-runnable in the game-less package; the core boots via src/platform-server.js. Mirrors src/preview-server.js. (task 2134)
|
|
164
173
|
// the art feature's CLI tooling lives under scripts/ (legacy top-level) but belongs
|
|
165
174
|
// to the excluded art module — exclude it with the feature it serves.
|
|
166
175
|
'scripts/art/',
|
|
176
|
+
'scripts/gds/art-stage.js', // art sandbox-staging CLI: requires modules/art-pipeline's build_tilesheet.py; excluded with the art feature it serves so a core file never requires an excluded module (task 2135)
|
|
167
177
|
'scripts/tile-add.js',
|
|
168
178
|
'scripts/tile-find.js',
|
|
169
179
|
'scripts/tile-recommend.js',
|
|
180
|
+
// The art pipeline's operational RECIPE — belongs to the excluded art module; exclude it
|
|
181
|
+
// with the feature it serves (mirrors scripts/art/ above). docs/recipes/ is allowlisted
|
|
182
|
+
// wholesale, so this deny is what keeps the game-art recipe out of a non-art core. (task 2153)
|
|
183
|
+
'docs/recipes/pixel-art-pipeline.md',
|
|
184
|
+
// Host-feature TESTS that statically import an EXCLUDED module's source. tests/ is
|
|
185
|
+
// allowlisted (the platform/methodology suite is core), but these cover the game/art
|
|
186
|
+
// HOST modules and import their source directly — so package-core (which selects via
|
|
187
|
+
// isPublishable) would ship them WITHOUT the module they need → MODULE_NOT_FOUND when a
|
|
188
|
+
// core CI/consumer runs them, and the R89 cutover would DELETE OTB's own game/art tests
|
|
189
|
+
// (they cover kept host modules; they cannot live in core). Exclude each with the feature
|
|
190
|
+
// it serves — mirrors scripts/gds/art-stage.js above. The guard in tests/publish_manifest.mjs
|
|
191
|
+
// derives this set from disk and fails if a new host-module test is added but not listed. (task 2147)
|
|
192
|
+
'tests/walkability.mjs', // → modules/game/world
|
|
193
|
+
'tests/terrain_picker.mjs', // → modules/game/public/game/world
|
|
194
|
+
'tests/snapshot_picker.mjs', // → modules/game/public/game/world
|
|
195
|
+
'tests/sprite_facing.mjs', // → modules/game/public/game/player
|
|
196
|
+
'tests/turn_in_place.mjs', // → modules/game/public/game/player
|
|
197
|
+
'tests/day_cycle.mjs', // → modules/game/public/game/fx
|
|
198
|
+
'tests/art_key.mjs', // → modules/art-pipeline
|
|
170
199
|
];
|
|
171
200
|
|
|
172
201
|
// (4) INSTANCE IDENTITY + HISTORY — this host's literals, ops config, build history, and
|
|
@@ -178,6 +207,11 @@ const INSTANCE_EXCLUDE = [
|
|
|
178
207
|
'config/devbox-app.json',
|
|
179
208
|
'config/hierarchy.json',
|
|
180
209
|
'CODEOWNERS', // names the owner (a protected surface, excluded as identity)
|
|
210
|
+
// instance SEED migrations — this host's scope-truth SQL (planning seeds, world data).
|
|
211
|
+
// ADR 0105: a consumer's core must not carry them; migrate.sh reads instance seeds from
|
|
212
|
+
// resolveInstanceRoot() (SEED_INSTANCE), so the consumer repo owns them. Core migrations
|
|
213
|
+
// (migrations/core_NNN_*.sql + bare legacy migrations/NNN_*.sql) still publish. (task 2140)
|
|
214
|
+
'migrations/instance/',
|
|
181
215
|
// instance-specific docs + project history
|
|
182
216
|
'docs/project-context.md',
|
|
183
217
|
'docs/lore/',
|
|
@@ -192,6 +226,30 @@ const INSTANCE_EXCLUDE = [
|
|
|
192
226
|
'docs/graphics-stress-test-plan.md',
|
|
193
227
|
'docs/security-baseline.md',
|
|
194
228
|
'docs/routes-permissions.md',
|
|
229
|
+
// instance-specific OPERATIONAL recipes — this host's staging + load-test artifacts, its
|
|
230
|
+
// specific control-plane / vanity-door standups, and its one-time monolith-decouple runbook.
|
|
231
|
+
// docs/recipes/ is allowlisted wholesale for the PORTABLE methodology recipes; these teach
|
|
232
|
+
// nothing a different instance would use, so they stay in this repo and never ship in the
|
|
233
|
+
// core (mirrors migrations/instance above). Redaction only de-brands them — this stops the
|
|
234
|
+
// irrelevant-noise at the source. The module-owned RECIPE redesign is deferred (idea 536). (task 2153)
|
|
235
|
+
'docs/recipes/staging-data.md',
|
|
236
|
+
'docs/recipes/parallel-load-test.md',
|
|
237
|
+
'docs/recipes/parallel-load-results-2026-05-30.md',
|
|
238
|
+
'docs/recipes/claude-gemini-bongos-doors.md',
|
|
239
|
+
'docs/recipes/cloudbongos-standup.md',
|
|
240
|
+
'docs/recipes/cloudbongos-staging-gate.md',
|
|
241
|
+
'docs/recipes/amazonprimea-decouple-r89.md',
|
|
242
|
+
'docs/recipes/amazonprimea-decouple-rollback-r89.md',
|
|
243
|
+
// instance-specific GAME-DESIGN specs — this host's pixel-art / level briefs (the container
|
|
244
|
+
// buildings, its palette, the world-map scroll). docs/design/ is allowlisted wholesale for the
|
|
245
|
+
// PORTABLE design docs (modular-architecture/*, the vanilla-hall-ui redesign scope); these four
|
|
246
|
+
// describe THIS instance's game and genericize to nothing, so they stay in this repo and never
|
|
247
|
+
// ship in the core. Redaction only de-brands NAMES — the world-narrative prose in them is not a
|
|
248
|
+
// name and survives redaction, so exclude at the source (mirrors the recipe carve-out above). (task 2155)
|
|
249
|
+
'docs/design/container-exterior.md',
|
|
250
|
+
'docs/design/container-exterior-tiles.md',
|
|
251
|
+
'docs/design/container-interior.md',
|
|
252
|
+
'docs/design/world-map-scroll.md',
|
|
195
253
|
'blockers/',
|
|
196
254
|
'limitations/',
|
|
197
255
|
'generative-ideas.md',
|