Files
webmanager-mvp/project_docs/API_GOLDEN.md
T
2026-03-15 15:51:13 +01:00

4.2 KiB

API_GOLDEN.md

Dit document definieert stabiele API responses. Velden mogen niet wijzigen zonder golden tests te updaten.

Browse

GET /api/browse

Response shape:

{
  "path": "storage1",
  "directories": [],
  "files": []
}

File Ops (direct)

POST /api/files/mkdir

Success:

{ "path": "storage1/parent/new_dir" }

Conflict (already_exists):

{
  "error": {
    "code": "already_exists",
    "message": "Target path already exists",
    "details": { "path": "storage1/parent/new_dir" }
  }
}

Invalid name (invalid_request):

{
  "error": {
    "code": "invalid_request",
    "message": "Invalid name",
    "details": { "name": "bad/name" }
  }
}

POST /api/files/rename

Success:

{ "path": "storage1/parent/new_name.ext" }

Conflict (already_exists) + invalid name (invalid_request) gebruiken dezelfde error-shape als mkdir.

POST /api/files/delete

Success (202):

{
  "task_id": "<uuid>",
  "status": "queued"
}

Non-empty directory:

{
  "error": {
    "code": "directory_not_empty",
    "message": "Directory is not empty",
    "details": { "path": "storage1/parent/non_empty" }
  }
}

Task-based create endpoints

POST /api/files/copy

POST /api/files/move

POST /api/files/delete

Success (202):

{
  "task_id": "<uuid>",
  "status": "queued"
}

Notes:

  • Batch move is supported as one task-based operation via { "sources": [...], "destination_base": "..." }.
  • Cross-root batch move is supported for file-only selections.
  • Cross-root batch move with any directory in the selection remains unsupported in v1.
  • Batch delete is supported as one task-based operation via { "paths": [...], "recursive_paths": [...] }.
  • Single delete remains supported via { "path": "...", "recursive": true|false }.

Tasks read endpoints

GET /api/tasks

Response shape:

{
  "items": [
    {
      "id": "<uuid>",
      "operation": "copy",
      "status": "running",
      "source": "storage1/a.txt",
      "destination": "storage2/a.txt",
      "created_at": "2026-03-10T10:00:00Z",
      "finished_at": null
    }
  ]
}

GET /api/tasks/{task_id}

Response shape:

{
  "id": "<uuid>",
  "operation": "move",
  "status": "running",
  "source": "storage1/a.txt",
  "destination": "storage2/a.txt",
  "done_bytes": 1024,
  "total_bytes": 4096,
  "done_items": null,
  "total_items": null,
  "current_item": "storage1/a.txt",
  "failed_item": null,
  "error_code": null,
  "error_message": null,
  "created_at": "2026-03-10T10:00:00Z",
  "started_at": "2026-03-10T10:00:01Z",
  "finished_at": null
}

Voor task-based file-actions copy, move, duplicate en delete betekenen progressvelden:

  • done_items: aantal volledig verwerkte bestanden
  • total_items: exact aantal te verwerken bestanden in de hele task
  • current_item: taakrelatief bestandspad als beschikbaar, anders bestandsnaam

Voor move geldt een expliciete uitzondering:

  • file-gebaseerde move-paden rapporteren file-progress
  • same-root directory moves behouden directe rename-semantiek en rapporteren daarom grovere item-progress per directory-operatie

Voor delete geldt:

  • recursive delete van directorytrees rapporteert file-progress per verwijderd bestand
  • lege mappen of directory-only deletes houden done_items = 0, total_items = 0 en gebruiken geen kunstmatige file-teller

POST /api/tasks/{task_id}/cancel

Success for cancellable file-action task:

{
  "id": "<uuid>",
  "operation": "copy",
  "status": "cancelling",
  "source": "2 items",
  "destination": "storage1/dest",
  "done_bytes": null,
  "total_bytes": null,
  "done_items": 0,
  "total_items": 2,
  "current_item": "storage1/a.txt",
  "failed_item": null,
  "error_code": null,
  "error_message": null,
  "created_at": "2026-03-10T10:00:00Z",
  "started_at": "2026-03-10T10:00:01Z",
  "finished_at": null
}

Not cancellable:

{
  "error": {
    "code": "task_not_cancellable",
    "message": "Task cannot be cancelled",
    "details": { "task_id": "<uuid>", "status": "completed" }
  }
}

Task not found:

{
  "error": {
    "code": "task_not_found",
    "message": "Task was not found",
    "details": { "task_id": "task-missing" }
  }
}