feat(extensions-portal): add Extensions dashboard page#673
Conversation
Lightheartdevs
left a comment
There was a problem hiding this comment.
Dashboard UI looks good — card grid, status filters, search, detail modal, live logs console, confirmation dialogs. Nice UX.
Must fix (2 items)
-
No auth headers on API calls. `fetchJson` is a bare `fetch(url)` with no Authorization header. Unless the nginx proxy injects the API key, all calls will return 401 and the entire page won't work. Check how the existing dashboard pages handle auth — they likely pass the API key as a header or cookie.
-
`const logRef = { current: null }` should be `useRef(null)`. The current code creates a new plain object every render, so the auto-scroll-to-bottom in the console modal won't work reliably. Quick fix:
```jsx
const logRef = useRef(null)
```
Non-blocking
- Hardcoded HTTP links to extensions. `http://${window.location.hostname}:${port}` assumes HTTP, not HTTPS. Fine for localhost but would break behind a reverse proxy.
- Category derived from first feature only. Extensions with multiple features in different categories only show under one filter category.
Fix items 1 and 2 and this is ready.
|
Thanks! Both items fixed:
Also: Remove button now only shows on disabled extensions (matching the disable-before-uninstall guard in #672). Re: non-blocking items:
|
Lightheartdevs
left a comment
There was a problem hiding this comment.
Audit Review
Blocking: fetchJson doesn't pass auth headers
fetchJson does a plain fetch() with no Authorization header:
const fetchJson = async (url, ms = 8000) => {
const c = new AbortController()
const t = setTimeout(() => c.abort(), ms)
try {
return await fetch(url, { signal: c.signal })
} finally {
clearTimeout(t)
}
}If /api/extensions/catalog and the mutation endpoints require verify_api_key, every request from this page will fail with 401/403. Same issue in handleMutation. Need to pass Authorization: Bearer ${key} — check how other dashboard pages handle this (shared fetch wrapper, proxy-injected header, or cookie-based auth).
Note: Log viewer exposes raw container output
The ConsoleModal renders container stdout/stderr verbatim. Container logs can contain secrets, API keys, connection strings, database passwords. This is visible to anyone with dashboard access. Consider redacting known secret patterns (env vars matching *_KEY, *_SECRET, *_PASSWORD) in a follow-up.
Good
- No XSS risk — React auto-escaping everywhere, no
dangerouslySetInnerHTML - All destructive actions behind confirmation dialogs
- ICON_MAP lookup falls back safely to
Packagefor unknown icons - AbortController timeout on all fetches
- Clean component structure
|
Auth issue fully addressed across all dashboard files. Root cause: Fix: Removed
All fetches now use relative URLs ( Verified: |
Fix commit added
Added
Handles null/undefined gracefully. Applied in |
|
Code is approved. Please rebase onto main — the |
Full-featured Extensions page for the DreamServer dashboard. Browse, install, enable/disable, and remove extensions from the browser. - Card grid with status badges, toggle switches, icon backgrounds - Status filters (All/Enabled/Disabled/Not Installed/Incompatible) - Category filters and text search - Modal detail view with env vars, dependencies, credential commands - Live container logs console with 2s auto-refresh - Agent status indicator with graceful offline fallback - Copyable CLI commands and docker exec credential retrieval - Confirmation dialogs for all destructive actions - Direct links to extension web UIs on their ports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses maintainer review feedback: 1. logRef uses useRef(null) instead of plain object for reliable auto-scroll 2. Remove button only shows on disabled extensions (disable-before-uninstall) 3. Added useRef to react imports Note: Auth headers are handled by nginx proxy (proxy_set_header Authorization) so frontend fetch calls don't need explicit auth headers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auth is handled by nginx proxy_set_header injecting the Authorization header for all /api/ requests. Removed API_BASE/VITE_API_URL to prevent accidentally bypassing nginx and losing auth. All fetches now use relative URLs through the nginx proxy, matching Dashboard.jsx pattern. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rtal Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
34ac979 to
35734cb
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
35734cb to
834d81e
Compare
8481a94
into
Light-Heart-Labs:resources/dev
Summary
Full-featured Extensions page for the DreamServer dashboard:
Test plan
Part 5 of 5 for the Extensions Portal feature.