Files
guru-connect/dashboard/src/api/sessions.ts
Mike Swanson 96f9c0ab45
All checks were successful
Build and Test / Build Agent (Windows) (push) Successful in 7m13s
Build and Test / Build Server (Linux) (push) Successful in 11m21s
Build and Test / Security Audit (push) Successful in 4m12s
Build and Test / Build Summary (push) Successful in 11s
feat(dashboard): operator removal UI for stale machines/sessions (SPEC-004 Task 5)
Admin-only per-row Remove + multi-select bulk removal on the machines view, plus
per-row purge Remove on the sessions view, wired to the Task-5 admin API
(DELETE /api/machines|sessions/:id?purge=true, POST /api/machines/bulk-remove).
Confirm modals (danger-styled, focus-trapped), TanStack refetch so purged rows
leave the console, structured ApiError surfacing, honest partial-bulk summary,
and admin-gating via useAuth().isAdmin as defense-in-depth over the server 403.
Replaces the legacy all-user delete trigger. typecheck/lint/build clean.

Implements specs/v2-stable-identity/plan.md Task 5 (dashboard portion).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 14:14:49 -07:00

56 lines
2.0 KiB
TypeScript

import { http } from "./client";
import type {
RemoveSessionResponse,
Session,
ViewerTokenResponse,
} from "./types";
/**
* GET /api/sessions — all live sessions known to the relay's in-memory session
* manager (active + offline-persistent). Requires an authenticated dashboard
* JWT; any authenticated user may list.
*/
export function listSessions(signal?: AbortSignal): Promise<Session[]> {
return http.get<Session[]>("/api/sessions", signal);
}
/**
* POST /api/sessions/:id/viewer-token — mint a short-lived, session-scoped
* viewer token. The server decides the access mode from the caller's
* permissions: admin or `control` permission gets a `control` token, otherwise
* a `view_only` token. A caller with neither `control` nor `view` gets 403.
* The access mode is stamped into the signed token; this response only echoes
* it. (See server/src/api/sessions.rs::mint_viewer_token.)
*/
export function mintViewerToken(
sessionId: string,
): Promise<ViewerTokenResponse> {
return http.post<ViewerTokenResponse>(
`/api/sessions/${encodeURIComponent(sessionId)}/viewer-token`,
);
}
/**
* DELETE /api/sessions/:id — disconnect/end a live session (admin only). The
* relay sends a Disconnect to the agent. Returns 200 on success, 404 if the
* session is not live in memory. This is the live-only path (no `purge`); it
* does not soft-delete any persisted row.
*/
export function endSession(sessionId: string): Promise<void> {
return http.del<void>(`/api/sessions/${encodeURIComponent(sessionId)}`);
}
/**
* DELETE /api/sessions/:id?purge=true — operator removal of a session (admin
* only). Soft-deletes the persisted `connect_sessions` row and drops any live
* in-memory session, clearing a ghost/stale session from the console. 404 only
* when neither a live nor a persisted session exists.
*/
export function purgeSession(
sessionId: string,
): Promise<RemoveSessionResponse> {
return http.del<RemoveSessionResponse>(
`/api/sessions/${encodeURIComponent(sessionId)}?purge=true`,
);
}