@wenathlan/saddle 2.0.154 → 2.0.159

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.
Files changed (314) hide show
  1. package/Dockerfile +167 -1334
  2. package/README.md +59 -60
  3. package/biome.jsonc +3 -3
  4. package/browser.ts +482 -0
  5. package/cli.ts +274 -0
  6. package/distribution.ts +731 -0
  7. package/docker.config +29 -8
  8. package/docs/{architecture.1.8.19.mmd → architecture1819.md} +6 -0
  9. package/docs/artifactavailability.md +2 -2
  10. package/docs/browser.md +18 -1
  11. package/docs/{containerplatforms.2.1.0.md → containerplatforms210.md} +1 -1
  12. package/docs/{documentmap.1.8.12.md → documentmap1812.md} +1 -1
  13. package/docs/extension.md +13 -2
  14. package/docs/features.md +5 -0
  15. package/docs/libraryapi.md +1 -1
  16. package/docs/{ninety.modalities.md → ninetymodalities.md} +87 -4
  17. package/docs/{planning.ninety.md → planningninety.md} +6 -6
  18. package/docs/{releasenotes.1.8.13.md → releasenotes1813.md} +2 -2
  19. package/docs/{releasenotes.1.8.14.md → releasenotes1814.md} +1 -1
  20. package/docs/{repo.synthesis.1.8.16.md → reposynthesis1816.md} +1 -1
  21. package/docs/todo.md +2 -2
  22. package/docs/{todo.1.8.15.md → todo1815.md} +1 -1
  23. package/docs/{todo.1.8.16.md → todo1816.md} +5 -5
  24. package/execution.ts +677 -0
  25. package/foundation.ts +314 -0
  26. package/index.ts +36 -34
  27. package/isolation.ts +84 -0
  28. package/modalityregistry.ts +189 -145
  29. package/modes.ts +170 -0
  30. package/mttg.config +1 -1
  31. package/orchestrator.ts +49 -15
  32. package/package.json +105 -89
  33. package/qemu.config +2 -2
  34. package/sandbox.ts +3279 -0
  35. package/scheduler.ts +1 -1
  36. package/server.ts +52 -0
  37. package/tsconfig.json +12 -13
  38. package/virtual.ts +7528 -0
  39. package/workloadlaw.ts +293 -0
  40. package/dist/App.d.ts +0 -5
  41. package/dist/App.js +0 -52
  42. package/dist/Sol/Sol.d.ts +0 -3
  43. package/dist/Sol/Sol.js +0 -46
  44. package/dist/Sol/agentbrowser/agentbrowser.d.ts +0 -9
  45. package/dist/Sol/agentbrowser/agentbrowser.js +0 -121
  46. package/dist/Sol/architecture/architecture.d.ts +0 -9
  47. package/dist/Sol/architecture/architecture.js +0 -93
  48. package/dist/Sol/compute/compute.d.ts +0 -9
  49. package/dist/Sol/compute/compute.js +0 -22
  50. package/dist/Sol/console/console.d.ts +0 -15
  51. package/dist/Sol/console/console.js +0 -292
  52. package/dist/Sol/dashboard/dashboard.d.ts +0 -10
  53. package/dist/Sol/dashboard/dashboard.js +0 -181
  54. package/dist/Sol/docs/docs.d.ts +0 -9
  55. package/dist/Sol/docs/docs.js +0 -28
  56. package/dist/Sol/home/home.d.ts +0 -35
  57. package/dist/Sol/home/home.js +0 -239
  58. package/dist/Sol/integrations/integrations.d.ts +0 -9
  59. package/dist/Sol/integrations/integrations.js +0 -83
  60. package/dist/Sol/intro/intro.d.ts +0 -7
  61. package/dist/Sol/intro/intro.js +0 -102
  62. package/dist/Sol/login/login.d.ts +0 -16
  63. package/dist/Sol/login/login.js +0 -49
  64. package/dist/Sol/notfound/notfound.d.ts +0 -9
  65. package/dist/Sol/notfound/notfound.js +0 -15
  66. package/dist/Sol/onboarding/onboarding.d.ts +0 -25
  67. package/dist/Sol/onboarding/onboarding.js +0 -60
  68. package/dist/Sol/playground/playground.d.ts +0 -9
  69. package/dist/Sol/playground/playground.js +0 -127
  70. package/dist/Sol/register/register.d.ts +0 -16
  71. package/dist/Sol/register/register.js +0 -193
  72. package/dist/Sol/shell/Shell.d.ts +0 -124
  73. package/dist/Sol/shell/Shell.js +0 -335
  74. package/dist/Sol/wingets/ComputeBootladder.d.ts +0 -6
  75. package/dist/Sol/wingets/ComputeBootladder.js +0 -71
  76. package/dist/Sol/wingets/ComputeModalitycatalog.d.ts +0 -7
  77. package/dist/Sol/wingets/ComputeModalitycatalog.js +0 -71
  78. package/dist/Sol/wingets/ConsoleApibadge.d.ts +0 -7
  79. package/dist/Sol/wingets/ConsoleApibadge.js +0 -5
  80. package/dist/Sol/wingets/ConsoleEdgelaw.d.ts +0 -6
  81. package/dist/Sol/wingets/ConsoleEdgelaw.js +0 -36
  82. package/dist/Sol/wingets/ConsoleEventstimeline.d.ts +0 -19
  83. package/dist/Sol/wingets/ConsoleEventstimeline.js +0 -12
  84. package/dist/Sol/wingets/ConsoleSnapshotcontrols.d.ts +0 -8
  85. package/dist/Sol/wingets/ConsoleSnapshotcontrols.js +0 -8
  86. package/dist/Sol/wingets/ConsoleSpecpanel.d.ts +0 -21
  87. package/dist/Sol/wingets/ConsoleSpecpanel.js +0 -75
  88. package/dist/Sol/wingets/ConsoleTerminal.d.ts +0 -22
  89. package/dist/Sol/wingets/ConsoleTerminal.js +0 -77
  90. package/dist/Sol/wingets/DashboardAccountpanel.d.ts +0 -18
  91. package/dist/Sol/wingets/DashboardAccountpanel.js +0 -65
  92. package/dist/Sol/wingets/DashboardAdminpanel.d.ts +0 -6
  93. package/dist/Sol/wingets/DashboardAdminpanel.js +0 -90
  94. package/dist/Sol/wingets/DashboardAuditlog.d.ts +0 -8
  95. package/dist/Sol/wingets/DashboardAuditlog.js +0 -50
  96. package/dist/Sol/wingets/DashboardCreatesandboxform.d.ts +0 -10
  97. package/dist/Sol/wingets/DashboardCreatesandboxform.js +0 -71
  98. package/dist/Sol/wingets/DashboardEventstimeline.d.ts +0 -8
  99. package/dist/Sol/wingets/DashboardEventstimeline.js +0 -83
  100. package/dist/Sol/wingets/DashboardGlobalsandboxestable.d.ts +0 -8
  101. package/dist/Sol/wingets/DashboardGlobalsandboxestable.js +0 -57
  102. package/dist/Sol/wingets/DashboardMeshnodestable.d.ts +0 -8
  103. package/dist/Sol/wingets/DashboardMeshnodestable.js +0 -103
  104. package/dist/Sol/wingets/DashboardSandboxlist.d.ts +0 -10
  105. package/dist/Sol/wingets/DashboardSandboxlist.js +0 -163
  106. package/dist/Sol/wingets/DashboardUserstable.d.ts +0 -8
  107. package/dist/Sol/wingets/DashboardUserstable.js +0 -78
  108. package/dist/Sol/wingets/HomeEntrygate.d.ts +0 -23
  109. package/dist/Sol/wingets/HomeEntrygate.js +0 -73
  110. package/dist/Sol/wingets/HomeMetricstrip.d.ts +0 -9
  111. package/dist/Sol/wingets/HomeMetricstrip.js +0 -4
  112. package/dist/Sol/wingets/HomeRuntimediagram.d.ts +0 -1
  113. package/dist/Sol/wingets/HomeRuntimediagram.js +0 -22
  114. package/dist/Sol/wingets/LoginForm.d.ts +0 -19
  115. package/dist/Sol/wingets/LoginForm.js +0 -141
  116. package/dist/Sol/wingets/RegisterPasswordconfirm.d.ts +0 -13
  117. package/dist/Sol/wingets/RegisterPasswordconfirm.js +0 -16
  118. package/dist/Sol/wingets/RegisterPasswordmeter.d.ts +0 -19
  119. package/dist/Sol/wingets/RegisterPasswordmeter.js +0 -65
  120. package/dist/Sol/wingets/RegisterUsernamerules.d.ts +0 -11
  121. package/dist/Sol/wingets/RegisterUsernamerules.js +0 -16
  122. package/dist/Sol/wingets/index.d.ts +0 -39
  123. package/dist/Sol/wingets/index.js +0 -39
  124. package/dist/alternatives.d.ts +0 -508
  125. package/dist/alternatives.js +0 -950
  126. package/dist/api.d.ts +0 -154
  127. package/dist/api.js +0 -174
  128. package/dist/auth.d.ts +0 -268
  129. package/dist/auth.js +0 -476
  130. package/dist/automation.d.ts +0 -425
  131. package/dist/automation.js +0 -566
  132. package/dist/browser.d.ts +0 -561
  133. package/dist/browser.js +0 -1058
  134. package/dist/capacitor.config.d.ts +0 -45
  135. package/dist/capacitor.config.js +0 -48
  136. package/dist/catalog.d.ts +0 -43
  137. package/dist/catalog.js +0 -44
  138. package/dist/cli.d.ts +0 -16
  139. package/dist/cli.js +0 -168
  140. package/dist/communication.d.ts +0 -181
  141. package/dist/communication.js +0 -376
  142. package/dist/compute.d.ts +0 -1160
  143. package/dist/compute.js +0 -2272
  144. package/dist/dashboardlib.d.ts +0 -58
  145. package/dist/dashboardlib.js +0 -161
  146. package/dist/db.d.ts +0 -569
  147. package/dist/db.js +0 -1080
  148. package/dist/distribution.d.ts +0 -528
  149. package/dist/distribution.js +0 -810
  150. package/dist/drizzle.config.d.ts +0 -20
  151. package/dist/drizzle.config.js +0 -18
  152. package/dist/edgelandes.d.ts +0 -70
  153. package/dist/edgelandes.host.d.ts +0 -26
  154. package/dist/edgelandes.host.js +0 -1089
  155. package/dist/edgelandes.inproc.d.ts +0 -27
  156. package/dist/edgelandes.inproc.js +0 -952
  157. package/dist/edgelandes.js +0 -1133
  158. package/dist/edgelandes.ninety.d.ts +0 -31
  159. package/dist/edgelandes.ninety.js +0 -174
  160. package/dist/edgelandes.virtual.d.ts +0 -25
  161. package/dist/edgelandes.virtual.js +0 -629
  162. package/dist/edgeplane.d.ts +0 -121
  163. package/dist/edgeplane.js +0 -341
  164. package/dist/examplelocaljob.d.ts +0 -1
  165. package/dist/examplelocaljob.js +0 -14
  166. package/dist/execution.d.ts +0 -529
  167. package/dist/execution.js +0 -760
  168. package/dist/family.d.ts +0 -16
  169. package/dist/family.js +0 -42
  170. package/dist/familyurl.d.ts +0 -21
  171. package/dist/familyurl.js +0 -24
  172. package/dist/format.d.ts +0 -18
  173. package/dist/format.js +0 -59
  174. package/dist/foundation.d.ts +0 -172
  175. package/dist/foundation.js +0 -312
  176. package/dist/index.d.ts +0 -735
  177. package/dist/index.js +0 -1020
  178. package/dist/integration.d.ts +0 -235
  179. package/dist/integration.js +0 -228
  180. package/dist/intelligence.d.ts +0 -93
  181. package/dist/intelligence.js +0 -144
  182. package/dist/isolation.d.ts +0 -128
  183. package/dist/isolation.js +0 -95
  184. package/dist/labels.d.ts +0 -665
  185. package/dist/labels.js +0 -707
  186. package/dist/localauth.d.ts +0 -127
  187. package/dist/localauth.js +0 -413
  188. package/dist/media.d.ts +0 -343
  189. package/dist/media.js +0 -985
  190. package/dist/mesh.d.ts +0 -177
  191. package/dist/mesh.js +0 -468
  192. package/dist/modalityregistry.d.ts +0 -109
  193. package/dist/modalityregistry.js +0 -1386
  194. package/dist/modes.d.ts +0 -358
  195. package/dist/modes.js +0 -133
  196. package/dist/onboardingstate.d.ts +0 -79
  197. package/dist/onboardingstate.js +0 -282
  198. package/dist/orchestrator.d.ts +0 -1338
  199. package/dist/orchestrator.js +0 -4310
  200. package/dist/packager/targetcli.js +0 -4
  201. package/dist/paths.d.ts +0 -2
  202. package/dist/paths.js +0 -14
  203. package/dist/performance.d.ts +0 -415
  204. package/dist/performance.js +0 -826
  205. package/dist/quantum.d.ts +0 -809
  206. package/dist/quantum.js +0 -2072
  207. package/dist/render.d.ts +0 -380
  208. package/dist/render.js +0 -1072
  209. package/dist/runall.d.ts +0 -2
  210. package/dist/runall.js +0 -39
  211. package/dist/runtimeprobe.d.ts +0 -4
  212. package/dist/runtimeprobe.js +0 -8
  213. package/dist/sandbox.d.ts +0 -355
  214. package/dist/sandbox.js +0 -1721
  215. package/dist/sandboxenvprofile.d.ts +0 -29
  216. package/dist/sandboxenvprofile.js +0 -89
  217. package/dist/sandboxprofile.d.ts +0 -137
  218. package/dist/sandboxprofile.js +0 -241
  219. package/dist/sandboxqueue.d.ts +0 -108
  220. package/dist/sandboxqueue.js +0 -201
  221. package/dist/sandboxquota.d.ts +0 -121
  222. package/dist/sandboxquota.js +0 -236
  223. package/dist/scheduler.d.ts +0 -595
  224. package/dist/scheduler.js +0 -1258
  225. package/dist/scriptlanes.d.ts +0 -182
  226. package/dist/scriptlanes.js +0 -660
  227. package/dist/scripts.buildengine.d.ts +0 -1
  228. package/dist/scripts.buildengine.js +0 -39
  229. package/dist/scripts.securitygate.d.ts +0 -1
  230. package/dist/scripts.securitygate.js +0 -68
  231. package/dist/scripts.validateflatnative.d.ts +0 -1
  232. package/dist/scripts.validateflatnative.js +0 -72
  233. package/dist/security.d.ts +0 -500
  234. package/dist/security.js +0 -1169
  235. package/dist/seedcatalog.d.ts +0 -13
  236. package/dist/seedcatalog.js +0 -46
  237. package/dist/server.d.ts +0 -20
  238. package/dist/server.js +0 -53
  239. package/dist/speccatalog.d.ts +0 -31
  240. package/dist/speccatalog.js +0 -163
  241. package/dist/tiers.d.ts +0 -1001
  242. package/dist/tiers.js +0 -2169
  243. package/dist/utils.d.ts +0 -2
  244. package/dist/utils.js +0 -5
  245. package/dist/vaulthandoff.d.ts +0 -141
  246. package/dist/vaulthandoff.js +0 -444
  247. package/dist/virtual.d.ts +0 -640
  248. package/dist/virtual.js +0 -1284
  249. package/dist/virtualcpu.d.ts +0 -315
  250. package/dist/virtualcpu.js +0 -1180
  251. package/dist/virtualgpu.d.ts +0 -344
  252. package/dist/virtualgpu.js +0 -1000
  253. package/dist/virtualization.d.ts +0 -606
  254. package/dist/virtualization.js +0 -1186
  255. package/dist/virtualmemory.d.ts +0 -817
  256. package/dist/virtualmemory.js +0 -1795
  257. package/dist/vite.config.d.ts +0 -3
  258. package/dist/vite.config.js +0 -48
  259. package/dist/vitest.config.d.ts +0 -2
  260. package/dist/vitest.config.js +0 -25
  261. package/dist/webserver.d.ts +0 -166
  262. package/dist/webserver.js +0 -2226
  263. package/dist/workloadlaw.d.ts +0 -133
  264. package/dist/workloadlaw.js +0 -193
  265. package/docs/.gitkeep +0 -0
  266. package/docs/architecture.1.8.19.md +0 -76
  267. package/docs/logs/examplesession.json +0 -54
  268. package/docs/repo.analysis.1.8.21.json +0 -2617
  269. package/docs/repo.candidates.1.8.21.jsonl +0 -666
  270. package/docs/repo.selected.1.8.21.json +0 -786
  271. package/manifest.json +0 -20
  272. package/media.ts +0 -1337
  273. package/virtualcpu.ts +0 -1274
  274. package/virtualgpu.ts +0 -1182
  275. package/virtualization.ts +0 -1628
  276. package/virtualmemory.ts +0 -2303
  277. /package/docs/{artifactresearch.1.8.9.md → artifactresearch189.md} +0 -0
  278. /package/docs/{batches.1816.to.1820.md → batches1816to1820.md} +0 -0
  279. /package/docs/{brancharchive.2026.08.18.md → brancharchive20260818.md} +0 -0
  280. /package/docs/{containerplatforms.1.8.17.md → containerplatforms1817.md} +0 -0
  281. /package/docs/{e2ugh.engine.md → e2ughengine.md} +0 -0
  282. /package/docs/{flatbuildresearch.1.8.11.md → flatbuildresearch1811.md} +0 -0
  283. /package/docs/{licenseaudit.1.8.12.md → licenseaudit1812.md} +0 -0
  284. /package/docs/{mobileconversionresearch.1.8.10.md → mobileconversionresearch1810.md} +0 -0
  285. /package/docs/{nativeidentityresearch.1.8.11.md → nativeidentityresearch1811.md} +0 -0
  286. /package/docs/{native.wrappers.md → nativewrappers.md} +0 -0
  287. /package/docs/{planning.1.8.18.md → planning1818.md} +0 -0
  288. /package/docs/{planning.1.8.19.md → planning1819.md} +0 -0
  289. /package/docs/{planning.engine.md → planningengine.md} +0 -0
  290. /package/docs/{releasenotes.1.8.12.md → releasenotes1812.md} +0 -0
  291. /package/docs/{releasenotes.1.8.15.md → releasenotes1815.md} +0 -0
  292. /package/docs/{releasenotes.1.8.16.md → releasenotes1816.md} +0 -0
  293. /package/docs/{releasenotes.1.8.17.md → releasenotes1817.md} +0 -0
  294. /package/docs/{releasenotes.1.8.18.md → releasenotes1818.md} +0 -0
  295. /package/docs/{releasenotes.1.8.19.md → releasenotes1819.md} +0 -0
  296. /package/docs/{reorganization.1.8.8.md → reorganization188.md} +0 -0
  297. /package/docs/{reorganization.1.8.9.md → reorganization189.md} +0 -0
  298. /package/docs/{repo.research.1.8.16.md → reporesearch1816.md} +0 -0
  299. /package/docs/{repo.research.1.8.21.md → reporesearch1821.md} +0 -0
  300. /package/docs/{repo.synthesis.1.8.21.md → reposynthesis1821.md} +0 -0
  301. /package/docs/{research.1.8.18.isolation.md → research1818isolation.md} +0 -0
  302. /package/docs/{research.1.8.19.virtual.browser.md → research1819virtualbrowser.md} +0 -0
  303. /package/docs/{scanningresearch.1.8.11.md → scanningresearch1811.md} +0 -0
  304. /package/docs/{securityaudit.1.8.7.md → securityaudit187.md} +0 -0
  305. /package/docs/{securityreferences.1.8.11.md → securityreferences1811.md} +0 -0
  306. /package/docs/{securityresearch.1.8.11.md → securityresearch1811.md} +0 -0
  307. /package/docs/{signingresearch.1.8.12.md → signingresearch1812.md} +0 -0
  308. /package/docs/{tauri.glib.risk.1.8.11.md → tauriglibrisk1811.md} +0 -0
  309. /package/docs/{todo.1.8.18.md → todo1818.md} +0 -0
  310. /package/docs/{todo.1.8.19.md → todo1819.md} +0 -0
  311. /package/docs/{toolchainresearch.1.8.9.md → toolchainresearch189.md} +0 -0
  312. /package/docs/{web.duplicatecleanup.md → webduplicatecleanup.md} +0 -0
  313. /package/docs/{web.ideas.md → webideas.md} +0 -0
  314. /package/docs/{workflowimprovements.2026.08.19.md → workflowimprovements20260819.md} +0 -0
