@bongos/core 1.20.61 → 1.20.63
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 +82 -37
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +5 -1
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/adr/0357-the-update-rule-set-on-deploy-is-the-one-the-sweep-follows.md +2 -0
- package/docs/api/openapi.json +96 -3
- package/docs/api-reference.md +4 -3
- package/docs/copy-inventory.md +372 -324
- package/docs/copy-registry.json +881 -417
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +4 -1
- package/docs/page-readings.json +544 -481
- package/docs/recipes/upgrading-the-core.md +32 -1
- package/modules/provisioning/demo.js +176 -0
- package/modules/provisioning/migrations/provisioning_035_demo.sql +26 -0
- package/modules/provisioning/module.json +5 -3
- package/modules/provisioning/pollers/demo-archive.js +61 -0
- package/modules/provisioning/provisioning.js +2 -2
- package/modules/provisioning/routes/demo.js +54 -0
- package/modules/provisioning/routes/provisioning.js +7 -4
- package/modules/public-landing/public/projects-demo.states.json +53 -0
- package/modules/public-landing/public/projects.html +300 -23
- package/modules/public-landing/public/projects.probes.json +3 -3
- package/modules/public-landing/public/projects.states.json +2 -1
- package/modules/ui-design/kit/fixtures/provisioning-instances-demo.json +114 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +20 -0
- package/scripts/gds/provision-core-upgrade.js +16 -1
- package/scripts/gds/update-channel.js +11 -2
- package/scripts/gds/update-sweep.js +717 -0
- package/src/module-api.js +1 -1
- package/tests/core_upgrade_runner.mjs +13 -0
- package/tests/update_channel_db.mjs +13 -6
- package/tests/update_subscription_engine.mjs +5 -5
- package/tests/update_sweep_home.mjs +100 -0
- package/tests/wizard_demo.mjs +264 -0
- package/tests/wizard_front_door.mjs +16 -20
|
@@ -124,7 +124,31 @@ h1[tabindex="-1"]:focus:not(:focus-visible){outline:none;}
|
|
|
124
124
|
.doorPill{display:inline-grid;grid-template-columns:1fr 1fr;gap:6px;padding:7px;margin:6px 0 16px;border-radius:999px;border:1px solid var(--rule);background:color-mix(in srgb,var(--bg) 55%,transparent);}
|
|
125
125
|
#view-new .doorPill .btn.ghost{border-color:transparent;}
|
|
126
126
|
#view-new .doorPill .btn.ghost:hover{border-color:var(--rule);}
|
|
127
|
-
|
|
127
|
+
/* the demo route (task 1004420): two screens inside the fork. Steppers on the wizard's
|
|
128
|
+
field grammar, the fit check as a hairline band, the picked defaults as a ledger, and a
|
|
129
|
+
dashed ring on the planet for the time box (the canvas's "when it closes, the demo ends") */
|
|
130
|
+
.demoSteppers{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;}
|
|
131
|
+
.demoStep{display:flex;align-items:center;gap:12px;margin-top:6px;}
|
|
132
|
+
.demoStep output{min-width:2ch;text-align:center;font-family:var(--font-display);font-weight:300;font-size:28px;color:var(--ink);}
|
|
133
|
+
.demoStep .btn{min-width:40px;min-height:40px;justify-content:center;}
|
|
134
|
+
.demoFit{border-top:1px solid var(--rule);padding:14px 0 6px;margin:0 0 10px;max-width:62ch;}
|
|
135
|
+
.demoFitLine{font-size:15.5px;line-height:1.5;color:var(--ink);margin:8px 0 12px;}
|
|
136
|
+
.demoFitTry{font-size:14px;color:var(--ink-soft);margin:0 0 4px;}
|
|
137
|
+
.demoTry{margin:0 0 6px;padding-left:18px;font-size:14.5px;line-height:1.6;color:var(--ink);}
|
|
138
|
+
.demoLedger{display:grid;grid-template-columns:150px minmax(0,1fr);gap:0;margin:6px 0 18px;border-top:1px solid var(--rule);}
|
|
139
|
+
.demoLedger dt,.demoLedger dd{margin:0;padding:11px 0;border-bottom:1px solid var(--rule-soft);}
|
|
140
|
+
.demoLedger dt{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);padding-top:14px;}
|
|
141
|
+
.demoLedger dd{font-size:15.5px;color:var(--ink);}
|
|
142
|
+
.demoLedger dd small{display:block;font-size:13.5px;color:var(--ink-soft);margin-top:2px;}
|
|
143
|
+
.demoInvites{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;}
|
|
144
|
+
.demoRing{position:absolute;inset:4%;border:1px dashed color-mix(in srgb,var(--accent) 55%,transparent);border-radius:50%;}
|
|
145
|
+
.demoKeep{border-top:1px solid var(--rule);padding-top:14px;margin:6px 0 10px;}
|
|
146
|
+
.demoKeepH{font-family:var(--font-display);font-weight:300;font-size:24px;letter-spacing:-.02em;text-transform:lowercase;color:var(--ink);margin:0 0 10px;}
|
|
147
|
+
.demoKeepCells{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;}
|
|
148
|
+
.demoClock{font-size:15.5px;color:var(--ink);margin:0 0 10px;}
|
|
149
|
+
.demoSoonWarn{color:var(--warn);font-weight:600;}
|
|
150
|
+
.demoStageCap{position:absolute;left:16px;right:16px;bottom:14px;margin:0;font-size:13px;line-height:1.4;color:var(--ink);}
|
|
151
|
+
@media (max-width:640px){ .demoSteppers,.demoInvites,.demoKeepCells{grid-template-columns:1fr;} .demoLedger{grid-template-columns:1fr;} .demoLedger dt{border-bottom:0;padding-bottom:0;} }
|
|
128
152
|
/* the seed on the field plate: the world's own render, a hairline orbit and a
|
|
129
153
|
dashed one, the chrome blob cut out on top — nothing drawn but hairlines */
|
|
130
154
|
.forkBody{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,380px);gap:48px;align-items:center;}
|
|
@@ -912,6 +936,32 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
912
936
|
again. For a project whose app has no platform chosen, the OWNER is offered
|
|
913
937
|
Connect Render (task 1004184): the setup wizard's own Render step, cloned into
|
|
914
938
|
#mAppConnectForm on first open, so there is one flow and one set of words. -->
|
|
939
|
+
<!-- the demo (task 1004420, BV2.PS09; the canvas's DemoKeep): a project marked demo
|
|
940
|
+
shows its soft time box counting down, then asks "keep your planet?". Carry it
|
|
941
|
+
over and it is a real project from here on; keep it as a demo and it still goes
|
|
942
|
+
offline 30 days after it started (D9), restorable like any project taken
|
|
943
|
+
offline. The owner is told the date here from the start. Hidden for every
|
|
944
|
+
project that is not a demo. -->
|
|
945
|
+
<div class="card mSec" id="mDemo" hidden>
|
|
946
|
+
<h2>Demo planet</h2>
|
|
947
|
+
<p class="demoClock" id="mDemoClock"></p>
|
|
948
|
+
<div class="demoKeep" id="mDemoKeep" hidden>
|
|
949
|
+
<p class="demoKeepH">Keep your planet?</p>
|
|
950
|
+
<div class="demoKeepCells">
|
|
951
|
+
<div>
|
|
952
|
+
<button type="button" class="btn" data-demo-settle="carried">Carry it over</button>
|
|
953
|
+
<p class="finePrint">It becomes a real project: its settings, team and work stay as they are, and the demo’s time limit and 30-day rule stop applying.</p>
|
|
954
|
+
</div>
|
|
955
|
+
<div>
|
|
956
|
+
<button type="button" class="btn ghost" data-demo-settle="kept">Keep it as a demo</button>
|
|
957
|
+
<p class="finePrint">Leave it as it is: a finished demo you can come back to until it goes offline.</p>
|
|
958
|
+
</div>
|
|
959
|
+
</div>
|
|
960
|
+
</div>
|
|
961
|
+
<p class="finePrint" id="mDemoOffline"></p>
|
|
962
|
+
<div class="projMsg" id="mDemoMsg" role="status" aria-live="polite"></div>
|
|
963
|
+
</div>
|
|
964
|
+
|
|
915
965
|
<div class="card mSec" id="mAppCard" hidden>
|
|
916
966
|
<h2>Where its app runs</h2>
|
|
917
967
|
<div id="mApp"></div>
|
|
@@ -1273,35 +1323,105 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1273
1323
|
<!-- step 2 · the front door, part two: demo or create (task 1004417; the canvas's
|
|
1274
1324
|
Fork.dc.html). Two equal ways in, so it is the world's door pill (DESIGN.md):
|
|
1275
1325
|
two doors joined into one object, equal in size, the accent only on the one
|
|
1276
|
-
that goes on. The seed stands on the field plate beside it. The demo
|
|
1277
|
-
|
|
1278
|
-
leading anywhere. -->
|
|
1326
|
+
that goes on. The seed stands on the field plate beside it. The demo door opens
|
|
1327
|
+
the demo route's two screens in place (task 1004420, BV2.PS09). -->
|
|
1279
1328
|
<section class="panel" id="panel-fork" aria-labelledby="fork-h">
|
|
1280
1329
|
<div class="forkBody">
|
|
1281
1330
|
<div>
|
|
1282
|
-
<
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
<
|
|
1286
|
-
<
|
|
1287
|
-
|
|
1331
|
+
<div id="forkIntro">
|
|
1332
|
+
<h1 id="fork-h">You are now creating a digital planet</h1>
|
|
1333
|
+
<p class="lede">If that sounds like too much for now, try our demo system. Otherwise, proceed with planet initiation :)</p>
|
|
1334
|
+
<form data-next="3">
|
|
1335
|
+
<div class="doorPill" role="group" aria-label="How to begin">
|
|
1336
|
+
<button type="button" class="btn big ghost" id="wizDemo" aria-controls="demoSetup" aria-expanded="false">Try the demo</button>
|
|
1337
|
+
<button type="submit" class="btn big">Begin planet creation</button>
|
|
1338
|
+
</div>
|
|
1339
|
+
<div class="nav">
|
|
1340
|
+
<button type="button" class="btn ghost" data-back="1">← Back</button>
|
|
1341
|
+
<span></span>
|
|
1342
|
+
</div>
|
|
1343
|
+
</form>
|
|
1344
|
+
</div>
|
|
1345
|
+
<!-- the demo route (task 1004420, BV2.PS09; the canvas's DemoSetup and DemoReady).
|
|
1346
|
+
Two screens inside the fork, then the ordinary wizard from the name step on:
|
|
1347
|
+
a demo is a normal project marked "demo" (D9). The fit check is a copy of
|
|
1348
|
+
modules/provisioning/demo.js fitCheck, held equal by tests/wizard_demo.mjs. -->
|
|
1349
|
+
<div id="demoSetup" class="demoView" hidden>
|
|
1350
|
+
<h1 id="demo-h1">Training wheels</h1>
|
|
1351
|
+
<p class="lede">A small, time-boxed project to learn the platform by doing. Everyone uses their own AI plan.</p>
|
|
1352
|
+
<div class="demoSteppers">
|
|
1353
|
+
<div class="wizField"><span id="demoPeopleLbl">People, you included</span>
|
|
1354
|
+
<div class="demoStep" role="group" aria-labelledby="demoPeopleLbl">
|
|
1355
|
+
<button type="button" class="btn small ghost" data-demo-step="people" data-by="-1" aria-label="One fewer person">−</button>
|
|
1356
|
+
<output id="demoPeople" aria-live="polite">3</output>
|
|
1357
|
+
<button type="button" class="btn small ghost" data-demo-step="people" data-by="1" aria-label="One more person">+</button>
|
|
1358
|
+
</div>
|
|
1359
|
+
</div>
|
|
1360
|
+
<div class="wizField"><span id="demoHoursLbl">Hours each</span>
|
|
1361
|
+
<div class="demoStep" role="group" aria-labelledby="demoHoursLbl">
|
|
1362
|
+
<button type="button" class="btn small ghost" data-demo-step="hours" data-by="-1" aria-label="One hour less">−</button>
|
|
1363
|
+
<output id="demoHours" aria-live="polite">4</output>
|
|
1364
|
+
<button type="button" class="btn small ghost" data-demo-step="hours" data-by="1" aria-label="One hour more">+</button>
|
|
1365
|
+
</div>
|
|
1366
|
+
</div>
|
|
1367
|
+
</div>
|
|
1368
|
+
<label class="wizField"><span>Your demo project idea</span>
|
|
1369
|
+
<textarea id="demoIdea" rows="3" maxlength="600" placeholder="A shared reading list for our team: everyone adds books, we vote, and the winner is next month’s read."></textarea>
|
|
1370
|
+
</label>
|
|
1371
|
+
<div class="demoFit" aria-live="polite">
|
|
1372
|
+
<p class="routeLbl">First read</p>
|
|
1373
|
+
<p class="demoFitLine"><span id="demoFitSum">3 people × 4 hours = 12 builder-hours.</span> <span id="demoFitVerdict">Enough for a small version. Trim it to one shared list, voting and a winner reveal; accounts and notifications will not fit.</span></p>
|
|
1374
|
+
<p class="demoFitTry">What you’ll get to try</p>
|
|
1375
|
+
<ul class="demoTry">
|
|
1376
|
+
<li>Claim a task and ship it</li>
|
|
1377
|
+
<li>See your work graded</li>
|
|
1378
|
+
<li>Put an idea to a vote in the Board Room</li>
|
|
1379
|
+
<li>Watch your rank grow with shipped work</li>
|
|
1380
|
+
</ul>
|
|
1288
1381
|
</div>
|
|
1289
|
-
<p class="demoSoon" id="demoSoon" hidden>The demo isn’t open yet. It’s being built now; until it opens, begin planet creation to make a real project.</p>
|
|
1290
1382
|
<div class="nav">
|
|
1291
|
-
<button type="button" class="btn ghost"
|
|
1292
|
-
<
|
|
1383
|
+
<button type="button" class="btn ghost" id="demoBack1">← Back</button>
|
|
1384
|
+
<button type="button" class="btn" id="demoNext1">See the settings</button>
|
|
1293
1385
|
</div>
|
|
1294
|
-
</
|
|
1386
|
+
</div>
|
|
1387
|
+
<div id="demoReady" class="demoView" hidden>
|
|
1388
|
+
<h1 id="demo-h2">Your demo planet’s settings</h1>
|
|
1389
|
+
<p class="lede">We picked sensible settings so you can start straight away, and you can change any of them later. Next you name it and choose where its code lives, and then it is created.</p>
|
|
1390
|
+
<dl class="demoLedger">
|
|
1391
|
+
<dt>People</dt><dd><span id="demoLPeople">3</span><small id="demoLPeopleSub">You, plus the two people you invite below</small></dd>
|
|
1392
|
+
<dt>Time box</dt><dd><span id="demoLHours">4 hours each</span><small id="demoLTotal">12 builder-hours in total. When it runs out you are asked whether to keep your planet; your work is never stopped.</small></dd>
|
|
1393
|
+
<dt>Government</dt><dd>Monarchy / BDFL<small>One leader decides: you make the calls.</small></dd>
|
|
1394
|
+
<dt>Rewards</dt><dd>None<small>It’s a demo, for learning.</small></dd>
|
|
1395
|
+
<dt>Framing</dt><dd>All managed for you</dd>
|
|
1396
|
+
<dt>Who can see it</dt><dd>Only your team</dd>
|
|
1397
|
+
<dt>AI usage</dt><dd>Everyone uses their own AI plan</dd>
|
|
1398
|
+
</dl>
|
|
1399
|
+
<div class="demoInvites" id="demoInvites">
|
|
1400
|
+
<label class="wizField"><span>Invite by GitHub handle</span>
|
|
1401
|
+
<input type="text" id="demoInvite1" placeholder="teammate’s handle" autocomplete="off" autocapitalize="off" spellcheck="false" maxlength="39">
|
|
1402
|
+
</label>
|
|
1403
|
+
<label class="wizField"><span>And one more</span>
|
|
1404
|
+
<input type="text" id="demoInvite2" placeholder="teammate’s handle" autocomplete="off" autocapitalize="off" spellcheck="false" maxlength="39">
|
|
1405
|
+
</label>
|
|
1406
|
+
</div>
|
|
1407
|
+
<p class="finePrint">A demo nobody keeps goes offline 30 days after it starts. You are told before, and it can be brought back.</p>
|
|
1408
|
+
<div class="nav">
|
|
1409
|
+
<button type="button" class="btn ghost" id="demoBack2">← Back</button>
|
|
1410
|
+
<button type="button" class="btn" id="demoStart">Name my demo planet</button>
|
|
1411
|
+
</div>
|
|
1412
|
+
</div>
|
|
1295
1413
|
</div>
|
|
1296
|
-
<div class="forkStage" aria-hidden="true">
|
|
1414
|
+
<div class="forkStage" id="forkStage" aria-hidden="true">
|
|
1297
1415
|
<span class="forkOrbit"></span>
|
|
1298
1416
|
<span class="forkOrbit forkOrbitDash"></span>
|
|
1417
|
+
<span class="demoRing" id="demoRing" hidden></span>
|
|
1299
1418
|
<img class="forkSeed" src="/assets/world/r2-chrome-blob-one-cut.webp" alt="">
|
|
1419
|
+
<p class="demoStageCap" id="demoStageCap" hidden>time box · <span id="demoStageHours">12</span> builder-hours · when the dashed ring closes, the demo asks whether to keep your planet</p>
|
|
1300
1420
|
</div>
|
|
1301
1421
|
</div>
|
|
1302
1422
|
<div class="forkRoutes">
|
|
1303
1423
|
<div>
|
|
1304
|
-
<p class="routeLbl">Route 1 · demo
|
|
1424
|
+
<p class="routeLbl">Route 1 · demo</p>
|
|
1305
1425
|
<p class="routeT">Training wheels</p>
|
|
1306
1426
|
<p class="routeD">Pick how many people, how many hours each, and an idea. The platform checks that it fits, picks the settings, and you learn by building something small. Keep your planet at the end if you like it.</p>
|
|
1307
1427
|
</div>
|
|
@@ -1685,6 +1805,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
1685
1805
|
<button type="button" class="btn small ghost" data-invite-skip="wizInvite">Skip</button>
|
|
1686
1806
|
</div>
|
|
1687
1807
|
<div class="inviteWhy" id="wizInviteWhy"></div>
|
|
1808
|
+
<p class="inviteWhy" id="wizDemoTeam" hidden></p>
|
|
1688
1809
|
<ul class="suggList" id="wizInviteSugg"></ul>
|
|
1689
1810
|
<ul class="inviteList" id="wizInviteList"></ul>
|
|
1690
1811
|
<div class="projMsg" id="wizInviteMsg" role="status" aria-live="polite"></div>
|
|
@@ -4311,7 +4432,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4311
4432
|
request omits the field), [] = the owner switched them all off, [...] =
|
|
4312
4433
|
what they picked. Never seed it with the preselect — that would store an
|
|
4313
4434
|
answer nobody gave. */
|
|
4314
|
-
var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', look: null, termsAck: false };
|
|
4435
|
+
var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', demo: null, look: null, termsAck: false };
|
|
4315
4436
|
try { Object.assign(state, JSON.parse(sessionStorage.getItem(DRAFT_KEY) || '{}')); } catch (e) {}
|
|
4316
4437
|
var authKnown = false; /* flips true when the boot's /me settles, either way */
|
|
4317
4438
|
|
|
@@ -4608,18 +4729,109 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
4608
4729
|
}
|
|
4609
4730
|
|
|
4610
4731
|
/* ── the front door (task 1004417) ── the tick mirrors into the draft; the
|
|
4611
|
-
demo door opens
|
|
4732
|
+
demo door opens the demo route (task 1004420, below) */
|
|
4612
4733
|
$('termsAck').checked = !!state.termsAck;
|
|
4613
4734
|
$('termsAck').addEventListener('change', function () {
|
|
4614
4735
|
state.termsAck = !!this.checked;
|
|
4615
4736
|
if (state.termsAck) { $('h-terms').textContent = '\u00a0'; $('h-terms').className = 'hint'; }
|
|
4616
4737
|
saveDraft();
|
|
4617
4738
|
});
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4739
|
+
/* ── the demo route (task 1004420, BV2.PS09) ──
|
|
4740
|
+
"Try the demo" opens two screens inside the fork: set up (people, hours each, the
|
|
4741
|
+
idea, and a first read of what fits) and the picked defaults with two invites.
|
|
4742
|
+
"Start the demo" goes on through the ordinary wizard from the name step: a demo is
|
|
4743
|
+
a normal project marked "demo" (D9), so the create carries `demo` and the server
|
|
4744
|
+
applies the demo's picked answers and makes it private to the team. The time box
|
|
4745
|
+
is soft (D3). The limits and the fit sentences are copies of
|
|
4746
|
+
modules/provisioning/demo.js, held equal by tests/wizard_demo.mjs. */
|
|
4747
|
+
var DEMO_LIMITS = { people: [1, 12], hours: [1, 40] };
|
|
4748
|
+
var demoDraft = state.demo
|
|
4749
|
+
? { people: state.demo.people, hours: state.demo.hours_each, idea: state.demo.idea || '', invites: state.demo.invites || [] }
|
|
4750
|
+
: { people: 3, hours: 4, idea: '', invites: [] };
|
|
4751
|
+
function demoFit(people, hours) {
|
|
4752
|
+
var total = people * hours;
|
|
4753
|
+
var verdict = total < 8 ? 'tight' : total < 20 ? 'small' : 'plenty';
|
|
4754
|
+
var sentence = {
|
|
4755
|
+
tight: 'Too tight for this idea. Try one list with voting only, or add hours.',
|
|
4756
|
+
small: 'Enough for a small version. Trim it to one shared list, voting and a winner reveal; accounts and notifications will not fit.',
|
|
4757
|
+
plenty: 'Plenty for this idea, with room for one extra feature.'
|
|
4758
|
+
}[verdict];
|
|
4759
|
+
return { total: total, verdict: verdict, sentence: sentence };
|
|
4760
|
+
}
|
|
4761
|
+
function demoHandle(v) {
|
|
4762
|
+
var h = String(v || '').trim().replace(/^@/, '');
|
|
4763
|
+
return /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/.test(h) ? h : '';
|
|
4764
|
+
}
|
|
4765
|
+
function paintDemo() {
|
|
4766
|
+
var fit = demoFit(demoDraft.people, demoDraft.hours);
|
|
4767
|
+
$('demoPeople').textContent = String(demoDraft.people);
|
|
4768
|
+
$('demoHours').textContent = String(demoDraft.hours);
|
|
4769
|
+
$('demoFitSum').textContent = demoDraft.people + (demoDraft.people === 1 ? ' person' : ' people') + ' × ' + demoDraft.hours + (demoDraft.hours === 1 ? ' hour' : ' hours') + ' = ' + fit.total + ' builder-hours.';
|
|
4770
|
+
$('demoFitVerdict').textContent = fit.sentence;
|
|
4771
|
+
$('demoLPeople').textContent = String(demoDraft.people);
|
|
4772
|
+
var others = demoDraft.people - 1;
|
|
4773
|
+
$('demoLPeopleSub').textContent = others === 0 ? 'Just you' : others === 1 ? 'You, plus the person you invite below' : others === 2 ? 'You, plus the two people you invite below' : 'You, plus ' + others + ' people: invite two below, and the rest from your hall';
|
|
4774
|
+
$('demoLHours').textContent = demoDraft.hours + (demoDraft.hours === 1 ? ' hour each' : ' hours each');
|
|
4775
|
+
$('demoLTotal').textContent = fit.total + ' builder-hours in total. When it runs out you are asked whether to keep your planet; your work is never stopped.';
|
|
4776
|
+
$('demoStageHours').textContent = String(fit.total);
|
|
4777
|
+
$('demoInvites').hidden = others === 0;
|
|
4778
|
+
$('demoInvite2').closest('label').hidden = others < 2;
|
|
4779
|
+
}
|
|
4780
|
+
function demoShow(which) {
|
|
4781
|
+
$('forkIntro').hidden = which !== 'intro';
|
|
4782
|
+
$('demoSetup').hidden = which !== 'setup';
|
|
4783
|
+
$('demoReady').hidden = which !== 'ready';
|
|
4784
|
+
$('demoRing').hidden = which === 'intro';
|
|
4785
|
+
$('demoStageCap').hidden = which === 'intro';
|
|
4786
|
+
$('wizDemo').setAttribute('aria-expanded', which === 'intro' ? 'false' : 'true');
|
|
4787
|
+
if (which !== 'intro') {
|
|
4788
|
+
paintDemo();
|
|
4789
|
+
var h = $(which === 'setup' ? 'demo-h1' : 'demo-h2');
|
|
4790
|
+
h.setAttribute('tabindex', '-1'); h.focus({ preventScroll: false });
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
$('demoIdea').value = demoDraft.idea;
|
|
4794
|
+
$('demoInvite1').value = demoDraft.invites[0] || '';
|
|
4795
|
+
$('demoInvite2').value = demoDraft.invites[1] || '';
|
|
4796
|
+
$('wizDemo').addEventListener('click', function () { demoShow('setup'); });
|
|
4797
|
+
root.querySelectorAll('[data-demo-step]').forEach(function (b) {
|
|
4798
|
+
b.addEventListener('click', function () {
|
|
4799
|
+
var key = b.getAttribute('data-demo-step');
|
|
4800
|
+
var lim = DEMO_LIMITS[key];
|
|
4801
|
+
var next = demoDraft[key] + Number(b.getAttribute('data-by'));
|
|
4802
|
+
demoDraft[key] = Math.min(lim[1], Math.max(lim[0], next));
|
|
4803
|
+
paintDemo();
|
|
4804
|
+
});
|
|
4805
|
+
});
|
|
4806
|
+
$('demoIdea').addEventListener('input', function () { demoDraft.idea = this.value; });
|
|
4807
|
+
$('demoNext1').addEventListener('click', function () { demoShow('ready'); });
|
|
4808
|
+
$('demoBack1').addEventListener('click', function () { demoShow('intro'); $('wizDemo').focus(); });
|
|
4809
|
+
$('demoBack2').addEventListener('click', function () { demoShow('setup'); });
|
|
4810
|
+
$('demoStart').addEventListener('click', function () {
|
|
4811
|
+
var invites = [demoHandle($('demoInvite1').value), demoHandle($('demoInvite2').value)]
|
|
4812
|
+
.filter(function (h, i, all) { return h && all.indexOf(h) === i; })
|
|
4813
|
+
.slice(0, Math.max(0, demoDraft.people - 1));
|
|
4814
|
+
state.demo = { people: demoDraft.people, hours_each: demoDraft.hours, idea: String(demoDraft.idea || '').trim(), invites: invites };
|
|
4815
|
+
/* the idea is the project's description unless one was already written, and the
|
|
4816
|
+
team is the people count — both the founder can still change on the way */
|
|
4817
|
+
if (state.demo.idea && !String(state.description || '').trim()) {
|
|
4818
|
+
state.description = state.demo.idea;
|
|
4819
|
+
$('f-desc').value = state.description;
|
|
4820
|
+
}
|
|
4821
|
+
state.teamShape = demoDraft.people > 1 ? 'small-team' : 'solo';
|
|
4822
|
+
saveDraft();
|
|
4823
|
+
show(3, true);
|
|
4622
4824
|
});
|
|
4825
|
+
/* the done panel's invite step names the demo's teammates (task 1004420): the hub
|
|
4826
|
+
holds no invite of its own, so the founder sends each from the project's own box */
|
|
4827
|
+
function paintDemoTeam() {
|
|
4828
|
+
var line = $('wizDemoTeam');
|
|
4829
|
+
var who = state.demo && state.demo.invites && state.demo.invites.length ? state.demo.invites : [];
|
|
4830
|
+
line.hidden = !who.length;
|
|
4831
|
+
line.textContent = who.length ? 'Your demo teammates: ' + who.map(function (h) { return '@' + h; }).join(', ') + '. Invite each one here.' : '';
|
|
4832
|
+
if (who.length && !$('wizInviteWho').value) $('wizInviteWho').value = who[0];
|
|
4833
|
+
}
|
|
4834
|
+
|
|
4623
4835
|
|
|
4624
4836
|
/* ── field wiring ── */
|
|
4625
4837
|
$('newName').value = state.name;
|
|
@@ -5200,6 +5412,8 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5200
5412
|
/* per-panel validation on Next */
|
|
5201
5413
|
function validateStep(step) {
|
|
5202
5414
|
if (step === 9) return validateRender();
|
|
5415
|
+
/* the fork's own door is "Begin planet creation": a real project, not the demo */
|
|
5416
|
+
if (step === 2) { state.demo = null; return true; }
|
|
5203
5417
|
/* the front door's one tick (task 1004417): nothing past it until it is given */
|
|
5204
5418
|
if (step === 1) {
|
|
5205
5419
|
if (!state.termsAck) {
|
|
@@ -5434,6 +5648,11 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5434
5648
|
['App', appRow()],
|
|
5435
5649
|
['Look', lookRow()]
|
|
5436
5650
|
];
|
|
5651
|
+
/* the demo route (task 1004420): the review says it is a demo, and what that means */
|
|
5652
|
+
if (state.demo) {
|
|
5653
|
+
rows.unshift(['Demo', esc(state.demo.people + (state.demo.people === 1 ? ' person' : ' people') + ', ' + state.demo.hours_each + ' hours each.') +
|
|
5654
|
+
' Private to your team, no rewards, all managed. When the time box runs out you are asked whether to keep your planet.']);
|
|
5655
|
+
}
|
|
5437
5656
|
$('reviewList').innerHTML = rows.map(function (r) {
|
|
5438
5657
|
return '<li><span class="k">' + r[0] + '</span><span class="v">' + r[1] + '</span></li>';
|
|
5439
5658
|
}).join('');
|
|
@@ -5535,6 +5754,9 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5535
5754
|
modules: modulesForCreate(),
|
|
5536
5755
|
/* the front door's tick (task 1004417) — the server stamps WHICH terms */
|
|
5537
5756
|
terms_acknowledged: state.termsAck ? true : undefined,
|
|
5757
|
+
/* the demo route (task 1004420): a normal project marked demo — the server
|
|
5758
|
+
applies the demo's picked answers and keeps it private to the team */
|
|
5759
|
+
demo: state.demo ? { people: state.demo.people, hours_each: state.demo.hours_each } : undefined,
|
|
5538
5760
|
hosting_shape: 'cloud-host',
|
|
5539
5761
|
/* ONLY a bring-your-own domain travels (task 1002898 N2). The server owns
|
|
5540
5762
|
the assigned <slug>.<apex> default (task 1002704) and applies it to an
|
|
@@ -5828,6 +6050,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
5828
6050
|
sets only AFTER this runs. */
|
|
5829
6051
|
var created = createdRecord();
|
|
5830
6052
|
setInviteSlug('wizInvite', (me && created && created.id && created.slug) ? created.slug : '');
|
|
6053
|
+
paintDemoTeam();
|
|
5831
6054
|
loadInviteSuggestions('wizInvite', (me && created && created.slug) ? created.id : '');
|
|
5832
6055
|
$('wizInviteLater').innerHTML = 'You can invite builders any time from ' + projectPageLink('the project’s own page') + '.';
|
|
5833
6056
|
renderSteps();
|
|
@@ -6196,7 +6419,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
6196
6419
|
is three-valued and null is its "nothing said" sentinel; leaving the key out
|
|
6197
6420
|
left it UNDEFINED, which is not null — so pickedModules() reached .slice()
|
|
6198
6421
|
on it and the second project's Modules step threw. */
|
|
6199
|
-
state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', look: null, termsAck: false };
|
|
6422
|
+
state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later', demo: null, look: null, termsAck: false };
|
|
6200
6423
|
$('newName').value = ''; $('f-owner').value = ''; $('f-repo').value = ''; $('f-slug').value = ''; $('f-domain').value = '';
|
|
6201
6424
|
$('f-noaddr').checked = false; $('f-desc').value = '';
|
|
6202
6425
|
/* Re-seed the owner from the signed-in account for the next project. */
|
|
@@ -7077,6 +7300,59 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
7077
7300
|
$('mPlanet').innerHTML = ledgerRow(['planet', planetWords(pl) + (pl.chosen ? '<small>your choice.</small>' : pl.curated ? '' : '<small>chosen for it by the platform.</small>')]);
|
|
7078
7301
|
$('mPlanet').hidden = false;
|
|
7079
7302
|
}
|
|
7303
|
+
/* ── the demo card (task 1004420, BV2.PS09) ──
|
|
7304
|
+
Fetch-free like the rest of renderManage, so the once-a-minute tick keeps the
|
|
7305
|
+
countdown current: everything it draws is the row's own `demo` view, which the server
|
|
7306
|
+
shapes (remaining_seconds, time_up, offline_on). The time box is SOFT (D3): the clock
|
|
7307
|
+
only ever counts down and then asks; nothing here stops the work. */
|
|
7308
|
+
function demoLeft(seconds) {
|
|
7309
|
+
var m = Math.max(0, Math.round(seconds / 60));
|
|
7310
|
+
var h = Math.floor(m / 60);
|
|
7311
|
+
return h ? h + ' h ' + (m % 60) + ' min' : m + ' min';
|
|
7312
|
+
}
|
|
7313
|
+
function renderDemoCard(inst) {
|
|
7314
|
+
var d = inst && inst.demo;
|
|
7315
|
+
$('mDemo').hidden = !d;
|
|
7316
|
+
if (!d) return;
|
|
7317
|
+
var hours = d.hours_each + (d.hours_each === 1 ? ' hour' : ' hours');
|
|
7318
|
+
$('mDemoClock').textContent = d.time_up
|
|
7319
|
+
? 'The time box has run out: ' + d.people + ' × ' + hours + '. Your work keeps going either way.'
|
|
7320
|
+
: demoLeft(d.remaining_seconds) + ' left in the time box (' + d.people + ' × ' + hours + ' = ' + d.builder_hours + ' builder-hours). Nothing stops when it runs out.';
|
|
7321
|
+
$('mDemoKeep').hidden = !(d.time_up && !d.outcome);
|
|
7322
|
+
var date = listedDate(d.offline_on);
|
|
7323
|
+
$('mDemoOffline').textContent = (d.outcome === 'kept' ? 'Kept as a demo. ' : '') +
|
|
7324
|
+
(d.offline_soon ? 'This demo goes offline on ' + date + ' unless you carry it over. ' : 'A demo nobody carries over goes offline on ' + date + '. ') +
|
|
7325
|
+
'It can be brought back afterwards.';
|
|
7326
|
+
$('mDemoOffline').classList.toggle('demoSoonWarn', !!d.offline_soon);
|
|
7327
|
+
}
|
|
7328
|
+
/* guarded: some tests run regions of this script in a vm with no document */
|
|
7329
|
+
if (typeof document !== 'undefined' && document.querySelectorAll) document.querySelectorAll('[data-demo-settle]').forEach(function (b) {
|
|
7330
|
+
b.addEventListener('click', function () {
|
|
7331
|
+
var inst = manageInst;
|
|
7332
|
+
if (!inst || !inst.demo) return;
|
|
7333
|
+
var outcome = b.getAttribute('data-demo-settle');
|
|
7334
|
+
document.querySelectorAll('[data-demo-settle]').forEach(function (x) { x.disabled = true; });
|
|
7335
|
+
$('mDemoMsg').textContent = '';
|
|
7336
|
+
fetch(API + '/provisioning/instances/' + encodeURIComponent(inst.id) + '/demo', {
|
|
7337
|
+
method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' },
|
|
7338
|
+
body: JSON.stringify({ outcome: outcome })
|
|
7339
|
+
}).then(function (r) { return r.json().catch(function () { return {}; }).then(function (data) { return { ok: r.ok, data: data }; }); })
|
|
7340
|
+
.then(function (res) {
|
|
7341
|
+
document.querySelectorAll('[data-demo-settle]').forEach(function (x) { x.disabled = false; });
|
|
7342
|
+
if (!res.ok) { $('mDemoMsg').textContent = (res.data && res.data.error && res.data.error.message) || 'That didn’t go through. Try again.'; return; }
|
|
7343
|
+
inst.demo = res.data.demo;
|
|
7344
|
+
renderDemoCard(inst);
|
|
7345
|
+
$('mDemoMsg').textContent = outcome === 'carried'
|
|
7346
|
+
? 'It’s a real project now. Its settings, team and work carry on as they are.'
|
|
7347
|
+
: 'Kept as a demo.';
|
|
7348
|
+
})
|
|
7349
|
+
.catch(function () {
|
|
7350
|
+
document.querySelectorAll('[data-demo-settle]').forEach(function (x) { x.disabled = false; });
|
|
7351
|
+
$('mDemoMsg').textContent = 'That didn’t go through. Try again.';
|
|
7352
|
+
});
|
|
7353
|
+
});
|
|
7354
|
+
});
|
|
7355
|
+
|
|
7080
7356
|
function renderManage(inst) {
|
|
7081
7357
|
manageInst = inst;
|
|
7082
7358
|
$('mLoading').hidden = true;
|
|
@@ -7123,6 +7399,7 @@ summary{min-height:24px;padding:3px 0;}
|
|
|
7123
7399
|
renderPick(inst);
|
|
7124
7400
|
renderCardPick(inst);
|
|
7125
7401
|
renderLookCard(inst);
|
|
7402
|
+
renderDemoCard(inst);
|
|
7126
7403
|
/* invite a builder (task 1002346): fetch-free too — the widget needs only the
|
|
7127
7404
|
slug, and the API is the wall. This read is own-scoped and 404s for anyone
|
|
7128
7405
|
who is not the owner, so reaching renderManage at all IS the ownership
|
|
@@ -161,9 +161,9 @@
|
|
|
161
161
|
{ "name": "the wizard driver (task 1003346): name, type, about, home (fresh; the stub grants repo access, so the new repository is named from the project), address (the handle's verdict), the review as a ledger, then the filing — the done panel with the standup rail and the human steps", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
162
162
|
"steps": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#panel-fork button[type=submit]"],["wait",400],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400],["click","#panel-look button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500]],
|
|
163
163
|
"expect": {"visible":["#panel-done","#liveProgress .prog","#liveProgress .prog .stages li.now","#humanSteps li"],"hidden":["#panel-review","#panel-name"],"text":[["#done-h","The drums are rolling"]],"attr":[["#panel-done","class","panel on"]]} },
|
|
164
|
-
{ "name": "the front door (task 1004417): Proceed is refused until the terms are ticked, the fork's demo door
|
|
165
|
-
"steps": [["wait",600],["click","#panel-terms button[type=submit]"],["wait",300],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#wizDemo"],["wait",200],["click","#panel-fork button[type=submit]"],["wait",400]],
|
|
166
|
-
"expect": {"visible":["#panel-name","#view-new .steps","#view-new .steps li.now"],"hidden":["#panel-fork","#panel-terms"],"attr":[["#wizDemo","aria-expanded","
|
|
164
|
+
{ "name": "the front door (task 1004417): Proceed is refused until the terms are ticked, the fork's demo door opens the demo's setup and Back returns to the doors, and Begin planet creation goes on to the name step with the rail back", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
165
|
+
"steps": [["wait",600],["click","#panel-terms button[type=submit]"],["wait",300],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#wizDemo"],["wait",200],["click","#demoBack1"],["wait",200],["click","#panel-fork button[type=submit]"],["wait",400]],
|
|
166
|
+
"expect": {"visible":["#panel-name","#view-new .steps","#view-new .steps li.now"],"hidden":["#panel-fork","#panel-terms"],"attr":[["#wizDemo","aria-expanded","false"],["#view-new .steps li.now","data-step","3"]]} },
|
|
167
167
|
{ "name": "the front door at 390: the fork's two doors stack inside one pill and the walk still reaches the name step", "auth": true, "width": 390, "url": "/projects?view=new",
|
|
168
168
|
"steps": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400]],
|
|
169
169
|
"expect": {"visible":["#panel-fork",".doorPill","#wizDemo","#panel-fork button[type=submit]"],"hidden":["#view-new .steps"]} },
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"in-new": { "auth": true, "url": "/projects?view=new", "expect": { "visible": ["#panel-terms", "#termsAck"], "hidden": ["#qWrap", "#view-new .steps", "#panel-name"] } },
|
|
40
40
|
"in-new-terms-refused": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#panel-terms button[type=submit]"],["wait",300]], "expect": {"visible":["#panel-terms","#h-terms"],"hidden":["#panel-fork"],"text":[["#h-terms","Tick the box to go on. It’s how your project records that you acknowledged the terms."]]} },
|
|
41
41
|
"in-new-fork": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-fork",".doorPill","#wizDemo",".forkStage",".forkRoutes"],"hidden":["#panel-terms","#view-new .steps","#demoSoon",".bongoCell"]} },
|
|
42
|
-
"in-new-fork-demo": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#wizDemo"],["wait",
|
|
42
|
+
"in-new-fork-demo": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#wizDemo"],["wait",300]], "expect": {"visible":["#panel-fork","#demoSetup","#demoFitVerdict","#demoRing"],"hidden":["#forkIntro","#demoReady"],"attr":[["#wizDemo","aria-expanded","true"]]} },
|
|
43
|
+
"in-new-demo-ready": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#wizDemo"],["wait",300],["click","[data-demo-step=\"hours\"][data-by=\"1\"]"],["click","#demoNext1"],["wait",300]], "expect": {"visible":["#demoReady",".demoLedger","#demoInvite1","#demoInvite2"],"hidden":["#demoSetup","#forkIntro"],"text":[["#demoLHours","5 hours each"]]} },
|
|
43
44
|
"in-new-name": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#panel-fork button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-name","#newName","#view-new .steps"],"hidden":["#panel-fork","#panel-terms"]} },
|
|
44
45
|
"out-new": { "auth": false, "url": "/projects?view=new", "expect": { "hidden": ["#qWrap"] } },
|
|
45
46
|
"in-new-type": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["click","#termsAck"],["click","#panel-terms button[type=submit]"],["wait",400],["click","#panel-fork button[type=submit]"],["wait",400],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-type"],"hidden":["#panel-name","#qWrap"]} },
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_": "The demo route (task 1004420): provisioning-instances.json with project 101 marked as a demo whose time box has run out, so its page asks keep-your-planet. Only projects-demo.states.json points at this.",
|
|
3
|
+
"instances": [
|
|
4
|
+
{
|
|
5
|
+
"id": 101,
|
|
6
|
+
"slug": "demo",
|
|
7
|
+
"status": "active",
|
|
8
|
+
"domain": "demo.cloudbongos.com",
|
|
9
|
+
"target_ref": "builder/demo",
|
|
10
|
+
"hosting_shape": "co-tenant",
|
|
11
|
+
"onboard_mode": "scaffold",
|
|
12
|
+
"created_at": "2026-08-01T10:00:00.000Z",
|
|
13
|
+
"provisioned_at": "2026-08-01T10:20:00.000Z",
|
|
14
|
+
"updated_at": "$now-3m",
|
|
15
|
+
"last_verified_at": "$now-3m",
|
|
16
|
+
"last_verified_up": true,
|
|
17
|
+
"error_note": null,
|
|
18
|
+
"dns_note": null,
|
|
19
|
+
"torn_down_at": null,
|
|
20
|
+
"open_intent": null,
|
|
21
|
+
"demo": {
|
|
22
|
+
"people": 3,
|
|
23
|
+
"hours_each": 4,
|
|
24
|
+
"builder_hours": 12,
|
|
25
|
+
"started_at": "2026-09-28T09:00:00Z",
|
|
26
|
+
"ends_at": "2026-09-28T13:00:00Z",
|
|
27
|
+
"remaining_seconds": 0,
|
|
28
|
+
"time_up": true,
|
|
29
|
+
"outcome": null,
|
|
30
|
+
"offline_on": "2026-10-28T09:00:00.000Z",
|
|
31
|
+
"offline_soon": false
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": 102,
|
|
36
|
+
"slug": "harbor",
|
|
37
|
+
"status": "provisioning",
|
|
38
|
+
"planet_template": "blob-frost-tint",
|
|
39
|
+
"planet_accent": "sun-lit",
|
|
40
|
+
"domain": null,
|
|
41
|
+
"target_ref": "builder/harbor",
|
|
42
|
+
"hosting_shape": "cloud-host",
|
|
43
|
+
"owner_monthly_usd": null,
|
|
44
|
+
"onboard_mode": "scaffold",
|
|
45
|
+
"created_at": "$now-6m",
|
|
46
|
+
"provisioned_at": null,
|
|
47
|
+
"updated_at": "$now-2m",
|
|
48
|
+
"last_verified_at": null,
|
|
49
|
+
"last_verified_up": null,
|
|
50
|
+
"error_note": null,
|
|
51
|
+
"dns_note": null,
|
|
52
|
+
"torn_down_at": null,
|
|
53
|
+
"open_intent": {
|
|
54
|
+
"action": "standup",
|
|
55
|
+
"state": "running",
|
|
56
|
+
"created_at": "$now-6m"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": 103,
|
|
61
|
+
"slug": "tidepool",
|
|
62
|
+
"status": "error",
|
|
63
|
+
"domain": "tidepool.cloudbongos.com",
|
|
64
|
+
"target_ref": "builder/tidepool",
|
|
65
|
+
"hosting_shape": "co-tenant",
|
|
66
|
+
"onboard_mode": "adopt",
|
|
67
|
+
"created_at": "2026-08-20T09:00:00.000Z",
|
|
68
|
+
"provisioned_at": null,
|
|
69
|
+
"updated_at": "$now-1d",
|
|
70
|
+
"last_verified_at": null,
|
|
71
|
+
"last_verified_up": null,
|
|
72
|
+
"error_note": "The deploy could not read the repository: it is private, and the deploy key only reads public ones.",
|
|
73
|
+
"dns_note": null,
|
|
74
|
+
"torn_down_at": null,
|
|
75
|
+
"open_intent": null
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": 104,
|
|
79
|
+
"slug": "old-lantern",
|
|
80
|
+
"status": "torn_down",
|
|
81
|
+
"domain": "old-lantern.cloudbongos.com",
|
|
82
|
+
"target_ref": "builder/old-lantern",
|
|
83
|
+
"hosting_shape": "co-tenant",
|
|
84
|
+
"onboard_mode": "scaffold",
|
|
85
|
+
"created_at": "2026-07-02T09:00:00.000Z",
|
|
86
|
+
"provisioned_at": "2026-07-02T09:30:00.000Z",
|
|
87
|
+
"updated_at": "2026-08-15T12:00:00.000Z",
|
|
88
|
+
"last_verified_at": "2026-08-15T11:50:00.000Z",
|
|
89
|
+
"last_verified_up": true,
|
|
90
|
+
"error_note": null,
|
|
91
|
+
"dns_note": null,
|
|
92
|
+
"torn_down_at": "2026-08-15T12:00:00.000Z",
|
|
93
|
+
"open_intent": null
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"id": 105,
|
|
97
|
+
"slug": "mooring",
|
|
98
|
+
"status": "active",
|
|
99
|
+
"domain": "mooring.cloudbongos.com",
|
|
100
|
+
"target_ref": "builder/mooring",
|
|
101
|
+
"hosting_shape": "co-tenant",
|
|
102
|
+
"onboard_mode": "scaffold",
|
|
103
|
+
"created_at": "2026-08-10T09:00:00.000Z",
|
|
104
|
+
"provisioned_at": "2026-08-10T09:20:00.000Z",
|
|
105
|
+
"updated_at": "$now-20m",
|
|
106
|
+
"last_verified_at": "$now-20m",
|
|
107
|
+
"last_verified_up": false,
|
|
108
|
+
"error_note": null,
|
|
109
|
+
"dns_note": null,
|
|
110
|
+
"torn_down_at": null,
|
|
111
|
+
"open_intent": null
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.63",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.20.
|
|
9
|
+
"version": "1.20.63",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.63",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|