- Least privilege. Every component receives only the permissions it needs — nothing more.
- Defense in depth. Multiple isolation layers: Tauri capabilities, window-level permissions, sandboxed artifact windows.
- Credentials never in plaintext. API keys live in the OS keychain, never in files, env vars, or React state.
- Untrusted by default. All external input — agent output, plugin manifests, remote JSON, file paths — is treated as hostile until validated.
- Auditability. Permission grants, plugin registrations, and credential access are logged.
- API keys (OpenAI, market data providers) are stored in the operating system keychain:
- macOS: Keychain
- Windows: Credential Manager
- Linux: libsecret
- Keys are never:
- Stored in plaintext files or
.env. - Passed to React components.
- Included in logs or error messages.
- Committed to version control.
- Stored in plaintext files or
- React receives only a status indicator: "OpenAI: configured" / "OpenAI: not configured".
| Window | Tauri Capabilities |
|---|---|
| Main | core:default, opener:default, shell:allow-open, store:default |
| Artifact | core:default only |
Artifact windows cannot:
- Access the filesystem.
- Open URLs or execute shell commands.
- Access the Tauri store (key-value persistence).
- Make HTTP requests.
- Access the main window's state or DOM.
Plugins are internal-only in the MVP. Even so, every plugin is untrusted:
- Plugin manifests are validated against a schema.
- Plugin input is validated before rendering.
- Plugins cannot access Tauri commands beyond
core:default. - Plugin errors are isolated — a plugin crash cannot take down the main application.
- Plugin code is statically reviewed before inclusion (no dynamic code loading).
- The application may read and write only within its designated app data directory.
- User file access (opening documents, importing CSVs) uses OS-native file dialogs — the application never has unrestricted filesystem access.
- All file paths are normalized and validated to prevent directory traversal attacks.
- Artifact windows have no filesystem access whatsoever.
- The main window may make network requests through the Tauri HTTP plugin.
- External URLs are validated against a configurable allowlist before requests are dispatched.
- Artifact windows have no network access.
- Agent tasks may fetch web content through the Rust backend, which enforces the allowlist and rate limiting.
- Agent output is validated against Zod schemas before reaching the UI.
- Agent output is never rendered as raw HTML in the main window.
- Agent-generated artifacts are validated against their input schema before rendering.
- The agent cannot generate arbitrary code for execution.
All external data is validated at the boundary:
- TypeScript (frontend): Zod schemas validate Tauri command responses and user input.
- Rust (backend): Serde with explicit validation validates API responses, file contents, and plugin manifests.
- Agent output: Validated against structured output schemas before being treated as data.
- Structured logs via
tracing— neverprintln!orconsole.logfor production paths. - Logs must redact:
- API keys and access tokens.
- Cookies and session identifiers.
- Sensitive user data (portfolio values, positions).
- Internal file paths beyond the app data directory.
- No telemetry or analytics are sent externally unless explicitly enabled by the user.
AppErrorenforces typed, recoverable error handling — nounwrap()orexpect()in production paths..envfiles are in.gitignoreand never committed.- Pre-commit hooks (future) will scan for secrets, hardcoded credentials, and
unwrap()calls. - CI will run
cargo clippywith-D warningsand security-focused lint rules.