- Add unit tests (hostname-validator, TLDs, payload-schemas) and integration tests for message handler registry - Refactor native host message router into handler registry (handlers/state, tunnels, ssh, rdp, backup, ca, connections) - Add ESLint config and npm test + lint steps in CI - Dashboard: visibility-based refresh pause, configurable refresh interval (2s/5s/10s/paused) - Accessibility: ARIA on nav and modals, focus trap and restore, prefers-reduced-motion - Empty states: primary action buttons for virtual hosts, servers, service tunnels - Native host rate limiting for backup and CA operations; update SECURITY.md - CONTRIBUTING: "Adding a new dashboard page", dev workflow; add npm run dev script
This commit is contained in:
+30
-1
@@ -181,6 +181,25 @@ chrome.runtime.sendMessage({
|
||||
|
||||
Add an entry under the Commands section with the request payload shape, response shape, and any notes on optional fields.
|
||||
|
||||
## Adding a new dashboard page
|
||||
|
||||
To add a new page to the dashboard (e.g. a new section in the sidebar and a full-page view):
|
||||
|
||||
1. **Add the page HTML** in `extension/dashboard/dashboard.html`: a `<div class="page" id="page-<key>">` with your content, and a sidebar nav item `<div class="nav-item" data-page="<key">` with icon and label.
|
||||
|
||||
2. **Register the page** in `extension/dashboard/core/navigation.js`: add an entry to `PAGE_TITLES` (e.g. `myPage: 'My Page Title'`).
|
||||
|
||||
3. **Create the page module** `extension/dashboard/pages/<name>.js` that exports:
|
||||
- `update<Name>(state)` — called on every refresh with the full state; use it to re-render your table or widgets.
|
||||
- `setup<Name>Events()` — called once at init; attach click handlers, form submit, etc.
|
||||
|
||||
4. **Wire the page into the dashboard**:
|
||||
- In `extension/dashboard/refresh.js`, inside the `refresh()` function, call your `update<Name>(state)` after the existing `update*` calls.
|
||||
- In `extension/dashboard/events.js`, inside `setupEvents()`, call your `setup<Name>Events()`.
|
||||
- In `extension/dashboard/dashboard.html`, add a `<script src="pages/<name>.js">` in the same order as the other page scripts (before `refresh.js` and `init.js`).
|
||||
|
||||
5. **Optional**: if your page needs to request data from the native host, use `sendToNative(type, payload)` from `core/messaging.js` and ensure the native host has a handler for that message type (see "Adding a new native host message type" above).
|
||||
|
||||
## Code style
|
||||
|
||||
- **No build step for the extension** — the dashboard JS files are loaded directly by the browser in dependency order (see the `<script>` tags at the bottom of `dashboard.html`). There is no bundler or transpiler for the extension.
|
||||
@@ -189,9 +208,19 @@ Add an entry under the Commands section with the request payload shape, response
|
||||
- **Error handling** — all async functions should catch errors and return `{ ok: false, error: e.message }` rather than throwing, so the extension always gets a structured response.
|
||||
- **Timers and listeners** — always store timer IDs and remove event listeners in cleanup paths to avoid leaks (see `docs/ARCHITECTURE.md` for the resource management patterns used throughout).
|
||||
|
||||
## Dev workflow
|
||||
|
||||
For a quick local development loop:
|
||||
|
||||
1. Run `npm run dev` to build the native host launcher and run the installer (so the native messaging manifest points to your build). This prints the path to the extension directory.
|
||||
2. Open Chrome → `chrome://extensions` → enable **Developer mode** → **Load unpacked** → select the `extension/` directory.
|
||||
3. After code changes: reload the extension from `chrome://extensions`; for native host changes, run `npm run build:host` again and reload the extension so the host restarts.
|
||||
|
||||
To run only the host build without installing: `npm run build:host`. To run the full installer: `npm run setup`.
|
||||
|
||||
## Testing
|
||||
|
||||
There is currently no automated test suite. Manual testing workflow:
|
||||
There is an automated test suite for hostname validation, TLD data, payload schemas, and the message handler registry. Run `npm test`. Manual testing workflow:
|
||||
|
||||
1. Make changes to the native host source
|
||||
2. Run `npm run build:host` to regenerate the launcher
|
||||
|
||||
@@ -78,6 +78,8 @@ The native host runs as your user account (not root). It:
|
||||
- Spawns child processes: `ssh` (for SSH sessions), `tar` (for backups), `security`/`certutil`/`pkexec` (for CA installation)
|
||||
- Does not require elevated privileges for normal operation
|
||||
|
||||
The extension is trusted in the sense that it runs in the user's browser and can send any message to the native host. The native host **validates all incoming payloads** and applies **rate limits** to expensive or sensitive operations (backup create/restore/delete, CA install) to reduce the impact of a compromised extension (e.g. backup spam or CA install loops). See `native-host/host/rate-limit.js` for limits.
|
||||
|
||||
---
|
||||
|
||||
## Proxy security
|
||||
@@ -126,6 +128,7 @@ This prevents accidentally routing real internet traffic through the local proxy
|
||||
| Stale CA after reinstall causing cert errors | Fingerprint verification on every CA install check |
|
||||
| Multiple native host instances with no tunnels | Process exits on EADDRINUSE; only one instance owns the ports |
|
||||
| Custom TLD colliding with real internet domain | TLD blocklist validation in dashboard before saving |
|
||||
| Compromised extension spamming backups or CA install | Rate limits (e.g. max 3 backup creates, 5 CA installs per minute) |
|
||||
|
||||
## Threats not mitigated
|
||||
|
||||
|
||||
Reference in New Issue
Block a user