// Types REST partagés (préfixe /api/v1). import type { GroupSummary, PostCreateHook, RepoSummary, SessionSummary, WorktreeSummary } from './protocol.js'; export interface ApiError { error: { code: string; message: string; details?: unknown }; } export interface LoginRequest { token: string; } export interface LoginResponse { ok: true; label: string; } export interface MeResponse { ok: true; /** id du token de la session courante — sert à marquer « courant » dans la liste des tokens. */ tokenId: string; tokenLabel: string; serverVersion: string; } // ---- Gestion des tokens d'accès (onglet Réglages) ---- export interface TokenInfo { id: string; label: string; createdAt: string; lastUsedAt: string | null; /** true pour le token de la session courante. */ current: boolean; } export interface TokensListResponse { tokens: TokenInfo[]; } export interface CreateTokenRequest { label: string; } export interface CreateTokenResponse { id: string; label: string; /** valeur en clair — affichée une seule fois, jamais re-récupérable. */ token: string; } export interface CreateSessionRequest { cwd: string; /** binaire à lancer — défaut "claude" ; "bash" sert aux tests d'acceptation sans quota */ command?: 'claude' | 'bash'; } export interface SessionsListResponse { sessions: SessionSummary[]; } export interface SessionResponse { session: SessionSummary; } // POST /sessions/:id/resume et /sessions/:id/fork (P2) : aucun corps — cwd et command // sont TOUJOURS dérivés du :id (lu sur disque), jamais fournis par le client (cf. spike S1). export type ResumeSessionRequest = Record; export type ForkSessionRequest = Record; // ---- Repos & worktrees (P3) ---- export interface ReposListResponse { repos: RepoSummary[]; } export interface RepoResponse { repo: RepoSummary; } export interface CreateRepoRequest { path: string; label?: string; postCreateHooks?: PostCreateHook[]; preTrust?: boolean; } export interface UpdateRepoRequest { label?: string; postCreateHooks?: PostCreateHook[]; preTrust?: boolean; /** true = masquer le repo (exclu du dashboard, conservé en DB) ; false = ré-afficher. */ hidden?: boolean; } /** Résultat d'un scan de découverte (POST /api/v1/repos/discover). */ export interface DiscoverReposResponse { /** dossiers-repos trouvés sur disque. */ scanned: number; /** repos réellement insérés (nouveaux, non déjà enregistrés). */ added: number; durationMs: number; /** true si la limite (maxRepos / timeout) a été atteinte avant la fin du scan. */ truncated: boolean; } export interface WorktreesListResponse { worktrees: WorktreeSummary[]; } export interface WorktreeResponse { worktree: WorktreeSummary; } export interface HookRunResult { hookId: string; label: string; exitCode: number | null; output: string; durationMs: number; } export interface CreateWorktreeRequest { branch: string; /** true : créer la branche (`-b`) ; false : checkout d'une branche existante. */ newBranch: boolean; /** point de départ de la nouvelle branche (défaut : HEAD courant du repo). */ baseRef?: string; /** chemin cible du worktree (défaut : `/-wt-`). */ path?: string; runHooks?: boolean; preTrust?: boolean; /** lancer une session dans le worktree créé (défaut : aucune). */ startSession?: 'claude' | 'bash' | null; } export interface CreateWorktreeResponse { worktree: WorktreeSummary; hookResults: HookRunResult[]; session: SessionSummary | null; } export interface AdoptWorktreeRequest { path: string; runHooks?: boolean; preTrust?: boolean; } // ---- Groupes de travail (P5) ---- export interface GroupsListResponse { groups: GroupSummary[]; } export interface GroupResponse { group: GroupSummary; } export interface CreateGroupRequest { label: string; description?: string; color?: string; /** ids de repos initiaux (défaut : []). */ repoIds?: string[]; } export interface UpdateGroupRequest { label?: string; /** null pour effacer. */ description?: string | null; color?: string | null; } export interface AddRepoRequest { repoId: string; } // ---- Navigateur de répertoires (sélecteur de dossier côté web) ---- export interface FsEntry { name: string; /** chemin absolu du dossier */ path: string; /** présent (true) uniquement en mode markRepos quand le dossier est un dépôt git */ isRepo?: boolean; } export interface FsListResponse { /** chemin absolu listé (normalisé) */ path: string; /** parent (null à la racine `/`) — pour le bouton « remonter » */ parent: string | null; /** home de l'utilisateur côté serveur — point de départ par défaut */ home: string; /** sous-dossiers uniquement, triés sans tenir compte de la casse */ entries: FsEntry[]; } // ---- Web Push (P4) ---- export interface VapidKeyResponse { /** clé publique VAPID (applicationServerKey côté navigateur). */ key: string; } export interface PushSubscribeRequest { endpoint: string; keys: { p256dh: string; auth: string }; } export interface PushUnsubscribeRequest { endpoint: string; } // ---- Réglages & info serveur (onglet Réglages) ---- /** Config runtime non sensible du daemon — lecture seule (changée via flags CLI + redémarrage). */ export interface ServerInfo { version: string; port: number; bind: string; allowedOrigins: string[]; dataDir: string; /** clé publique VAPID (sûre à exposer) ; null si push indisponible. */ vapidPublicKey: string | null; vapidContact: string; } export interface SettingsResponse { /** réglages modifiables à chaud (allow-list serveur — jamais les secrets). */ settings: { /** racines absolues scannées pour la découverte auto des repos (défaut : aucune → pas de scan). */ scanRoots: string[]; /** intervalle du re-scan périodique en minutes ; 0 = périodique désactivé. */ scanIntervalMin: number; }; server: ServerInfo; } export interface UpdateSettingsRequest { /** racines absolues à scanner (chemins normalisés, ≤ 16) ; remplace la liste. */ scanRoots?: string[]; /** intervalle du re-scan périodique en minutes (0–1440 ; 0 désactive). */ scanIntervalMin?: number; } // ---- Journal d'audit (conformité entreprise) ---- export interface AuditLogEntry { id: string; /** horodatage ISO 8601 */ ts: string; /** tokenId de l'acteur, 'system' (auto) ou 'anonymous' (avant auth) */ actor: string; /** verbe.objet, ex. 'token.create', 'settings.update' */ action: string; resourceId: string | null; /** métadonnées non sensibles (jamais de secret) */ details: unknown; result: string; } export interface AuditLogsResponse { entries: AuditLogEntry[]; /** curseur de pagination (ts à passer en `before`) ; null si fin de liste. */ nextBefore: string | null; } // ---- RGPD : export / suppression des données liées au token authentifié ---- export interface DataExportResponse { exportedAt: string; tokens: Array<{ id: string; label: string; createdAt: string; lastUsedAt: string | null; current: boolean }>; pushSubscriptions: Array<{ endpoint: string; userAgent: string | null; createdAt: string; lastOkAt: string | null }>; sessions: Array<{ id: string; cwd: string; command: string; title: string | null; createdAt: string; endedAt: string | null; exitCode: number | null }>; settings: { scanRoots: string[]; scanIntervalMin: number }; } export interface DeleteMyDataRequest { /** code de confirmation renvoyé par un premier appel sans `confirm` ; doit être renvoyé pour exécuter. */ confirm?: string; } export interface DeleteMyDataResponse { /** 'pending' = confirmation requise (renvoie `confirm`) ; 'done' = suppression effectuée. */ status: 'pending' | 'done'; confirm?: string; /** récapitulatif de ce qui sera/a été supprimé. */ summary: { pushSubscriptions: number; tokenRevoked: boolean }; }