@@ -1,93 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * architecture page anchor — layer 3 of the anchor architecture.
4
- * The file carrying the folder's own name is the path manager of the page:
5
- * it imports the loose components beside it, mounts the page and re-exports
6
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
- * this file. This anchor carries the former main component of the folder,
8
- * which now lives here as the page mount itself.
9
- */
10
- import { ArrowUpRightRegular as ArrowUpRight, BrainCircuitRegular as Cpu, DatabaseRegular as Database, BranchForkRegular as GitBranch, GlobeRegular as Globe2, ShieldTaskRegular as ShieldCheck, } from '@fluentui/react-icons';
11
- // Signal & Ledger: the architecture as a diagram-as-ledger — layered hairline
12
- // rows (the runtime forms of sandboxprofile: runtime/packages, full/docker,
13
- // published/registries) with mono annotations and connector dashes, then the
14
- // four layers, the provider chain and the physical limit band. No floating
15
- // boxes: every layer is a ruled row on the same spine. The page ships zero
16
- // fixed data of its own: the runtime forms ride the declared vocabulary of
17
- // sandboxprofile, the provider chain and the layer words ride the label
18
- // store (labels.ts — the seed mirrors the rows into the labels table), and
19
- // every word reads through the typed accessor — the copy law.
20
- import { useEffect, useState } from 'react';
21
- import { PageShell } from '../shell/Shell.tsx';
22
- import { mediaSlots } from '../../catalog';
23
- import { label } from '../../labels.ts';
24
- import { SANDBOXFORMS } from '../../sandboxprofile.ts';
25
- /** the ledger annotations of the three runtime forms: the copy rides the
26
- * store under the architecture.form.* family, keyed by the declared form
27
- * ids of sandboxprofile (the ids are data, the words are copy). */
28
- const formlabels = {
29
- 'runtime-node': {
30
- name: label('architecture.form.runtimeNode.name'),
31
- pkg: label('architecture.form.runtimeNode.pkg'),
32
- note: label('architecture.form.runtimeNode.note'),
33
- },
34
- 'full-docker': {
35
- name: label('architecture.form.fullDocker.name'),
36
- pkg: label('architecture.form.fullDocker.pkg'),
37
- note: label('architecture.form.fullDocker.note'),
38
- },
39
- published: {
40
- name: label('architecture.form.published.name'),
41
- pkg: label('architecture.form.published.pkg'),
42
- note: label('architecture.form.published.note'),
43
- },
44
- };
45
- /** the four layers of the map: the glyph is presentation code, every word
46
- * rides the store (the home surfaces() precedent). */
47
- function layers() {
48
- return [
49
- {
50
- icon: GitBranch,
51
- name: label('architecture.layer.repository.name'),
52
- sub: label('architecture.layer.repository.sub'),
53
- body: label('architecture.layer.repository.body'),
54
- },
55
- {
56
- icon: Cpu,
57
- name: label('architecture.layer.runner.name'),
58
- sub: label('architecture.layer.runner.sub'),
59
- body: label('architecture.layer.runner.body'),
60
- },
61
- {
62
- icon: Database,
63
- name: label('architecture.layer.memory.name'),
64
- sub: label('architecture.layer.memory.sub'),
65
- body: label('architecture.layer.memory.body'),
66
- },
67
- {
68
- icon: Globe2,
69
- name: label('architecture.layer.surface.name'),
70
- sub: label('architecture.layer.surface.sub'),
71
- body: label('architecture.layer.surface.body'),
72
- },
73
- ];
74
- }
75
- /** the provider chain as config: the ordered ids ride the label store
76
- * (architecture.chain.providers — the seed ingests the row into the labels
77
- * table like every other string) and the page only splits the row; no fixed
78
- * provider array survives inside the component. */
79
- function providerchain() {
80
- return label('architecture.chain.providers').split(' · ');
81
- }
82
- export default function Architecture() {
83
- const [media, setMedia] = useState(undefined);
84
- useEffect(() => {
85
- void mediaSlots().then((rows) => setMedia(rows.find((slot) => slot.id === 'media.runtime.map')));
86
- }, []);
87
- return (_jsxs(PageShell, { section: label('architecture.shell.section'), label: label('architecture.shell.label'), title: label('architecture.shell.title'), intro: label('architecture.shell.intro'), media: media, children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.model.eyebrow') }), _jsx("h2", { className: "section-title", children: label('architecture.model.title') })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label('architecture.model.body1') }), _jsx("p", { children: label('architecture.model.body2') })] })] }), _jsxs("section", { className: "content-section", "aria-label": label('architecture.forms.aria'), children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.forms.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.forms.mono') })] }), _jsx("ol", { className: "r3-forms", children: SANDBOXFORMS.map((form, index) => (_jsxs("li", { className: "r3-form-row", children: [_jsx("span", { className: "r3-form-index", children: `0${index + 1}` }), _jsx("span", { className: "r3-form-name", children: formlabels[form].name }), _jsx("span", { className: "r3-form-pkg", children: formlabels[form].pkg }), _jsx("span", { className: "r3-form-note", children: formlabels[form].note })] }, form))) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.layers.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.layers.mono') })] }), _jsx("div", { className: "layer-stack", children: layers().map((layer, index) => {
88
- const Icon = layer.icon;
89
- return (_jsxs("div", { className: "layer-row", children: [_jsxs("span", { className: "layer-index", children: ["0", index + 1] }), _jsx(Icon, { fontSize: 20, strokeWidth: 1.5, "aria-hidden": "true" }), _jsxs("div", { className: "layer-name", children: [_jsx("strong", { children: layer.name }), _jsx("span", { children: layer.sub })] }), _jsx("p", { children: layer.body }), _jsx(ArrowUpRight, { fontSize: 16, "aria-hidden": "true" })] }, layer.name));
90
- }) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.chain.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.chain.mono') })] }), _jsx("div", { className: "provider-grid", children: providerchain().map((name, index) => (_jsxs("div", { className: `provider-cell ${index === 0 ? 'is-active' : ''}`, children: [_jsxs("span", { className: "provider-index", children: ["0", index + 1] }), _jsx("strong", { children: name }), _jsx("small", { children: label(index === 0
91
- ? 'architecture.chain.preferred'
92
- : 'architecture.chain.fallback') })] }, name))) })] }), _jsxs("section", { className: "content-section architecture-note", children: [_jsx(ShieldCheck, { fontSize: 21, "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.limit.eyebrow') }), _jsx("p", { children: label('architecture.limit.body') })] })] })] }));
93
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * compute page anchor — layer 3 of the anchor architecture.
3
- * The file carrying the folder's own name is the path manager of the page:
4
- * it imports the loose components beside it, mounts the page and re-exports
5
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
- * this file. This anchor carries the former main component of the folder,
7
- * which now lives here as the page mount itself.
8
- */
9
- export default function Compute(): import("react").JSX.Element;
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * compute page anchor — layer 3 of the anchor architecture.
4
- * The file carrying the folder's own name is the path manager of the page:
5
- * it imports the loose components beside it, mounts the page and re-exports
6
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
- * this file. This anchor carries the former main component of the folder,
8
- * which now lives here as the page mount itself.
9
- */
10
- // Signal & Ledger: the compute face — the engine presents itself honestly.
11
- // The page mounts the two api surfaces (the boot ladder and the modality
12
- // catalog) and carries no provider table of its own: every row the visitor
13
- // reads is served by the saddle engine through the internal api — the
14
- // fixed provider and state arrays died with the old page. Every word the
15
- // page itself speaks rides the label store (labels.ts — the copy law).
16
- import { BoxRegular as Box } from "@fluentui/react-icons";
17
- import { PageShell } from "../shell/Shell.tsx";
18
- import { label } from "../../labels.ts";
19
- import { ComputeBootladder, ComputeModalitycatalog } from "../wingets";
20
- export default function Compute() {
21
- return (_jsxs(PageShell, { section: label("compute.shell.section"), label: label("compute.shell.label"), title: label("compute.shell.title"), intro: label("compute.shell.intro"), children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label("compute.split.eyebrow") }), _jsx("h2", { className: "section-title", children: label("compute.split.title") })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label("compute.split.body1") }), _jsx("p", { children: label("compute.split.body2") })] })] }), _jsx(ComputeBootladder, {}), _jsx(ComputeModalitycatalog, {}), _jsxs("section", { className: "content-section note-band", children: [_jsx(Box, { fontSize: 21, "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label("compute.note.eyebrow") }), _jsx("p", { children: label("compute.note.body") })] })] })] }));
22
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * console page anchor — layer 3 of the anchor architecture.
3
- * The file carrying the folder's own name is the path manager of the page:
4
- * it imports the loose components beside it, mounts the page and re-exports
5
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
- * this file. This anchor carries the former main component of the folder,
7
- * which now lives here as the page mount itself.
8
- */
9
- export * from '../wingets';
10
- /**
11
- * the console page: wires the spec panel, terminal, events timeline and
12
- * lifecycle controls to the browser-pure engine (sandbox.ts) and, when
13
- * available, the self-hosted /api/v1 contract.
14
- */
15
- export default function Console(): import("react").JSX.Element;
@@ -1,292 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * console page anchor — layer 3 of the anchor architecture.
4
- * The file carrying the folder's own name is the path manager of the page:
5
- * it imports the loose components beside it, mounts the page and re-exports
6
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
- * this file. This anchor carries the former main component of the folder,
8
- * which now lives here as the page mount itself.
9
- */
10
- // Real sandbox console: faithful absorption of console.html + console.js —
11
- // the spec panel, the animated boot sequence, the interactive terminal, the
12
- // bus event timeline, snapshot/stop and the api detection badge. when the
13
- // self-hosted node answers, the sandbox is also created through
14
- // /api/v1/sandboxes and commands run through the api exec endpoint;
15
- // otherwise the same dispatcher runs locally in the browser.
16
- import { useEffect, useRef, useState } from 'react';
17
- import { Link } from 'wouter';
18
- import { PageShell } from '../shell/Shell.tsx';
19
- import { apibase, apifetch, fetchhealth } from '../../api';
20
- import { label, labelfill } from '../../labels.ts';
21
- import { bootSequence, cpudata, createSandboxState, dispatch, gpudata } from '../../sandbox.ts';
22
- import { ApiBadge as ApiBadge } from '../wingets';
23
- import { ConsoleEdgelaw as ConsoleEdgelaw } from '../wingets';
24
- import { EventsTimeline as EventsTimeline } from '../wingets';
25
- import { SnapshotControls as SnapshotControls } from '../wingets';
26
- import { SpecPanel as SpecPanel } from '../wingets';
27
- import { Terminal as Terminal } from '../wingets';
28
- export * from '../wingets';
29
- /** display cap for very large payloads such as cpuinfo at 192 vcpus. */
30
- const displaycap = 120000;
31
- /** the session key the home landing writes and this page reads once (then spent). */
32
- const declaredkey = 'saddle.declared';
33
- /** initial spec selection mirroring the static page defaults. */
34
- const initialspec = {
35
- model: cpudata[0].model,
36
- quotamb: 16,
37
- vcpus: 8,
38
- ramgb: 32,
39
- gpu: gpudata[0].id,
40
- mig: 'off',
41
- };
42
- /** the sleep used to animate the boot sequence line by line. */
43
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
44
- /**
45
- * the console page: wires the spec panel, terminal, events timeline and
46
- * lifecycle controls to the browser-pure engine (sandbox.ts) and, when
47
- * available, the self-hosted /api/v1 contract.
48
- */
49
- export default function Console() {
50
- const rowseq = useRef(0);
51
- const eventseq = useRef(0);
52
- const engineref = useRef(null);
53
- const apiref = useRef(null);
54
- const [selection, setSelection] = useState(initialspec);
55
- const [rows, setRows] = useState([]);
56
- const [events, setEvents] = useState([]);
57
- const [running, setRunning] = useState(false);
58
- const [busy, setBusy] = useState(false);
59
- const [termstate, setTermstate] = useState('halted');
60
- const [prompt, setPrompt] = useState(labelfill('console.prompt', { host: 'saddle' }));
61
- const [apimode, setApimode] = useState(false);
62
- const [badgelabel, setBadgelabel] = useState(label('console.badge.local'));
63
- const [declared, setDeclared] = useState(null);
64
- /** api detection: probe the health endpoint once (1.5s budget). */
65
- useEffect(() => {
66
- let cancelled = false;
67
- const detect = async () => {
68
- const health = await fetchhealth(apibase(), 1500);
69
- if (cancelled)
70
- return;
71
- if (health !== null) {
72
- setApimode(true);
73
- setBadgelabel(labelfill('console.badge.api', {
74
- version: String(health.version),
75
- uptime: String(health.uptime),
76
- }));
77
- }
78
- else {
79
- setBadgelabel(label('console.badge.local'));
80
- }
81
- };
82
- detect().catch(() => {
83
- if (!cancelled)
84
- setBadgelabel(label('console.badge.local'));
85
- });
86
- return () => {
87
- cancelled = true;
88
- };
89
- }, []);
90
- /** the handed-over declaration of the landing prompt: read once, then spent. */
91
- useEffect(() => {
92
- try {
93
- const raw = sessionStorage.getItem(declaredkey);
94
- if (raw === null)
95
- return;
96
- sessionStorage.removeItem(declaredkey);
97
- const parsed = JSON.parse(raw);
98
- setDeclared({
99
- base: typeof parsed.base === 'string' ? parsed.base : null,
100
- os: typeof parsed.os === 'string' ? parsed.os : null,
101
- arch: typeof parsed.arch === 'string' ? parsed.arch : null,
102
- });
103
- }
104
- catch {
105
- /* a broken handoff spends itself silently */
106
- }
107
- }, []);
108
- /** appends one text block as a row; truncates giant payloads for display. */
109
- const printrow = (text, cls) => {
110
- rowseq.current += 1;
111
- const id = rowseq.current;
112
- if (text.length > displaycap) {
113
- rowseq.current += 1;
114
- const truncid = rowseq.current;
115
- setRows((prev) => [
116
- ...prev,
117
- { id, text: text.slice(0, displaycap), cls },
118
- {
119
- id: truncid,
120
- text: labelfill('console.boot.truncated', { bytes: String(text.length) }),
121
- cls: 'trunc',
122
- },
123
- ]);
124
- }
125
- else {
126
- setRows((prev) => [...prev, { id, text, cls }]);
127
- }
128
- };
129
- /** prepends one bus event; the timeline keeps at most 50 entries. */
130
- const logevent = (topic, detail, kind) => {
131
- eventseq.current += 1;
132
- const now = new Date();
133
- const item = {
134
- id: eventseq.current,
135
- time: now.toTimeString().slice(0, 8),
136
- topic,
137
- detail,
138
- kind,
139
- };
140
- setEvents((prev) => [item, ...prev].slice(0, 50));
141
- };
142
- const onselectionchange = (patch) => {
143
- setSelection((prev) => ({ ...prev, ...patch }));
144
- };
145
- /** boots the sandbox: spec commit, api-backed creation, animated dmesg. */
146
- const bootsandbox = async () => {
147
- setBusy(true);
148
- setRunning(false);
149
- setRows([]);
150
- setTermstate('booting');
151
- const spec = {
152
- model: selection.model,
153
- vcpus: selection.vcpus,
154
- ramgb: selection.ramgb,
155
- gpu: selection.gpu,
156
- mig: selection.mig,
157
- quotamb: selection.quotamb,
158
- };
159
- const state = createSandboxState(spec);
160
- engineref.current = state;
161
- setPrompt(labelfill('console.prompt', { host: state.hostname }));
162
- logevent('vm:creating', labelfill('console.event.creating', {
163
- model: spec.model,
164
- vcpus: String(state.vcpus),
165
- ram: String(spec.ramgb),
166
- gpu: spec.gpu,
167
- }), 'lifecycle');
168
- /* api-backed sandbox when the self-hosted server answers */
169
- if (apimode) {
170
- try {
171
- const response = await apifetch('/api/v1/sandboxes', {
172
- method: 'POST',
173
- body: JSON.stringify(spec),
174
- });
175
- if (response.ok) {
176
- const created = (await response.json());
177
- apiref.current = created.id;
178
- logevent('sandbox:created', labelfill('console.event.created', { id: created.id, state: created.state }), 'lifecycle');
179
- }
180
- }
181
- catch {
182
- apiref.current = null;
183
- logevent('sandbox:create-failed', label('console.event.createFailed'), 'lifecycle');
184
- }
185
- }
186
- printrow(labelfill('console.boot.line', {
187
- model: spec.model,
188
- vcpus: String(state.vcpus),
189
- ram: String(spec.ramgb),
190
- gpu: spec.gpu,
191
- }), 'boot');
192
- const lines = bootSequence(spec.model, state.vcpus, spec.ramgb, spec.gpu);
193
- for (const bootline of lines) {
194
- printrow(bootline, 'boot');
195
- await sleep(28 + Math.random() * 34);
196
- }
197
- printrow(label('console.boot.ready'), 'ok');
198
- logevent('vm:created', labelfill('console.event.specsCommitted', { id: state.id }), 'lifecycle');
199
- logevent('vm:started', label('console.event.started'), 'lifecycle');
200
- setRunning(true);
201
- setTermstate('running');
202
- setBusy(false);
203
- };
204
- const onstart = () => {
205
- bootsandbox().catch(() => {
206
- printrow(label('console.boot.failed'), 'err');
207
- setBusy(false);
208
- });
209
- };
210
- /** executes one command: api exec first, local dispatcher as fallback. */
211
- const runcommand = async (rawcommand) => {
212
- printrow(`${prompt} ${rawcommand}`, 'cmdline');
213
- if (rawcommand === 'clear') {
214
- setRows([]);
215
- return;
216
- }
217
- let result = null;
218
- let source = 'local';
219
- if (apiref.current !== null) {
220
- try {
221
- const response = await apifetch(`/api/v1/sandboxes/${apiref.current}/exec`, {
222
- method: 'POST',
223
- body: JSON.stringify({ command: rawcommand }),
224
- });
225
- if (response.ok) {
226
- result = (await response.json());
227
- source = 'api';
228
- }
229
- }
230
- catch {
231
- result = null;
232
- }
233
- }
234
- if (result === null) {
235
- result =
236
- engineref.current !== null
237
- ? dispatch(rawcommand, engineref.current)
238
- : { output: label('console.boot.notrunning'), exitCode: 1 };
239
- source = 'local';
240
- }
241
- if (result.output.length > 0) {
242
- printrow(result.output, result.exitCode === 0 ? '' : 'err');
243
- }
244
- logevent('exec:completed', labelfill('console.event.exec', {
245
- command: rawcommand,
246
- code: String(result.exitCode),
247
- source,
248
- }), 'exec');
249
- };
250
- /** snapshot: precopy stage 1 of 1, memory + disk. */
251
- const onsnapshot = () => {
252
- if (!running)
253
- return;
254
- const snapid = `snap-${Math.random().toString(16).slice(2, 10)}`;
255
- printrow(labelfill('console.snapshot.created', { id: snapid }), 'ok');
256
- logevent('snapshot:created', labelfill('console.event.snapshot', { id: snapid, sandbox: engineref.current?.id ?? 'n/a' }), 'snapshot');
257
- };
258
- /** teardown: local halt plus the api sandbox delete when connected. */
259
- const onstop = async () => {
260
- if (!running)
261
- return;
262
- setRunning(false);
263
- setTermstate('stopped');
264
- printrow(label('console.stop.done'), 'boot');
265
- logevent('vm:stopped', labelfill('console.event.stopped', { id: engineref.current?.id ?? 'n/a' }), 'lifecycle');
266
- if (apiref.current !== null) {
267
- const id = apiref.current;
268
- try {
269
- await apifetch(`/api/v1/sandboxes/${id}`, { method: 'DELETE' });
270
- logevent('vm:deleted', labelfill('console.event.deleted', { id }), 'lifecycle');
271
- }
272
- catch {
273
- logevent('vm:delete-failed', labelfill('console.event.deleteFailed', { id }), 'lifecycle');
274
- }
275
- apiref.current = null;
276
- }
277
- };
278
- return (_jsxs(PageShell, { section: label('console.shell.section'), label: label('console.shell.label'), title: label('console.shell.title'), intro: label('console.shell.intro'), children: [_jsx(ConsoleEdgelaw, {}), _jsxs("section", { className: "content-section console-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('console.eyebrow') }), _jsxs("div", { className: "console-heading-side", children: [_jsx(Link, { href: "/login", className: "console-signin", children: label('console.signin') }), _jsx(ApiBadge, { apion: apimode, label: badgelabel })] })] }), _jsxs("div", { className: "sandbox-grid", children: [_jsxs("section", { className: "sandbox-panel", "aria-labelledby": "specstitle", children: [_jsx("h2", { className: "sandbox-panel-title", id: "specstitle", children: label('console.specs.title') }), declared !== null &&
279
- (declared.base !== null || declared.os !== null || declared.arch !== null) && (_jsxs("p", { className: "r3-declared-ribbon", role: "note", children: [label('console.declared.head'), [
280
- declared.base !== null
281
- ? labelfill('console.declared.base', { value: declared.base })
282
- : null,
283
- declared.os !== null
284
- ? labelfill('console.declared.guest', { value: declared.os })
285
- : null,
286
- declared.arch !== null
287
- ? labelfill('console.declared.arch', { value: declared.arch })
288
- : null,
289
- ]
290
- .filter(Boolean)
291
- .join(' · '), label('console.declared.tail')] })), _jsx(SpecPanel, { spec: selection, onChange: onselectionchange, disabled: busy || running }), _jsxs("div", { className: "sandbox-actions", children: [_jsx("button", { className: "button button-primary", type: "button", onClick: onstart, disabled: busy || running, "aria-label": label('console.startAria'), children: label('console.start') }), _jsx(SnapshotControls, { running: running, onsnapshot: onsnapshot, onstop: onstop })] })] }), _jsx(Terminal, { rows: rows, prompt: prompt, state: termstate, enabled: running, oncommand: runcommand }), _jsx(EventsTimeline, { events: events })] }), _jsx("p", { className: "console-note", children: label('console.note') })] })] }));
292
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * dashboard page anchor — layer 3 of the anchor architecture.
3
- * The file carrying the folder's own name is the path manager of the page:
4
- * it imports the loose components beside it, mounts the page and re-exports
5
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
- * this file. This anchor carries the former main component of the folder,
7
- * which now lives here as the page mount itself.
8
- */
9
- export * from '../wingets';
10
- export default function Dashboard(): import("react").JSX.Element;
@@ -1,181 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * dashboard page anchor — layer 3 of the anchor architecture.
4
- * The file carrying the folder's own name is the path manager of the page:
5
- * it imports the loose components beside it, mounts the page and re-exports
6
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
- * this file. This anchor carries the former main component of the folder,
8
- * which now lives here as the page mount itself.
9
- */
10
- // Signal & Ledger: the e2ugh dashboard absorbed into the single interface —
11
- // session via the saddlesession cookie (api) or the browser-local account
12
- // (static edge), user view and admin view in the same React shell.
13
- import { useEffect, useRef, useState } from 'react';
14
- import { Link, useLocation } from 'wouter';
15
- import { apibase } from '../../api';
16
- import { apiresult, noderole, pick } from '../../dashboardlib';
17
- import { label, labelfill } from '../../labels.ts';
18
- /* the explicit .ts suffix keeps the resolution unambiguous while the
19
- * typed ES module that replaced the window-global localauth.js of the static edge (the original
20
- * beside the typed module - the same convention the Login page uses. */
21
- import { logout, probe, session as readlocalsession } from '../../localauth.ts';
22
- import { AccountPanel as AccountPanel } from '../wingets';
23
- import { AdminPanel as AdminPanel } from '../wingets';
24
- import { CreateSandboxForm as CreateSandboxForm } from '../wingets';
25
- import { DashboardEventstimeline as EventsTimeline } from '../wingets';
26
- import { SandboxList as SandboxList } from '../wingets';
27
- export * from '../wingets';
28
- export default function Dashboard() {
29
- const [, navigate] = useLocation();
30
- const [phase, setphase] = useState('booting');
31
- const [fatal, setfatal] = useState(null);
32
- const [me, setme] = useState(null);
33
- const [localview, setlocalview] = useState(null);
34
- const [nodelabel, setnodelabel] = useState(label('dashboard.node.pending'));
35
- const [tab, settab] = useState('user');
36
- const [sandboxreload, setsandboxreload] = useState(0);
37
- const [leaving, setleaving] = useState(false);
38
- const tabrefs = useRef({});
39
- /** decorative health read: paints the node role badge. */
40
- async function loadhealth() {
41
- try {
42
- const result = await apiresult('/api/v1/health');
43
- if (result.ok && result.body !== null && typeof result.body === 'object') {
44
- setnodelabel(noderole(result.body));
45
- return;
46
- }
47
- }
48
- catch {
49
- /* health is decorative; the badge simply stays neutral */
50
- }
51
- setnodelabel(label('dashboard.node.standalone'));
52
- }
53
- /** the account bootstrap: /auth/me fills the session or the fatal gate. */
54
- async function loadme() {
55
- let result;
56
- try {
57
- result = await apiresult('/api/v1/auth/me');
58
- }
59
- catch {
60
- setfatal(label('dashboard.fatal.apiUnreachable'));
61
- return;
62
- }
63
- if (result.status === 401 || result.status === 403) {
64
- setfatal(label('dashboard.fatal.needsSession'));
65
- return;
66
- }
67
- if (!result.ok || result.body === null || typeof result.body !== 'object') {
68
- setfatal(label('dashboard.fatal.payload'));
69
- return;
70
- }
71
- const envelope = result.body;
72
- const body = envelope.user !== null && typeof envelope.user === 'object'
73
- ? envelope.user
74
- : envelope;
75
- setme({
76
- username: String(pick(body, ['username', 'name', 'user'], 'unknown')),
77
- role: String(pick(body, ['role'], 'user')).toLowerCase(),
78
- createdat: pick(body, ['createdAt', 'created_at', 'createdat', 'registeredAt'], null),
79
- lastloginat: pick(body, ['lastLoginAt', 'last_login_at', 'lastlogin', 'lastLogin'], null),
80
- id: pick(body, ['id', 'uuid'], null),
81
- });
82
- }
83
- /* boot: probe the api once; no answer -> the static edge takes over with
84
- * the browser-local session (localauth), exactly like the original page. */
85
- useEffect(() => {
86
- let cancelled = false;
87
- void (async () => {
88
- const answers = await probe(apibase());
89
- if (cancelled) {
90
- return;
91
- }
92
- if (!answers) {
93
- setphase('local');
94
- setnodelabel(label('dashboard.node.edge'));
95
- const raw = (await readlocalsession());
96
- if (raw === null || raw === undefined) {
97
- setfatal(label('dashboard.fatal.noLocalSession'));
98
- return;
99
- }
100
- const view = {
101
- user: String(pick(raw, ['user', 'username'], 'unknown')),
102
- role: String(pick(raw, ['role'], 'user')),
103
- issuedat: Number(pick(raw, ['issuedat', 'issuedAt'], Date.now())),
104
- expiresat: Number(pick(raw, ['expiresat', 'expiresAt'], 0)),
105
- };
106
- setlocalview(view);
107
- setme({
108
- username: view.user,
109
- role: view.role === 'admin' ? 'admin' : 'local',
110
- createdat: null,
111
- lastloginat: new Date(view.issuedat).toISOString(),
112
- id: null,
113
- });
114
- return;
115
- }
116
- setphase('api');
117
- void loadhealth();
118
- void loadme();
119
- })();
120
- return () => {
121
- cancelled = true;
122
- };
123
- }, []);
124
- /** ends the session (cookie or local) and returns to the sign in page. */
125
- async function dolgout() {
126
- setleaving(true);
127
- /* clears the local browser session too (no-op on the api mode) */
128
- void logout();
129
- try {
130
- await apiresult('/api/v1/auth/logout', { method: 'POST' });
131
- }
132
- catch {
133
- /* the cookie may already be gone; proceed to the login page */
134
- }
135
- navigate('/login');
136
- }
137
- /** selects one tab and moves the roving focus onto it. */
138
- function selecttab(next) {
139
- settab(next);
140
- requestAnimationFrame(() => {
141
- tabrefs.current[next]?.focus();
142
- });
143
- }
144
- const mode = phase === 'local' ? 'local' : 'api';
145
- const adminvisible = me !== null && me.role === 'admin';
146
- const userbadge = me === null
147
- ? label('dashboard.userbadge.pending')
148
- : mode === 'local'
149
- ? me.role === 'admin'
150
- ? labelfill('dashboard.userbadge.localAdmin', { name: me.username })
151
- : labelfill('dashboard.userbadge.local', { name: me.username })
152
- : me.role === 'admin'
153
- ? labelfill('dashboard.userbadge.admin', { name: me.username })
154
- : me.username;
155
- const roleclass = nodelabel === 'main' || nodelabel === 'clone'
156
- ? `dash-rolebadge ${nodelabel}`
157
- : 'dash-rolebadge';
158
- return (_jsx("div", { className: "dash", children: _jsxs("div", { className: "dash-wrap", children: [_jsxs("header", { className: "dash-topbar", children: [_jsx("h1", { children: _jsx(Link, { href: "/console", children: label('dashboard.brand') }) }), _jsx("span", { className: "dash-tagline", children: label('dashboard.tagline') }), _jsx("span", { className: roleclass, "aria-live": "polite", children: labelfill('dashboard.nodeBadge', { label: nodelabel }) }), _jsx("span", { className: "dash-spacer" }), _jsx("span", { className: "dash-userbadge", children: userbadge }), _jsx("button", { type: "button", "aria-label": label('dashboard.logoutAria'), disabled: leaving, onClick: () => {
159
- void dolgout();
160
- }, children: label('dashboard.logout') })] }), fatal !== null && (_jsxs("div", { className: "dash-panel dash-fatal", "aria-live": "polite", children: [_jsx("h2", { children: label('dashboard.fatal.title') }), _jsx("p", { children: fatal }), _jsxs("div", { className: "dash-actions", children: [_jsx(Link, { className: "dash-btn", href: "/login", children: label('dashboard.fatal.signin') }), _jsx(Link, { className: "dash-btn", href: "/console", children: label('dashboard.fatal.backConsole') })] })] })), fatal === null && (_jsxs("div", { className: "dash-tabs", role: "tablist", "aria-label": label('dashboard.tabsAria'), onKeyDown: (event) => {
161
- if (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft') {
162
- return;
163
- }
164
- if (adminvisible) {
165
- event.preventDefault();
166
- selecttab(tab === 'user' ? 'admin' : 'user');
167
- }
168
- }, children: [_jsx("button", { type: "button", role: "tab", id: "tab-user", ref: (node) => {
169
- tabrefs.current.user = node;
170
- }, "aria-selected": tab === 'user', "aria-controls": "panel-user", tabIndex: tab === 'user' ? 0 : -1, onClick: () => {
171
- selecttab('user');
172
- }, children: label('dashboard.tab.user') }), adminvisible && (_jsx("button", { type: "button", role: "tab", id: "tab-admin", ref: (node) => {
173
- tabrefs.current.admin = node;
174
- }, "aria-selected": tab === 'admin', "aria-controls": "panel-admin", tabIndex: tab === 'admin' ? 0 : -1, onClick: () => {
175
- selecttab('admin');
176
- }, children: label('dashboard.tab.admin') }))] })), fatal === null && (_jsx("div", { role: "tabpanel", id: "panel-user", "aria-labelledby": "tab-user", hidden: tab !== 'user', children: _jsxs("div", { className: "dash-grid2", children: [_jsx("div", { children: _jsxs("section", { className: "dash-panel", "aria-labelledby": "boxtitle", children: [_jsx("h2", { id: "boxtitle", children: label('dashboard.panel.sandboxes') }), _jsx(CreateSandboxForm, { mode: mode, oncreated: () => {
177
- setsandboxreload((key) => key + 1);
178
- }, onrefresh: () => {
179
- setsandboxreload((key) => key + 1);
180
- } }), _jsx(SandboxList, { mode: mode, reloadkey: sandboxreload, ready: me !== null })] }) }), _jsxs("div", { children: [_jsxs("section", { className: "dash-panel", "aria-labelledby": "infotitle", children: [_jsx("h2", { id: "infotitle", children: label('dashboard.panel.account') }), _jsx(AccountPanel, { mode: mode, user: me, local: localview })] }), _jsxs("section", { className: "dash-panel", "aria-labelledby": "eventstitle", children: [_jsx("h2", { id: "eventstitle", children: label('dashboard.panel.events') }), _jsx(EventsTimeline, { mode: mode, ready: me !== null })] })] })] }) })), fatal === null && adminvisible && (_jsx("div", { role: "tabpanel", id: "panel-admin", "aria-labelledby": "tab-admin", hidden: tab !== 'admin', children: _jsx(AdminPanel, { mode: mode }) })), _jsxs("footer", { className: "dash-footer", children: [_jsx("span", { children: label('dashboard.footer.cookie') }), _jsx("span", { children: label('dashboard.footer.storage') }), _jsx("span", { style: { marginLeft: 'auto' }, children: label('dashboard.footer.api') })] })] }) }));
181
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * docs page anchor — layer 3 of the anchor architecture.
3
- * The file carrying the folder's own name is the path manager of the page:
4
- * it imports the loose components beside it, mounts the page and re-exports
5
- * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
- * this file. This anchor carries the former main component of the folder,
7
- * which now lives here as the page mount itself.
8
- */
9
- export default function Docs(): import("react").JSX.Element;