fix(electrobun): address all 22 Codex review #2 findings
CRITICAL:
- DocsTab XSS: DOMPurify sanitization on all {@html} output
- File RPC path traversal: guardPath() validates against project CWDs
HIGH:
- SSH injection: spawn /usr/bin/ssh via PTY args, no shell string
- Search XSS: strip HTML, highlight matches client-side with <mark>
- Terminal listener leak: cleanup functions stored + called in onDestroy
- FileBrowser race: request token, discard stale responses
- SearchOverlay race: same request token pattern
- App startup ordering: groups.list chains into active_group restore
- PtyClient timeout: 5-second auth timeout on connect()
- Rule 55: 6 {#if} patterns converted to style:display toggle
MEDIUM:
- Agent persistence: only persist NEW messages (lastPersistedIndex)
- Search errors: typed error response, "Invalid query" UI
- Health store wired: agent events call recordActivity/setProjectStatus
- index.ts SRP: split into 8 domain handler modules (298 lines)
- App.svelte: extracted workspace-store.svelte.ts
- rpc.ts: typed AppRpcHandle, removed `any`
LOW:
- CommandPalette listener wired in App.svelte
- Dead code removed (removeGroup, onDragStart, plugin loaded)
This commit is contained in:
parent
8e756d3523
commit
1cd4558740
28 changed files with 1342 additions and 1164 deletions
|
|
@ -3,20 +3,31 @@
|
|||
*
|
||||
* main.ts creates the Electroview and RPC, then sets it here.
|
||||
* All other modules import from this file instead of main.ts.
|
||||
*
|
||||
* Fix #17: Typed RPC interface instead of `any`.
|
||||
*/
|
||||
|
||||
import type { PtyRPCSchema } from '../shared/pty-rpc-schema.ts';
|
||||
import type { PtyRPCSchema, PtyRPCRequests, PtyRPCMessages } from '../shared/pty-rpc-schema.ts';
|
||||
|
||||
// Placeholder type — matches the shape Electroview.defineRPC returns.
|
||||
// Uses `any` for the internal Electrobun RPC wrapper type since it is
|
||||
// not exported from the electrobun package.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type ElectrobunRpc = any;
|
||||
// ── Typed RPC interface ──────────────────────────────────────────────────────
|
||||
|
||||
let _rpc: ElectrobunRpc | null = null;
|
||||
type RequestFn<K extends keyof PtyRPCRequests> = (params: PtyRPCRequests[K]['params']) => Promise<PtyRPCRequests[K]['response']>;
|
||||
|
||||
type MessagePayload<K extends keyof PtyRPCMessages> = PtyRPCMessages[K];
|
||||
type MessageListener<K extends keyof PtyRPCMessages> = (payload: MessagePayload<K>) => void;
|
||||
|
||||
export interface AppRpcHandle {
|
||||
request: { [K in keyof PtyRPCRequests]: RequestFn<K> };
|
||||
addMessageListener: <K extends keyof PtyRPCMessages>(event: K, handler: MessageListener<K>) => void;
|
||||
removeMessageListener?: <K extends keyof PtyRPCMessages>(event: K, handler: MessageListener<K>) => void;
|
||||
}
|
||||
|
||||
// ── Internal holder ──────────────────────────────────────────────────────────
|
||||
|
||||
let _rpc: AppRpcHandle | null = null;
|
||||
|
||||
/** Called once from main.ts after Electroview.defineRPC(). */
|
||||
export function setAppRpc(rpc: ElectrobunRpc): void {
|
||||
export function setAppRpc(rpc: AppRpcHandle): void {
|
||||
_rpc = rpc;
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +35,7 @@ export function setAppRpc(rpc: ElectrobunRpc): void {
|
|||
* The app-wide RPC handle.
|
||||
* Safe to call after main.ts has executed (Svelte components mount after).
|
||||
*/
|
||||
export const appRpc: ElectrobunRpc = new Proxy({} as ElectrobunRpc, {
|
||||
export const appRpc: AppRpcHandle = new Proxy({} as AppRpcHandle, {
|
||||
get(_target, prop) {
|
||||
if (!_rpc) {
|
||||
throw new Error(`[rpc] accessed before init — property "${String(prop)}"`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue