Référence API
Référence API
Section intitulée « Référence API »Cette référence couvre deux surfaces:
- l’API IPC exposée au renderer via
window.obscuraFlow; - l’API REST backend utilisée par
ApiClient.
API renderer
Section intitulée « API renderer »L’API renderer est exposée par src/preload/index.ts.
getBootstrapState()
Section intitulée « getBootstrapState() »Retourne l’état applicatif complet.
getBootstrapState(): Promise<AppStateSnapshot>Le snapshot contient aussi localResources, qui décrit l’état CPU, mémoire et disque local au moment du bootstrap.
getLocalResources()
Section intitulée « getLocalResources() »Retourne un échantillon léger des ressources locales consommées par l’application.
getLocalResources(): Promise<LocalResourceSnapshot>Le snapshot contient:
cpuPercent: CPU du process Obscura Flow;memoryMb: mémoire résidente du process;memoryIncreaseMb: hausse mémoire depuis la baseline locale;freeDiskGbettotalDiskGb: état du volume applicatif;warnings: liste des pressions détectées (cpu,memory,disk).
checkApiHealth()
Section intitulée « checkApiHealth() »Contrôle le health de l’API et retourne un snapshot applicatif mis à jour.
checkApiHealth(): Promise<AppStateSnapshot>createWorkspace(params)
Section intitulée « createWorkspace(params) »Crée un workspace local et tente une synchronisation API.
createWorkspace(params: { name: string; description?: string;}): Promise<AppStateSnapshot>openWorkspace()
Section intitulée « openWorkspace() »Ouvre un fichier .obf via un sélecteur système.
openWorkspace(): Promise<AppStateSnapshot | null>openRecentWorkspace(filePath)
Section intitulée « openRecentWorkspace(filePath) »Ouvre un workspace depuis son chemin récent.
openRecentWorkspace(filePath: string): Promise<AppStateSnapshot>removeRecentWorkspace(filePath)
Section intitulée « removeRecentWorkspace(filePath) »Retire un workspace de la liste des récents.
removeRecentWorkspace(filePath: string): Promise<AppStateSnapshot>closeWorkspace()
Section intitulée « closeWorkspace() »Ferme le workspace courant.
closeWorkspace(): Promise<AppStateSnapshot>showWorkspaces()
Section intitulée « showWorkspaces() »Prépare la vue My workspaces, charge les workspaces distants via GET /workspaces et tente de drainer la synchronisation en attente.
showWorkspaces(): Promise<AppStateSnapshot>browseDirectory(defaultPath?)
Section intitulée « browseDirectory(defaultPath?) »Ouvre un sélecteur système de dossier.
browseDirectory(defaultPath?: string): Promise<string | null>authenticate(credentials)
Section intitulée « authenticate(credentials) »Authentifie l’utilisateur et récupère la licence lorsque disponible.
authenticate(credentials: { email: string; password: string;}): Promise<AppStateSnapshot>logout()
Section intitulée « logout() »Supprime la session locale.
logout(): Promise<AppStateSnapshot>updateSettings(settings)
Section intitulée « updateSettings(settings) »Met à jour les settings globaux de l’application.
updateSettings(settings: Partial<AppSettings>): Promise<AppStateSnapshot>updateWorkspaceSettings(settings)
Section intitulée « updateWorkspaceSettings(settings) »Remplace les settings du workspace courant, sauvegarde le .obf et tente une synchronisation API.
updateWorkspaceSettings(settings: WorkspaceSettings): Promise<AppStateSnapshot>updateWorkspaceDetails(details)
Section intitulée « updateWorkspaceDetails(details) »Met à jour le nom et la description du workspace courant, sauvegarde le .obf et tente une synchronisation API.
updateWorkspaceDetails(details: { name: string; description: string;}): Promise<AppStateSnapshot>archiveProject(params)
Section intitulée « archiveProject(params) »Archive le project demandé dans un dossier Archive Package dédié sous
workspace.settings.paths.archiveDirectory, avec le moteur et le format de nommage
configurés dans les settings du workspace. La progression est envoyée via
onProjectArchiveProgress.
archiveProject({ projectId: string }): Promise<AppStateSnapshot>Chaque nouvelle archive produit trois fichiers regroupés dans le même dossier:
- l’archive compressée (
.zip,.tar.gzou.zstselon le moteur); manifest.json;signature.ed25519.
Le manifest contient l’identité de l’archive, le projet, le workspace, le moteur de
compression, le checksum de l’archive, l’inventaire des fichiers sources, la taille totale,
la version d’application et manifestVersion. La signature Ed25519 porte sur le manifest
canonique.
L’historique est persisté localement dans workspace.archiveHistory. archivePath reste
présent pour compatibilité, tandis que les nouveaux records renseignent aussi
packageDirectory, manifestPath, signaturePath, packageStatus,
localIntegrityStatus, packageManifest, signature et workflowSteps. Après une archive
réussie, le client synchronise aussi l’entrée via POST /archives en mappant
ArchiveHistoryItem vers CreateArchiveRequest. Si l’API est indisponible, une opération
offline entity: archive est ajoutée à la file de synchronisation.
closeProject(params)
Section intitulée « closeProject(params) »Ferme explicitement un projet archivé. L’action est non destructive: le projet devient read-only, sort des workflows actifs, mais reste searchable, exportable, restorable et visible dans les centres d’archives/intégrité.
closeProject({ projectId: string }): Promise<AppStateSnapshot>reopenProject(params)
Section intitulée « reopenProject(params) »Rouvre un projet fermé ou archivé en créant une nouvelle révision. Les archives, manifests, signatures, rapports d’intégrité et événements précédents ne sont jamais supprimés.
reopenProject({ projectId: string }): Promise<AppStateSnapshot>Les anciens records fichier unique restent visibles. Au chargement, les archives sans
métadonnées package sont normalisées avec packageStatus: "legacy" et
localIntegrityStatus: "unknown" si aucun statut local n’existe.
uploadArchiveToRemote(params)
Section intitulée « uploadArchiveToRemote(params) »Upload un Archive Package vers la destination remote configurée. L’action est bloquée si la validation locale du package n’est pas complète et valide.
uploadArchiveToRemote({ archiveId: string; target: 'primary' | 'secondary';}): Promise<AppStateSnapshot>L’upload envoie toujours les trois fichiers ensemble sous une clé stable:
archives/<workspaceId>/<projectId>/<archiveId>/archive.extarchives/<workspaceId>/<projectId>/<archiveId>/manifest.jsonarchives/<workspaceId>/<projectId>/<archiveId>/signature.ed25519Après transfert, le client vérifie la présence distante, les tailles, les checksums quand
disponibles et la correspondance du manifest distant. Le résultat est persisté dans
archiveHistory[].remoteCopies[].
listRemoteArchiveInventory(params?)
Section intitulée « listRemoteArchiveInventory(params?) »Retourne l’inventaire des archives distantes construit depuis archiveHistory.remoteCopies.
listRemoteArchiveInventory({ target?: 'primary' | 'secondary';}): Promise<RemoteArchiveInventoryItem[]>validateRemoteArchive(params)
Section intitulée « validateRemoteArchive(params) »Relit les métadonnées distantes et valide que le package distant correspond au package local.
validateRemoteArchive({ archiveId: string; target: 'primary' | 'secondary';}): Promise<AppStateSnapshot>downloadRemoteArchivePackage(params)
Section intitulée « downloadRemoteArchivePackage(params) »Télécharge les fichiers du package distant dans le dossier local du package.
downloadRemoteArchivePackage({ archiveId: string; target: 'primary' | 'secondary';}): Promise<AppStateSnapshot>deleteRemoteArchivePackage(params)
Section intitulée « deleteRemoteArchivePackage(params) »Supprime les fichiers distants du package après double confirmation côté UI.
deleteRemoteArchivePackage({ archiveId: string; target: 'primary' | 'secondary';}): Promise<AppStateSnapshot>readArchiveSignatureManifest(params)
Section intitulée « readArchiveSignatureManifest(params) »Lit le manifest associé à une archive locale. La résolution privilégie les chemins package persistés, puis les chemins legacy adjacents.
readArchiveSignatureManifest({ archiveId: string;}): Promise<string>startProjectIndexRebuild()
Section intitulée « startProjectIndexRebuild() »Lance la reconstruction de l’index projet pour le workspace courant.
startProjectIndexRebuild(): Promise<AppStateSnapshot>cancelProjectIndexRebuild()
Section intitulée « cancelProjectIndexRebuild() »Annule la reconstruction d’index en cours.
cancelProjectIndexRebuild(): Promise<void>retryProjectIndexRebuild()
Section intitulée « retryProjectIndexRebuild() »Relance une reconstruction d’index après un échec.
retryProjectIndexRebuild(): Promise<AppStateSnapshot>cancelProjectArchive(params)
Section intitulée « cancelProjectArchive(params) »Demande l’arrêt de l’archive en cours pour le project.
cancelProjectArchive({ projectId: string }): Promise<void>openExternalUrl(url)
Section intitulée « openExternalUrl(url) »Ouvre une URL externe via le shell Electron.
openExternalUrl(url: string): Promise<void>logEvent(event, details?)
Section intitulée « logEvent(event, details?) »Écrit un événement renderer dans le logger main.
logEvent(event: string, details?: Record<string, unknown>): Promise<void>onMenuAction(listener)
Section intitulée « onMenuAction(listener) »Écoute les actions du menu natif.
onMenuAction(listener: (action: MenuAction) => void): () => voidTypes applicatifs
Section intitulée « Types applicatifs »AppStateSnapshot
Section intitulée « AppStateSnapshot »interface AppStateSnapshot { appName: string; appVersion: string; currentWorkspace: ObscuraWorkspaceFile | null; settings: AppSettings; isDirty: boolean; lastError: string | null; offline: boolean; apiHealthStatus: ApiHealthStatus; syncStatus: SyncStatus; lastSyncAt: string | null;}SyncStatus
Section intitulée « SyncStatus »type SyncStatus = 'idle' | 'syncing' | 'success' | 'failed' | 'offline' | 'conflict';ApiHealthStatus
Section intitulée « ApiHealthStatus »interface ApiHealthStatus { state: 'idle' | 'checking' | 'online' | 'offline'; message: string | null; checkedAt: string | null;}API REST backend
Section intitulée « API REST backend »L’URL de base par défaut est:
https://141.253.100.136.sslip.io/apiElle est configurable dans les settings globaux.
GET /health ou GET /api/health
Section intitulée « GET /health ou GET /api/health »Utilisé pour vérifier la disponibilité de l’API.
L’application choisit le chemin selon l’URL de base configurée:
- si l’URL se termine par
/api, le chemin appelé est/health; - sinon, le chemin appelé est
/api/health.
Réponses acceptées:
okou:
{ "status": "ok"}ou:
{ "ok": true}Authentification
Section intitulée « Authentification »POST /auth/login
Section intitulée « POST /auth/login »Authentifie l’utilisateur.
Request:
{ "email": "user@example.com", "password": "password"}Response:
{ "token": "jwt-or-api-token", "user": { "id": "user-id", "email": "user@example.com", "username": "optional", "fullName": "optional", "role": "optional" }}POST /auth/logout
Section intitulée « POST /auth/logout »Notifie le backend de la déconnexion lorsque l’utilisateur possède une session locale.
Headers:
Authorization: Bearer <token>L’application supprime toujours la session locale, même si le backend est temporairement indisponible.
GET /me/license
Section intitulée « GET /me/license »Récupère la licence de l’utilisateur connecté.
Headers:
Authorization: Bearer <token>Response:
{ "licenseKey": "license-key", "plan": "pro", "status": "active", "expiresAt": "2026-12-31T23:59:59.000Z"}Workspaces
Section intitulée « Workspaces »GET /workspaces
Section intitulée « GET /workspaces »Liste les workspaces de l’utilisateur courant.
Headers optionnels:
Authorization: Bearer <token>Response:
[ { "schema": "obscura-flow-workspace-v1", "exportedAt": "2026-05-09T12:00:00.000Z", "workspace": { "id": "backend-or-workspace-id", "name": "Workspace name", "description": "Workspace description", "rootPath": "/local/path", "filePath": "/local/path/workspace.obf" }, "settings": {}, "projects": [], "archiveHistory": [] }]POST /workspaces
Section intitulée « POST /workspaces »Crée un workspace dans l’API.
Request:
{ "schema": "obscura-flow-workspace-v1", "exportedAt": "2026-05-09T12:00:00.000Z", "workspace": { "id": "local-workspace-uuid", "name": "Workspace name", "description": "Workspace description", "rootPath": "/local/path", "filePath": "/local/path/workspace.obf" }, "settings": {}, "projects": [], "archiveHistory": []}Response: WorkspaceEnvelope.
GET /workspaces/{id}
Section intitulée « GET /workspaces/{id} »Charge un workspace par identifiant backend.
PATCH /workspaces/{id}
Section intitulée « PATCH /workspaces/{id} »Met à jour un workspace existant.
Le body est identique à POST /workspaces.
DELETE /workspaces/{id}
Section intitulée « DELETE /workspaces/{id} »Endpoint référencé par le contrat OpenAPI initial. Non utilisé par l’application desktop actuelle.
Project lifecycle
Section intitulée « Project lifecycle »Les champs lifecycle ajoutés au payload projet sont:
{ "status": "ACTIVE", "workflowState": "completed", "revision": 1, "isReadOnly": false, "archivedAt": null, "closedAt": null, "reopenedAt": null, "lastWorkflowCompletionAt": null}Statuts supportés: DRAFT, ACTIVE, ARCHIVED, CLOSED, REOPENED.
GET /projects/{id}/lifecycle
Section intitulée « GET /projects/{id}/lifecycle »Retourne l’état lifecycle source-of-truth du projet.
GET /projects/{id}/revisions
Section intitulée « GET /projects/{id}/revisions »Retourne les révisions immutables du projet. Chaque révision contient id, projectId,
revisionNumber, status, createdAt, createdBy, reopenedFromRevision, archiveId,
integrityStatus, notes, metadataSnapshot et workflowSnapshot.
GET /projects/{id}/events
Section intitulée « GET /projects/{id}/events »Retourne l’historique d’audit immuable du projet. Les événements supportés sont
PROJECT_CREATED, PROJECT_ARCHIVED, PROJECT_SIGNED, PROJECT_SYNCED, PROJECT_CLOSED,
PROJECT_REOPENED, PROJECT_REVISION_CREATED, PROJECT_ARCHIVE_REGENERATED,
PROJECT_INTEGRITY_FAILED et PROJECT_INTEGRITY_VALIDATED.
POST /projects/{id}/archive
Section intitulée « POST /projects/{id}/archive »Demande une archive/re-archive côté API. Le client desktop continue de produire le package
localement et synchronise ensuite l’historique via POST /archives.
POST /projects/{id}/close
Section intitulée « POST /projects/{id}/close »Ferme explicitement le projet, fixe status = CLOSED, isReadOnly = true, closedAt, et
ajoute un événement PROJECT_CLOSED.
POST /projects/{id}/reopen
Section intitulée « POST /projects/{id}/reopen »Valide l’intégrité de la dernière archive connue puis crée une nouvelle révision. Le projet
revient en workflow actif avec archive OUTDATED et intégrité PENDING, sans supprimer les
archives, signatures, manifests ou rapports précédents.
POST /projects/{id}/revisions/{revision}/restore
Section intitulée « POST /projects/{id}/revisions/{revision}/restore »Demande une restauration depuis une révision conservée. L’historique de révision reste immuable.
Synchronisation
Section intitulée « Synchronisation »POST /sync/push
Section intitulée « POST /sync/push »Envoie les opérations locales en attente.
Les entités synchronisables incluent workspace, project, archive, lineage,
projectRevision et projectEvent.
Request:
{ "clientId": "desktop-client-uuid", "source": "desktop", "operations": [ { "entity": "workspace", "id": "local-operation-or-workspace-id", "operation": "updated", "version": 2, "payload": { "localWorkspaceId": "workspace-uuid", "backendWorkspaceId": "backend-id-or-null", "workspace": {} } } ]}Response:
{ "applied": [], "conflicts": [], "failed": []}GET /sync/changes?clientId={clientId}&limit=200&since={cursor}
Section intitulée « GET /sync/changes?clientId={clientId}&limit=200&since={cursor} »Récupère les événements de synchronisation distants.
Response:
{ "cursor": "last-event-id", "events": [ { "id": "event-id", "entityType": "workspace", "entityId": "workspace-id", "operation": "updated", "version": 2, "source": "web", "userId": "user-uuid", "payload": {}, "createdAt": "2026-05-09T12:00:00.000Z" } ], "count": 1, "total": 1, "hasMore": false}POST /sync/ack
Section intitulée « POST /sync/ack »Accuse réception du dernier événement traité.
Request:
{ "clientId": "desktop-client-uuid", "lastEventId": "event-id"}GET /sync/state
Section intitulée « GET /sync/state »Endpoint référencé par le contrat OpenAPI initial. Non utilisé directement par l’application desktop actuelle.
POST /sync/events
Section intitulée « POST /sync/events »Endpoint référencé par le contrat OpenAPI initial. Non utilisé directement par l’application desktop actuelle.
Archives
Section intitulée « Archives »POST /archives
Section intitulée « POST /archives »Crée une entrée d’historique d’archive dans l’API après une archive locale réussie.
Headers:
Authorization: Bearer <token>Request (CreateArchiveRequest):
{ "workspaceId": "workspace-uuid", "projectId": "project-uuid", "projectName": "EXIF Project", "archiveFile": "2026-05-12_gipsy-soul.zip", "archivePath": "/Users/demo/Archives/2026-05-12_gipsy-soul.zip", "packageDirectory": "/Users/demo/Archives/2026-05-12_gipsy-soul", "manifestPath": "/Users/demo/Archives/2026-05-12_gipsy-soul/manifest.json", "signaturePath": "/Users/demo/Archives/2026-05-12_gipsy-soul/signature.ed25519", "packageStatus": "valid", "localIntegrityStatus": "valid", "engine": "zip", "fileSizeBytes": 1048576, "checksum": "sha256:abcdef...", "archivedAt": "2026-05-12T15:50:22.000Z", "status": "completed"}Response: ArchiveHistoryItem.
Roadmap API Archive Package:
POST /archive-packagespour enregistrer les métadonnées de package courant;GET /archive-packages/{id}pour récupérer manifest, état d’intégrité et références distantes;POST /archive-packages/{id}/verifypour lancer une validation locale/remote;POST /archive-packages/{id}/repairpour demander une action de réparation supportée;POST /archive-packages/{id}/restore/simulateet/restorepour restaurer depuis un package vérifié.
Les endpoints futurs doivent pouvoir représenter chaque objet distant du package courant: archive compressée, manifest et signature. Ils pourront ensuite évoluer vers des objets additionnels comme lineage, restore map, rapports et logs.
GET /archives
Section intitulée « GET /archives »Liste l’historique d’archives pour l’utilisateur courant.
Headers:
Authorization: Bearer <token>GET /archives/{id}
Section intitulée « GET /archives/{id} »Récupère une entrée d’archive par identifiant backend.