From 497d92f353d59a290ed22e48b1c12b0b20c67fcd Mon Sep 17 00:00:00 2001
From: Kyros Koh
Date: Wed, 12 Aug 2026 16:26:26 +0800
Subject: [PATCH 1/6] Add product PRD with M1 trust-and-gates roadmap.
Captures current v1.3 scope, requirements, and prioritized bugs/enhancements so milestone work can be tracked as issues.
---
PRD.md | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
create mode 100644 PRD.md
diff --git a/PRD.md b/PRD.md
new file mode 100644
index 0000000..365390a
--- /dev/null
+++ b/PRD.md
@@ -0,0 +1,238 @@
+# CloudTerm — Product Requirements Document
+
+| Field | Value |
+|-------|-------|
+| **Product** | CloudTerm |
+| **Owner** | CloudBlast |
+| **Version covered** | 1.3.0 (as shipped) |
+| **Status** | Living document — current product + next roadmap |
+| **License** | Fair-code (free to use/modify/share; commercial resale needs a CloudBlast license) |
+| **Repo** | https://github.com/BradPerbs/cloudterm |
+
+---
+
+## 1. Vision
+
+CloudTerm is a **desktop multi-protocol terminal workspace**: one window for SSH, SFTP, Telnet, serial, RDP, VNC, and BMC/IPMI, with encrypted local vault storage, optional CloudBlast cloud sync, and a local AI agent that can act through live sessions (with approval).
+
+**North star:** Replace tool sprawl (PuTTY + WinSCP + RDP client + VNC + serial terminal + snippet managers) with a single, trustworthy, modern app that travels with the user’s setup across machines.
+
+---
+
+## 2. Problem
+
+| Pain | Today without CloudTerm |
+|------|-------------------------|
+| Tool sprawl | Separate apps per protocol; repeated logins and context switching |
+| Setup doesn’t travel | Hosts, keys, snippets, known hosts differ per laptop |
+| AI is paste-driven | Assistants don’t see the live terminal; users copy/paste riskily |
+| CloudBlast customers | Manually re-enter VPS details instead of seeing servers ready to connect |
+
+---
+
+## 3. Goals & non-goals
+
+### Goals
+
+1. **One workspace** for every common remote-access protocol on Windows, macOS, and Linux.
+2. **Secrets stay local** — vault-locked encrypted storage; cloud sync encrypts before upload.
+3. **CloudBlast differentiation** — free encrypted sync for everyone; auto host list for CloudBlast VPS customers.
+4. **Session-aware AI** — local CLIs (Claude Code / Codex / OpenCode) with approval gates; no credential tools.
+5. **Trustworthy distribution** — signed installs, predictable updates, clear fair-code terms.
+
+### Non-goals (near term)
+
+- Becoming a full IDE or browser-based terminal SaaS
+- Replacing enterprise PAM / jump-box products
+- Storing plaintext credentials in the cloud
+- Shipping AI that can extract or export vault secrets
+- Guaranteeing recovery if the vault password is forgotten
+
+---
+
+## 4. Personas
+
+| Persona | Needs | Success looks like |
+|---------|--------|-------------------|
+| **Sysadmin / SRE** | Many hosts, jump hosts, tunnels, monitoring | Folders/tags/search; reconnect; uptime checks; activity log |
+| **Developer** | SSH + SFTP + occasional RDP/VNC | Fast connect, split panes, snippets, remote edit |
+| **CloudBlast customer** | Servers appear without manual entry | Sign in → VPS hosts ready |
+| **Multi-machine user** | Same setup on laptop + desktop | Encrypted cloud snapshot restore on sign-in |
+| **AI-assisted operator** | Agent reads session and runs approved commands | Clear approval UX; safe defaults |
+
+---
+
+## 5. Current product (v1.3)
+
+### 5.1 User-facing capabilities
+
+| Area | Capability |
+|------|------------|
+| **Sessions** | SSH, Telnet, serial; jump hosts; SOCKS/HTTP proxies; tabs & split panes (max 8); themes; find; broadcast; screenshots; session log |
+| **Files** | SFTP (list/mkdir/delete/rename, transfers, resume, conflicts, drag-and-drop); remote edit → upload on save |
+| **Networking** | Local / remote / dynamic port forwarding with traffic counters |
+| **Desktops** | RDP (IronRDP WASM), VNC (noVNC, SSH-tunnelled), BMC/IPMI web UI (sandboxed webview + auto-login) |
+| **Inventory** | Hosts, folders, tags, search, quick-connect; keychain (generate/import, Windows Hello/TPM); snippets with `{{placeholders}}` |
+| **Import** | `~/.ssh/config`, PuTTY, MobaXterm |
+| **Security** | App lock / vault (password or OS keystore); encrypted backup export/restore |
+| **Cloud** | CloudBlast OAuth (PKCE, system browser); VPS server sync; encrypted cross-device snapshot |
+| **Ops** | Host TCP monitoring + notifications; activity log; auto-update from GitHub Releases (winget on Windows) |
+| **AI** | Claude Code / Codex / OpenCode; tools: hosts, sessions, terminal read/write, files, connect/disconnect — approval modes |
+| **i18n** | In-app: en, zh, vi, pt, ru (README also offers Español — see gap below) |
+
+### 5.2 Architecture (summary)
+
+```
+Renderer (React + xterm / IronRDP / noVNC)
+ ↕ IPC + MessagePort (session bytes)
+Main (Electron): store, vault, transport (ssh|telnet|serial),
+ sftp, tunnels, rdp, vnc, bmc, account, AI, monitor
+```
+
+- **Security defaults:** `contextIsolation`, no `nodeIntegration`, `sandbox`; secrets resolved in main; vault lock gates IPC.
+- **Persistence:** `sessions.json`, `vault.json`, window state, cloud snapshot under Electron `userData`; UI prefs in `localStorage`.
+
+### 5.3 Platforms & distribution
+
+| Channel | Notes |
+|---------|--------|
+| GitHub Releases | NSIS + portable (Win), DMG/zip (macOS), AppImage (Linux) |
+| winget | `CloudBlast.CloudTerm` — see `docs/winget.md` |
+| Signing | **Not code-signed today** — SmartScreen / enterprise friction |
+
+---
+
+## 6. Requirements
+
+### 6.1 Functional (must remain true)
+
+| ID | Requirement |
+|----|-------------|
+| F1 | User can open SSH / Telnet / serial sessions from a host record without leaving the app |
+| F2 | Credentials and private keys never leave the main process (RDP CredSSP path is the documented exception) |
+| F3 | Vault lock blocks sensitive IPC until unlocked |
+| F4 | SFTP and tunnels can reuse an active SSH connection |
+| F5 | Cloud snapshot is encrypted client-side before upload |
+| F6 | AI cannot read vault secrets; destructive/session-changing tools require approval unless user opts into a looser mode |
+| F7 | Auto-update can be disabled (`CLOUDBLAST_UPDATE_DISABLED`) for air-gapped use |
+
+### 6.2 Non-functional
+
+| ID | Requirement | Current gap |
+|----|-------------|-------------|
+| N1 | PR builds run automated tests | Release-only CI; no PR test workflow |
+| N2 | Installers code-signed on Windows (and ideally macOS) | Unsigned |
+| N3 | Core paths (SSH connect, SFTP, lock/unlock) covered by automated smoke | Unit tests only; no E2E |
+| N4 | Cold start acceptable for SSH-only users | RDP/VNC/WASM always in bundle weight |
+| N5 | CJK IME composition usable in terminal | Known TODO in `xterm.css` |
+| N6 | Marketing locales match in-app locales | Spanish README without in-app `es` |
+
+---
+
+## 7. Success metrics (suggested)
+
+| Metric | Target (directional) |
+|--------|----------------------|
+| Crash-free sessions / week | Track via optional anonymous telemetry later; start with GitHub issue rate |
+| Time-to-first-connect (fresh install → SSH) | < 2 minutes with import or CloudBlast sync |
+| Update adoption (7-day) | Majority on latest within a week of release (post-signing) |
+| Test gate | `npm test` green on every PR before merge |
+| AI incident rate | Near-zero reports of unexpected `run_command` without approval on default settings |
+
+---
+
+## 8. Roadmap — bugs, enhancements, optimizations
+
+Priorities: **P0** ship-blocking / trust / safety · **P1** product quality · **P2** polish & scale.
+
+### 8.1 Bug fixes & reliability (P0–P1)
+
+| Priority | Item | Rationale | Notes |
+|----------|------|-----------|-------|
+| **P0** | Add CI workflow that runs `npm test` on PRs | Regressions can ship with release-only CI | Mirror local `npm test` script |
+| **P0** | Harden AI approval defaults + first-run warning | “Never ask” + `run_command` is high risk | Prefer ask-before-run; document modes clearly |
+| **P0** | Audit RDP password lifetime in renderer/WASM | Documented secret exception | Zero after auth; no logs; teardown tests |
+| **P0** | Fix or quarantine IME composition positioning | Blocks CJK users; zh locale is shipped | `src/renderer/xterm.css` TODO |
+| **P1** | Session restore reconnect policy | Tabs restore without live sockets | Explicit “reconnect all” or per-tab option |
+| **P1** | Update download UX | `autoDownload = true` may surprise corporate users | Optional “ask before download” |
+| **P1** | Align Spanish: add `es` locale **or** remove es README until ready | Docs/product mismatch | |
+
+### 8.2 Enhancements (P1–P2)
+
+| Priority | Item | Rationale |
+|----------|------|-----------|
+| **P1** | Code-sign Windows (and ideally macOS) builds | SmartScreen, winget, enterprise adoption |
+| **P1** | Split oversized modules (`ipc.js`, `store.js`, `App.jsx`, `TerminalView.jsx`) by domain | Safer reviews; fewer regressions |
+| **P1** | E2E smoke: mock SSH → SFTP → lock/unlock | Catch IPC/UI wiring unit tests miss |
+| **P1** | SSH/SFTP integration tests (container or mock) | Core path under-tested vs edge protocols |
+| **P1** | True 1024² app icon (replace upscaled soft cloud) | Documented in `resources/README.md` |
+| **P1** | Rename npm package / clarify branding (`cloudblast-ssh` → `cloudterm`) | Contributor & packaging clarity |
+| **P2** | Accessibility pass on dialogs + terminal chrome | Enterprise procurement |
+| **P2** | Portable winget package parity | Mentioned as future in `docs/winget.md` |
+| **P2** | Document env vars & `userData` layout under `docs/` | Support / IT / contributors |
+| **P2** | Gradual TypeScript on `store` / `vault` / `ai/tools` | Catch IPC/secret-field shape bugs |
+
+### 8.3 Optimizations (P2)
+
+| Priority | Item | Rationale |
+|----------|------|-----------|
+| **P2** | Lazy-load RDP / VNC / noVNC chunks | Faster cold start for SSH-only users |
+| **P2** | Cap / paginate activity & AI event retention more aggressively | Long-lived processes; large event buffers |
+| **P2** | Parallelize `npm test` (today sequential `&&`) | Faster local + CI feedback |
+| **P2** | Profile WebGL terminals under multi-pane load | Cap is 8 panes; validate GPU cost |
+
+### 8.4 Explicitly out of scope for this PRD cycle
+
+- Vault password recovery without user-held secret
+- Server-side decryption of cloud snapshots
+- AI tools that return private keys or vault DEK material
+
+---
+
+## 9. Security & threat notes (product constraints)
+
+| Topic | Stance |
+|-------|--------|
+| Vault | Protects against disk theft; forgotten password = data unrecoverable by design |
+| Cloud snapshot | Protects DB theft in transit/at rest; **not** a compromised CloudBlast app server acting as a malicious client |
+| AI | Local CLIs under user accounts; approval modes are the control plane |
+| BMC webview | Sandboxed but still untrusted vendor JS on LAN — treat as higher risk surface |
+| RDP | Password must reach WASM for CredSSP — minimize lifetime and logging |
+| OAuth | System browser + PKCE; client id `cloudblast-desktop` |
+
+---
+
+## 10. Milestones (suggested)
+
+| Milestone | Scope | Exit criteria |
+|-----------|--------|---------------|
+| **M1 — Trust & gates** | PR CI for tests; AI default hardening; RDP password audit; IME fix plan | Tests on every PR; safer AI defaults; documented RDP secret handling |
+| **M2 — Distribution** | Code signing; icon quality; optional update consent | Signed Win (+ mac if feasible); reduced SmartScreen friction |
+| **M3 — Quality depth** | Module splits; E2E smoke; SSH/SFTP integration tests | Reviewable IPC surfaces; smoke green in CI |
+| **M4 — Polish** | Locale alignment; lazy-load remoting; docs for env/`userData`; a11y pass | Marketing ↔ app parity; measurable startup win |
+
+---
+
+## 11. Open questions
+
+1. Should cloud sync remain forever-free for non-CloudBlast users, or become tiered later?
+2. Is code signing budgeted for Windows only first, or Win+mac together?
+3. Should “never ask” AI mode remain available, or be removed / hidden behind an advanced unlock?
+4. Telemetry: opt-in crash/usage metrics, or stay fully silent?
+5. Rename `appId` / package name in a major version, or keep `com.cloudblast.ssh` for upgrade continuity?
+
+---
+
+## 12. References
+
+| Doc | Path / URL |
+|-----|------------|
+| User README | `README.md` (+ zh-CN, es, ru) |
+| Winget publish | `docs/winget.md` |
+| Resources / icon notes | `resources/README.md` |
+| License | `LICENSE` |
+| Product site | https://cloudblast.io |
+
+---
+
+*This PRD describes the product as of v1.3.0 and a prioritized improvement backlog. Update milestones when releases ship.*
From 21ee134abb8edbae83f22f78daf49266dc3c9a57 Mon Sep 17 00:00:00 2001
From: Kyros Koh
Date: Wed, 12 Aug 2026 16:46:42 +0800
Subject: [PATCH 2/6] Ship M1 trust gates: PR CI, safer AI approvals, RDP
secret lifetime, IME plan.
---
.github/workflows/ci.yml | 29 +++++
docs/assistant-approvals.md | 29 +++++
docs/ime-composition.md | 58 ++++++++++
docs/rdp-credentials.md | 41 +++++++
src/main/activity.js | 5 +-
src/main/ai/settings.js | 7 ++
src/renderer/components/RdpView.jsx | 60 +++++-----
.../components/assistant/ApprovalMenu.jsx | 105 ++++++++++++------
.../components/assistant/AssistantPanel.jsx | 31 +++++-
.../components/settings/AssistantSection.jsx | 26 ++++-
src/renderer/i18n/locales/en.js | 11 +-
src/renderer/i18n/locales/pt.js | 11 +-
src/renderer/i18n/locales/ru.js | 10 +-
src/renderer/i18n/locales/vi.js | 11 +-
src/renderer/i18n/locales/zh.js | 9 +-
src/renderer/xterm.css | 3 +-
test/assistant-approval.test.js | 19 +++-
test/rdp.test.js | 46 ++++++++
18 files changed, 423 insertions(+), 88 deletions(-)
create mode 100644 .github/workflows/ci.yml
create mode 100644 docs/assistant-approvals.md
create mode 100644 docs/ime-composition.md
create mode 100644 docs/rdp-credentials.md
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..925825f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,29 @@
+# Run the same unit suite developers run locally on every PR and on main.
+# Packaging stays in release.yml; these tests are plain Node and do not need
+# Electron or a matrix of OS runners.
+
+name: CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: npm
+
+ - run: npm ci
+
+ - run: npm test
diff --git a/docs/assistant-approvals.md b/docs/assistant-approvals.md
new file mode 100644
index 0000000..ce3340a
--- /dev/null
+++ b/docs/assistant-approvals.md
@@ -0,0 +1,29 @@
+# Assistant approval modes
+
+The local AI agent can read live terminals and run tools against saved hosts.
+Approval modes decide when those tools stop for a person.
+
+| Mode | Value | Behaviour |
+|------|-------|-----------|
+| Ask every time | `always` | Every tool waits, including reads |
+| Ask before changes | `writes` | **Default.** Reads run freely; mutating tools ask |
+| Never ask | `never` | Nothing asks (except the block list) |
+
+## Defaults and hardening
+
+- New installs ship with `writes` and `allowLocalTools: false`.
+- The first time the assistant panel opens, a short warning explains the modes
+ and that tools act on live sessions. Dismissing it sets
+ `acknowledgedApprovalWarning` in `assistant.json`.
+- Switching to **Never ask** from the composer chip or Settings requires an
+ explicit confirm dialog. The block list (`blockedCommands`, seeded with
+ `rm -rf`) still refuses matching commands under every mode, including never.
+
+## Where it lives
+
+- Persistence: `userData/assistant.json` via `src/main/ai/settings.js`
+- Policy: `src/main/ai/tools.js` (`isAutoApproved`, `blockedReason`)
+- UI: composer `ApprovalMenu`, Settings → Assistant
+
+Settings for the assistant stay machine-local on purpose and do not sync with
+cloud snapshots.
diff --git a/docs/ime-composition.md b/docs/ime-composition.md
new file mode 100644
index 0000000..ead9a63
--- /dev/null
+++ b/docs/ime-composition.md
@@ -0,0 +1,58 @@
+# IME composition positioning (CJK)
+
+CloudTerm ships Chinese (`zh`) and other locales, but CJK Input Method Editor
+(IME) candidate windows can appear mis-positioned in the terminal. This is a
+known limitation tracked as GitHub
+[#7](https://github.com/BradPerbs/cloudterm/issues/7).
+
+## Symptom
+
+While composing CJK (or other IME) text in an SSH/Telnet/serial pane, the
+composition / candidate UI may not sit on the caret. English and dead-key Latin
+input are unaffected.
+
+## Current code
+
+- Terminal: `src/renderer/components/TerminalView.jsx` (`@xterm/xterm` ^5.4)
+- Styles: vendored `src/renderer/xterm.css` (upstream still carries
+ `/* TODO: Composition position got messed up somewhere */` on
+ `.xterm .composition-view`)
+- No app-level `compositionstart` / IME hooks — positioning is entirely xterm’s
+ `CompositionHelper` + CSS
+
+Likely aggravators to test (not yet proven):
+
+- Pane mount uses `p-3` + `overflow-hidden` on the open target
+- WebGL addon vs DOM renderer
+- Non-default `lineHeight` / `letterSpacing`
+- Hardcoded black/white `.composition-view` vs themed terminal
+
+## Repro matrix (for a later fix)
+
+| Dimension | Values |
+|-----------|--------|
+| OS | Windows, macOS |
+| IME | zh / ja / ko system IMEs |
+| Renderer | WebGL on, WebGL off |
+| Typography | default vs custom lineHeight / letterSpacing |
+
+Compare against a stock xterm.js demo on the same Electron version to separate
+CloudTerm layout from upstream bugs.
+
+## Ranked options
+
+1. **CSS / layout-only** — ensure composition view is not clipped; theme
+ `.composition-view`; reduce padding/`overflow` interaction on the mount node.
+2. **Bump `@xterm/xterm`** — evaluate 6.x for upstream IME fixes vs breakage in
+ addons / WebGL.
+3. **App composition sync** — listen for composition events and reposition
+ (last resort; fights the library).
+4. **Quarantine (this milestone)** — document the limitation, keep #7 open,
+ cross-link the CSS TODO. Full N5 fix is out of M1 exit criteria.
+
+## Quarantine stance (M1)
+
+Until a verified fix lands: treat CJK IME in the terminal as best-effort.
+Prefer composing in an external editor for critical CJK input if positioning
+blocks work. Do not close #7 until zh QA passes on Windows and macOS with WebGL
+on and off.
diff --git a/docs/rdp-credentials.md b/docs/rdp-credentials.md
new file mode 100644
index 0000000..d2c4cef
--- /dev/null
+++ b/docs/rdp-credentials.md
@@ -0,0 +1,41 @@
+# RDP credentials (CredSSP exception)
+
+Most secrets in CloudTerm never leave the main process. RDP is the documented
+exception: Network Level Authentication (CredSSP) runs inside IronRDP’s
+WebAssembly client in the renderer, so the decrypted password must reach that
+client once when a session opens.
+
+## Lifetime
+
+1. **Vault / store** — `rdpPassword` is encrypted at rest like other host
+ secrets (`src/main/store.js`).
+2. **Open** — `rdp.open` decrypts via `resolveDesktop`, returns
+ `{ username, domain, password, … }` once over IPC, and does **not** keep the
+ password on the live session object or in `snapshot()`.
+3. **Renderer** — `RdpView` loads IronRDP **before** calling `open`, so the
+ secret does not sit on the IPC result through WASM compile. It passes the
+ password into `SessionBuilder`, then clears `result.password` in a `finally`
+ that covers every post-open exit (missing canvas, cancel, connect error).
+4. **Reconnect** — always re-calls `open`; nothing retains the password for
+ reuse.
+
+## Logging and redaction
+
+- Host list IPC redacts `rdpPassword` (exposes `hasRdpPassword` only).
+- Activity change diffs treat `rdpPassword` and `bmcPassword` as secrets
+ (`secret: true`, empty `from`/`to`).
+- Error paths describe rejected credentials without echoing the value.
+
+## Residual risk
+
+JavaScript strings are immutable: clearing a property drops the reference; the
+engine may retain the buffer until GC. IronRDP’s WASM heap is opaque to the
+app — there is no upstream API to zeroize credentials after NLA. Treat the
+renderer process as a higher-trust surface for the duration of CredSSP, then
+minimize lifetime as above.
+
+## Contrast with VNC / BMC
+
+VNC authenticates in the main process; the viewer never receives the password.
+BMC uses a sandboxed webview with its own auto-login path — also not this
+CredSSP handoff.
diff --git a/src/main/activity.js b/src/main/activity.js
index 620a4f7..87daa9e 100644
--- a/src/main/activity.js
+++ b/src/main/activity.js
@@ -280,7 +280,9 @@ function clear() {
* Change detection
* ------------------------------------------------------------------ */
-const SECRET_FIELDS = new Set(['password', 'privateKey', 'passphrase', 'vncPassword']);
+const SECRET_FIELDS = new Set([
+ 'password', 'privateKey', 'passphrase', 'vncPassword', 'rdpPassword', 'bmcPassword',
+]);
/**
* Bookkeeping the app writes on its own. `lastConnectedAt` alone is written on
@@ -290,6 +292,7 @@ const SECRET_FIELDS = new Set(['password', 'privateKey', 'passphrase', 'vncPassw
const NOISE_FIELDS = new Set([
'id', 'lastConnectedAt', 'os', 'distro',
'hasPassword', 'hasPrivateKey', 'hasPassphrase', 'hasVncPassword',
+ 'hasRdpPassword', 'hasBmcPassword',
]);
/** How many of a list of words are worth naming before it becomes a paragraph. */
diff --git a/src/main/ai/settings.js b/src/main/ai/settings.js
index 45954d2..c6a4587 100644
--- a/src/main/ai/settings.js
+++ b/src/main/ai/settings.js
@@ -95,6 +95,10 @@ const DEFAULTS = {
// of things nobody here asked for is filler, and the useful ones are the
// ones a particular person asks their particular fleet over and over.
quickPrompts: [],
+ // Whether the first-run warning about approval modes has been dismissed.
+ // False until the person has seen that tools act on live sessions and that
+ // "never ask" runs mutating tools without prompts.
+ acknowledgedApprovalWarning: false,
};
const stateFile = () => path.join(app.getPath('userData'), 'assistant.json');
@@ -148,6 +152,9 @@ function sanitize(raw) {
.filter(Boolean)
.slice(0, 12);
}
+ if ('acknowledgedApprovalWarning' in raw) {
+ next.acknowledgedApprovalWarning = Boolean(raw.acknowledgedApprovalWarning);
+ }
}
return next;
}
diff --git a/src/renderer/components/RdpView.jsx b/src/renderer/components/RdpView.jsx
index 10cddc7..ab6f3e6 100644
--- a/src/renderer/components/RdpView.jsx
+++ b/src/renderer/components/RdpView.jsx
@@ -260,22 +260,10 @@ function RdpView({ paneId, host, isActive, isFocused, isLive, toolbarHost = null
// about what the last one was told this machine had copied.
warnedRef.current = false;
lastSentRef.current = null;
- setStatus('opening');
- const result = await open(host?.id);
- if (!current()) return;
-
- if (!result?.success) {
- setStatus('error');
- setError(result?.message || 'Could not open the desktop');
- return;
- }
-
- // From here the password is in hand. Everything between this line and
- // the builder call is deliberately short and deliberately synchronous
- // where it can be.
+ // Load WASM before asking main for the password, so the secret does not
+ // sit on the IPC result through a multi-megabyte compile.
setStatus('loading');
-
let ironrdp;
try {
ironrdp = await loadIronRdp();
@@ -283,27 +271,42 @@ function RdpView({ paneId, host, isActive, isFocused, isLive, toolbarHost = null
if (!current()) return;
setStatus('error');
setError(`The RDP module failed to load: ${loadError.message}`);
- close(host?.id);
return;
}
if (!current()) return;
ironrdpRef.current = ironrdp;
- const canvas = canvasRef.current;
- const frame = frameRef.current;
- if (!canvas || !frame) return;
-
- setScaling(SCALING[result.scaling] ? result.scaling : 'fit');
- setStatus('connecting');
+ setStatus('opening');
+ const result = await open(host?.id);
+ if (!current()) {
+ if (result) result.password = '';
+ return;
+ }
- const ratio = window.devicePixelRatio || 1;
- const scaleFactor = scaleFactorFor(ratio);
- const width = clampWidth((frame.clientWidth || MIN_WIDTH) * ratio);
- const height = clampHeight((frame.clientHeight || MIN_HEIGHT) * ratio);
+ if (!result?.success) {
+ setStatus('error');
+ setError(result?.message || 'Could not open the desktop');
+ return;
+ }
+ // From here the password is in hand. Everything between this line and
+ // the builder call is deliberately short; the wipe in `finally` covers
+ // every exit, including cancel, missing canvas, and connect errors.
let live;
try {
+ const canvas = canvasRef.current;
+ const frame = frameRef.current;
+ if (!canvas || !frame) return;
+
+ setScaling(SCALING[result.scaling] ? result.scaling : 'fit');
+ setStatus('connecting');
+
+ const ratio = window.devicePixelRatio || 1;
+ const scaleFactor = scaleFactorFor(ratio);
+ const width = clampWidth((frame.clientWidth || MIN_WIDTH) * ratio);
+ const height = clampHeight((frame.clientHeight || MIN_HEIGHT) * ratio);
+
const builder = new ironrdp.SessionBuilder();
builder.username(result.username || '');
builder.password(result.password || '');
@@ -409,7 +412,8 @@ function RdpView({ paneId, host, isActive, isFocused, isLive, toolbarHost = null
return;
} finally {
// The builder has copied what it needs. Nothing here should keep a
- // reference to the credential after this point.
+ // reference to the credential after this point — including early
+ // exits above that never reached connect.
result.password = '';
}
@@ -428,8 +432,8 @@ function RdpView({ paneId, host, isActive, isFocused, isLive, toolbarHost = null
setSize(agreedSize(live));
setStatus('connected');
- detachInputRef.current = attachInput(canvas, () => sessionRef.current, ironrdp);
- if (isActive && isFocused) canvas.focus();
+ detachInputRef.current = attachInput(canvasRef.current, () => sessionRef.current, ironrdp);
+ if (isActive && isFocused) canvasRef.current?.focus();
// `run` resolves when the session ends, however it ends. Anything other
// than a shutdown we asked for is worth showing, because the pane
diff --git a/src/renderer/components/assistant/ApprovalMenu.jsx b/src/renderer/components/assistant/ApprovalMenu.jsx
index 88900f6..eb5de84 100644
--- a/src/renderer/components/assistant/ApprovalMenu.jsx
+++ b/src/renderer/components/assistant/ApprovalMenu.jsx
@@ -1,5 +1,7 @@
+import { useState } from 'react';
import { ArrowDown01Icon, FlashIcon, SecurityCheckIcon, Shield01Icon } from 'hugeicons-react';
import PanelMenu from './PanelMenu';
+import ConfirmDialog from '../ui/ConfirmDialog';
/**
* What the assistant will do before asking, as a chip in the composer.
@@ -14,6 +16,10 @@ import PanelMenu from './PanelMenu';
* Icon only. It is a standing state rather than an action, and the composer row
* has one label on it already; two competing bits of small text is what makes
* that row look like a toolbar.
+ *
+ * Switching to "never ask" is gated behind a confirm. One click from a chip is
+ * otherwise how someone turns off every approval without reading what that
+ * means for deletes and restarts on live hosts.
*/
const APPROVALS = [
@@ -31,13 +37,14 @@ const APPROVALS = [
},
{
value: 'never',
- label: 'Yolo Mode',
+ label: 'Never ask',
hint: 'Nothing stops, deletes included',
icon: ,
},
];
export default function ApprovalMenu({ settings, onChange }) {
+ const [confirmNever, setConfirmNever] = useState(false);
const current = APPROVALS.find(option => option.value === settings.approval) || APPROVALS[1];
// The one state worth colouring. Somebody who has turned approvals off and
@@ -45,43 +52,67 @@ export default function ApprovalMenu({ settings, onChange }) {
// and the chip is the only place in the panel that can tell them.
const loud = current.value === 'never';
+ const pick = (value) => {
+ if (value === 'never' && settings.approval !== 'never') {
+ setConfirmNever(true);
+ return;
+ }
+ onChange({ approval: value });
+ };
+
return (
- onChange({ approval: value }),
- options: APPROVALS,
- },
- ]}
- trigger={({ open, toggle }) => (
-
+ <>
+ (
+
+ )}
+ />
+
+ {confirmNever && (
+ {
+ setConfirmNever(false);
+ onChange({ approval: 'never' });
+ }}
+ onCancel={() => setConfirmNever(false)}
+ />
)}
- />
+ >
);
}
diff --git a/src/renderer/components/assistant/AssistantPanel.jsx b/src/renderer/components/assistant/AssistantPanel.jsx
index 7a4889d..4264ee4 100644
--- a/src/renderer/components/assistant/AssistantPanel.jsx
+++ b/src/renderer/components/assistant/AssistantPanel.jsx
@@ -4,6 +4,7 @@ import {
PlusSignIcon,
ArrowUp01Icon,
StopCircleIcon,
+ Alert02Icon,
} from 'hugeicons-react';
import Tooltip from '../ui/Tooltip';
import AgentMark from './AgentMark';
@@ -17,6 +18,7 @@ import ScopeMenu from './ScopeMenu';
import ModelMenu from './ModelMenu';
import ApprovalMenu from './ApprovalMenu';
import HistoryMenu from './HistoryMenu';
+import Dialog, { DialogButton } from '../ui/Dialog';
import {
GLOBAL,
describe,
@@ -478,7 +480,8 @@ function AssistantConversation({
It reads this terminal, runs commands on their own channel, and can work
- across every host you have saved.
+ across every host you have saved. Approvals default to ask-before-changes;
+ switch modes from the composer chip or Settings.
- **使用本机已有的 Claude Code、Codex 或 OpenCode**,沿用你自己的账号和配置
-- **读取当前会话并操作远程服务器**,执行更改前会先征求你的同意
+- **读取当前会话并操作远程服务器**,执行更改前会先征求你的同意;提供三种审批模式,详见 [docs/assistant-approvals.md](docs/assistant-approvals.md)(英文)
- **每个对话可单独选择模型和推理强度**,并在运行时显示用量
### 终端
@@ -268,6 +268,14 @@ npm run dev
npm run build
```
+提交 pull request 前请运行单元测试:
+
+```bash
+npm test
+```
+
+更多文档见 [CHANGELOG.md](CHANGELOG.md) 与 [docs/README.md](docs/README.md)(英文)。
+
### 快捷键
| | | | |
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..b865864
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,14 @@
+# CloudTerm documentation
+
+Operator and contributor notes live here. User-facing marketing and setup
+instructions are in the root [README](../README.md).
+
+| Doc | Audience | Summary |
+|-----|----------|---------|
+| [Assistant approval modes](assistant-approvals.md) | Users, contributors | How `always` / `writes` / `never` approval works, defaults, and block list |
+| [RDP credentials](rdp-credentials.md) | Contributors, security review | CredSSP exception: password lifetime, logging, residual risk |
+| [IME composition](ime-composition.md) | Contributors | CJK IME candidate positioning — known limitation and fix plan |
+| [Winget publishing](winget.md) | Maintainers | First-time and automated Windows package updates |
+
+Product scope, roadmap, and milestones are in [PRD.md](../PRD.md). Release
+history is in [CHANGELOG.md](../CHANGELOG.md).
From bd6b5feaac800b78e3145152271aa62db2123a28 Mon Sep 17 00:00:00 2001
From: Kyros Koh
Date: Wed, 12 Aug 2026 17:18:23 +0800
Subject: [PATCH 5/6] Harden dependencies and document pending code signing.
Run npm audit fix and block high-severity production advisories in CI. Wire optional Authenticode signing in release.yml (secrets not yet configured). Add docs/security.md and update PRD, README, and winget docs to state that the Windows certificate is pending procurement. Fix a broken comment in AssistantPanel.jsx that blocked production builds.
---
.github/workflows/ci.yml | 4 +
.github/workflows/release.yml | 12 +-
CHANGELOG.md | 12 +-
PRD.md | 10 +-
README.md | 7 +
docs/README.md | 1 +
docs/security.md | 105 ++
docs/winget.md | 10 +-
package-lock.json | 933 ++++++++++--------
package.json | 5 +-
.../components/assistant/AssistantPanel.jsx | 3 +-
11 files changed, 696 insertions(+), 406 deletions(-)
create mode 100644 docs/security.md
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 925825f..16420ae 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,4 +26,8 @@ jobs:
- run: npm ci
+ # Production deps only: dev-only tools (Vite/esbuild) may still report
+ # advisories that do not affect the packaged app.
+ - run: npm audit --omit=dev --audit-level=high
+
- run: npm test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bf7f9de..6947f53 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -128,9 +128,15 @@ jobs:
- name: Package
run: npx electron-builder ${{ matrix.args }} --publish never
env:
- # There is no signing certificate on a CI runner. Without this,
- # electron-builder hunts for one and fails the macOS build.
- CSC_IDENTITY_AUTO_DISCOVERY: false
+ # When WIN_CSC_LINK / CSC_LINK secrets are set, electron-builder signs
+ # the Windows installer and portable exe (or the macOS bundle). Without
+ # them, builds stay unsigned — see docs/security.md.
+ WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
+ WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
+ CSC_LINK: ${{ secrets.CSC_LINK }}
+ CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
+ # Only hunt the macOS keychain when a Developer ID cert is supplied.
+ CSC_IDENTITY_AUTO_DISCOVERY: ${{ secrets.CSC_LINK != '' && 'true' || 'false' }}
# The agent SDK carries the Claude CLI as an optional platform package,
# a 253MB binary that the app deliberately does not ship: the provider
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2528efb..03a5f89 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,12 +4,20 @@ All notable changes to CloudTerm are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions align
with [GitHub Releases](https://github.com/BradPerbs/cloudterm/releases).
-## [Unreleased]
+## [1.3.1] - 2026-08-12
### Added
- GitHub Actions CI (`.github/workflows/ci.yml`) runs `npm test` on every pull
request and on pushes to `main`.
+- CI runs `npm audit --omit=dev` to block high-severity vulnerabilities in
+ production dependencies.
+- Optional Authenticode / macOS code signing in release builds when
+ `WIN_CSC_LINK` / `CSC_LINK` repository secrets are configured (certificate
+ **pending procurement** — builds stay unsigned until secrets are added). See
+ [docs/security.md](docs/security.md).
+- [Security documentation](docs/security.md): VirusTotal/SmartScreen, signing,
+ dependency audit, vulnerability reporting.
- First-run assistant warning explaining that tools act on live sessions and
what each approval mode means.
- Confirm dialog before switching the assistant to **Never ask**.
@@ -19,6 +27,8 @@ with [GitHub Releases](https://github.com/BradPerbs/cloudterm/releases).
### Changed
+- npm production and dev dependencies updated (`npm audit fix`); esbuild
+ overridden to a patched release for the dev toolchain.
- Default assistant approval mode is **Ask before changes** (`writes`): reads
run freely; mutating tools stop for approval.
- New installs ship with `allowLocalTools: false`.
diff --git a/PRD.md b/PRD.md
index bed35da..44182cb 100644
--- a/PRD.md
+++ b/PRD.md
@@ -98,7 +98,7 @@ Main (Electron): store, vault, transport (ssh|telnet|serial),
|---------|--------|
| GitHub Releases | NSIS + portable (Win), DMG/zip (macOS), AppImage (Linux) |
| winget | `CloudBlast.CloudTerm` — see `docs/winget.md` |
-| Signing | **Not code-signed today** — SmartScreen / enterprise friction |
+| Signing | **Unsigned** — Windows Authenticode cert **pending procurement**; CI ready when secrets are set — see [docs/security.md](docs/security.md) |
---
@@ -121,7 +121,7 @@ Main (Electron): store, vault, transport (ssh|telnet|serial),
| ID | Requirement | Current gap |
|----|-------------|-------------|
| N1 | PR builds run automated tests | **Shipped (M1):** `.github/workflows/ci.yml` on PRs and `main` |
-| N2 | Installers code-signed on Windows (and ideally macOS) | Unsigned |
+| N2 | Installers code-signed on Windows (and ideally macOS) | **Pending** — cert procurement in progress; release CI wired for signing |
| N3 | Core paths (SSH connect, SFTP, lock/unlock) covered by automated smoke | Unit tests only; no E2E |
| N4 | Cold start acceptable for SSH-only users | RDP/VNC/WASM always in bundle weight |
| N5 | CJK IME composition usable in terminal | Known limitation — documented in `docs/ime-composition.md`; fix tracked in #7 |
@@ -161,7 +161,7 @@ Priorities: **P0** ship-blocking / trust / safety · **P1** product quality · *
| Priority | Item | Rationale |
|----------|------|-----------|
-| **P1** | Code-sign Windows (and ideally macOS) builds | SmartScreen, winget, enterprise adoption |
+| **P1** | Code-sign Windows (and ideally macOS) builds | SmartScreen, winget, enterprise adoption | **In progress** — Windows cert pending; `release.yml` ready |
| **P1** | Split oversized modules (`ipc.js`, `store.js`, `App.jsx`, `TerminalView.jsx`) by domain | Safer reviews; fewer regressions |
| **P1** | E2E smoke: mock SSH → SFTP → lock/unlock | Catch IPC/UI wiring unit tests miss |
| **P1** | SSH/SFTP integration tests (container or mock) | Core path under-tested vs edge protocols |
@@ -207,7 +207,7 @@ Priorities: **P0** ship-blocking / trust / safety · **P1** product quality · *
| Milestone | Scope | Exit criteria |
|-----------|--------|---------------|
| **M1 — Trust & gates** | PR CI for tests; AI default hardening; RDP password audit; IME fix plan | **Shipped** — CI on PRs; safer AI defaults; RDP docs + tests; IME quarantined in `docs/ime-composition.md` |
-| **M2 — Distribution** | Code signing; icon quality; optional update consent | Signed Win (+ mac if feasible); reduced SmartScreen friction |
+| **M2 — Distribution** | Code signing; icon quality; optional update consent | Signed Win (+ mac if feasible); reduced SmartScreen friction — **cert pending** |
| **M3 — Quality depth** | Module splits; E2E smoke; SSH/SFTP integration tests | Reviewable IPC surfaces; smoke green in CI |
| **M4 — Polish** | Locale alignment; lazy-load remoting; docs for env/`userData`; a11y pass | Marketing ↔ app parity; measurable startup win |
@@ -216,7 +216,7 @@ Priorities: **P0** ship-blocking / trust / safety · **P1** product quality · *
## 11. Open questions
1. Should cloud sync remain forever-free for non-CloudBlast users, or become tiered later?
-2. Is code signing budgeted for Windows only first, or Win+mac together?
+2. Code signing: **Windows certificate procurement in progress**; macOS Developer ID deferred until after first signed Windows release.
3. Should “never ask” AI mode remain available, or be removed / hidden behind an advanced unlock?
4. Telemetry: opt-in crash/usage metrics, or stay fully silent?
5. Rename `appId` / package name in a major version, or keep `com.cloudblast.ssh` for upgrade continuity?
diff --git a/README.md b/README.md
index ea02115..b9dde5f 100644
--- a/README.md
+++ b/README.md
@@ -300,6 +300,12 @@ winget install CloudBlast.CloudTerm
Or browse [all GitHub releases](https://github.com/BradPerbs/cloudterm/releases).
+> **Windows SmartScreen / VirusTotal:** Installers are **unsigned** while a
+> code-signing certificate is being procured. This can trigger SmartScreen or
+> heuristic scanner warnings (often 1–3 vendors on VirusTotal). See
+> [docs/security.md](docs/security.md) for details and what to expect after
+> signing is enabled.
+
### Build from source
```bash
@@ -348,6 +354,7 @@ The same suite runs on every pull request via GitHub Actions (`.github/workflows
| [docs/rdp-credentials.md](docs/rdp-credentials.md) | RDP password handling (CredSSP exception) |
| [docs/ime-composition.md](docs/ime-composition.md) | CJK IME positioning (known limitation) |
| [docs/winget.md](docs/winget.md) | Publishing to Windows Package Manager |
+| [docs/security.md](docs/security.md) | Signing status, SmartScreen/VirusTotal, npm audit |
Full index: [docs/README.md](docs/README.md).
diff --git a/docs/README.md b/docs/README.md
index b865864..363f6a0 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -9,6 +9,7 @@ instructions are in the root [README](../README.md).
| [RDP credentials](rdp-credentials.md) | Contributors, security review | CredSSP exception: password lifetime, logging, residual risk |
| [IME composition](ime-composition.md) | Contributors | CJK IME candidate positioning — known limitation and fix plan |
| [Winget publishing](winget.md) | Maintainers | First-time and automated Windows package updates |
+| [Security](security.md) | Users, maintainers, IT | Signing status (cert pending), SmartScreen/VirusTotal, npm audit, reporting |
Product scope, roadmap, and milestones are in [PRD.md](../PRD.md). Release
history is in [CHANGELOG.md](../CHANGELOG.md).
diff --git a/docs/security.md b/docs/security.md
new file mode 100644
index 0000000..5bbc3e2
--- /dev/null
+++ b/docs/security.md
@@ -0,0 +1,105 @@
+# Security
+
+CloudTerm holds SSH keys, passwords, and live server sessions. This page
+covers distribution trust (SmartScreen, VirusTotal), dependency hygiene, and
+where to report issues.
+
+## Code signing status
+
+| Item | Status |
+|------|--------|
+| Windows Authenticode certificate | **Pending procurement** |
+| macOS Developer ID certificate | **Not started** (Windows first) |
+| CI signing wiring (`release.yml`) | **Ready** — signs automatically once secrets are set |
+| Current release builds | **Unsigned** |
+
+A Windows code-signing certificate is being procured. Until `WIN_CSC_LINK` and
+`WIN_CSC_KEY_PASSWORD` are added as repository secrets, tagged releases continue
+to ship unsigned installers and portable executables. See [Enabling code signing in CI](#enabling-code-signing-in-ci) below for the steps once the certificate arrives.
+
+## VirusTotal and SmartScreen (unsigned builds)
+
+Release builds are **not code-signed today** (certificate pending). On Windows that means:
+
+- **SmartScreen** may warn on first download ("Windows protected your PC").
+- **VirusTotal** and some enterprise scanners may flag the portable exe
+ (`CloudTerm-x64.exe`) or the NSIS installer with heuristic detections
+ (often 1–3 vendors out of 60+). This is common for unsigned Electron apps
+ packaged with NSIS; it does not mean the published GitHub release binary
+ contains malware.
+
+What actually reduces those warnings:
+
+1. **Authenticode signing** — sign the app binary and the installer with an
+ Extended Validation or standard code-signing certificate.
+2. **Reputation** — signed builds gain SmartScreen reputation over time as
+ more users install them.
+3. **False-positive review** — submit the file hash to vendors that flagged it
+ for whitelisting (use the full VirusTotal report to see which engines).
+
+### Enabling code signing in CI
+
+**Prerequisite:** a code-signing certificate must be procured and converted to
+the secrets below. Windows certificate procurement is **in progress**; macOS
+Developer ID is planned after Windows.
+
+When repository secrets are configured, [release.yml](../.github/workflows/release.yml)
+passes them to electron-builder:
+
+| Secret | Platform | Purpose |
+|--------|----------|---------|
+| `WIN_CSC_LINK` | Windows | Base64-encoded `.pfx` or path to cert |
+| `WIN_CSC_KEY_PASSWORD` | Windows | PFX password |
+| `CSC_LINK` | macOS | Developer ID Application cert (`.p12`) |
+| `CSC_KEY_PASSWORD` | macOS | P12 password |
+
+Obtain certificates from a public CA (e.g. DigiCert, Sectigo). Store the PFX
+as base64:
+
+```powershell
+[Convert]::ToBase64String([IO.File]::ReadAllBytes('cloudterm.pfx')) | Set-Clipboard
+```
+
+Paste the result into `WIN_CSC_LINK`. After the next tagged release, installers
+and the portable exe are signed automatically.
+
+Unsigned builds continue to work when these secrets are absent.
+
+## npm dependencies
+
+CI runs `npm audit --omit=dev --audit-level=high` on every pull request and
+push to `main`. That checks **production** dependencies only — the libraries
+shipped inside the packaged app.
+
+Dev-only tools (Vite, esbuild, electron-builder) may still show advisories
+locally when you run `npm audit` without `--omit=dev`. Those affect the
+development server, not end users.
+
+To refresh production deps after an advisory:
+
+```bash
+npm audit fix
+npm audit --omit=dev
+npm test
+```
+
+## Application security model (summary)
+
+| Area | Behaviour |
+|------|-----------|
+| Renderer | Sandboxed; no Node integration; context isolation |
+| Secrets | Passwords and keys stay in the main process; vault lock blocks sensitive IPC |
+| RDP | Password cleared from renderer after CredSSP — see [rdp-credentials.md](rdp-credentials.md) |
+| Assistant | Default approval mode asks before mutating tools — see [assistant-approvals.md](assistant-approvals.md) |
+| External links | Only `http:` and `https:` via `open-external` IPC |
+| Updates | Auto-install only when platform signature checks apply; unsigned mac builds use notify-only mode |
+| BMC webview | Guest pages sandboxed; only `http(s)` in `bmc-*` partitions |
+
+## Reporting a vulnerability
+
+Open a [GitHub Security Advisory](https://github.com/BradPerbs/cloudterm/security/advisories/new)
+or email the maintainers listed in the repository. Include steps to reproduce
+and affected version.
+
+Do **not** file public issues for undisclosed credential theft or RCE paths
+before a fix is available.
diff --git a/docs/winget.md b/docs/winget.md
index 5b8618a..8c71f8b 100644
--- a/docs/winget.md
+++ b/docs/winget.md
@@ -97,10 +97,12 @@ may come back with questions on the pull request itself.
Two things that come up:
-- The installer is not code signed. That is allowed, and plenty of packages in
- winget are the same, but SmartScreen and occasionally the pipeline's own
- scanner have opinions about unsigned installers and the review can stall on
- it. Reply on the pull request if it does.
+- The installer is not code signed (**Windows certificate pending procurement**).
+ CI is wired to sign automatically once `WIN_CSC_LINK` is configured — see
+ [security.md](security.md). That is allowed in winget, and plenty of packages
+ are the same, but SmartScreen and occasionally the pipeline's own scanner
+ have opinions about unsigned installers and the review can stall on it. Reply
+ on the pull request if it does.
- The publisher name has to be one you can claim. `CloudBlast` is fine here.
It is also permanent in practice: the identifier is the directory name, the
thing people type, and what every already-installed copy is matched against,
diff --git a/package-lock.json b/package-lock.json
index 40b1082..477b9f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cloudblast-ssh",
- "version": "1.0.0",
+ "version": "1.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cloudblast-ssh",
- "version": "1.0.0",
+ "version": "1.3.0",
"hasInstallScript": true,
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
@@ -43,7 +43,7 @@
"patch-package": "^8.0.1",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17",
- "vite": "^5.0.12",
+ "vite": "^5.4.21",
"wait-on": "^7.2.0"
}
},
@@ -201,13 +201,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
- "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/helper-validator-identifier": "^7.29.7",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
@@ -216,9 +216,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
- "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -226,21 +226,21 @@
}
},
"node_modules/@babel/core": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
- "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/generator": "^7.28.6",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -257,14 +257,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
- "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -274,14 +274,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -308,9 +308,9 @@
"license": "ISC"
},
"node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -318,29 +318,29 @@
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -360,9 +360,9 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -370,9 +370,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -380,9 +380,9 @@
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -390,27 +390,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
- "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
- "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.6"
+ "@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -461,33 +461,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
- "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
+ "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/generator": "^7.28.6",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.28.6",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.8",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
"debug": "^4.3.1"
},
"engines": {
@@ -495,14 +495,14 @@
}
},
"node_modules/@babel/types": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
- "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -535,10 +535,11 @@
}
},
"node_modules/@electron/asar/node_modules/brace-expansion": {
- "version": "1.1.16",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz",
- "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -965,9 +966,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
"cpu": [
"ppc64"
],
@@ -978,13 +979,13 @@
"aix"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
"cpu": [
"arm"
],
@@ -995,13 +996,13 @@
"android"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
"cpu": [
"arm64"
],
@@ -1012,13 +1013,13 @@
"android"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
"cpu": [
"x64"
],
@@ -1029,13 +1030,13 @@
"android"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
"cpu": [
"arm64"
],
@@ -1046,13 +1047,13 @@
"darwin"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
"cpu": [
"x64"
],
@@ -1063,13 +1064,13 @@
"darwin"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
"cpu": [
"arm64"
],
@@ -1080,13 +1081,13 @@
"freebsd"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
"cpu": [
"x64"
],
@@ -1097,13 +1098,13 @@
"freebsd"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
"cpu": [
"arm"
],
@@ -1114,13 +1115,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
"cpu": [
"arm64"
],
@@ -1131,13 +1132,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
"cpu": [
"ia32"
],
@@ -1148,13 +1149,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
"cpu": [
"loong64"
],
@@ -1165,13 +1166,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
"cpu": [
"mips64el"
],
@@ -1182,13 +1183,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
"cpu": [
"ppc64"
],
@@ -1199,13 +1200,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
"cpu": [
"riscv64"
],
@@ -1216,13 +1217,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
"cpu": [
"s390x"
],
@@ -1233,13 +1234,13 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
"cpu": [
"x64"
],
@@ -1250,13 +1251,30 @@
"linux"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
"cpu": [
"x64"
],
@@ -1267,13 +1285,30 @@
"netbsd"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
"cpu": [
"x64"
],
@@ -1284,13 +1319,30 @@
"openbsd"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
"cpu": [
"x64"
],
@@ -1301,13 +1353,13 @@
"sunos"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
"cpu": [
"arm64"
],
@@ -1318,13 +1370,13 @@
"win32"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
"cpu": [
"ia32"
],
@@ -1335,13 +1387,13 @@
"win32"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
"cpu": [
"x64"
],
@@ -1352,7 +1404,7 @@
"win32"
],
"engines": {
- "node": ">=12"
+ "node": ">=18"
}
},
"node_modules/@fontsource/inter": {
@@ -1576,6 +1628,26 @@
}
}
},
+ "node_modules/@napi-rs/lzma-linux-x64-gnu": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
+ "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^22.20 || ^24.12 || >=25"
+ }
+ },
"node_modules/@noble/hashes": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz",
@@ -1822,9 +1894,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz",
- "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz",
+ "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==",
"cpu": [
"arm"
],
@@ -1836,9 +1908,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz",
- "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz",
+ "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==",
"cpu": [
"arm64"
],
@@ -1850,9 +1922,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz",
- "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz",
+ "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==",
"cpu": [
"arm64"
],
@@ -1864,9 +1936,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz",
- "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz",
+ "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==",
"cpu": [
"x64"
],
@@ -1878,9 +1950,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz",
- "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz",
+ "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==",
"cpu": [
"arm64"
],
@@ -1892,9 +1964,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz",
- "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz",
+ "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==",
"cpu": [
"x64"
],
@@ -1906,13 +1978,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz",
- "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz",
+ "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==",
"cpu": [
"arm"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1920,13 +1995,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz",
- "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz",
+ "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==",
"cpu": [
"arm"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1934,13 +2012,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz",
- "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz",
+ "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1948,13 +2029,16 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz",
- "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz",
+ "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==",
"cpu": [
"arm64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1962,13 +2046,16 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz",
- "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz",
+ "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==",
"cpu": [
"loong64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1976,13 +2063,16 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz",
- "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz",
+ "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==",
"cpu": [
"loong64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1990,13 +2080,16 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz",
- "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz",
+ "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==",
"cpu": [
"ppc64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2004,13 +2097,16 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz",
- "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz",
+ "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==",
"cpu": [
"ppc64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2018,13 +2114,16 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz",
- "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz",
+ "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==",
"cpu": [
"riscv64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2032,13 +2131,16 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz",
- "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz",
+ "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==",
"cpu": [
"riscv64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2046,13 +2148,16 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz",
- "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz",
+ "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==",
"cpu": [
"s390x"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2060,13 +2165,16 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz",
- "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz",
+ "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2074,13 +2182,16 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz",
- "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz",
+ "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==",
"cpu": [
"x64"
],
"dev": true,
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -2088,9 +2199,9 @@
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz",
- "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz",
+ "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==",
"cpu": [
"x64"
],
@@ -2102,9 +2213,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz",
- "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz",
+ "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==",
"cpu": [
"arm64"
],
@@ -2116,9 +2227,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz",
- "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz",
+ "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==",
"cpu": [
"arm64"
],
@@ -2130,9 +2241,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz",
- "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz",
+ "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==",
"cpu": [
"ia32"
],
@@ -2144,9 +2255,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz",
- "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz",
+ "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==",
"cpu": [
"x64"
],
@@ -2158,9 +2269,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz",
- "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz",
+ "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==",
"cpu": [
"x64"
],
@@ -2526,9 +2637,9 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"dev": true,
"license": "MIT"
},
@@ -2694,6 +2805,19 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
"node_modules/ajv": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
@@ -2882,10 +3006,11 @@
}
},
"node_modules/app-builder-lib/node_modules/brace-expansion": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz",
- "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
@@ -3151,15 +3276,16 @@
"dev": true
},
"node_modules/axios": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.3.tgz",
- "integrity": "sha512-ERT8kdX7DZjtUm7IitEyV7InTHAF42iJuMArIiDIV5YtPanJkgw4hw5Dyg9fh0mihdWNn1GKaeIWErfe56UQ1g==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz",
+ "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.4",
- "proxy-from-env": "^1.1.0"
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.6",
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
}
},
"node_modules/balanced-match": {
@@ -3272,9 +3398,9 @@
"optional": true
},
"node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
+ "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3701,15 +3827,15 @@
"license": "MIT"
},
"node_modules/concurrently": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
- "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==",
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.4.tgz",
+ "integrity": "sha512-TZ0CEhyzvFjgtAvHTusDMgj7wNdihCh7LLLrzdUOXIhdlnL2JBBGA9eJxR24rtqgmdjh3OA3hrN1rCHj6HM8qA==",
"dev": true,
"license": "MIT",
"dependencies": {
"chalk": "4.1.2",
"rxjs": "7.8.2",
- "shell-quote": "1.8.3",
+ "shell-quote": "1.9.0",
"supports-color": "8.1.1",
"tree-kill": "1.2.2",
"yargs": "17.7.2"
@@ -3995,10 +4121,11 @@
}
},
"node_modules/dir-compare/node_modules/brace-expansion": {
- "version": "1.1.16",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz",
- "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4407,9 +4534,9 @@
"optional": true
},
"node_modules/esbuild": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -4417,32 +4544,35 @@
"esbuild": "bin/esbuild"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
}
},
"node_modules/escalade": {
@@ -4632,9 +4762,9 @@
"peer": true
},
"node_modules/fast-uri": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
- "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
"funding": [
{
"type": "github",
@@ -4644,7 +4774,8 @@
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
- ]
+ ],
+ "license": "BSD-3-Clause"
},
"node_modules/fastq": {
"version": "1.20.1",
@@ -4708,9 +4839,9 @@
}
},
"node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"dev": true,
"funding": [
{
@@ -4729,17 +4860,17 @@
}
},
"node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
@@ -4928,9 +5059,9 @@
}
},
"node_modules/glob/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4939,9 +5070,9 @@
}
},
"node_modules/glob/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5103,9 +5234,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -5115,9 +5246,10 @@
}
},
"node_modules/hono": {
- "version": "4.12.32",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.32.tgz",
- "integrity": "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==",
+ "version": "4.13.1",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz",
+ "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==",
+ "license": "MIT",
"engines": {
"node": ">=16.9.0"
}
@@ -5174,6 +5306,20 @@
"node": ">=10.19.0"
}
},
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/hugeicons-react": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/hugeicons-react/-/hugeicons-react-0.4.0.tgz",
@@ -5397,9 +5543,9 @@
}
},
"node_modules/joi": {
- "version": "17.13.3",
- "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
- "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==",
+ "version": "17.13.4",
+ "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.4.tgz",
+ "integrity": "sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -5425,9 +5571,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
- "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
+ "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"funding": [
{
"type": "github",
@@ -5438,6 +5584,7 @@
"url": "https://github.com/sponsors/nodeca"
}
],
+ "license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -5598,9 +5745,9 @@
"license": "MIT"
},
"node_modules/lodash": {
- "version": "4.17.23",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
- "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
@@ -5764,9 +5911,9 @@
}
},
"node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5812,9 +5959,9 @@
"optional": true
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"dev": true,
"funding": [
{
@@ -6110,9 +6257,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6194,9 +6341,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"dev": true,
"funding": [
{
@@ -6214,7 +6361,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.17",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -6439,11 +6586,14 @@
}
},
"node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/pump": {
"version": "3.0.3",
@@ -6752,13 +6902,13 @@
}
},
"node_modules/rollup": {
- "version": "4.56.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz",
- "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==",
+ "version": "4.62.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz",
+ "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/estree": "1.0.8"
+ "@types/estree": "1.0.9"
},
"bin": {
"rollup": "dist/bin/rollup"
@@ -6768,31 +6918,32 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.56.0",
- "@rollup/rollup-android-arm64": "4.56.0",
- "@rollup/rollup-darwin-arm64": "4.56.0",
- "@rollup/rollup-darwin-x64": "4.56.0",
- "@rollup/rollup-freebsd-arm64": "4.56.0",
- "@rollup/rollup-freebsd-x64": "4.56.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.56.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.56.0",
- "@rollup/rollup-linux-arm64-gnu": "4.56.0",
- "@rollup/rollup-linux-arm64-musl": "4.56.0",
- "@rollup/rollup-linux-loong64-gnu": "4.56.0",
- "@rollup/rollup-linux-loong64-musl": "4.56.0",
- "@rollup/rollup-linux-ppc64-gnu": "4.56.0",
- "@rollup/rollup-linux-ppc64-musl": "4.56.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.56.0",
- "@rollup/rollup-linux-riscv64-musl": "4.56.0",
- "@rollup/rollup-linux-s390x-gnu": "4.56.0",
- "@rollup/rollup-linux-x64-gnu": "4.56.0",
- "@rollup/rollup-linux-x64-musl": "4.56.0",
- "@rollup/rollup-openbsd-x64": "4.56.0",
- "@rollup/rollup-openharmony-arm64": "4.56.0",
- "@rollup/rollup-win32-arm64-msvc": "4.56.0",
- "@rollup/rollup-win32-ia32-msvc": "4.56.0",
- "@rollup/rollup-win32-x64-gnu": "4.56.0",
- "@rollup/rollup-win32-x64-msvc": "4.56.0",
+ "@napi-rs/lzma-linux-x64-gnu": "1.5.1",
+ "@rollup/rollup-android-arm-eabi": "4.62.4",
+ "@rollup/rollup-android-arm64": "4.62.4",
+ "@rollup/rollup-darwin-arm64": "4.62.4",
+ "@rollup/rollup-darwin-x64": "4.62.4",
+ "@rollup/rollup-freebsd-arm64": "4.62.4",
+ "@rollup/rollup-freebsd-x64": "4.62.4",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.4",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.4",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.4",
+ "@rollup/rollup-linux-arm64-musl": "4.62.4",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.4",
+ "@rollup/rollup-linux-loong64-musl": "4.62.4",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.4",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.4",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.4",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.4",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.4",
+ "@rollup/rollup-linux-x64-gnu": "4.62.4",
+ "@rollup/rollup-linux-x64-musl": "4.62.4",
+ "@rollup/rollup-openbsd-x64": "4.62.4",
+ "@rollup/rollup-openharmony-arm64": "4.62.4",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.4",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.4",
+ "@rollup/rollup-win32-x64-gnu": "4.62.4",
+ "@rollup/rollup-win32-x64-msvc": "4.62.4",
"fsevents": "~2.3.2"
}
},
@@ -7068,9 +7219,9 @@
}
},
"node_modules/shell-quote": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
- "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz",
+ "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7539,9 +7690,9 @@
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7991,9 +8142,9 @@
"license": "ISC"
},
"node_modules/yaml": {
- "version": "2.8.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
- "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
"dev": true,
"license": "ISC",
"bin": {
diff --git a/package.json b/package.json
index 840b284..0cb7d46 100644
--- a/package.json
+++ b/package.json
@@ -172,7 +172,7 @@
"patch-package": "^8.0.1",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17",
- "vite": "^5.0.12",
+ "vite": "^5.4.21",
"wait-on": "^7.2.0"
},
"dependencies": {
@@ -199,5 +199,8 @@
"ssh2": "^1.15.0",
"ws": "^8.21.1",
"zod": "^4.0.0"
+ },
+ "overrides": {
+ "esbuild": "^0.25.0"
}
}
diff --git a/src/renderer/components/assistant/AssistantPanel.jsx b/src/renderer/components/assistant/AssistantPanel.jsx
index 4264ee4..246e955 100644
--- a/src/renderer/components/assistant/AssistantPanel.jsx
+++ b/src/renderer/components/assistant/AssistantPanel.jsx
@@ -716,7 +716,8 @@ function AssistantConversation({
>
);
}
- *
+
+/**
* One element that changes width, not two swapped for each other: a swap has
* nothing to animate between, and the rail is the same column with everything
* but the button clipped off. That is how the sidebar opens on the other side
From 8e11a913876982bf011ddd9920733b1a734aedad Mon Sep 17 00:00:00 2001
From: Kyros Koh
Date: Thu, 13 Aug 2026 10:45:10 +0800
Subject: [PATCH 6/6] Address CodeRabbit review on M1 trust gates.
Harden CI credentials, unique session logs, strict approval acknowledgement, and restore localized approval UI before upstream merge.
Fixes #5
Fixes #6
Fixes #8
Addresses #7
---
.github/workflows/ci.yml | 3 +
.gitignore | 3 +
CHANGELOG.md | 7 +-
PRD.md | 241 ------------------
README.es.md | 7 +-
README.md | 7 +-
README.ru.md | 9 +-
README.zh-CN.md | 2 +-
docs/assistant-approvals.md | 6 +-
src/main/ai/settings.js | 4 +-
src/main/session-log.js | 24 +-
.../components/assistant/ApprovalMenu.jsx | 27 +-
.../components/assistant/AssistantPanel.jsx | 14 +-
src/renderer/i18n/locales/en.js | 13 +-
src/renderer/i18n/locales/pt.js | 11 +-
src/renderer/i18n/locales/ru.js | 11 +-
src/renderer/i18n/locales/vi.js | 11 +-
src/renderer/i18n/locales/zh.js | 12 +-
test/assistant-approval.test.js | 13 +-
test/session-log.test.js | 16 +-
20 files changed, 147 insertions(+), 294 deletions(-)
delete mode 100644 PRD.md
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 925825f..e638952 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,6 +18,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ # PR code runs npm ci / npm test; do not leave GITHUB_TOKEN in git config.
+ persist-credentials: false
- uses: actions/setup-node@v4
with:
diff --git a/.gitignore b/.gitignore
index 3510368..3a89e5e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,6 @@ releases/
# Local working notes and agent config, not part of the project
CLAUDE.md
.claude/
+
+# Local product planning notes; keep out of the shared tree
+PRD.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2528efb..ff7fce1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,8 +29,11 @@ with [GitHub Releases](https://github.com/BradPerbs/cloudterm/releases).
### Fixed
-- Session log transcript files are opened synchronously in `start()` so
- retention tests (and immediate `utime`) do not race the path.
+- Session log transcript files use a unique exclusive path per session so two
+ tabs in the same second cannot interleave into one file.
+- First-run approval warning only clears after **Got it** (not Escape / backdrop).
+- Assistant approval acknowledgement accepts only real booleans when loading
+ `assistant.json`.
## [1.3.0] - 2026-08-10
diff --git a/PRD.md b/PRD.md
deleted file mode 100644
index bed35da..0000000
--- a/PRD.md
+++ /dev/null
@@ -1,241 +0,0 @@
-# CloudTerm — Product Requirements Document
-
-| Field | Value |
-|-------|-------|
-| **Product** | CloudTerm |
-| **Owner** | CloudBlast |
-| **Version covered** | 1.3.0 (as shipped) |
-| **Status** | Living document — current product + next roadmap |
-| **License** | Fair-code (free to use/modify/share; commercial resale needs a CloudBlast license) |
-| **Repo** | https://github.com/BradPerbs/cloudterm |
-
----
-
-## 1. Vision
-
-CloudTerm is a **desktop multi-protocol terminal workspace**: one window for SSH, SFTP, Telnet, serial, RDP, VNC, and BMC/IPMI, with encrypted local vault storage, optional CloudBlast cloud sync, and a local AI agent that can act through live sessions (with approval).
-
-**North star:** Replace tool sprawl (PuTTY + WinSCP + RDP client + VNC + serial terminal + snippet managers) with a single, trustworthy, modern app that travels with the user’s setup across machines.
-
----
-
-## 2. Problem
-
-| Pain | Today without CloudTerm |
-|------|-------------------------|
-| Tool sprawl | Separate apps per protocol; repeated logins and context switching |
-| Setup doesn’t travel | Hosts, keys, snippets, known hosts differ per laptop |
-| AI is paste-driven | Assistants don’t see the live terminal; users copy/paste riskily |
-| CloudBlast customers | Manually re-enter VPS details instead of seeing servers ready to connect |
-
----
-
-## 3. Goals & non-goals
-
-### Goals
-
-1. **One workspace** for every common remote-access protocol on Windows, macOS, and Linux.
-2. **Secrets stay local** — vault-locked encrypted storage; cloud sync encrypts before upload.
-3. **CloudBlast differentiation** — free encrypted sync for everyone; auto host list for CloudBlast VPS customers.
-4. **Session-aware AI** — local CLIs (Claude Code / Codex / OpenCode) with approval gates; no credential tools.
-5. **Trustworthy distribution** — signed installs, predictable updates, clear fair-code terms.
-
-### Non-goals (near term)
-
-- Becoming a full IDE or browser-based terminal SaaS
-- Replacing enterprise PAM / jump-box products
-- Storing plaintext credentials in the cloud
-- Shipping AI that can extract or export vault secrets
-- Guaranteeing recovery if the vault password is forgotten
-
----
-
-## 4. Personas
-
-| Persona | Needs | Success looks like |
-|---------|--------|-------------------|
-| **Sysadmin / SRE** | Many hosts, jump hosts, tunnels, monitoring | Folders/tags/search; reconnect; uptime checks; activity log |
-| **Developer** | SSH + SFTP + occasional RDP/VNC | Fast connect, split panes, snippets, remote edit |
-| **CloudBlast customer** | Servers appear without manual entry | Sign in → VPS hosts ready |
-| **Multi-machine user** | Same setup on laptop + desktop | Encrypted cloud snapshot restore on sign-in |
-| **AI-assisted operator** | Agent reads session and runs approved commands | Clear approval UX; safe defaults |
-
----
-
-## 5. Current product (v1.3)
-
-### 5.1 User-facing capabilities
-
-| Area | Capability |
-|------|------------|
-| **Sessions** | SSH, Telnet, serial; jump hosts; SOCKS/HTTP proxies; tabs & split panes (max 8); themes; find; broadcast; screenshots; session log |
-| **Files** | SFTP (list/mkdir/delete/rename, transfers, resume, conflicts, drag-and-drop); remote edit → upload on save |
-| **Networking** | Local / remote / dynamic port forwarding with traffic counters |
-| **Desktops** | RDP (IronRDP WASM), VNC (noVNC, SSH-tunnelled), BMC/IPMI web UI (sandboxed webview + auto-login) |
-| **Inventory** | Hosts, folders, tags, search, quick-connect; keychain (generate/import, Windows Hello/TPM); snippets with `{{placeholders}}` |
-| **Import** | `~/.ssh/config`, PuTTY, MobaXterm |
-| **Security** | App lock / vault (password or OS keystore); encrypted backup export/restore |
-| **Cloud** | CloudBlast OAuth (PKCE, system browser); VPS server sync; encrypted cross-device snapshot |
-| **Ops** | Host TCP monitoring + notifications; activity log; auto-update from GitHub Releases (winget on Windows) |
-| **AI** | Claude Code / Codex / OpenCode; tools: hosts, sessions, terminal read/write, files, connect/disconnect — approval modes |
-| **i18n** | In-app: en, zh, vi, pt, ru (README also offers Español — see gap below) |
-
-### 5.2 Architecture (summary)
-
-```
-Renderer (React + xterm / IronRDP / noVNC)
- ↕ IPC + MessagePort (session bytes)
-Main (Electron): store, vault, transport (ssh|telnet|serial),
- sftp, tunnels, rdp, vnc, bmc, account, AI, monitor
-```
-
-- **Security defaults:** `contextIsolation`, no `nodeIntegration`, `sandbox`; secrets resolved in main; vault lock gates IPC.
-- **Persistence:** `sessions.json`, `vault.json`, window state, cloud snapshot under Electron `userData`; UI prefs in `localStorage`.
-
-### 5.3 Platforms & distribution
-
-| Channel | Notes |
-|---------|--------|
-| GitHub Releases | NSIS + portable (Win), DMG/zip (macOS), AppImage (Linux) |
-| winget | `CloudBlast.CloudTerm` — see `docs/winget.md` |
-| Signing | **Not code-signed today** — SmartScreen / enterprise friction |
-
----
-
-## 6. Requirements
-
-### 6.1 Functional (must remain true)
-
-| ID | Requirement |
-|----|-------------|
-| F1 | User can open SSH / Telnet / serial sessions from a host record without leaving the app |
-| F2 | Credentials and private keys never leave the main process (RDP CredSSP path is the documented exception) |
-| F3 | Vault lock blocks sensitive IPC until unlocked |
-| F4 | SFTP and tunnels can reuse an active SSH connection |
-| F5 | Cloud snapshot is encrypted client-side before upload |
-| F6 | AI cannot read vault secrets; destructive/session-changing tools require approval unless user opts into a looser mode |
-| F7 | Auto-update can be disabled (`CLOUDBLAST_UPDATE_DISABLED`) for air-gapped use |
-
-### 6.2 Non-functional
-
-| ID | Requirement | Current gap |
-|----|-------------|-------------|
-| N1 | PR builds run automated tests | **Shipped (M1):** `.github/workflows/ci.yml` on PRs and `main` |
-| N2 | Installers code-signed on Windows (and ideally macOS) | Unsigned |
-| N3 | Core paths (SSH connect, SFTP, lock/unlock) covered by automated smoke | Unit tests only; no E2E |
-| N4 | Cold start acceptable for SSH-only users | RDP/VNC/WASM always in bundle weight |
-| N5 | CJK IME composition usable in terminal | Known limitation — documented in `docs/ime-composition.md`; fix tracked in #7 |
-| N6 | Marketing locales match in-app locales | Spanish README without in-app `es` |
-
----
-
-## 7. Success metrics (suggested)
-
-| Metric | Target (directional) |
-|--------|----------------------|
-| Crash-free sessions / week | Track via optional anonymous telemetry later; start with GitHub issue rate |
-| Time-to-first-connect (fresh install → SSH) | < 2 minutes with import or CloudBlast sync |
-| Update adoption (7-day) | Majority on latest within a week of release (post-signing) |
-| Test gate | `npm test` green on every PR before merge |
-| AI incident rate | Near-zero reports of unexpected `run_command` without approval on default settings |
-
----
-
-## 8. Roadmap — bugs, enhancements, optimizations
-
-Priorities: **P0** ship-blocking / trust / safety · **P1** product quality · **P2** polish & scale.
-
-### 8.1 Bug fixes & reliability (P0–P1)
-
-| Priority | Item | Rationale | Notes |
-|----------|------|-----------|-------|
-| **P0** | Add CI workflow that runs `npm test` on PRs | Regressions can ship with release-only CI | **Done** — `.github/workflows/ci.yml` |
-| **P0** | Harden AI approval defaults + first-run warning | “Never ask” + `run_command` is high risk | **Done** — default `writes`, warning, confirm for `never`; see `docs/assistant-approvals.md` |
-| **P0** | Audit RDP password lifetime in renderer/WASM | Documented secret exception | **Done** — see `docs/rdp-credentials.md`; tests in `test/rdp.test.js` |
-| **P0** | Fix or quarantine IME composition positioning | Blocks CJK users; zh locale is shipped | **Quarantined (M1)** — `docs/ime-composition.md`; #7 open |
-| **P1** | Session restore reconnect policy | Tabs restore without live sockets | Explicit “reconnect all” or per-tab option |
-| **P1** | Update download UX | `autoDownload = true` may surprise corporate users | Optional “ask before download” |
-| **P1** | Align Spanish: add `es` locale **or** remove es README until ready | Docs/product mismatch | |
-
-### 8.2 Enhancements (P1–P2)
-
-| Priority | Item | Rationale |
-|----------|------|-----------|
-| **P1** | Code-sign Windows (and ideally macOS) builds | SmartScreen, winget, enterprise adoption |
-| **P1** | Split oversized modules (`ipc.js`, `store.js`, `App.jsx`, `TerminalView.jsx`) by domain | Safer reviews; fewer regressions |
-| **P1** | E2E smoke: mock SSH → SFTP → lock/unlock | Catch IPC/UI wiring unit tests miss |
-| **P1** | SSH/SFTP integration tests (container or mock) | Core path under-tested vs edge protocols |
-| **P1** | True 1024² app icon (replace upscaled soft cloud) | Documented in `resources/README.md` |
-| **P1** | Rename npm package / clarify branding (`cloudblast-ssh` → `cloudterm`) | Contributor & packaging clarity |
-| **P2** | Accessibility pass on dialogs + terminal chrome | Enterprise procurement |
-| **P2** | Portable winget package parity | Mentioned as future in `docs/winget.md` |
-| **P2** | Document env vars & `userData` layout under `docs/` | Support / IT / contributors |
-| **P2** | Gradual TypeScript on `store` / `vault` / `ai/tools` | Catch IPC/secret-field shape bugs |
-
-### 8.3 Optimizations (P2)
-
-| Priority | Item | Rationale |
-|----------|------|-----------|
-| **P2** | Lazy-load RDP / VNC / noVNC chunks | Faster cold start for SSH-only users |
-| **P2** | Cap / paginate activity & AI event retention more aggressively | Long-lived processes; large event buffers |
-| **P2** | Parallelize `npm test` (today sequential `&&`) | Faster local + CI feedback |
-| **P2** | Profile WebGL terminals under multi-pane load | Cap is 8 panes; validate GPU cost |
-
-### 8.4 Explicitly out of scope for this PRD cycle
-
-- Vault password recovery without user-held secret
-- Server-side decryption of cloud snapshots
-- AI tools that return private keys or vault DEK material
-
----
-
-## 9. Security & threat notes (product constraints)
-
-| Topic | Stance |
-|-------|--------|
-| Vault | Protects against disk theft; forgotten password = data unrecoverable by design |
-| Cloud snapshot | Protects DB theft in transit/at rest; **not** a compromised CloudBlast app server acting as a malicious client |
-| AI | Local CLIs under user accounts; approval modes are the control plane |
-| BMC webview | Sandboxed but still untrusted vendor JS on LAN — treat as higher risk surface |
-| RDP | Password must reach WASM for CredSSP — minimize lifetime and logging |
-| OAuth | System browser + PKCE; client id `cloudblast-desktop` |
-
----
-
-## 10. Milestones (suggested)
-
-| Milestone | Scope | Exit criteria |
-|-----------|--------|---------------|
-| **M1 — Trust & gates** | PR CI for tests; AI default hardening; RDP password audit; IME fix plan | **Shipped** — CI on PRs; safer AI defaults; RDP docs + tests; IME quarantined in `docs/ime-composition.md` |
-| **M2 — Distribution** | Code signing; icon quality; optional update consent | Signed Win (+ mac if feasible); reduced SmartScreen friction |
-| **M3 — Quality depth** | Module splits; E2E smoke; SSH/SFTP integration tests | Reviewable IPC surfaces; smoke green in CI |
-| **M4 — Polish** | Locale alignment; lazy-load remoting; docs for env/`userData`; a11y pass | Marketing ↔ app parity; measurable startup win |
-
----
-
-## 11. Open questions
-
-1. Should cloud sync remain forever-free for non-CloudBlast users, or become tiered later?
-2. Is code signing budgeted for Windows only first, or Win+mac together?
-3. Should “never ask” AI mode remain available, or be removed / hidden behind an advanced unlock?
-4. Telemetry: opt-in crash/usage metrics, or stay fully silent?
-5. Rename `appId` / package name in a major version, or keep `com.cloudblast.ssh` for upgrade continuity?
-
----
-
-## 12. References
-
-| Doc | Path / URL |
-|-----|------------|
-| User README | `README.md` (+ zh-CN, es, ru) |
-| Changelog | `CHANGELOG.md` |
-| Contributor docs | `docs/README.md` |
-| Winget publish | `docs/winget.md` |
-| Resources / icon notes | `resources/README.md` |
-| License | `LICENSE` |
-| Product site | https://cloudblast.io |
-
----
-
-*This PRD describes the product as of v1.3.0 plus the M1 trust-and-gates
-work on `feat/m1-trust-gates`. Update milestones when releases ship.*
diff --git a/README.es.md b/README.es.md
index 666534f..5ab225d 100644
--- a/README.es.md
+++ b/README.es.md
@@ -121,9 +121,10 @@ para leerlo y modificarlo.
- **Trabaja en el terminal que ves**: los comandos se escriben en el panel y la
salida se queda en tu historial, o se ejecutan en un canal oculto si lo
prefieres
-- **Pregunta antes de cambiar nada** — tres modos de aprobación (cada
- herramienta / solo cambios / nunca), aviso al primer uso y confirmación antes
- de **Nunca preguntar**. Ver [docs/assistant-approvals.md](docs/assistant-approvals.md) (inglés)
+- **Los modos de aprobación controlan cuándo pregunta** — cada herramienta /
+ solo cambios / nunca (nunca auto-aprueba herramientas no bloqueadas), aviso
+ al primer uso y confirmación antes de **Nunca preguntar**. Ver
+ [docs/assistant-approvals.md](docs/assistant-approvals.md) (inglés)
- **Apuntado donde tú digas**: la sesión que tienes delante, una que fijes, o
todos los hosts que tengas guardados
- **Herramientas en vez de suposiciones**: conectar un host guardado, leer y
diff --git a/README.md b/README.md
index ea02115..e4596f4 100644
--- a/README.md
+++ b/README.md
@@ -137,9 +137,10 @@ Whichever you choose, the agent:
one it answers, without you pasting anything
- **Works in the terminal you can see**: commands are typed into the pane and
the output stays in your scrollback, or run on a hidden channel if you prefer
-- **Asks before it changes anything** — three approval modes (every tool /
- changes only / never), a first-run warning, and a confirm step before
- **Never ask**. See [assistant approvals](docs/assistant-approvals.md).
+- **Approval modes control when it asks** — every tool / changes only / never
+ (never auto-approves non-blocked tools), plus a first-run warning and a
+ confirm step before **Never ask**. See
+ [assistant approvals](docs/assistant-approvals.md).
- **Pointed where you like**: the session in front, one you pin, or every host
you have saved
- **Tools instead of guesses**: connect a saved host, read and write files,
diff --git a/README.ru.md b/README.ru.md
index 15d5f16..4561cb8 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -121,10 +121,11 @@ CloudTerm собирает все способы подключения к се
- **Работает в терминале, который вы видите**: команды печатаются в панели, а
вывод остаётся в вашем буфере. Или выполняются в скрытом канале, если так
удобнее
-- **Спрашивает, прежде чем что-то менять** — три режима одобрения (каждый
- инструмент / только изменения / никогда), предупреждение при первом запуске и
- подтверждение перед **Никогда не спрашивать**. См.
- [docs/assistant-approvals.md](docs/assistant-approvals.md) (англ.)
+- **Режим одобрения решает, когда спрашивать** — каждый инструмент / только
+ изменения / никогда (никогда само одобряет незаблокированные инструменты),
+ предупреждение при первом запуске и подтверждение перед **Никогда не
+ спрашивать**. См. [docs/assistant-approvals.md](docs/assistant-approvals.md)
+ (англ.)
- **Направлен туда, куда скажете**: сеанс перед вами, закреплённый сеанс или
все сохранённые хосты
- **Инструменты вместо догадок**: подключиться к сохранённому хосту, читать и
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 3dd0a27..6c16520 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -105,7 +105,7 @@ Windows 主机,或者任意服务商上的服务器。CloudTerm 由 VPS 云主
- **使用本机已有的 Claude Code、Codex 或 OpenCode**,沿用你自己的账号和配置
-- **读取当前会话并操作远程服务器**,执行更改前会先征求你的同意;提供三种审批模式,详见 [docs/assistant-approvals.md](docs/assistant-approvals.md)(英文)
+- **读取当前会话并操作远程服务器**;是否征求同意由审批模式决定(每次 / 仅更改 / 从不——从不模式会自动批准未拦截的工具),详见 [docs/assistant-approvals.md](docs/assistant-approvals.md)(英文)
- **每个对话可单独选择模型和推理强度**,并在运行时显示用量
### 终端
diff --git a/docs/assistant-approvals.md b/docs/assistant-approvals.md
index ce3340a..b98eb33 100644
--- a/docs/assistant-approvals.md
+++ b/docs/assistant-approvals.md
@@ -7,14 +7,14 @@ Approval modes decide when those tools stop for a person.
|------|-------|-----------|
| Ask every time | `always` | Every tool waits, including reads |
| Ask before changes | `writes` | **Default.** Reads run freely; mutating tools ask |
-| Never ask | `never` | Nothing asks (except the block list) |
+| Never ask | `never` | Nothing asks; blocked commands are still refused |
## Defaults and hardening
- New installs ship with `writes` and `allowLocalTools: false`.
- The first time the assistant panel opens, a short warning explains the modes
- and that tools act on live sessions. Dismissing it sets
- `acknowledgedApprovalWarning` in `assistant.json`.
+ and that tools act on live sessions. Choosing **Got it** sets
+ `acknowledgedApprovalWarning` in `assistant.json` (Escape / backdrop do not).
- Switching to **Never ask** from the composer chip or Settings requires an
explicit confirm dialog. The block list (`blockedCommands`, seeded with
`rm -rf`) still refuses matching commands under every mode, including never.
diff --git a/src/main/ai/settings.js b/src/main/ai/settings.js
index c6a4587..d299b42 100644
--- a/src/main/ai/settings.js
+++ b/src/main/ai/settings.js
@@ -152,8 +152,8 @@ function sanitize(raw) {
.filter(Boolean)
.slice(0, 12);
}
- if ('acknowledgedApprovalWarning' in raw) {
- next.acknowledgedApprovalWarning = Boolean(raw.acknowledgedApprovalWarning);
+ if (typeof raw.acknowledgedApprovalWarning === 'boolean') {
+ next.acknowledgedApprovalWarning = raw.acknowledgedApprovalWarning;
}
}
return next;
diff --git a/src/main/session-log.js b/src/main/session-log.js
index 344da1e..8a42a20 100644
--- a/src/main/session-log.js
+++ b/src/main/session-log.js
@@ -1,6 +1,7 @@
const { app } = require('electron');
const path = require('path');
const fs = require('fs');
+const crypto = require('crypto');
const activity = require('./activity');
/**
@@ -286,7 +287,7 @@ function start(tabId, { hostName = '', address = '', hostId = '', protocol = '',
const directory = current.directory || defaultDirectory();
const startedAt = new Date();
- const filePath = path.join(directory, `${slug(hostName || address)}_${stamp(startedAt)}.log`);
+ const baseName = `${slug(hostName || address)}_${stamp(startedAt)}`;
try {
fs.mkdirSync(directory, { recursive: true });
@@ -294,9 +295,24 @@ function start(tabId, { hostName = '', address = '', hostId = '', protocol = '',
// Open synchronously so a returned path already exists on disk. The
// stream open is otherwise async, and callers (and the retention
// tests) treat the path as ready the moment start() returns.
- // `a`, not `w`: two sessions to the same host within the same second
- // would otherwise have the second silently truncate the first.
- const fd = fs.openSync(filePath, 'a');
+ // Exclusive create (`wx`) plus a random suffix: two tabs that stamp
+ // the same second must not share or truncate one transcript.
+ let filePath;
+ let fd;
+ for (let attempt = 0; attempt < 8; attempt++) {
+ const suffix = crypto.randomBytes(attempt === 0 ? 3 : 4).toString('hex');
+ filePath = path.join(directory, `${baseName}_${suffix}.log`);
+ try {
+ fd = fs.openSync(filePath, 'wx');
+ break;
+ } catch (error) {
+ if (error.code !== 'EEXIST') throw error;
+ fd = undefined;
+ }
+ }
+ if (fd === undefined) {
+ throw new Error('Could not create a unique session log path');
+ }
const stream = fs.createWriteStream(null, { fd, encoding: 'utf8' });
stream.on('error', (error) => {
console.error(`Session log write failed for ${tabId}:`, error.message);
diff --git a/src/renderer/components/assistant/ApprovalMenu.jsx b/src/renderer/components/assistant/ApprovalMenu.jsx
index 9b4031d..c0af085 100644
--- a/src/renderer/components/assistant/ApprovalMenu.jsx
+++ b/src/renderer/components/assistant/ApprovalMenu.jsx
@@ -2,6 +2,7 @@ import { useState } from 'react';
import { ArrowDown01Icon, FlashIcon, SecurityCheckIcon, Shield01Icon } from 'hugeicons-react';
import PanelMenu from './PanelMenu';
import ConfirmDialog from '../ui/ConfirmDialog';
+import { useT } from '../../i18n';
/**
* What the assistant will do before asking, as a chip in the composer.
@@ -37,15 +38,23 @@ const APPROVALS = [
},
{
value: 'never',
- label: 'Never ask',
- hint: 'Nothing stops, deletes included',
+ labelKey: 'assistant.approvalNever',
+ hintKey: 'assistant.approvalNeverHint',
icon: ,
},
];
export default function ApprovalMenu({ settings, onChange }) {
+ const t = useT();
const [confirmNever, setConfirmNever] = useState(false);
- const current = APPROVALS.find(option => option.value === settings.approval) || APPROVALS[1];
+
+ const options = APPROVALS.map(option => ({
+ ...option,
+ label: t(option.labelKey),
+ hint: t(option.hintKey),
+ }));
+
+ const current = options.find(option => option.value === settings.approval) || options[1];
// The one state worth colouring. Somebody who has turned approvals off and
// then forgotten deserves to notice before the next destructive command,
@@ -69,7 +78,7 @@ export default function ApprovalMenu({ settings, onChange }) {
{
value: settings.approval,
onChange: pick,
- options: APPROVALS,
+ options,
},
]}
trigger={({ open, toggle }) => (
@@ -77,9 +86,9 @@ export default function ApprovalMenu({ settings, onChange }) {
type="button"
aria-haspopup="menu"
aria-expanded={open}
- aria-label={`Approvals: ${current.label}`}
+ aria-label={t('assistant.approvalsLabel', { mode: current.label })}
onClick={toggle}
- title={`Approvals: ${current.label}`}
+ title={t('assistant.approvalsLabel', { mode: current.label })}
className={`h-7 pl-1.5 pr-1 rounded-xl flex items-center gap-0.5 transition-colors
outline-none focus-visible:ring-2
focus-visible:ring-gray-900/20 dark:focus-visible:ring-white/25
@@ -102,9 +111,9 @@ export default function ApprovalMenu({ settings, onChange }) {
{confirmNever && (
{
setConfirmNever(false);
diff --git a/src/renderer/components/assistant/AssistantPanel.jsx b/src/renderer/components/assistant/AssistantPanel.jsx
index f22456c..7cc1c81 100644
--- a/src/renderer/components/assistant/AssistantPanel.jsx
+++ b/src/renderer/components/assistant/AssistantPanel.jsx
@@ -19,6 +19,7 @@ import ModelMenu from './ModelMenu';
import ApprovalMenu from './ApprovalMenu';
import HistoryMenu from './HistoryMenu';
import Dialog, { DialogButton } from '../ui/Dialog';
+import { useT } from '../../i18n';
import {
GLOBAL,
describe,
@@ -482,9 +483,7 @@ function AssistantConversation({
{t('assistant.welcome')}
- It reads this terminal, runs commands on their own channel, and can work
- across every host you have saved. Approvals default to ask-before-changes;
- switch modes from the composer chip or Settings.
+ {t('assistant.welcomeNote')}