v0.3.0
Added
-
More AI providers for the assistant and workflow creation. Beyond OpenRouter / OpenAI / Anthropic / Ollama, the assistant now natively supports Perplexity, Groq, DeepSeek, Mistral, xAI (Grok), and Together AI, plus a Custom (OpenAI-compatible) provider: set a base URL in Models and point it at any OpenAI-compatible endpoint (Azure OpenAI, LiteLLM, vLLM, LocalAI, Fireworks, ...). They route through the shared OpenAI-compatible chat path with live model listing where the provider exposes a
/modelsendpoint; Perplexity is offered tools-free since it rejects an unknowntoolsfield. Each area (Code Lab / Error Triage / Assistant) still picks its own provider and model, and keys resolve from the Secrets store by convention ($PERPLEXITY_KEY,$GROQ_KEY,$DEEPSEEK_KEY,$MISTRAL_KEY,$XAI_KEY,$TOGETHER_KEY,$CUSTOM_LLM_KEY). -
VPS deployment guide. A step-by-step walkthrough for hosting AgeniusDesk as a public web app on your own domain (DigitalOcean, Hostinger, or any Ubuntu VPS): provision, point DNS, run in Docker bound to localhost, and front it with Caddy for automatic HTTPS, plus a public-deployment hardening checklist. Ships
docker-compose.prod.example.yml(Caddy reverse-proxy overlay) andCaddyfile.exampleso the all-Docker path is copy-paste. See docs/DEPLOY.md. -
Community-module frontend isolation (sandboxed iframe). A community module's frontend view no longer runs in the app page. It loads in an
<iframe sandbox="allow-scripts ...">withoutallow-same-origin, so the module's code runs in an opaque origin and cannot read or change the host DOM,window, cookies, or storage: a buggy or hostile module can break itself but not the AgeniusDesk UI. The module reaches the host only through apostMessagebridge that reimplementswindow.AgeniusDesk(fetch,notify,navigate,openInHarness); the host verifies the message source and restrictsfetchto same-origin/api/paths (adding auth and CSRF host-side). The host also pushes the active theme's CSS variables into the frame and auto-resizes it to content height. Module code that already usesAgeniusDesk.*keeps working unchanged. -
Community-module backend isolation (out-of-process, opt-in). A community module's backend can now run OUTSIDE the app process, selected in Settings > Modules (or the
AGD_MODULE_ISOLATIONenv var, which overrides the setting). Two tiers:- Subprocess runs each module in a sandboxed child process: host
backendimports are blocked, the env is scrubbed to an allowlist, and the host reaches it through a reverse proxy with a per-spawn secret. - Container runs each module in its own hardened Docker container (read-only rootfs, all Linux capabilities dropped,
no-new-privileges, no Docker socket, pid/memory/cpu limits; modules that declare no network join an internal network with zero internet). This is the real OS boundary.
Either way, privileged actions go through a loopback capability bridge, never direct host access: vault read/write scoped to the module's declared paths (checked against the symlink-resolved location), and a tool-free
assistant.completethat runs the LLM host-side so the provider key never reaches the module. The default stays in-process, so existing installs are unchanged. The reference YouTube Research module is dual-mode: the same code runs in-process or isolated. - Subprocess runs each module in a sandboxed child process: host
-
Fleet Health view. A dedicated view aggregating workflow health across every connected n8n instance: per-instance active/total workflows, error rate over recent executions, and the unhealthy workflows, plus a combined roll-up. Live parallel fan-out; a degraded or unreachable instance is shown, not fatal. The "one client becomes ten" pane.
-
Auto-install the error handler on connect. Adding an n8n instance now best-effort installs + activates the Global Error Handler workflow into it (idempotent), so its errors flow to AgeniusDesk from the moment it's connected. It posts to a container-reachable dashboard URL (
AGD_PUBLIC_HOST, else a configured host alias). n8n's public API cannot set the instance-wide Error Workflow, so the connect result surfaces that one remaining manual step.
Fixed
- Stored XSS in the shared error item (pre-release). The error renderer shared across Overview, Errors, and Fleet Health escaped an error's
workflow_id/execution_idtoo weakly for theonclick/hrefcontexts it writes them into. Since those fields arrive on the login-exempt error webhook, a crafted value could break out of the attribute and run script in the operator's dashboard. The component now escapes the attribute/JS delimiters (matching the source renderer) and percent-encodes ids in URLs; a node-driven regression test renders a hostile error and asserts no breakout. - Role floor on error operations. Error-store endpoints that reach into n8n (purge executions, install/activate the error handler) or clear stored errors now require the operator role, matching every other n8n-mutating route; reads and the machine webhook stay open.
- Error handler vs. webhook token. The auto-installed Global Error Handler now sends the
x-agd-webhook-tokenheader (from$env.AGD_WEBHOOK_TOKEN), so error delivery keeps working when the dashboard requires a webhook token instead of silently dropping every error.
Next
- Container tier hardening: drop the module worker to a non-root uid, and a per-host egress proxy that enforces the manifest's declared
network.hosts(today a network-declaring module reaches any host).