Aller au contenu

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.

L’API renderer est exposée par src/preload/index.ts.

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.

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;
  • freeDiskGb et totalDiskGb: état du volume applicatif;
  • warnings: liste des pressions détectées (cpu, memory, disk).

Contrôle le health de l’API et retourne un snapshot applicatif mis à jour.

checkApiHealth(): Promise<AppStateSnapshot>

Crée un workspace local et tente une synchronisation API.

createWorkspace(params: {
name: string;
description?: string;
}): Promise<AppStateSnapshot>

Ouvre un fichier .obf via un sélecteur système.

openWorkspace(): Promise<AppStateSnapshot | null>

Ouvre un workspace depuis son chemin récent.

openRecentWorkspace(filePath: string): Promise<AppStateSnapshot>

Retire un workspace de la liste des récents.

removeRecentWorkspace(filePath: string): Promise<AppStateSnapshot>

Ferme le workspace courant.

closeWorkspace(): Promise<AppStateSnapshot>

Prépare la vue My workspaces, charge les workspaces distants via GET /workspaces et tente de drainer la synchronisation en attente.

showWorkspaces(): Promise<AppStateSnapshot>

Ouvre un sélecteur système de dossier.

browseDirectory(defaultPath?: string): Promise<string | null>

Authentifie l’utilisateur et récupère la licence lorsque disponible.

authenticate(credentials: {
email: string;
password: string;
}): Promise<AppStateSnapshot>

Supprime la session locale.

logout(): Promise<AppStateSnapshot>

Met à jour les settings globaux de l’application.

updateSettings(settings: Partial<AppSettings>): Promise<AppStateSnapshot>

Remplace les settings du workspace courant, sauvegarde le .obf et tente une synchronisation API.

updateWorkspaceSettings(settings: WorkspaceSettings): Promise<AppStateSnapshot>

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>

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.gz ou .zst selon 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.

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>

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.

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.ext
archives/<workspaceId>/<projectId>/<archiveId>/manifest.json
archives/<workspaceId>/<projectId>/<archiveId>/signature.ed25519

Aprè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[].

Retourne l’inventaire des archives distantes construit depuis archiveHistory.remoteCopies.

listRemoteArchiveInventory({
target?: 'primary' | 'secondary';
}): Promise<RemoteArchiveInventoryItem[]>

Relit les métadonnées distantes et valide que le package distant correspond au package local.

validateRemoteArchive({
archiveId: string;
target: 'primary' | 'secondary';
}): Promise<AppStateSnapshot>

Télécharge les fichiers du package distant dans le dossier local du package.

downloadRemoteArchivePackage({
archiveId: string;
target: 'primary' | 'secondary';
}): Promise<AppStateSnapshot>

Supprime les fichiers distants du package après double confirmation côté UI.

deleteRemoteArchivePackage({
archiveId: string;
target: 'primary' | 'secondary';
}): Promise<AppStateSnapshot>

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>

Lance la reconstruction de l’index projet pour le workspace courant.

startProjectIndexRebuild(): Promise<AppStateSnapshot>

Annule la reconstruction d’index en cours.

cancelProjectIndexRebuild(): Promise<void>

Relance une reconstruction d’index après un échec.

retryProjectIndexRebuild(): Promise<AppStateSnapshot>

Demande l’arrêt de l’archive en cours pour le project.

cancelProjectArchive({ projectId: string }): Promise<void>

Ouvre une URL externe via le shell Electron.

openExternalUrl(url: string): Promise<void>

Écrit un événement renderer dans le logger main.

logEvent(event: string, details?: Record<string, unknown>): Promise<void>

Écoute les actions du menu natif.

onMenuAction(listener: (action: MenuAction) => void): () => void
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;
}
type SyncStatus = 'idle' | 'syncing' | 'success' | 'failed' | 'offline' | 'conflict';
interface ApiHealthStatus {
state: 'idle' | 'checking' | 'online' | 'offline';
message: string | null;
checkedAt: string | null;
}

L’URL de base par défaut est:

https://141.253.100.136.sslip.io/api

Elle est configurable dans les settings globaux.

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:

ok

ou:

{
"status": "ok"
}

ou:

{
"ok": true
}

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"
}
}

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.

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"
}

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": []
}
]

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.

Charge un workspace par identifiant backend.

Met à jour un workspace existant.

Le body est identique à POST /workspaces.

Endpoint référencé par le contrat OpenAPI initial. Non utilisé par l’application desktop actuelle.

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.

Retourne l’état lifecycle source-of-truth du projet.

Retourne les révisions immutables du projet. Chaque révision contient id, projectId, revisionNumber, status, createdAt, createdBy, reopenedFromRevision, archiveId, integrityStatus, notes, metadataSnapshot et workflowSnapshot.

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.

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.

Ferme explicitement le projet, fixe status = CLOSED, isReadOnly = true, closedAt, et ajoute un événement PROJECT_CLOSED.

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.

Demande une restauration depuis une révision conservée. L’historique de révision reste immuable.

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
}

Accuse réception du dernier événement traité.

Request:

{
"clientId": "desktop-client-uuid",
"lastEventId": "event-id"
}

Endpoint référencé par le contrat OpenAPI initial. Non utilisé directement par l’application desktop actuelle.

Endpoint référencé par le contrat OpenAPI initial. Non utilisé directement par l’application desktop actuelle.

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-packages pour 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}/verify pour lancer une validation locale/remote;
  • POST /archive-packages/{id}/repair pour demander une action de réparation supportée;
  • POST /archive-packages/{id}/restore/simulate et /restore pour 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.

Liste l’historique d’archives pour l’utilisateur courant.

Headers:

Authorization: Bearer <token>

Récupère une entrée d’archive par identifiant backend.