@bongos/core 1.19.423 → 1.19.425
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 +66 -31
- package/clients/bongos-client/index.d.ts +2 -2
- package/docs/adr/0208-application-lifecycle-the-handle-waits-and-the-vouch-has-no-minter.md +164 -0
- package/docs/adr/README.md +1 -0
- package/docs/api/openapi.json +10 -5
- package/docs/api-reference.md +2 -2
- package/docs/copy-inventory.md +208 -208
- package/docs/copy-registry.json +260 -260
- package/docs/design/mocks/hub/wizard.html +421 -0
- package/docs/design/projects-hub-direction-v2.md +26 -0
- package/docs/file-map.md +2 -0
- package/docs/module-api-changelog.md +4 -0
- package/migrations/core_230_access_requests_applicant_vouch.sql +79 -0
- package/modules/discord/discord-approvals.js +7 -2
- package/modules/hall-ui/public/watch.js +10 -1
- package/modules/onboarding/routes/access-requests.js +115 -11
- package/modules/platform-identity/application-echo.js +115 -0
- package/modules/platform-identity/migrations/platform_identity_016_application_echo.sql +68 -0
- package/modules/platform-identity/routes/my-projects.js +57 -2
- package/modules/ui-design/kit/serve.js +3 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +63 -0
- package/public-landing/projects.html +207 -199
- package/public-landing/projects.probes.json +7 -1
- package/public-landing/projects.states.json +7 -1
- package/src/module-api.js +1 -1
- package/tests/application_echo.mjs +446 -0
- package/tests/application_lifecycle.mjs +634 -0
- package/tests/own_scope_guard.mjs +5 -0
- package/tests/projects_hub.mjs +56 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" data-mode="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>The create wizard, in the world</title>
|
|
7
|
+
<link rel="icon" href="data:,">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400&family=Manrope:wght@300;400;500;600&display=swap">
|
|
11
|
+
<link rel="stylesheet" href="../../../../public-landing/assets/cosmos.css">
|
|
12
|
+
<style>
|
|
13
|
+
body{
|
|
14
|
+
/* The composition round for task 1003346 (docs/design/projects-hub-direction-v2.md §15). cosmos.css
|
|
15
|
+
carries the hub's contract, the planets and the fixed status vocabulary; this sheet adds only the
|
|
16
|
+
wizard's composition in the world's grammar: the six-step strip as the lifecycle rail, the type and
|
|
17
|
+
home choices as hairline cells, fields with one bottom hairline, the review as ledger rows, pills for
|
|
18
|
+
the doors with the accent only on the primary one, the standup strip as the same rail. Dark only
|
|
19
|
+
(ADR 0204). Every colour is a token. */
|
|
20
|
+
--orb-shadow:opacity(1);
|
|
21
|
+
}
|
|
22
|
+
.mock .worldOrb{position:relative;left:auto;top:auto;transform:none;display:block;cursor:default;}
|
|
23
|
+
.mock .worldOrb .disc{display:block;margin:0;}
|
|
24
|
+
|
|
25
|
+
/* ── the view: one column, a lowercase display title, one clause ── */
|
|
26
|
+
.view{max-width:1180px;margin:0 auto;padding:34px var(--gutter) 60px;}
|
|
27
|
+
.vTitle{font-family:var(--font-display);font-weight:300;font-size:clamp(28px,3.4vw,44px);letter-spacing:-.035em;line-height:1.04;text-transform:lowercase;color:var(--ink);margin:0;max-width:18ch;text-wrap:balance;}
|
|
28
|
+
.vLede{font-size:15.5px;line-height:1.5;color:var(--ink-soft);max-width:62ch;margin:10px 0 0;}
|
|
29
|
+
.vLede b{color:var(--ink);font-weight:500;}
|
|
30
|
+
.eyebrow{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);margin:0 0 14px;}
|
|
31
|
+
|
|
32
|
+
/* ── the six-step strip as the lifecycle rail: hairlines, a 7px dot, one lit step ── */
|
|
33
|
+
.wizRail{display:grid;grid-template-columns:repeat(6,1fr);gap:0 10px;list-style:none;margin:0 0 40px;padding:0;}
|
|
34
|
+
.wizRail li{position:relative;border-top:1px solid var(--rule);padding:12px 0 0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);line-height:1.3;}
|
|
35
|
+
.wizRail li::before{content:"";position:absolute;top:-4px;left:0;width:7px;height:7px;border-radius:50%;border:1px solid var(--rule);background:var(--bg);}
|
|
36
|
+
.wizRail li.done{border-top-color:var(--ink-soft);color:var(--ink-soft);}
|
|
37
|
+
.wizRail li.done::before{background:var(--ink-soft);border-color:var(--ink-soft);}
|
|
38
|
+
.wizRail li.now{border-top-color:var(--accent);color:var(--ink);}
|
|
39
|
+
.wizRail li.now::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
|
|
40
|
+
.wizRail li.done{cursor:pointer;}
|
|
41
|
+
.wizRail li .snum{display:block;font-family:var(--font-display);font-weight:300;font-size:22px;letter-spacing:-.02em;color:inherit;text-transform:none;margin-bottom:2px;}
|
|
42
|
+
|
|
43
|
+
/* ── the step: title, clause, the field, the doors ── */
|
|
44
|
+
.step{max-width:640px;}
|
|
45
|
+
.hairField{display:block;border-bottom:1px solid var(--rule);padding:14px 0 10px;margin:26px 0 0;}
|
|
46
|
+
.hairField>span{display:block;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);margin-bottom:6px;}
|
|
47
|
+
.hairField>span small{text-transform:none;letter-spacing:0;color:var(--ink-faint);}
|
|
48
|
+
.hairField input,.hairField textarea{display:block;width:100%;min-height:32px;background:none;border:0;font-family:var(--font-body);font-size:17px;color:var(--ink);padding:4px 0;resize:vertical;}
|
|
49
|
+
.hairField input::placeholder,.hairField textarea::placeholder{color:var(--ink-faint);}
|
|
50
|
+
.hairField input:focus,.hairField textarea:focus{outline:none;}
|
|
51
|
+
.hairField:focus-within{border-bottom-color:var(--ink);}
|
|
52
|
+
.hairField .hint{font-size:13.5px;line-height:1.45;color:var(--ink-faint);margin-top:8px;min-height:18px;}
|
|
53
|
+
.hairField .hint.ok{color:var(--ok);}
|
|
54
|
+
.hairField .hint.err{color:var(--err);}
|
|
55
|
+
.hairField .hint code,.fact code,.ledger code{font-family:var(--font-mono);font-size:12.5px;color:var(--ink-soft);background:none;padding:0;}
|
|
56
|
+
.fact{font-size:13.5px;line-height:1.5;color:var(--ink-soft);margin:14px 0 0;max-width:62ch;}
|
|
57
|
+
.fact a,.vLede a{color:var(--ink);text-decoration:underline;text-underline-offset:3px;display:inline-block;padding:3px 0;min-height:24px;line-height:18px;}
|
|
58
|
+
/* the doors: a row under the step, back as a plain pill, the primary on the accent, the skip as text */
|
|
59
|
+
.doors{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:34px 0 0;}
|
|
60
|
+
.door{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 20px;border:1px solid var(--rule);border-radius:var(--radius-pill);background:none;font-family:var(--font-body);font-size:15px;color:var(--ink);text-transform:lowercase;text-decoration:none;cursor:pointer;white-space:nowrap;}
|
|
61
|
+
.door:hover{border-color:var(--ink-faint);}
|
|
62
|
+
.door.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-on);font-weight:500;}
|
|
63
|
+
.door.primary:hover{background:color-mix(in srgb,var(--accent) 88%,var(--ink));}
|
|
64
|
+
.door.big{min-height:48px;padding:0 26px;font-size:16px;}
|
|
65
|
+
.door.invert{background:var(--ink);border-color:var(--ink);color:var(--bg);font-weight:500;gap:10px;}
|
|
66
|
+
.door.invert svg{width:17px;height:17px;fill:currentColor;}
|
|
67
|
+
.doors .push{margin-left:auto;}
|
|
68
|
+
.textDoor{background:none;border:0;padding:10px 4px;min-height:44px;font-family:var(--font-body);font-size:15px;color:var(--ink-soft);text-transform:lowercase;text-decoration:underline;text-underline-offset:4px;cursor:pointer;}
|
|
69
|
+
.textDoor:hover{color:var(--ink);}
|
|
70
|
+
|
|
71
|
+
/* ── a choice: hairline cells of one band; the chosen one carries the dot and the ink ── */
|
|
72
|
+
.choice{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);margin:26px 0 0;}
|
|
73
|
+
.choice label{display:grid;gap:6px;align-content:start;padding:16px 18px 18px;border-left:1px solid var(--rule-soft);cursor:pointer;color:var(--ink-soft);position:relative;}
|
|
74
|
+
.choice label:first-child{border-left:0;padding-left:0;}
|
|
75
|
+
.choice .ch{display:flex;align-items:center;gap:10px;font-family:var(--font-body);font-weight:500;font-size:15px;color:var(--ink);}
|
|
76
|
+
.choice .ch::before{content:"";width:7px;height:7px;border-radius:50%;border:1px solid var(--rule);background:var(--bg);flex:none;}
|
|
77
|
+
.choice label.on .ch::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
|
|
78
|
+
.choice .cb{font-size:13px;line-height:1.45;color:var(--ink-faint);}
|
|
79
|
+
.choice input{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);}
|
|
80
|
+
.choice.two{grid-template-columns:1fr 1fr;}
|
|
81
|
+
.choice.two label{padding:22px 22px 24px;}
|
|
82
|
+
.choice.two .ch{font-size:17px;}
|
|
83
|
+
.choice.two .cb{font-size:14px;color:var(--ink-soft);max-width:36ch;}
|
|
84
|
+
|
|
85
|
+
/* ── the review: a ledger of what is about to be filed ── */
|
|
86
|
+
.ledger{display:grid;grid-template-columns:172px 1fr;gap:0 22px;margin:26px 0 0;}
|
|
87
|
+
.ledger > *{border-top:1px solid var(--rule-soft);padding:13px 0;}
|
|
88
|
+
.ledger .k{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);padding-top:16px;}
|
|
89
|
+
.ledger .v{font-size:15px;line-height:1.5;color:var(--ink);overflow-wrap:anywhere;}
|
|
90
|
+
.ledger .v em{font-style:normal;color:var(--warn);}
|
|
91
|
+
.ledger .v small{display:block;font-size:13px;color:var(--ink-soft);}
|
|
92
|
+
.ledger.last > :nth-last-child(-n+2){border-bottom:1px solid var(--rule-soft);}
|
|
93
|
+
|
|
94
|
+
/* ── the address as a fact with its two alternatives in the open ── */
|
|
95
|
+
.addrBig{font-family:var(--font-display);font-weight:300;font-size:clamp(24px,3vw,36px);letter-spacing:-.03em;line-height:1.1;color:var(--ink);margin:26px 0 8px;overflow-wrap:anywhere;}
|
|
96
|
+
.addrBig b{font-weight:500;color:var(--accent-deep);}
|
|
97
|
+
details.fold{margin:18px 0 0;}
|
|
98
|
+
details.fold summary{cursor:pointer;display:inline-flex;align-items:center;min-height:24px;font-size:14.5px;color:var(--ink-soft);}
|
|
99
|
+
details.fold summary:hover,details.fold[open] summary{color:var(--ink);}
|
|
100
|
+
.opt{display:flex;align-items:flex-start;gap:12px;margin:18px 0 0;font-size:14.5px;line-height:1.5;color:var(--ink-soft);cursor:pointer;}
|
|
101
|
+
.opt input{margin:4px 0 0;flex:none;width:16px;height:16px;accent-color:var(--accent);}
|
|
102
|
+
|
|
103
|
+
/* ── the done panel: the standup as the same rail, then the steps only you can play ── */
|
|
104
|
+
.rail{display:grid;grid-template-columns:repeat(3,1fr);gap:0 10px;list-style:none;margin:26px 0 0;padding:0;max-width:520px;}
|
|
105
|
+
.rail li{position:relative;border-top:1px solid var(--rule);padding:12px 0 0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);line-height:1.3;}
|
|
106
|
+
.rail li::before{content:"";position:absolute;top:-4px;left:0;width:7px;height:7px;border-radius:50%;border:1px solid var(--rule);background:var(--bg);}
|
|
107
|
+
.rail li.done{border-top-color:var(--ink-soft);color:var(--ink-soft);}
|
|
108
|
+
.rail li.done::before{background:var(--ink-soft);border-color:var(--ink-soft);}
|
|
109
|
+
.rail li.now{border-top-color:var(--accent);color:var(--ink);}
|
|
110
|
+
.rail li.now::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
|
|
111
|
+
.railNote{margin:8px 0 0;font-size:13px;line-height:1.45;color:var(--ink-soft);max-width:520px;}
|
|
112
|
+
.humanSteps{list-style:none;margin:34px 0 0;padding:0;counter-reset:hs;max-width:640px;}
|
|
113
|
+
.humanSteps li{display:grid;grid-template-columns:44px 1fr;gap:0 16px;border-top:1px solid var(--rule-soft);padding:16px 0 18px;counter-increment:hs;}
|
|
114
|
+
.humanSteps li > *{grid-column:2;}
|
|
115
|
+
.humanSteps li:last-child{border-bottom:1px solid var(--rule-soft);}
|
|
116
|
+
.humanSteps li::before{content:counter(hs,decimal-leading-zero);font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);color:var(--ink-faint);padding-top:3px;}
|
|
117
|
+
.humanSteps b{display:block;font-family:var(--font-body);font-weight:500;font-size:16px;color:var(--ink);}
|
|
118
|
+
.humanSteps p{margin:4px 0 0;font-size:14px;line-height:1.5;color:var(--ink-soft);max-width:56ch;}
|
|
119
|
+
.humanSteps li.sdone::before{color:var(--ok);content:"done";text-transform:uppercase;}
|
|
120
|
+
.humanSteps li.sdone b{color:var(--ink-soft);}
|
|
121
|
+
.humanSteps .doors{margin:12px 0 0;}
|
|
122
|
+
.samePath{font-size:13px;color:var(--ink-faint);margin:18px 0 0;}
|
|
123
|
+
|
|
124
|
+
/* ── v2 · the rail beside: the six steps as a ledger on the left, the step on the right, the planet forming at its foot ── */
|
|
125
|
+
.beside{display:grid;grid-template-columns:260px 1fr;gap:0 48px;align-items:start;}
|
|
126
|
+
.sideRail{list-style:none;margin:0;padding:0;border-top:1px solid var(--rule);}
|
|
127
|
+
.sideRail li{display:grid;grid-template-columns:28px 1fr;gap:0 10px;align-items:baseline;border-bottom:1px solid var(--rule-soft);padding:14px 0;font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;color:var(--ink-faint);position:relative;}
|
|
128
|
+
.sideRail li::before{content:"";width:7px;height:7px;border-radius:50%;border:1px solid var(--rule);background:var(--bg);align-self:center;}
|
|
129
|
+
.sideRail li.done{color:var(--ink-soft);}
|
|
130
|
+
.sideRail li.done::before{background:var(--ink-soft);border-color:var(--ink-soft);}
|
|
131
|
+
.sideRail li.now{color:var(--ink);}
|
|
132
|
+
.sideRail li.now::before{background:var(--accent);border-color:var(--accent);outline:4px solid color-mix(in srgb,var(--accent) 22%,transparent);}
|
|
133
|
+
.sideRail li.now::after{content:"";position:absolute;left:0;bottom:-1px;width:100%;height:2px;background:var(--accent);}
|
|
134
|
+
.sideRail .sub{display:block;grid-column:2;font-family:var(--font-body);font-size:13px;letter-spacing:0;text-transform:none;color:var(--ink-faint);margin-top:2px;}
|
|
135
|
+
.sideRail li.done .sub{color:var(--ink-soft);}
|
|
136
|
+
.forming{margin:34px 0 0;display:grid;gap:12px;justify-items:start;}
|
|
137
|
+
.forming .fact{margin:0;}
|
|
138
|
+
|
|
139
|
+
/* ── the sheet furniture ── */
|
|
140
|
+
.sheet{padding:34px var(--gutter) 60px;max-width:1180px;margin:0 auto;}
|
|
141
|
+
.sheet h2{font-family:var(--font-display);font-weight:300;font-size:clamp(26px,3.1vw,42px);letter-spacing:-.035em;line-height:1.06;color:var(--ink);margin:0 0 6px;}
|
|
142
|
+
.sheet > p{font-size:15.5px;line-height:1.5;color:var(--ink-soft);max-width:62ch;margin:0 0 26px;}
|
|
143
|
+
section[data-state]{display:none;}
|
|
144
|
+
body[data-state="gate"] section[data-state="gate"],
|
|
145
|
+
body[data-state="name"] section[data-state="name"],
|
|
146
|
+
body[data-state="type"] section[data-state="type"],
|
|
147
|
+
body[data-state="about"] section[data-state="about"],
|
|
148
|
+
body[data-state="home"] section[data-state="home"],
|
|
149
|
+
body[data-state="address"] section[data-state="address"],
|
|
150
|
+
body[data-state="review"] section[data-state="review"],
|
|
151
|
+
body[data-state="done"] section[data-state="done"],
|
|
152
|
+
body[data-state="beside"] section[data-state="beside"]{display:block;}
|
|
153
|
+
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
|
|
154
|
+
.skip{position:absolute;left:12px;top:-60px;background:var(--bg-card);color:var(--ink);padding:11px 18px;border-radius:999px;}
|
|
155
|
+
.skip:focus{top:12px;}
|
|
156
|
+
.bar{height:var(--top-h);display:flex;align-items:center;padding:0 var(--gutter);border-bottom:1px solid var(--rule);font-family:var(--font-body);font-weight:500;font-size:17px;letter-spacing:-.015em;color:var(--ink);}
|
|
157
|
+
.mock .foot{padding:18px var(--gutter);font-size:14px;color:var(--ink-soft);text-align:center;}
|
|
158
|
+
a:focus-visible,button:focus-visible,label:focus-within,summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}
|
|
159
|
+
|
|
160
|
+
@media (max-width:900px){
|
|
161
|
+
.wizRail{grid-template-columns:repeat(3,1fr);gap:18px 10px;margin-bottom:30px;}
|
|
162
|
+
.wizRail li .snum{font-size:18px;}
|
|
163
|
+
.choice{grid-template-columns:1fr;}
|
|
164
|
+
.choice label{border-left:0;padding-left:0;border-top:1px solid var(--rule-soft);}
|
|
165
|
+
.choice label:first-child{border-top:0;}
|
|
166
|
+
.choice.two{grid-template-columns:1fr;}
|
|
167
|
+
.ledger{grid-template-columns:1fr;gap:0;}
|
|
168
|
+
.ledger .k{padding-bottom:0;}
|
|
169
|
+
.ledger .v{border-top:0;padding-top:6px;}
|
|
170
|
+
.doors .push{margin-left:0;}
|
|
171
|
+
.beside{grid-template-columns:1fr;gap:26px 0;}
|
|
172
|
+
.sideRail{display:grid;grid-template-columns:repeat(3,1fr);gap:18px 10px;border-top:0;}
|
|
173
|
+
.sideRail li{display:block;border-bottom:0;border-top:1px solid var(--rule);padding:12px 0 0;}
|
|
174
|
+
.sideRail li::before{position:absolute;top:-4px;left:0;}
|
|
175
|
+
.sideRail li.now::after{top:-1px;bottom:auto;height:1px;}
|
|
176
|
+
.sideRail .sub{display:none;}
|
|
177
|
+
.forming{display:none;}
|
|
178
|
+
}
|
|
179
|
+
</style>
|
|
180
|
+
</head>
|
|
181
|
+
<body class="mock" data-state="name">
|
|
182
|
+
<!--
|
|
183
|
+
The create wizard, the composition round (task 1003346, goal 1000080).
|
|
184
|
+
?state=gate signed out: the display title, the clause, the inverted sign-in door, the consent line
|
|
185
|
+
?state=name step 1 of six: the rail on top, one hairline field, the doors
|
|
186
|
+
?state=type step 2: the type as five hairline cells of one band, the chosen one carrying the dot
|
|
187
|
+
?state=about step 3 (optional): a hairline textarea, the team as three cells, skip as a text door
|
|
188
|
+
?state=home step 4: fresh or adopt as two cells, the repository field, the repo-access line
|
|
189
|
+
?state=address step 5: the handle field, the address in the display voice, the two alternatives in the open
|
|
190
|
+
?state=review step 6: the review as a ledger, one primary door, the trust line
|
|
191
|
+
?state=done the standup as the rail, then the steps only you can play as a numbered ledger
|
|
192
|
+
?state=beside v2 the rail beside: the six steps as a ledger on the left, the step on the right, the planet forming at its foot
|
|
193
|
+
-->
|
|
194
|
+
<a class="skip" href="#main">Skip to content</a>
|
|
195
|
+
<header class="bar">Cloud Bongos</header>
|
|
196
|
+
<main id="main">
|
|
197
|
+
<h1 class="vh">The create wizard</h1>
|
|
198
|
+
|
|
199
|
+
<section data-state="gate">
|
|
200
|
+
<div class="view">
|
|
201
|
+
<p class="eyebrow">new project</p>
|
|
202
|
+
<h2 class="vTitle">create a project</h2>
|
|
203
|
+
<p class="vLede">Your own Cloud Bongos project: its own repository, its own home on the web, and a hall of AI builders who do the building. You set the direction; agents lay down the code. Sign in with GitHub so the project belongs to <b>you</b> from the very first beat.</p>
|
|
204
|
+
<div class="doors"><a class="door invert big" href="#"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>sign in with github</a></div>
|
|
205
|
+
<p class="fact">Signing in asks GitHub for repository access. GitHub words this as access to all your repositories; that is the only permission it offers that can write to a private repo. We use it to create (or read) the one repo your project lives in and push its starting files. Nothing else is touched.</p>
|
|
206
|
+
<p class="fact">Free while we find our feet. Your project's repo and server are yours. Cloud Bongos is <a href="#">open source (AGPL-3.0)</a> and capture-resistant by design.</p>
|
|
207
|
+
</div>
|
|
208
|
+
</section>
|
|
209
|
+
|
|
210
|
+
<section data-state="name">
|
|
211
|
+
<div class="view">
|
|
212
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
213
|
+
<li class="now" aria-current="step"><span class="snum">1</span>Name</li>
|
|
214
|
+
<li><span class="snum">2</span>Type</li>
|
|
215
|
+
<li><span class="snum">3</span>About</li>
|
|
216
|
+
<li><span class="snum">4</span>Home</li>
|
|
217
|
+
<li><span class="snum">5</span>Address</li>
|
|
218
|
+
<li><span class="snum">6</span>Create</li>
|
|
219
|
+
</ol>
|
|
220
|
+
<div class="step">
|
|
221
|
+
<h2 class="vTitle">start a project</h2>
|
|
222
|
+
<p class="vLede">Your own project: its own repository, its own home on the web, and a hall of AI builders who do the building. You set the direction; agents lay down the code.</p>
|
|
223
|
+
<label class="hairField"><span>Project name</span><input type="text" placeholder="What should it be called?" aria-label="Project name"><div class="hint"> </div></label>
|
|
224
|
+
<div class="doors"><button type="button" class="door primary push">continue</button></div>
|
|
225
|
+
<p class="fact">Free while we find our feet. Your project's repo and server are yours. Cloud Bongos is <a href="#">open source (AGPL-3.0)</a> and capture-resistant by design.</p>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
</section>
|
|
229
|
+
|
|
230
|
+
<section data-state="type">
|
|
231
|
+
<div class="view">
|
|
232
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
233
|
+
<li class="done"><span class="snum">1</span>Name</li>
|
|
234
|
+
<li class="now" aria-current="step"><span class="snum">2</span>Type</li>
|
|
235
|
+
<li><span class="snum">3</span>About</li>
|
|
236
|
+
<li><span class="snum">4</span>Home</li>
|
|
237
|
+
<li><span class="snum">5</span>Address</li>
|
|
238
|
+
<li><span class="snum">6</span>Create</li>
|
|
239
|
+
</ol>
|
|
240
|
+
<div class="step" style="max-width:none">
|
|
241
|
+
<h2 class="vTitle">what kind of project is it?</h2>
|
|
242
|
+
<p class="vLede">Pick the shape that fits best. It is how the project is listed on the map, and it stays as you pick it for now. Not sure is a fine answer.</p>
|
|
243
|
+
<div class="choice" role="group" aria-label="Project type">
|
|
244
|
+
<label class="on"><input type="radio" name="t" checked><span class="ch">Game</span><span class="cb">A world people play in. Its hall builds levels, characters and the loop.</span></label>
|
|
245
|
+
<label><input type="radio" name="t"><span class="ch">Research</span><span class="cb">A question and the work to answer it. Notes, data, a paper, a tool.</span></label>
|
|
246
|
+
<label><input type="radio" name="t"><span class="ch">Business</span><span class="cb">A product or a service with customers. A shop, an app, a company.</span></label>
|
|
247
|
+
<label><input type="radio" name="t"><span class="ch">Non-profit</span><span class="cb">A cause with a community around it. Nobody owns it for profit.</span></label>
|
|
248
|
+
<label><input type="radio" name="t"><span class="ch">Not sure</span><span class="cb">Fine. It can change later, and nothing else waits on it.</span></label>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="doors"><button type="button" class="door">back</button><button type="button" class="door primary push">next</button></div>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
</section>
|
|
254
|
+
|
|
255
|
+
<section data-state="about">
|
|
256
|
+
<div class="view">
|
|
257
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
258
|
+
<li class="done"><span class="snum">1</span>Name</li>
|
|
259
|
+
<li class="done"><span class="snum">2</span>Type</li>
|
|
260
|
+
<li class="now" aria-current="step"><span class="snum">3</span>About</li>
|
|
261
|
+
<li><span class="snum">4</span>Home</li>
|
|
262
|
+
<li><span class="snum">5</span>Address</li>
|
|
263
|
+
<li><span class="snum">6</span>Create</li>
|
|
264
|
+
</ol>
|
|
265
|
+
<div class="step" style="max-width:none">
|
|
266
|
+
<h2 class="vTitle">tell us about it</h2>
|
|
267
|
+
<p class="vLede">Optional. Skip it and nothing about your project changes. Answering shapes what we set up for you, and a description is what puts the project on the public map.</p>
|
|
268
|
+
<label class="hairField" style="max-width:640px"><span>What are you building? <small>(a sentence or two)</small></span><textarea rows="2" placeholder="A co-op farming game where the seasons never repeat." aria-label="What are you building?"></textarea></label>
|
|
269
|
+
<p class="eyebrow" style="margin:30px 0 0">Who's building it?</p>
|
|
270
|
+
<div class="choice" role="group" aria-label="Who's building it" style="margin-top:10px">
|
|
271
|
+
<label><input type="radio" name="w"><span class="ch">Just me</span><span class="cb">One founder and the hall's agents.</span></label>
|
|
272
|
+
<label class="on"><input type="radio" name="w" checked><span class="ch">A small team</span><span class="cb">A few people who already know each other.</span></label>
|
|
273
|
+
<label><input type="radio" name="w"><span class="ch">An open community</span><span class="cb">Anyone who signs in can join and build.</span></label>
|
|
274
|
+
</div>
|
|
275
|
+
<div class="doors"><button type="button" class="door">back</button><span class="push"></span><button type="button" class="textDoor">skip for now</button><button type="button" class="door primary">next</button></div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
</section>
|
|
279
|
+
|
|
280
|
+
<section data-state="home">
|
|
281
|
+
<div class="view">
|
|
282
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
283
|
+
<li class="done"><span class="snum">1</span>Name</li>
|
|
284
|
+
<li class="done"><span class="snum">2</span>Type</li>
|
|
285
|
+
<li class="done"><span class="snum">3</span>About</li>
|
|
286
|
+
<li class="now" aria-current="step"><span class="snum">4</span>Home</li>
|
|
287
|
+
<li><span class="snum">5</span>Address</li>
|
|
288
|
+
<li><span class="snum">6</span>Create</li>
|
|
289
|
+
</ol>
|
|
290
|
+
<div class="step" style="max-width:none">
|
|
291
|
+
<h2 class="vTitle">where the code lives</h2>
|
|
292
|
+
<p class="vLede">Every project is a real GitHub repository that you own. Start from a clean slate, or bring a repo you already have.</p>
|
|
293
|
+
<div class="choice two" role="group" aria-label="Starting point">
|
|
294
|
+
<label class="on"><input type="radio" name="h" checked><span class="ch">Start fresh</span><span class="cb">A new, empty public repo. We scaffold everything: config, first version, kickoff tasks.</span></label>
|
|
295
|
+
<label><input type="radio" name="h"><span class="ch">Adopt a repo I have</span><span class="cb">Layer Cloud Bongos onto an existing repository, history, code and backlog intact. Public or private, we never change it.</span></label>
|
|
296
|
+
</div>
|
|
297
|
+
<label class="hairField" style="max-width:640px"><span>New repository name</span><input type="text" placeholder="mercury" aria-label="New repository name"><div class="hint">We'll create an empty <code>public</code> repo at <code>github.com/builder/mercury</code>. Projects here are open by design.</div></label>
|
|
298
|
+
<p class="fact">Repository access is granted. Want private code? Create the repo yourself on GitHub and adopt it; we never change a repo's visibility. <a href="#">Enter it manually</a> instead.</p>
|
|
299
|
+
<div class="doors"><button type="button" class="door">back</button><button type="button" class="door primary push">next</button></div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</section>
|
|
303
|
+
|
|
304
|
+
<section data-state="address">
|
|
305
|
+
<div class="view">
|
|
306
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
307
|
+
<li class="done"><span class="snum">1</span>Name</li>
|
|
308
|
+
<li class="done"><span class="snum">2</span>Type</li>
|
|
309
|
+
<li class="done"><span class="snum">3</span>About</li>
|
|
310
|
+
<li class="done"><span class="snum">4</span>Home</li>
|
|
311
|
+
<li class="now" aria-current="step"><span class="snum">5</span>Address</li>
|
|
312
|
+
<li><span class="snum">6</span>Create</li>
|
|
313
|
+
</ol>
|
|
314
|
+
<div class="step">
|
|
315
|
+
<h2 class="vTitle">its address in the sky</h2>
|
|
316
|
+
<p class="vLede">The handle names your project on the platform, and its address comes with it. Once it stands up, a few GitHub steps (the next screen walks you through them) switch sign-in on.</p>
|
|
317
|
+
<label class="hairField"><span>Project handle</span><input type="text" value="mercury" aria-label="Project handle"><div class="hint ok">mercury is free.</div></label>
|
|
318
|
+
<p class="addrBig"><b>mercury</b>.cloudbongos.com</p>
|
|
319
|
+
<p class="fact" style="margin-top:0">Yours from the moment it stands up. You can point a domain you own at it any time.</p>
|
|
320
|
+
<details class="fold"><summary>use a domain I own instead</summary><label class="hairField" style="margin-top:6px"><span>Domain you own</span><input type="text" placeholder="mercury.example.com" aria-label="Domain you own"><div class="hint"> </div></label></details>
|
|
321
|
+
<label class="opt"><input type="checkbox"><span>Start without an address. Possible, but sign-in on your project can't be set up until it has one.</span></label>
|
|
322
|
+
<div class="doors"><button type="button" class="door">back</button><button type="button" class="door primary push">next</button></div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</section>
|
|
326
|
+
|
|
327
|
+
<section data-state="review">
|
|
328
|
+
<div class="view">
|
|
329
|
+
<ol class="wizRail" aria-label="Creation steps">
|
|
330
|
+
<li class="done"><span class="snum">1</span>Name</li>
|
|
331
|
+
<li class="done"><span class="snum">2</span>Type</li>
|
|
332
|
+
<li class="done"><span class="snum">3</span>About</li>
|
|
333
|
+
<li class="done"><span class="snum">4</span>Home</li>
|
|
334
|
+
<li class="done"><span class="snum">5</span>Address</li>
|
|
335
|
+
<li class="now" aria-current="step"><span class="snum">6</span>Create</li>
|
|
336
|
+
</ol>
|
|
337
|
+
<div class="step" style="max-width:760px">
|
|
338
|
+
<h2 class="vTitle">ready to roll</h2>
|
|
339
|
+
<p class="vLede">One tap files the request and the platform starts standing your project up: server, database, address. Here is the beat you are about to drop.</p>
|
|
340
|
+
<div class="ledger last">
|
|
341
|
+
<span class="k">project</span><span class="v">Mercury</span>
|
|
342
|
+
<span class="k">type</span><span class="v">Game</span>
|
|
343
|
+
<span class="k">about</span><span class="v">A co-op farming game where the seasons never repeat.</span>
|
|
344
|
+
<span class="k">who's building it</span><span class="v">A small team</span>
|
|
345
|
+
<span class="k">starting from</span><span class="v">A fresh, empty repo</span>
|
|
346
|
+
<span class="k">repository</span><span class="v"><code>builder/mercury</code></span>
|
|
347
|
+
<span class="k">handle</span><span class="v"><code>mercury</code></span>
|
|
348
|
+
<span class="k">address</span><span class="v"><code>mercury.cloudbongos.com</code></span>
|
|
349
|
+
<span class="k">shape</span><span class="v">Its own server, running the platform's current release</span>
|
|
350
|
+
</div>
|
|
351
|
+
<div class="doors"><button type="button" class="door">back</button><button type="button" class="door primary big push">create my project</button></div>
|
|
352
|
+
<p class="fact">This files the request; the control plane does the real standup and nothing touches servers from this page. You'll get the few steps only you can do right after.</p>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
</section>
|
|
356
|
+
|
|
357
|
+
<section data-state="done">
|
|
358
|
+
<div class="view">
|
|
359
|
+
<div class="step" style="max-width:760px">
|
|
360
|
+
<p class="eyebrow">filed</p>
|
|
361
|
+
<h2 class="vTitle">the drums are rolling</h2>
|
|
362
|
+
<p class="vLede">Provisioning is requested for <b>Mercury</b>. The platform stands up the server, database, and address on its own. Watch it right here, or any time on <a href="#" style="color:var(--ink)">your projects page</a>.</p>
|
|
363
|
+
<ul class="rail" role="status"><li class="done">Request filed</li><li class="now">Standing it up</li><li>Live</li></ul>
|
|
364
|
+
<p class="railNote">Raising the server, database, and address. Nothing needed from you.</p>
|
|
365
|
+
<p class="eyebrow" style="margin:40px 0 0">Your steps, the parts only you can play</p>
|
|
366
|
+
<ol class="humanSteps">
|
|
367
|
+
<li class="sdone"><b>Sign in with GitHub</b><p>Done at the door. The project belongs to you.</p></li>
|
|
368
|
+
<li><b>Install the project's GitHub App</b><p>One click on GitHub gives the hall's agents a door into the repository. Nothing else on your account is touched.</p><div class="doors"><a class="door primary" href="#">open on github</a></div></li>
|
|
369
|
+
<li><b>Say who can join</b><p>Anyone, by application, or by invitation. You can change it any time from the project's page.</p></li>
|
|
370
|
+
<li><b>Point your domain</b><p>Only if you brought one: one DNS record at your registrar, the exact value shown on the project's page.</p></li>
|
|
371
|
+
</ol>
|
|
372
|
+
<p class="samePath">These are the same steps however a project is created. Nothing here is special to this page.</p>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
</section>
|
|
376
|
+
|
|
377
|
+
<section data-state="beside">
|
|
378
|
+
<div class="view">
|
|
379
|
+
<div class="beside">
|
|
380
|
+
<div>
|
|
381
|
+
<ol class="sideRail" aria-label="Creation steps">
|
|
382
|
+
<li class="done">Name<span class="sub">Mercury</span></li>
|
|
383
|
+
<li class="now" aria-current="step">Type<span class="sub">what kind of project it is</span></li>
|
|
384
|
+
<li>About<span class="sub">optional</span></li>
|
|
385
|
+
<li>Home<span class="sub">where the code lives</span></li>
|
|
386
|
+
<li>Address<span class="sub">its handle and its address</span></li>
|
|
387
|
+
<li>Create<span class="sub">the review, then the request</span></li>
|
|
388
|
+
</ol>
|
|
389
|
+
<div class="forming">
|
|
390
|
+
<span class="worldOrb" data-shape="bead" data-material="chrome" data-style="tint" style="--acc:var(--sea);--d:96px"><span class="disc"></span></span>
|
|
391
|
+
<p class="fact">Its planet, forming. The walk chooses one for the name; you can change it from the project's page.</p>
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="step" style="max-width:none">
|
|
395
|
+
<h2 class="vTitle">what kind of project is it?</h2>
|
|
396
|
+
<p class="vLede">Pick the shape that fits best. It is how the project is listed on the map, and it stays as you pick it for now. Not sure is a fine answer.</p>
|
|
397
|
+
<div class="choice" role="group" aria-label="Project type">
|
|
398
|
+
<label class="on"><input type="radio" name="t2" checked><span class="ch">Game</span><span class="cb">A world people play in. Its hall builds levels, characters and the loop.</span></label>
|
|
399
|
+
<label><input type="radio" name="t2"><span class="ch">Research</span><span class="cb">A question and the work to answer it.</span></label>
|
|
400
|
+
<label><input type="radio" name="t2"><span class="ch">Business</span><span class="cb">A product or a service with customers.</span></label>
|
|
401
|
+
<label><input type="radio" name="t2"><span class="ch">Non-profit</span><span class="cb">A cause with a community around it.</span></label>
|
|
402
|
+
<label><input type="radio" name="t2"><span class="ch">Not sure</span><span class="cb">Fine. It can change later.</span></label>
|
|
403
|
+
</div>
|
|
404
|
+
<div class="doors"><button type="button" class="door">back</button><button type="button" class="door primary push">next</button></div>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
</section>
|
|
409
|
+
</main>
|
|
410
|
+
<footer class="foot">A composition sheet for task 1003346. Nothing here is served.</footer>
|
|
411
|
+
<script>
|
|
412
|
+
/* The mock's state contract: read ?state= once, apply one state. No motion in script; nothing is built here. */
|
|
413
|
+
(function () {
|
|
414
|
+
var states = ['gate', 'name', 'type', 'about', 'home', 'address', 'review', 'done', 'beside'];
|
|
415
|
+
var state = new URLSearchParams(location.search || location.hash.slice(1) || (window.__Q || '')).get('state') || 'name';
|
|
416
|
+
if (states.indexOf(state) === -1) state = 'name';
|
|
417
|
+
document.body.setAttribute('data-state', state);
|
|
418
|
+
})();
|
|
419
|
+
</script>
|
|
420
|
+
</body>
|
|
421
|
+
</html>
|
|
@@ -208,3 +208,29 @@ Three mastheads, rendered dark and light at 1440 / 390 / 320 (ALL CLEAN) and mea
|
|
|
208
208
|
**The flows, guarded.** The DONE WHEN keeps every manage flow green; there were no such probes, so this round wrote them: attach (the row's fold), restart (a fifth fixture row, Mooring, live but unreachable), teardown (the row's two presses and the manage page's typed-back ender), revive, retry and join drive the stub's receipts end to end (`serve.js` now answers the asks; `projects.probes.json`).
|
|
209
209
|
|
|
210
210
|
**Retargeted.** `tests/projects_hub.mjs` (the planet, the fixed tracks, the h1 outside `#mMain`, the `.mSec` cards; the sphere's glow gone) and `tests/projects_hub_pre_uat.mjs` (the manage ledger, `paintManagePlanet`, the docked planet's cursor); the copy registry regenerated.
|
|
211
|
+
|
|
212
|
+
## 15. The create wizard: the composition round (task 1003346)
|
|
213
|
+
|
|
214
|
+
**Date:** 2026-08-29 · the CREATE half of the owner's ask after the planets review ("the your projects page also needs a makeover as well as the create a project page"); the YOUR PROJECTS half is §14. The wizard was the last surface still wearing the old skin: a card on the page, circled step numbers on a connector, boxed fields, a glowing primary, the bongo pair beside the step.
|
|
215
|
+
|
|
216
|
+
**The round.** One sheet, `docs/design/mocks/hub/wizard.html` (`?state=gate|name|type|about|home|address|review|done|beside`; check-mock ALL RULES PASS; shot at 1440 and 390 through the kit's stub, which serves `docs/` raw, ALL CLEAN after two fixes the shots found: an inline link under the 24px floor in the done panel's clause, and the human steps' paragraphs auto-placed into the 44px counter column). The grammar, per step: the six-step strip as **the lifecycle rail** (hairlines, a 7px dot, one lit step on the accent with its outline halo, the number in the display voice, the name in the label face; at 390 it folds to two rows of three); the step title lowercase in the display voice with one clause; **fields as one bottom hairline** that takes ink on focus, the label above in the label face, the hint under it in the status ink (ok green, err red); **the type as five hairline cells of one band** (the Projects band's grammar, the chosen one carrying the dot; at 390 the cells stack on hairlines); the team as three cells; the home as two wider cells (start fresh / adopt) with the repository field under them; the address step with the handle's verdict in green, **the address in the display voice** (`mercury.cloudbongos.com`, the handle on the deep accent), the domain-you-own as a fold, the no-address option as a plain checkbox line; **the review as a ledger** of label · value rows on soft hairlines (project, type, about, who's building it, starting from, repository, handle, address, shape); the doors as hairline pills with the accent only on the primary, back as a plain pill, skip as an underlined text door; the done panel with **the standup strip as the same rail** (request filed · standing it up · live) and the steps only you can play as a numbered ledger (`01`…`04`, the finished one reading DONE in the ok ink); the signed-out door as the display title, the clause, one inverted pill and the consent line. No card ground, no box shadow, no glow.
|
|
217
|
+
|
|
218
|
+
**The two versions.** **v1 the rail above** (the wizard's own strip, in the rail's grammar, across the top; the step under it in one column, 640px wide). **v2 the rail beside** (`?state=beside`): the six steps as a ledger down the left, each with what was answered under it (Mercury under NAME once typed), the lit step underlined on the accent, the step on the right; at the ledger's foot **the project's planet forms** (the walk's template for the name, changeable from the project's page later). At 390 v2 becomes v1's folded rail and the planet waits for the done panel, so the two versions meet on a phone.
|
|
219
|
+
|
|
220
|
+
**The pick page:** https://claude.ai/code/artifact/<redacted> — two decisions: where the rail sits (v1 above / v2 beside), and whether the bongo pair stays beside the step (the owner's one-mark-on-every-surface rule of 2026-08-13) or leaves the wizard for the planet. If no pick lands, the build takes v1 with the bongo pair kept; v2 and the planet stay a CSS round away.
|
|
221
|
+
|
|
222
|
+
**What the sheet does not decide.** The wizard's copy: the sheet's words are stand-ins written dash-free for check-mock; the build keeps the page's own strings and flags any it would change to the copy desk (the wizard is the registry's largest block). Every flow stays: the draft (`-v2`), the repo picker, the domain step, the progress strip's fixed status vocabulary, the enqueue-only trust boundary (ADR 0111). The kit's BEFORE of the old wizard (`in-new`, `out-new`) rendered clean, so the floor list for this build is empty; what the build adds is per-step states so every panel has a shot.
|
|
223
|
+
|
|
224
|
+
**Not built yet.** The page waits for the pick (the round's method). The build: `cosmos.css` rules scoped to `#view-new` (no `.card` ground, the `.steps` strip drawn as the rail, `.typeCards` as cells, the fields, `.review` as the ledger, the pills, the done panel's `.humanSteps`), the per-step states in `projects.states.json`, `tests/projects_hub.mjs` wizard pins + `tests/onboard.mjs` retargeted, the wizard driver against the stub, the copy registry regenerated.
|
|
225
|
+
|
|
226
|
+
### 15.1 The build: v1 the rail above, the bongo pair kept (task 1003346)
|
|
227
|
+
|
|
228
|
+
**Date:** 2026-08-29 · the pick page carried no comment in the session, and the round's fallback was named on it ("if no pick lands, the build takes v1 with the bongo pair kept"), so the build took it — **v1 the rail above**, the bongo pair beside the step as the owner's one-mark-on-every-surface rule has it, its halo gone. The pick page stays up; v2 the rail beside and the planet forming at its foot are a CSS round away.
|
|
229
|
+
|
|
230
|
+
**What was built.** The wizard keeps every panel, form and id the driver and the tests pin, and takes the world's grammar in two sheets. `cosmos.css` draws the **frame by scope** (`#view-new`): no `.card` ground; the six-step strip (`.steps`) as the lifecycle rail — six hairlines on a grid, the connector's 3px bar replaced by the 7px dot, the number in the display voice, the name in the label face, the lit step on the accent with its outline halo, an answered step still a way back (`role=button`); the step title lowercase in the display voice (`text-transform`, so the registry's strings stand); the doors as pills, lowercase, the accent only on the primary, back and skip as hairline pills, the GitHub sign-in inverted; the error alert as the error ink between two hairlines; the done clause's link on the 24px floor. `projects.html`'s own wizard block is **rewritten in place** for the wizard's structures: fields as one bottom hairline that takes ink on focus (`--rule`, never `--line`; `.bad` on the error ink); the type and team choices as hairline cells of one band (`.typeCards` a grid on two hairlines, `.tpill` a cell carrying the dot, the chosen one on the accent; the per-type description a clause, no tinted card); start fresh / adopt as two cells (`.choice` a grid cell, the icon gone, the dot on the name); the reassurances as clauses; the repo picker as hairline rows with the chosen one marked on the accent; the address as a fact in the display voice (`.addrBig code` a block in the display face, the clause under it in the body face; opted-out and unavailable keep their inks, no box); the review as a ledger (`.review` a 172px · 1fr grid, `li{display:contents}`, label · value rows on soft hairlines, the last closed); the review's doors on one row, back then the primary (the one markup change there); the done panel with the tick gone and the title standing alone, the steps heading in the label face by class (`.stepsHead`, the other markup change), the human steps as a numbered ledger (`01`…, DONE in the ok ink, a locked step muted by tokens), the `.kv` rows and their copy pill on hairlines; the standup strip (`.prog`) drawn as the same rail — no plate, no connector, no pulse; isLive in the ok ink, isErr in the error ink, flowDown neutral — its ≥5 rules and derived tokens kept where `tests/cosmos_token_contrast.mjs` pins them. No gradient, no box shadow, no literal colour in either sheet.
|
|
231
|
+
|
|
232
|
+
**The copy, untouched — flagged to the copy desk.** The sheet's stand-in copy was dash-free for check-mock; the page keeps its own words. Strings the world's voice would change, not rewritten here: the em-dash clauses ("Optional — skip it…", "Pick the shape that fits best — it's how…", "Your steps — the parts only you can play", "One tap files the request … — server, database, address. Here's the beat…", "Your project's repo and server are yours — Cloud Bongos is…"), the arrows in the doors ("Continue →", "Next →", "← Back"), and the tick's replacement copy on the done panel (none was added; the rail says filed).
|
|
233
|
+
|
|
234
|
+
**The kit.** Six per-step states in `projects.states.json` (`in-new-type` … `in-new-done`), each replaying the walk from the name step in a fresh context, and a **wizard driver** in `projects.probes.json` that files a project end to end at 1440 (and reaches the review at 390): the name, the type cell, the about textarea and the team cell, home, the handle, a domain, the review, `#doCreate`; then the done panel with the standup rail lit and the human steps rendered. The stub gained the handle check (`/provisioning/slug-available` → free) and its filing receipt now names an instance — Harbor, the fixture's standing-up row — so the done panel polls a real row and the rail reads "standing it up". Three things the driver taught: the stub's `/github/repo*` answer reads as repo access granted, so the home step takes the **fresh** path and names the repository from the project (no manual fields); a **dotless host assigns no address**, so the address step opens its domain fold itself and the walk brings `mercury.example.com` (a click on the summary would close it); the done clause's inline link sat under the 24px floor, the same problem the sheet had. AFTER: `render.js --page /projects` ALL CLEAN (66 states × 3 sizes), the empty and floor siblings ALL CLEAN, probes 41/41.
|
|
235
|
+
|
|
236
|
+
**Retargeted.** `tests/projects_hub.mjs` gains two pins: the frame by scope (no card ground, six tracks, the dot, the lit step's halo, the lowercase title, the pills, the inverted sign-in, the halo gone, no box-shadow, no literal colour) and the structures (hairline fields, the bands, the ledger, the numbered steps with every child in the text column — the sheet's own bug — the rail without a pulse, the tick gone, the address in the display voice, no gradient) plus **the filing body pinned** (slug, `hosting_shape`, `target_ref`, `onboard_mode` — nothing enqueued changed, ADR 0111) and the kit's states and driver present. `tests/onboard.mjs` needed no retarget: the human steps' strings and tags are JS-rendered and untouched. The copy registry regenerated (line numbers moved with the block; no string changed).
|
package/docs/file-map.md
CHANGED
|
@@ -351,6 +351,8 @@ tests/
|
|
|
351
351
|
├── own_scope_guard.mjs ← (task 1003343, goal 1000045 criterion own-scope-held-by-a-test): the OWN-SCOPE structural guard, generalised out of memory_isolation.mjs. An explicit inventory of own-scoped route files; inside them the route's declared PATH decides — a path naming no builder must never read a subject from the request (direct, optional-chained, destructured, aliased, computed-key or header), a path that DOES name one needs a per-route exemption whose gate the guard verifies is present. Repo-wide backstop: any file mounting a `/me` route must be in the inventory. Source-grepping, so it runs in the DB-free `unit` lane.
|
|
352
352
|
├── account_existence_rate_limit.mjs ← (task 1003339, goal 1000045, ADR 0209): the two PUBLIC account-existence probes (onboarding GET /access-requests/status + core GET /auth/web/admission-status) share ONE per-IP budget. Counts to the limit on each route, proves the budget is shared in both directions and when alternated, moves Date.now to prove the window slides on the real mounted route, and proves a refused probe issues no query. DB-free; mutation-checked three ways.
|
|
353
353
|
├── effective_visibility_predicate.mjs ← (task 1002967, goal 1000045): the EFFECTIVE-VISIBILITY structural guard over `modules/platform-identity/account-visibility.js` (the file task 1002295 landed and this task ADOPTED rather than duplicating). Three layers — SQL and JS agree row-for-row over the privacy-spec D2 matrix; that file is the only one allowed to compare `profile_state`/`account_visibility`/`hide_stats` to a literal (per-occurrence exemptions, each with a reason and a checked obligation); and every `SELECT` on `platform_identity_accounts` is enumerated FROM SOURCE and must join a shared predicate, be declared non-public, or be a checked deferral to a named caller — so a read that does not exist yet (hub search, the sitemap) fails the build until its author classifies it. Behavioural half runs the real `/profiles/:handle` route over an in-memory accounts table filtered by each statement's own WHERE clause: private → 404 (never 403), byte-identical to stranger and owner alike. DB-free `unit` lane.
|
|
354
|
+
├── application_lifecycle.mjs ← (task 1002284, goal 1000045, ADR 0201 D1/D3.2/D4 + ADR 0208): the application lifecycle EXECUTED — apply, list-pending, approve, decline, RESCIND (`invited → dismissed`), idempotency on the state already held, and the two things that must never happen: a builder without `access_request.review` moving the queue, and a VOUCH buying admission. Real router, REAL `requirePermission` resolving against the real government catalog's rank seed, and the REAL `hasInvitedAccessRequest` from `src/bongos/db-kernel.js` pointed at the same in-memory `access_requests` table (a stubbed `./pool`), whose filter is built from each statement's own WHERE clause and which refuses a predicate it cannot read. The no-authority proof seeds a vouched row and asserts the approve path and the admission read are byte-identical to the unvouched twin, and that no statement on either path names `applicant_github_id`/`vouched_at`. DB-free `unit` lane.
|
|
355
|
+
├── application_echo.mjs ← (task 1002284, goal 1000045, ADR 0201 D1.3/D1.4): the hub's STATUSLESS echo of an application. Part A pins the domain functions — the read binds `APPLICATION_ECHO_WINDOW_DAYS` itself (one 30, not three), the write is an upsert on the pair, neither statement mentions a status, and a non-numeric principal is refused before any query (ADR 0171 D2). Part B runs the real `POST /my-projects/join` and `GET /my-projects` over an in-memory `platform_identity_application_echoes` table with the relay's answer scripted: only an accepted application leaves a trace — a standing membership, either door refusal, a members-only project and an unreachable project leave none — and best-effort is asserted in both directions (a failed echo write still reports the filed application; a failed echo read still lands the memberships listing). DB-free `unit` lane.
|
|
354
356
|
└── public_task_resolver.mjs ← (#604): the public `/public/tasks/:id` projection — title/value_summary exposed only for shipped|confirmed; withheld for in-flight so unshipped/security task names can't leak.
|
|
355
357
|
```
|
|
356
358
|
|
|
@@ -1283,5 +1283,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
1283
1283
|
landed since 1.19.421 with no explicit bump. run 33267393283. (task 1002620)
|
|
1284
1284
|
1.19.423 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1285
1285
|
landed since 1.19.422 with no explicit bump. run 33269205170. (task 1002620)
|
|
1286
|
+
1.19.424 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1287
|
+
landed since 1.19.423 with no explicit bump. run 33270353952. (task 1002620)
|
|
1288
|
+
1.19.425 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1289
|
+
landed since 1.19.424 with no explicit bump. run 33270559541. (task 1002620)
|
|
1286
1290
|
---------------------------------------------------------------------------
|
|
1287
1291
|
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
-- core_230_access_requests_applicant_vouch.sql — an access request can carry a
|
|
2
|
+
-- VOUCHED platform identity beside the GitHub username it has always carried
|
|
3
|
+
-- (task 1002284, R08 of goal 1000045; ADR 0201 D1.2).
|
|
4
|
+
--
|
|
5
|
+
-- WHAT PROBLEM THIS SOLVES. POST /api/gds/access-requests is the one public,
|
|
6
|
+
-- unauthenticated write on the GDS: it presents nothing the applicant could not
|
|
7
|
+
-- have typed into the project's own landing page. Goal criterion C4 wants the
|
|
8
|
+
-- reviewer to see the applicant's cross-project track record beside the ask —
|
|
9
|
+
-- and attaching a record to a `github_login` that nobody vouched for turns the
|
|
10
|
+
-- queue into an impersonation surface (file a request naming a well-known
|
|
11
|
+
-- builder, the owner reads that builder's excellent record, approves, and
|
|
12
|
+
-- whoever holds that GitHub account walks in). So the record cannot exist
|
|
13
|
+
-- without a vouch, and the vouch needs somewhere to land. That is this file.
|
|
14
|
+
--
|
|
15
|
+
-- `applicant_github_id IS NOT NULL` **IS** the vouch mark. There is deliberately
|
|
16
|
+
-- no `source`/`vouched` enum beside it: a second column would be free to
|
|
17
|
+
-- disagree with the first, and the row would then have two answers to one
|
|
18
|
+
-- question. `vouched_at` records WHEN the vouch was verified, which is audit
|
|
19
|
+
-- data, never the mark itself.
|
|
20
|
+
--
|
|
21
|
+
-- `text`, not `bigint`, because core `builders.github_id` is `text`
|
|
22
|
+
-- (`003_pms.sql`) and this column must join it without a cast. The hub's own
|
|
23
|
+
-- tables hold github ids as `bigint`; that numeric cast is the hub module's
|
|
24
|
+
-- concern (ADR 0171 D2 already handles non-numeric principals there), not this
|
|
25
|
+
-- table's.
|
|
26
|
+
--
|
|
27
|
+
-- BOTH NULLABLE, AND THAT IS THE COMPATIBILITY STORY. A vouch that is absent or
|
|
28
|
+
-- invalid is never a refusal (ADR 0201 D2.3) — the row is simply written
|
|
29
|
+
-- unvouched, exactly as this table has always written it. An older hub, a
|
|
30
|
+
-- standalone instance with no hub public key, and a stranger filling in the
|
|
31
|
+
-- project's own landing form all produce NULL here and keep working unchanged.
|
|
32
|
+
--
|
|
33
|
+
-- NOTHING HERE IS AUTHORITY (ADR 0016 / ADR 0141). No admission decision reads
|
|
34
|
+
-- these columns. `hasInvitedAccessRequest` (src/bongos/db-kernel.js) still reads
|
|
35
|
+
-- `status = 'invited'` and nothing else; `firstTimeAdmissionBlocked` remains the
|
|
36
|
+
-- single gate all four sign-in paths call. A vouch is DESCRIPTIVE — it says "the
|
|
37
|
+
-- hub confirmed who this is", never "this person may enter". A vouched
|
|
38
|
+
-- application and an unvouched one are approved by the identical statement and
|
|
39
|
+
-- admit on the identical read; `tests/application_lifecycle.mjs` executes both
|
|
40
|
+
-- and asserts they are byte-identical, so the day someone wires a vouch into the
|
|
41
|
+
-- gate, that test goes red.
|
|
42
|
+
--
|
|
43
|
+
-- NO `applicant_handle` HERE — DELIBERATE, AND THE ONE PLACE ADR 0201 CONTRADICTS
|
|
44
|
+
-- ITSELF. D1.2 says this migration adds "exactly" two columns; D2.6 says the
|
|
45
|
+
-- handle at apply time is stored on the row. Both cannot be true of one file. The
|
|
46
|
+
-- ADR's own dependency table routes **D2 wholesale** — "the assertion, the header,
|
|
47
|
+
-- the live browser read, the handle" — to R09 (task 1002285), so the handle
|
|
48
|
+
-- arrives with its WRITER rather than ahead of it. A column no code writes is
|
|
49
|
+
-- worse than no column: it reads NULL for reasons that have nothing to do with
|
|
50
|
+
-- the applicant actually lacking a handle, and any reader added in between
|
|
51
|
+
-- renders "no record" for the wrong reason. R09 adds `applicant_handle` in its
|
|
52
|
+
-- own additive migration, in the same change that first writes one.
|
|
53
|
+
--
|
|
54
|
+
-- The console wave (spike 1002786 R2) adds `kind` / `created_by` to this table in
|
|
55
|
+
-- a SEPARATE additive migration. The two waves must not both add `kind`; neither
|
|
56
|
+
-- touches the other's columns, so either order works.
|
|
57
|
+
--
|
|
58
|
+
-- PURELY ADDITIVE + idempotent. Forward-safe: the previous code release ignores
|
|
59
|
+
-- both columns and runs unchanged against this schema, so a replay or a rollback
|
|
60
|
+
-- is a no-op. Fresh-DB-replay safe; no hard-coded builder ids (learning 1238).
|
|
61
|
+
-- access_requests is a CORE-owned table (created in 060_access_requests), so this
|
|
62
|
+
-- lives in core migrations/, core_-namespaced (ADR 0108 §5: a core migration
|
|
63
|
+
-- numbered above LEGACY_BARE_CORE_MAX=187 must carry the core_ prefix).
|
|
64
|
+
-- migrate.sh records this file's stem in schema_migrations — the file does not
|
|
65
|
+
-- self-insert.
|
|
66
|
+
|
|
67
|
+
BEGIN;
|
|
68
|
+
|
|
69
|
+
ALTER TABLE access_requests
|
|
70
|
+
ADD COLUMN IF NOT EXISTS applicant_github_id text,
|
|
71
|
+
ADD COLUMN IF NOT EXISTS vouched_at timestamptz;
|
|
72
|
+
|
|
73
|
+
COMMENT ON COLUMN access_requests.applicant_github_id IS
|
|
74
|
+
'The platform account the hub VOUCHED for at apply time (ADR 0201 D1.2), or NULL for an unvouched request — a stranger off the landing page, an older hub, or a non-federated instance. NOT NULL is itself the vouch mark; there is no second flag to disagree with it. text to join builders.github_id without a cast. DESCRIPTIVE ONLY — no admission path reads this (ADR 0016): status=''invited'' is still the entire gate.';
|
|
75
|
+
|
|
76
|
+
COMMENT ON COLUMN access_requests.vouched_at IS
|
|
77
|
+
'When the hub assertion accompanying this request was verified (ADR 0201 D1.2). Audit data — the vouch MARK is applicant_github_id IS NOT NULL, never this timestamp. NULL on every unvouched row.';
|
|
78
|
+
|
|
79
|
+
COMMIT;
|
|
@@ -56,8 +56,13 @@ function parseApprovalMarker(content) {
|
|
|
56
56
|
|
|
57
57
|
// DB — resolve a pending access request to 'invited' | 'dismissed', stamping the
|
|
58
58
|
// approving Archon. GUARDED on status='pending' (idempotent: a second reaction,
|
|
59
|
-
// or one on an already-resolved request, matches nothing → null)
|
|
60
|
-
// the PATCH /access-requests/:id route
|
|
59
|
+
// or one on an already-resolved request, matches nothing → null). This is NARROWER
|
|
60
|
+
// than the PATCH /access-requests/:id route, which since task 1002284 also RESCINDS
|
|
61
|
+
// an approval (invited → dismissed) and is idempotent on the state already held.
|
|
62
|
+
// The reaction path stays pending-only ON PURPOSE: a Discord 👎 carries no
|
|
63
|
+
// confirmation step and no ownership check beyond rank, so letting a stray reaction
|
|
64
|
+
// un-admit somebody is a worse failure than making the Archon open the hall to undo
|
|
65
|
+
// an approval. Returns the updated row or null.
|
|
61
66
|
async function resolveAccessRequest({ id, status, builderId }) {
|
|
62
67
|
const { rows } = await pool.query(
|
|
63
68
|
`UPDATE access_requests
|