@wenathlan/saddle 2.0.151 → 2.0.153
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/README.md +3 -3
- package/biome.jsonc +12 -5
- package/dist/App.d.ts +5 -0
- package/dist/App.js +52 -0
- package/dist/Sol/Sol.d.ts +3 -0
- package/dist/Sol/Sol.js +46 -0
- package/dist/Sol/agentbrowser/agentbrowser.d.ts +9 -0
- package/dist/Sol/agentbrowser/agentbrowser.js +121 -0
- package/dist/Sol/architecture/architecture.d.ts +9 -0
- package/dist/Sol/architecture/architecture.js +93 -0
- package/dist/Sol/compute/compute.d.ts +9 -0
- package/dist/Sol/compute/compute.js +22 -0
- package/dist/Sol/console/console.d.ts +15 -0
- package/dist/Sol/console/console.js +292 -0
- package/dist/Sol/dashboard/dashboard.d.ts +10 -0
- package/dist/Sol/dashboard/dashboard.js +181 -0
- package/dist/Sol/docs/docs.d.ts +9 -0
- package/dist/Sol/docs/docs.js +28 -0
- package/dist/Sol/home/home.d.ts +35 -0
- package/dist/Sol/home/home.js +239 -0
- package/dist/Sol/integrations/integrations.d.ts +9 -0
- package/dist/Sol/integrations/integrations.js +83 -0
- package/dist/Sol/intro/intro.d.ts +7 -0
- package/dist/Sol/intro/intro.js +102 -0
- package/dist/Sol/login/login.d.ts +16 -0
- package/dist/Sol/login/login.js +49 -0
- package/dist/Sol/notfound/notfound.d.ts +9 -0
- package/dist/Sol/notfound/notfound.js +15 -0
- package/dist/Sol/onboarding/onboarding.d.ts +25 -0
- package/dist/Sol/onboarding/onboarding.js +60 -0
- package/dist/Sol/playground/playground.d.ts +9 -0
- package/dist/Sol/playground/playground.js +127 -0
- package/dist/Sol/register/register.d.ts +16 -0
- package/dist/Sol/register/register.js +193 -0
- package/dist/Sol/shell/Shell.d.ts +124 -0
- package/dist/Sol/shell/Shell.js +335 -0
- package/dist/Sol/wingets/ComputeBootladder.d.ts +6 -0
- package/dist/Sol/wingets/ComputeBootladder.js +71 -0
- package/dist/Sol/wingets/ComputeModalitycatalog.d.ts +7 -0
- package/dist/Sol/wingets/ComputeModalitycatalog.js +71 -0
- package/dist/Sol/wingets/ConsoleApibadge.d.ts +7 -0
- package/dist/Sol/wingets/ConsoleApibadge.js +5 -0
- package/dist/Sol/wingets/ConsoleEdgelaw.d.ts +6 -0
- package/dist/Sol/wingets/ConsoleEdgelaw.js +36 -0
- package/dist/Sol/wingets/ConsoleEventstimeline.d.ts +19 -0
- package/dist/Sol/wingets/ConsoleEventstimeline.js +12 -0
- package/dist/Sol/wingets/ConsoleSnapshotcontrols.d.ts +8 -0
- package/dist/Sol/wingets/ConsoleSnapshotcontrols.js +8 -0
- package/dist/Sol/wingets/ConsoleSpecpanel.d.ts +21 -0
- package/dist/Sol/wingets/ConsoleSpecpanel.js +75 -0
- package/dist/Sol/wingets/ConsoleTerminal.d.ts +22 -0
- package/dist/Sol/wingets/ConsoleTerminal.js +77 -0
- package/dist/Sol/wingets/DashboardAccountpanel.d.ts +18 -0
- package/dist/Sol/wingets/DashboardAccountpanel.js +65 -0
- package/dist/Sol/wingets/DashboardAdminpanel.d.ts +6 -0
- package/dist/Sol/wingets/DashboardAdminpanel.js +90 -0
- package/dist/Sol/wingets/DashboardAuditlog.d.ts +8 -0
- package/dist/Sol/wingets/DashboardAuditlog.js +50 -0
- package/dist/Sol/wingets/DashboardCreatesandboxform.d.ts +10 -0
- package/dist/Sol/wingets/DashboardCreatesandboxform.js +71 -0
- package/dist/Sol/wingets/DashboardEventstimeline.d.ts +8 -0
- package/dist/Sol/wingets/DashboardEventstimeline.js +83 -0
- package/dist/Sol/wingets/DashboardGlobalsandboxestable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardGlobalsandboxestable.js +57 -0
- package/dist/Sol/wingets/DashboardMeshnodestable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardMeshnodestable.js +103 -0
- package/dist/Sol/wingets/DashboardSandboxlist.d.ts +10 -0
- package/dist/Sol/wingets/DashboardSandboxlist.js +163 -0
- package/dist/Sol/wingets/DashboardUserstable.d.ts +8 -0
- package/dist/Sol/wingets/DashboardUserstable.js +78 -0
- package/dist/Sol/wingets/HomeEntrygate.d.ts +23 -0
- package/dist/Sol/wingets/HomeEntrygate.js +73 -0
- package/dist/Sol/wingets/HomeMetricstrip.d.ts +9 -0
- package/dist/Sol/wingets/HomeMetricstrip.js +4 -0
- package/dist/Sol/wingets/HomeRuntimediagram.d.ts +1 -0
- package/dist/Sol/wingets/HomeRuntimediagram.js +22 -0
- package/dist/Sol/wingets/LoginForm.d.ts +19 -0
- package/dist/Sol/wingets/LoginForm.js +141 -0
- package/dist/Sol/wingets/RegisterPasswordconfirm.d.ts +13 -0
- package/dist/Sol/wingets/RegisterPasswordconfirm.js +16 -0
- package/dist/Sol/wingets/RegisterPasswordmeter.d.ts +19 -0
- package/dist/Sol/wingets/RegisterPasswordmeter.js +65 -0
- package/dist/Sol/wingets/RegisterUsernamerules.d.ts +11 -0
- package/dist/Sol/wingets/RegisterUsernamerules.js +16 -0
- package/dist/Sol/wingets/index.d.ts +39 -0
- package/dist/Sol/wingets/index.js +39 -0
- package/dist/alternatives.d.ts +508 -0
- package/dist/alternatives.js +950 -0
- package/dist/api.d.ts +154 -0
- package/dist/api.js +174 -0
- package/dist/auth.d.ts +268 -0
- package/dist/auth.js +476 -0
- package/dist/automation.d.ts +425 -0
- package/dist/automation.js +566 -0
- package/dist/browser.d.ts +561 -0
- package/dist/browser.js +1058 -0
- package/dist/capacitor.config.d.ts +45 -0
- package/dist/capacitor.config.js +48 -0
- package/dist/catalog.d.ts +43 -0
- package/dist/catalog.js +44 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +168 -0
- package/dist/communication.d.ts +181 -0
- package/dist/communication.js +376 -0
- package/dist/compute.d.ts +1160 -0
- package/dist/compute.js +2272 -0
- package/dist/dashboardlib.d.ts +58 -0
- package/dist/dashboardlib.js +161 -0
- package/dist/db.d.ts +569 -0
- package/dist/db.js +1080 -0
- package/dist/distribution.d.ts +528 -0
- package/dist/distribution.js +810 -0
- package/dist/drizzle.config.d.ts +20 -0
- package/dist/drizzle.config.js +18 -0
- package/dist/edgelandes.d.ts +70 -0
- package/dist/edgelandes.host.d.ts +26 -0
- package/dist/edgelandes.host.js +1089 -0
- package/dist/edgelandes.inproc.d.ts +27 -0
- package/dist/edgelandes.inproc.js +952 -0
- package/dist/edgelandes.js +1133 -0
- package/dist/edgelandes.ninety.d.ts +31 -0
- package/dist/edgelandes.ninety.js +174 -0
- package/dist/edgelandes.virtual.d.ts +25 -0
- package/dist/edgelandes.virtual.js +629 -0
- package/dist/edgeplane.d.ts +114 -0
- package/dist/edgeplane.js +305 -0
- package/dist/examplelocaljob.d.ts +1 -0
- package/{docs/example-localjob.ts → dist/examplelocaljob.js} +0 -1
- package/dist/execution.d.ts +529 -0
- package/dist/execution.js +760 -0
- package/dist/family.d.ts +16 -0
- package/dist/family.js +42 -0
- package/dist/familyurl.d.ts +21 -0
- package/dist/familyurl.js +24 -0
- package/dist/format.d.ts +18 -0
- package/dist/format.js +59 -0
- package/dist/foundation.d.ts +172 -0
- package/dist/foundation.js +312 -0
- package/dist/index.d.ts +735 -0
- package/dist/index.js +1020 -0
- package/dist/integration.d.ts +235 -0
- package/dist/integration.js +228 -0
- package/dist/intelligence.d.ts +93 -0
- package/dist/intelligence.js +144 -0
- package/dist/isolation.d.ts +128 -0
- package/dist/isolation.js +95 -0
- package/dist/labels.d.ts +665 -0
- package/dist/labels.js +751 -0
- package/dist/localauth.d.ts +127 -0
- package/dist/localauth.js +413 -0
- package/dist/media.d.ts +343 -0
- package/dist/media.js +985 -0
- package/dist/mesh.d.ts +177 -0
- package/dist/mesh.js +468 -0
- package/dist/modalityregistry.d.ts +109 -0
- package/dist/modalityregistry.js +1386 -0
- package/dist/modes.d.ts +358 -0
- package/dist/modes.js +133 -0
- package/dist/onboardingstate.d.ts +79 -0
- package/dist/onboardingstate.js +282 -0
- package/dist/orchestrator.d.ts +1338 -0
- package/dist/orchestrator.js +4310 -0
- package/dist/packager/targetcli.js +4 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +14 -0
- package/dist/performance.d.ts +415 -0
- package/dist/performance.js +826 -0
- package/dist/quantum.d.ts +809 -0
- package/dist/quantum.js +2072 -0
- package/dist/render.d.ts +380 -0
- package/dist/render.js +1072 -0
- package/dist/runall.d.ts +2 -0
- package/dist/runall.js +39 -0
- package/dist/runtimeprobe.d.ts +4 -0
- package/dist/runtimeprobe.js +8 -0
- package/dist/sandbox.d.ts +355 -0
- package/dist/sandbox.js +1721 -0
- package/dist/sandboxenvprofile.d.ts +29 -0
- package/dist/sandboxenvprofile.js +89 -0
- package/dist/sandboxprofile.d.ts +137 -0
- package/dist/sandboxprofile.js +241 -0
- package/dist/sandboxqueue.d.ts +108 -0
- package/dist/sandboxqueue.js +201 -0
- package/dist/sandboxquota.d.ts +121 -0
- package/dist/sandboxquota.js +236 -0
- package/dist/scheduler.d.ts +595 -0
- package/dist/scheduler.js +1258 -0
- package/dist/scriptlanes.d.ts +182 -0
- package/dist/scriptlanes.js +660 -0
- package/dist/scripts.buildengine.d.ts +1 -0
- package/dist/scripts.buildengine.js +39 -0
- package/dist/scripts.securitygate.d.ts +1 -0
- package/dist/scripts.securitygate.js +68 -0
- package/dist/scripts.validateflatnative.d.ts +1 -0
- package/dist/scripts.validateflatnative.js +72 -0
- package/dist/security.d.ts +500 -0
- package/dist/security.js +1169 -0
- package/dist/seedcatalog.d.ts +13 -0
- package/dist/seedcatalog.js +46 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +53 -0
- package/dist/speccatalog.d.ts +31 -0
- package/dist/speccatalog.js +163 -0
- package/dist/tiers.d.ts +1001 -0
- package/dist/tiers.js +2169 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +5 -0
- package/dist/vaulthandoff.d.ts +141 -0
- package/dist/vaulthandoff.js +444 -0
- package/dist/virtual.d.ts +640 -0
- package/dist/virtual.js +1284 -0
- package/dist/virtualcpu.d.ts +315 -0
- package/dist/virtualcpu.js +1180 -0
- package/dist/virtualgpu.d.ts +344 -0
- package/dist/virtualgpu.js +1000 -0
- package/dist/virtualization.d.ts +606 -0
- package/dist/virtualization.js +1186 -0
- package/dist/virtualmemory.d.ts +817 -0
- package/dist/virtualmemory.js +1795 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.js +43 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +25 -0
- package/dist/webserver.d.ts +166 -0
- package/dist/webserver.js +2226 -0
- package/dist/workloadlaw.d.ts +133 -0
- package/dist/workloadlaw.js +193 -0
- package/docs/artifactavailability.md +2 -2
- package/docs/{containerplatforms-2.1.0.md → containerplatforms.2.1.0.md} +1 -1
- package/docs/{documentmap-1.8.12.md → documentmap.1.8.12.md} +1 -1
- package/docs/ninety.modalities.md +108 -0
- package/docs/planning.ninety.md +391 -0
- package/docs/{releasenotes-1.8.13.md → releasenotes.1.8.13.md} +2 -2
- package/docs/{releasenotes-1.8.14.md → releasenotes.1.8.14.md} +1 -1
- package/docs/{repo-synthesis-1.8.16.md → repo.synthesis.1.8.16.md} +1 -1
- package/docs/{todo-1.8.15.md → todo.1.8.15.md} +1 -1
- package/docs/{todo-1.8.16.md → todo.1.8.16.md} +5 -5
- package/docs/todo.md +2 -2
- package/docs/workloadlaw.md +104 -0
- package/index.ts +1 -1
- package/manifest.json +1 -1
- package/modalityregistry.ts +1371 -34
- package/orchestrator.ts +1 -1
- package/package.json +78 -33
- package/docs/CONVERSA.txt +0 -1523
- package/docs/architecture-1.8.19.png +0 -0
- package/docs/assets/architecture.svg +0 -45
- package/docs/assets/saddle-browser-trace.webp +0 -0
- package/docs/assets/saddle-hero-bridge.webp +0 -0
- package/docs/assets/saddle-mark.webp +0 -0
- package/docs/assets/saddle-runtime-map.webp +0 -0
- package/docs/assets/saddlemark.svg +0 -13
- package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
- /package/docs/{architecture-1.8.19.md → architecture.1.8.19.md} +0 -0
- /package/docs/{architecture-1.8.19.mmd → architecture.1.8.19.mmd} +0 -0
- /package/docs/{artifactresearch-1.8.9.md → artifactresearch.1.8.9.md} +0 -0
- /package/docs/{batches-1816-1820.md → batches.1816.to.1820.md} +0 -0
- /package/docs/{brancharchive-2026-08-18.md → brancharchive.2026.08.18.md} +0 -0
- /package/docs/{containerplatforms-1.8.17.md → containerplatforms.1.8.17.md} +0 -0
- /package/docs/{e2ugh-engine.md → e2ugh.engine.md} +0 -0
- /package/docs/{flatbuildresearch-1.8.11.md → flatbuildresearch.1.8.11.md} +0 -0
- /package/docs/{licenseaudit-1.8.12.md → licenseaudit.1.8.12.md} +0 -0
- /package/docs/{mobileconversionresearch-1.8.10.md → mobileconversionresearch.1.8.10.md} +0 -0
- /package/docs/{native-wrappers.md → native.wrappers.md} +0 -0
- /package/docs/{nativeidentityresearch-1.8.11.md → nativeidentityresearch.1.8.11.md} +0 -0
- /package/docs/{releasenotes-1.8.12.md → releasenotes.1.8.12.md} +0 -0
- /package/docs/{releasenotes-1.8.15.md → releasenotes.1.8.15.md} +0 -0
- /package/docs/{releasenotes-1.8.16.md → releasenotes.1.8.16.md} +0 -0
- /package/docs/{releasenotes-1.8.17.md → releasenotes.1.8.17.md} +0 -0
- /package/docs/{releasenotes-1.8.18.md → releasenotes.1.8.18.md} +0 -0
- /package/docs/{releasenotes-1.8.19.md → releasenotes.1.8.19.md} +0 -0
- /package/docs/{reorganization-1.8.8.md → reorganization.1.8.8.md} +0 -0
- /package/docs/{reorganization-1.8.9.md → reorganization.1.8.9.md} +0 -0
- /package/docs/{repo-analysis-1.8.21.json → repo.analysis.1.8.21.json} +0 -0
- /package/docs/{repo-candidates-1.8.21.jsonl → repo.candidates.1.8.21.jsonl} +0 -0
- /package/docs/{repo-research-1.8.16.md → repo.research.1.8.16.md} +0 -0
- /package/docs/{repo-research-1.8.21.md → repo.research.1.8.21.md} +0 -0
- /package/docs/{repo-selected-1.8.21.json → repo.selected.1.8.21.json} +0 -0
- /package/docs/{repo-synthesis-1.8.21.md → repo.synthesis.1.8.21.md} +0 -0
- /package/docs/{research-1.8.18-isolation.md → research.1.8.18.isolation.md} +0 -0
- /package/docs/{research-1.8.19-virtual-browser.md → research.1.8.19.virtual.browser.md} +0 -0
- /package/docs/{scanningresearch-1.8.11.md → scanningresearch.1.8.11.md} +0 -0
- /package/docs/{securityaudit-1.8.7.md → securityaudit.1.8.7.md} +0 -0
- /package/docs/{securityreferences-1.8.11.md → securityreferences.1.8.11.md} +0 -0
- /package/docs/{securityresearch-1.8.11.md → securityresearch.1.8.11.md} +0 -0
- /package/docs/{signingresearch-1.8.12.md → signingresearch.1.8.12.md} +0 -0
- /package/docs/{tauri-glib-risk-1.8.11.md → tauri.glib.risk.1.8.11.md} +0 -0
- /package/docs/{todo-1.8.18.md → todo.1.8.18.md} +0 -0
- /package/docs/{todo-1.8.19.md → todo.1.8.19.md} +0 -0
- /package/docs/{toolchainresearch-1.8.9.md → toolchainresearch.1.8.9.md} +0 -0
- /package/docs/{web-duplicatecleanup.md → web.duplicatecleanup.md} +0 -0
- /package/docs/{web-ideas.md → web.ideas.md} +0 -0
- /package/docs/{workflowimprovements-2026-08-19.md → workflowimprovements.2026.08.19.md} +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Login form: faithful absorption of login.js — posts the credentials to
|
|
3
|
+
// /api/v1/auth/login, falls back to the browser-local accounts when no api
|
|
4
|
+
// answers, and honors the sanitized ?next= target on success.
|
|
5
|
+
import { useEffect, useRef, useState } from 'react';
|
|
6
|
+
import { Link, useLocation } from 'wouter';
|
|
7
|
+
import { apibase, apifetch, apistatustext } from '../../api.ts';
|
|
8
|
+
import { label } from '../../labels.ts';
|
|
9
|
+
/** fallback target when no ?next= parameter is present. */
|
|
10
|
+
const defaulttarget = 'dashboard';
|
|
11
|
+
/**
|
|
12
|
+
* only same-origin page-relative targets are honored; absolute urls,
|
|
13
|
+
* protocol relative (//host), backslash (\host), scheme (javascript:,
|
|
14
|
+
* data:), control characters and path traversal are all rejected.
|
|
15
|
+
* targets stay page-relative (no leading slash) so the redirect works
|
|
16
|
+
* both on the self-hosted node (/, /login) and inside sub-path static
|
|
17
|
+
* hosting such as github pages (/saddle/login). the redirect target
|
|
18
|
+
* never depends on an unvalidated user value. legacy ".html" suffixes
|
|
19
|
+
* from the absorbed static pages map to the spa route of the same name.
|
|
20
|
+
*
|
|
21
|
+
* @returns the sanitized page-relative target.
|
|
22
|
+
*/
|
|
23
|
+
export function safenext() {
|
|
24
|
+
try {
|
|
25
|
+
const raw = new URLSearchParams(window.location.search).get('next');
|
|
26
|
+
if (raw === null)
|
|
27
|
+
return defaulttarget;
|
|
28
|
+
const decoded = decodeURIComponent(raw);
|
|
29
|
+
if (!/^[A-Za-z0-9._\-/]*$/.test(decoded))
|
|
30
|
+
return defaulttarget;
|
|
31
|
+
if (decoded.trim() === '')
|
|
32
|
+
return defaulttarget;
|
|
33
|
+
if (decoded.startsWith('//') || decoded.startsWith('/\\'))
|
|
34
|
+
return defaulttarget;
|
|
35
|
+
if (decoded.includes('../') || decoded.includes('/./') || decoded.startsWith('./')) {
|
|
36
|
+
return defaulttarget;
|
|
37
|
+
}
|
|
38
|
+
return decoded.replace(/^\/+/, '').replace(/\.html$/, '');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return defaulttarget;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* the sign-in form: username + password only, generic error messages on
|
|
46
|
+
* purpose (no user enumeration, no cause leak), aria-invalid feedback and
|
|
47
|
+
* loading states while the submission is in flight.
|
|
48
|
+
*/
|
|
49
|
+
export default function LoginForm() {
|
|
50
|
+
const [, navigate] = useLocation();
|
|
51
|
+
const usernameref = useRef(null);
|
|
52
|
+
const [username, setUsername] = useState('');
|
|
53
|
+
const [password, setPassword] = useState('');
|
|
54
|
+
const [usernameinvalid, setUsernameinvalid] = useState(false);
|
|
55
|
+
const [passwordinvalid, setPasswordinvalid] = useState(false);
|
|
56
|
+
const [error, setError] = useState('');
|
|
57
|
+
const [pending, setPending] = useState(false);
|
|
58
|
+
const [apimode, setApimode] = useState('probing');
|
|
59
|
+
const [statusline, setStatusline] = useState(apistatustext());
|
|
60
|
+
/** static edge detection: probe the api once; no answer -> local mode. */
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
let cancelled = false;
|
|
63
|
+
const detect = async () => {
|
|
64
|
+
const base = apibase();
|
|
65
|
+
const localauth = await import('../../localauth.ts');
|
|
66
|
+
const apianswers = await localauth.probe(base);
|
|
67
|
+
if (cancelled)
|
|
68
|
+
return;
|
|
69
|
+
if (!apianswers) {
|
|
70
|
+
setApimode('local');
|
|
71
|
+
setStatusline(label('login.status.local'));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
setApimode('remote');
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
detect().catch(() => {
|
|
78
|
+
if (!cancelled)
|
|
79
|
+
setApimode('local');
|
|
80
|
+
});
|
|
81
|
+
return () => {
|
|
82
|
+
cancelled = true;
|
|
83
|
+
};
|
|
84
|
+
}, []);
|
|
85
|
+
/** username field focus, like the static page controller. */
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
usernameref.current?.focus();
|
|
88
|
+
}, []);
|
|
89
|
+
const clearerror = () => setError('');
|
|
90
|
+
const showerror = (message) => setError(message);
|
|
91
|
+
const onsubmit = async (event) => {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
clearerror();
|
|
94
|
+
const trimmedusername = username.trim();
|
|
95
|
+
if (trimmedusername.length === 0 || password.length === 0) {
|
|
96
|
+
setUsernameinvalid(trimmedusername.length === 0);
|
|
97
|
+
setPasswordinvalid(password.length === 0);
|
|
98
|
+
showerror(label('login.error.bothFields'));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
setUsernameinvalid(false);
|
|
102
|
+
setPasswordinvalid(false);
|
|
103
|
+
setPending(true);
|
|
104
|
+
/* static edge: no api at this base -> verify the local account */
|
|
105
|
+
if (apimode === 'local') {
|
|
106
|
+
try {
|
|
107
|
+
const localauth = await import('../../localauth.ts');
|
|
108
|
+
await localauth.login(trimmedusername, password);
|
|
109
|
+
navigate(`/${safenext()}`);
|
|
110
|
+
}
|
|
111
|
+
catch (loginerror) {
|
|
112
|
+
const message = loginerror instanceof Error ? loginerror.message : label('login.error.invalid');
|
|
113
|
+
showerror(message);
|
|
114
|
+
setPending(false);
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const response = await apifetch('/api/v1/auth/login', {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
body: JSON.stringify({ username: trimmedusername, password }),
|
|
122
|
+
});
|
|
123
|
+
if (response.ok) {
|
|
124
|
+
navigate(`/${safenext()}`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (response.status === 404) {
|
|
128
|
+
showerror(label('login.error.noAuth'));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
/* generic message on purpose: no user enumeration, no cause leak */
|
|
132
|
+
showerror(label('login.error.invalid'));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
showerror(label('login.error.unreachable'));
|
|
137
|
+
}
|
|
138
|
+
setPending(false);
|
|
139
|
+
};
|
|
140
|
+
return (_jsxs("form", { className: "auth-form", noValidate: true, onSubmit: onsubmit, children: [_jsxs("div", { className: "auth-field", children: [_jsx("label", { htmlFor: "username", children: label('login.field.username') }), _jsx("input", { ref: usernameref, className: "auth-input", id: "username", name: "username", type: "text", autoComplete: "username", spellCheck: false, autoCapitalize: "none", required: true, "aria-invalid": usernameinvalid ? 'true' : undefined, "aria-describedby": "usernamehint", value: username, onChange: (event) => setUsername(event.target.value) }), _jsx("p", { className: "auth-hint", id: "usernamehint", children: label('login.hint.username') })] }), _jsxs("div", { className: "auth-field", children: [_jsx("label", { htmlFor: "password", children: label('login.field.password') }), _jsx("input", { className: "auth-input", id: "password", name: "password", type: "password", autoComplete: "current-password", required: true, "aria-invalid": passwordinvalid ? 'true' : undefined, value: password, onChange: (event) => setPassword(event.target.value) })] }), error !== '' && (_jsx("p", { className: "auth-formerror", role: "alert", "aria-live": "polite", children: error })), _jsx("button", { className: "button button-primary auth-submit", type: "submit", disabled: pending, "aria-busy": pending ? 'true' : undefined, children: pending ? label('login.submitPending') : label('login.submit') }), _jsx("p", { className: "auth-statusline", children: statusline }), _jsxs("p", { className: "auth-statusline", children: [label('login.noAccount'), " ", _jsx(Link, { href: "/register", children: label('login.link.create') }), _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }), _jsx(Link, { href: "/console", children: label('login.link.backConsole') })] })] }));
|
|
141
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type PasswordConfirmProps = {
|
|
2
|
+
password: string;
|
|
3
|
+
value: string;
|
|
4
|
+
invalid: boolean;
|
|
5
|
+
onChange: (value: string) => void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* the confirmation field: blank stays neutral (the hint keeps its
|
|
9
|
+
* reserved height with a non-breaking space), a typed value flips the
|
|
10
|
+
* hint to match / no-match.
|
|
11
|
+
*/
|
|
12
|
+
export default function PasswordConfirm({ password, value, invalid, onChange, }: PasswordConfirmProps): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Password confirmation field: live match feedback — faithful absorption of
|
|
3
|
+
// the register.html confirm field and register.js paintconfirm().
|
|
4
|
+
import { label } from '../../labels.ts';
|
|
5
|
+
/**
|
|
6
|
+
* the confirmation field: blank stays neutral (the hint keeps its
|
|
7
|
+
* reserved height with a non-breaking space), a typed value flips the
|
|
8
|
+
* hint to match / no-match.
|
|
9
|
+
*/
|
|
10
|
+
export default function PasswordConfirm({ password, value, invalid, onChange, }) {
|
|
11
|
+
const empty = value.length === 0;
|
|
12
|
+
const match = password === value;
|
|
13
|
+
const hintclass = empty ? 'auth-hint' : match ? 'auth-hint ok' : 'auth-hint bad';
|
|
14
|
+
const hinttext = empty ? '\u00a0' : match ? label('register.confirm.match') : label('register.confirm.mismatch');
|
|
15
|
+
return (_jsxs("div", { className: "auth-field", children: [_jsx("label", { htmlFor: "password2", children: label('register.confirm.label') }), _jsx("input", { className: "auth-input", id: "password2", name: "password2", type: "password", autoComplete: "new-password", required: true, "aria-invalid": invalid ? 'true' : undefined, "aria-describedby": "password2hint", value: value, onChange: (event) => onChange(event.target.value) }), _jsx("p", { className: hintclass, id: "password2hint", children: hinttext })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* strength score 0-4: length gates, character classes add.
|
|
3
|
+
*
|
|
4
|
+
* @param password the typed password.
|
|
5
|
+
* @returns the score between 0 (empty) and 4 (strong).
|
|
6
|
+
*/
|
|
7
|
+
export declare function passwordstrength(password: string): number;
|
|
8
|
+
/** number of distinct character classes present in the password. */
|
|
9
|
+
export declare function classcount(password: string): number;
|
|
10
|
+
type PasswordMeterProps = {
|
|
11
|
+
password: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* the live password surface: the four-segment meter (aria-hidden
|
|
15
|
+
* decoration), the polite strength label, the minimum-length hint and
|
|
16
|
+
* the two password rule rows.
|
|
17
|
+
*/
|
|
18
|
+
export default function PasswordMeter({ password }: PasswordMeterProps): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Password strength meter: four segments, score 0-4 from length gates and
|
|
3
|
+
// character classes — faithful absorption of the register.html meter and
|
|
4
|
+
// register.js strength()/paintmeter().
|
|
5
|
+
import { label, labelfill } from '../../labels.ts';
|
|
6
|
+
/** the store keys of the strength names, score 0-4. */
|
|
7
|
+
const strengthkeys = [
|
|
8
|
+
'register.meter.strength0',
|
|
9
|
+
'register.meter.strength1',
|
|
10
|
+
'register.meter.strength2',
|
|
11
|
+
'register.meter.strength3',
|
|
12
|
+
'register.meter.strength4',
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* strength score 0-4: length gates, character classes add.
|
|
16
|
+
*
|
|
17
|
+
* @param password the typed password.
|
|
18
|
+
* @returns the score between 0 (empty) and 4 (strong).
|
|
19
|
+
*/
|
|
20
|
+
export function passwordstrength(password) {
|
|
21
|
+
if (password.length === 0)
|
|
22
|
+
return 0;
|
|
23
|
+
if (password.length < 8)
|
|
24
|
+
return 1;
|
|
25
|
+
let classes = 0;
|
|
26
|
+
if (/[a-z]/.test(password))
|
|
27
|
+
classes += 1;
|
|
28
|
+
if (/[A-Z]/.test(password))
|
|
29
|
+
classes += 1;
|
|
30
|
+
if (/[0-9]/.test(password))
|
|
31
|
+
classes += 1;
|
|
32
|
+
if (/[^a-zA-Z0-9]/.test(password))
|
|
33
|
+
classes += 1;
|
|
34
|
+
if (password.length >= 12 && classes >= 3)
|
|
35
|
+
return 4;
|
|
36
|
+
if (classes >= 3 || (password.length >= 11 && classes >= 2))
|
|
37
|
+
return 3;
|
|
38
|
+
if (classes === 2 || password.length >= 10)
|
|
39
|
+
return 2;
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
/** number of distinct character classes present in the password. */
|
|
43
|
+
export function classcount(password) {
|
|
44
|
+
let classes = 0;
|
|
45
|
+
if (/[a-z]/.test(password))
|
|
46
|
+
classes += 1;
|
|
47
|
+
if (/[A-Z]/.test(password))
|
|
48
|
+
classes += 1;
|
|
49
|
+
if (/[0-9]/.test(password))
|
|
50
|
+
classes += 1;
|
|
51
|
+
if (/[^a-zA-Z0-9]/.test(password))
|
|
52
|
+
classes += 1;
|
|
53
|
+
return classes;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* the live password surface: the four-segment meter (aria-hidden
|
|
57
|
+
* decoration), the polite strength label, the minimum-length hint and
|
|
58
|
+
* the two password rule rows.
|
|
59
|
+
*/
|
|
60
|
+
export default function PasswordMeter({ password }) {
|
|
61
|
+
const score = passwordstrength(password);
|
|
62
|
+
const lengthok = password.length >= 8;
|
|
63
|
+
const classesok = classcount(password) >= 2;
|
|
64
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", className: "auth-meter", children: [0, 1, 2, 3].map((index) => (_jsx("span", { className: index < score ? `on-${score}` : undefined }, index))) }), _jsx("p", { className: "auth-meterlabel", role: "status", "aria-live": "polite", children: labelfill('register.meter.strengthLabel', { name: label(strengthkeys[score]) }) }), _jsx("p", { className: "auth-hint", id: "passwordhint", children: label('register.meter.minHint') }), _jsxs("ul", { className: "auth-rules", id: "passwordrules", children: [_jsx("li", { className: lengthok ? 'ok' : undefined, children: label('register.meter.ruleLength') }), _jsx("li", { className: classesok ? 'ok' : undefined, children: label('register.meter.ruleClasses') })] })] }));
|
|
65
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** the username charset contract: 3-32 of lowercase a-z, 0-9, dot, dash. */
|
|
2
|
+
export declare const usernamere: RegExp;
|
|
3
|
+
type UsernameRulesProps = {
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* the live username checklist: each row flips to ok as the typed value
|
|
8
|
+
* satisfies the length and the charset rules.
|
|
9
|
+
*/
|
|
10
|
+
export default function UsernameRules({ value }: UsernameRulesProps): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Username rules checklist: 3-32 characters of [a-z0-9.-], auto-lowercased
|
|
3
|
+
// while typing — faithful absorption of the register.html checklist and
|
|
4
|
+
// register.js paintusername().
|
|
5
|
+
import { label } from '../../labels.ts';
|
|
6
|
+
/** the username charset contract: 3-32 of lowercase a-z, 0-9, dot, dash. */
|
|
7
|
+
export const usernamere = /^[a-z0-9.-]{3,32}$/;
|
|
8
|
+
/**
|
|
9
|
+
* the live username checklist: each row flips to ok as the typed value
|
|
10
|
+
* satisfies the length and the charset rules.
|
|
11
|
+
*/
|
|
12
|
+
export default function UsernameRules({ value }) {
|
|
13
|
+
const lengthok = value.length >= 3 && value.length <= 32;
|
|
14
|
+
const charsetok = usernamere.test(value);
|
|
15
|
+
return (_jsxs("ul", { className: "auth-rules", id: "usernamerules", children: [_jsx("li", { className: lengthok ? 'ok' : undefined, children: label('register.rules.length') }), _jsx("li", { className: charsetok ? 'ok' : undefined, children: label('register.rules.charset') })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.ts — the universal winget surface of saddle: every winget of the
|
|
3
|
+
* Sol/wingets folder answers from this one module, so the pages import
|
|
4
|
+
* their components from a single place and the dotted winget file name
|
|
5
|
+
* lives exactly once (here) instead of repeating across every page —
|
|
6
|
+
* the components stay complete independent files beside this surface.
|
|
7
|
+
*/
|
|
8
|
+
export { default as ComputeBootladder } from "./ComputeBootladder.tsx";
|
|
9
|
+
export { default as ComputeModalitycatalog } from "./ComputeModalitycatalog.tsx";
|
|
10
|
+
export { default as ApiBadge } from "./ConsoleApibadge.tsx";
|
|
11
|
+
export { default as ConsoleEdgelaw } from "./ConsoleEdgelaw.tsx";
|
|
12
|
+
export * from "./ConsoleEventstimeline.tsx";
|
|
13
|
+
export { default as EventsTimeline } from "./ConsoleEventstimeline.tsx";
|
|
14
|
+
export { default as SnapshotControls } from "./ConsoleSnapshotcontrols.tsx";
|
|
15
|
+
export * from "./ConsoleSpecpanel.tsx";
|
|
16
|
+
export { default as SpecPanel } from "./ConsoleSpecpanel.tsx";
|
|
17
|
+
export * from "./ConsoleTerminal.tsx";
|
|
18
|
+
export { default as Terminal } from "./ConsoleTerminal.tsx";
|
|
19
|
+
export * from "./DashboardAccountpanel.tsx";
|
|
20
|
+
export { default as AccountPanel } from "./DashboardAccountpanel.tsx";
|
|
21
|
+
export { default as AdminPanel } from "./DashboardAdminpanel.tsx";
|
|
22
|
+
export { default as AuditLog } from "./DashboardAuditlog.tsx";
|
|
23
|
+
export { default as CreateSandboxForm } from "./DashboardCreatesandboxform.tsx";
|
|
24
|
+
export { default as DashboardEventstimeline } from "./DashboardEventstimeline.tsx";
|
|
25
|
+
export { default as GlobalSandboxesTable } from "./DashboardGlobalsandboxestable.tsx";
|
|
26
|
+
export { default as MeshNodesTable } from "./DashboardMeshnodestable.tsx";
|
|
27
|
+
export { default as SandboxList } from "./DashboardSandboxlist.tsx";
|
|
28
|
+
export { default as UsersTable } from "./DashboardUserstable.tsx";
|
|
29
|
+
export * from "./HomeEntrygate.tsx";
|
|
30
|
+
export { default as HomeEntrygate } from "./HomeEntrygate.tsx";
|
|
31
|
+
export { default as MetricStrip } from "./HomeMetricstrip.tsx";
|
|
32
|
+
export { default as RuntimeDiagram } from "./HomeRuntimediagram.tsx";
|
|
33
|
+
export * from "./LoginForm.tsx";
|
|
34
|
+
export { default as LoginForm } from "./LoginForm.tsx";
|
|
35
|
+
export { default as PasswordConfirm } from "./RegisterPasswordconfirm.tsx";
|
|
36
|
+
export * from "./RegisterPasswordmeter.tsx";
|
|
37
|
+
export { default as PasswordMeter } from "./RegisterPasswordmeter.tsx";
|
|
38
|
+
export * from "./RegisterUsernamerules.tsx";
|
|
39
|
+
export { default as UsernameRules } from "./RegisterUsernamerules.tsx";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.ts — the universal winget surface of saddle: every winget of the
|
|
3
|
+
* Sol/wingets folder answers from this one module, so the pages import
|
|
4
|
+
* their components from a single place and the dotted winget file name
|
|
5
|
+
* lives exactly once (here) instead of repeating across every page —
|
|
6
|
+
* the components stay complete independent files beside this surface.
|
|
7
|
+
*/
|
|
8
|
+
export { default as ComputeBootladder } from "./ComputeBootladder.tsx";
|
|
9
|
+
export { default as ComputeModalitycatalog } from "./ComputeModalitycatalog.tsx";
|
|
10
|
+
export { default as ApiBadge } from "./ConsoleApibadge.tsx";
|
|
11
|
+
export { default as ConsoleEdgelaw } from "./ConsoleEdgelaw.tsx";
|
|
12
|
+
export * from "./ConsoleEventstimeline.tsx";
|
|
13
|
+
export { default as EventsTimeline } from "./ConsoleEventstimeline.tsx";
|
|
14
|
+
export { default as SnapshotControls } from "./ConsoleSnapshotcontrols.tsx";
|
|
15
|
+
export * from "./ConsoleSpecpanel.tsx";
|
|
16
|
+
export { default as SpecPanel } from "./ConsoleSpecpanel.tsx";
|
|
17
|
+
export * from "./ConsoleTerminal.tsx";
|
|
18
|
+
export { default as Terminal } from "./ConsoleTerminal.tsx";
|
|
19
|
+
export * from "./DashboardAccountpanel.tsx";
|
|
20
|
+
export { default as AccountPanel } from "./DashboardAccountpanel.tsx";
|
|
21
|
+
export { default as AdminPanel } from "./DashboardAdminpanel.tsx";
|
|
22
|
+
export { default as AuditLog } from "./DashboardAuditlog.tsx";
|
|
23
|
+
export { default as CreateSandboxForm } from "./DashboardCreatesandboxform.tsx";
|
|
24
|
+
export { default as DashboardEventstimeline } from "./DashboardEventstimeline.tsx";
|
|
25
|
+
export { default as GlobalSandboxesTable } from "./DashboardGlobalsandboxestable.tsx";
|
|
26
|
+
export { default as MeshNodesTable } from "./DashboardMeshnodestable.tsx";
|
|
27
|
+
export { default as SandboxList } from "./DashboardSandboxlist.tsx";
|
|
28
|
+
export { default as UsersTable } from "./DashboardUserstable.tsx";
|
|
29
|
+
export * from "./HomeEntrygate.tsx";
|
|
30
|
+
export { default as HomeEntrygate } from "./HomeEntrygate.tsx";
|
|
31
|
+
export { default as MetricStrip } from "./HomeMetricstrip.tsx";
|
|
32
|
+
export { default as RuntimeDiagram } from "./HomeRuntimediagram.tsx";
|
|
33
|
+
export * from "./LoginForm.tsx";
|
|
34
|
+
export { default as LoginForm } from "./LoginForm.tsx";
|
|
35
|
+
export { default as PasswordConfirm } from "./RegisterPasswordconfirm.tsx";
|
|
36
|
+
export * from "./RegisterPasswordmeter.tsx";
|
|
37
|
+
export { default as PasswordMeter } from "./RegisterPasswordmeter.tsx";
|
|
38
|
+
export * from "./RegisterUsernamerules.tsx";
|
|
39
|
+
export { default as UsernameRules } from "./RegisterUsernamerules.tsx";
|