Cyclone SP37
f1dc06ec3b
feat(sp37): POST /api/submit-batch endpoint
...
Thin HTTP wrapper around `cyclone.submission.submit_file` — the
HTTP twin of the `cyclone submit-batch` CLI (SP37 Task 5). Same
walker pattern, same `._*` AppleDouble skip, same `limit`
semantics, same per-file outcomes; both surfaces now agree on DB +
SFTP state byte-for-byte.
Body: `{ingest_dir, validate?, actor?, limit?}`. Response:
`{submitted, skipped, failed, results:[{file, outcome, batch_id,
error}]}`. Status codes:
- 200 on completed runs (per-file failures live in the body)
- 401 unauthenticated (matrix_gate)
- 404 no clearhouse seeded
- 409 clearhouse SFTP block in stub mode
- 422 ingest_dir missing on disk or Pydantic body error
Does NOT inject `sftp_client_factory` — submit_file uses its
default paramiko factory so SKIPPED is reachable in production.
Tests monkey-patch submit_file itself.
Permissions entry: `POST /api/submit-batch` → WRITE_ROLES (admin +
user), matching `POST /api/resubmit` posture.
Tests (11): happy path, AppleDouble skip, limit, empty ingest_dir
422, mixed-outcome 200, unexpected-exception-as-failed,
Pydantic-missing-422, on-disk-missing-422, no-clearhouse-404,
stub-mode-409, auth-gate-401.
2026-07-07 11:36:47 -06:00
..
2026-07-07 10:50:48 -06:00
2026-07-02 17:08:09 -06:00
2026-06-20 18:29:28 -06:00
2026-06-24 17:51:44 -06:00
2026-06-29 10:09:10 -06:00
2026-07-07 10:34:46 -06:00
2026-07-06 09:53:53 -06:00
2026-07-06 09:52:51 -06:00
2026-07-06 09:53:53 -06:00
2026-07-02 09:00:54 -06:00
2026-06-20 23:45:43 -06:00
2026-06-21 09:43:51 -06:00
2026-06-22 11:01:58 -06:00
2026-07-02 12:22:29 -06:00
2026-06-20 19:37:38 -06:00
2026-06-24 22:05:55 -06:00
2026-06-29 11:00:37 -06:00
2026-06-20 08:22:31 -06:00
2026-07-02 14:18:55 -06:00
2026-06-20 19:35:17 -06:00
2026-06-22 11:01:58 -06:00
2026-06-20 08:03:37 -06:00
2026-06-20 18:58:56 -06:00
2026-06-29 14:32:10 -06:00
2026-07-06 14:01:37 -06:00
2026-06-24 22:05:55 -06:00
2026-06-20 20:34:44 -06:00
2026-06-20 16:57:30 -06:00
2026-07-07 11:36:47 -06:00
2026-07-06 09:53:53 -06:00
2026-06-21 10:46:10 -06:00
2026-07-06 09:51:27 -06:00
2026-06-20 23:41:01 -06:00
2026-07-02 21:07:07 -06:00
2026-07-02 12:22:29 -06:00
2026-06-22 15:34:18 -06:00
2026-06-20 23:45:43 -06:00
2026-06-22 15:59:08 -06:00
2026-06-23 17:24:23 -06:00
2026-06-22 15:34:05 -06:00
2026-06-22 15:59:08 -06:00
2026-06-22 15:59:08 -06:00
2026-06-22 15:59:08 -06:00
2026-06-22 15:59:08 -06:00
2026-07-02 17:16:59 -06:00
2026-06-21 09:43:51 -06:00
2026-06-21 09:43:51 -06:00
2026-06-21 09:43:51 -06:00
2026-06-20 17:17:09 -06:00
2026-07-07 10:30:23 -06:00
2026-07-07 10:22:32 -06:00
2026-06-20 07:44:41 -06:00
2026-06-24 22:05:55 -06:00
2026-06-19 17:07:54 -06:00
2026-06-21 09:43:51 -06:00
2026-06-22 15:34:18 -06:00
2026-06-21 10:46:10 -06:00
2026-06-19 16:00:47 -06:00
2026-06-19 17:01:57 -06:00
2026-07-02 21:50:23 -06:00
2026-07-02 20:23:56 -06:00
2026-06-29 12:51:28 -06:00
2026-06-21 00:33:37 -06:00
2026-07-07 10:13:00 -06:00
2026-07-02 14:59:49 -06:00
2026-06-19 21:03:21 -06:00
2026-06-24 16:09:19 -06:00
2026-07-02 12:22:29 -06:00
2026-06-19 15:31:06 -06:00
2026-06-22 15:59:08 -06:00
2026-06-24 23:23:46 -06:00
2026-06-29 10:46:29 -06:00
2026-06-29 12:08:47 -06:00
2026-07-02 08:52:20 -06:00
2026-06-29 10:38:32 -06:00
2026-06-29 11:30:00 -06:00
2026-06-20 19:43:43 -06:00
2026-06-20 23:41:01 -06:00
2026-07-02 13:16:38 -06:00
2026-06-20 18:25:25 -06:00
2026-06-22 17:46:47 -06:00
2026-06-21 00:13:47 -06:00
2026-06-20 19:29:21 -06:00
2026-06-29 13:22:42 -06:00
2026-06-21 09:59:34 -06:00
2026-06-21 09:59:34 -06:00
2026-06-21 09:59:34 -06:00
2026-07-07 10:13:00 -06:00
2026-06-20 08:22:31 -06:00
2026-06-20 08:22:31 -06:00
2026-06-19 17:01:57 -06:00
2026-06-20 08:03:37 -06:00
2026-06-19 15:39:08 -06:00
2026-06-21 10:46:10 -06:00
2026-06-20 08:22:31 -06:00
2026-06-20 08:22:31 -06:00
2026-06-20 23:41:01 -06:00
2026-07-02 16:56:01 -06:00
2026-07-02 21:50:23 -06:00
2026-06-25 00:26:13 -06:00
2026-06-20 18:58:56 -06:00
2026-06-20 23:41:01 -06:00
2026-06-20 23:07:31 -06:00
2026-06-21 00:13:47 -06:00
2026-07-02 21:50:23 -06:00
2026-07-02 21:07:07 -06:00
2026-06-20 20:27:48 -06:00
2026-07-02 16:23:42 -06:00
2026-06-24 22:05:55 -06:00
2026-06-20 16:57:30 -06:00
2026-06-20 19:33:02 -06:00
2026-07-02 17:08:09 -06:00
2026-06-24 15:36:19 -06:00
2026-06-29 11:53:56 -06:00
2026-06-24 23:23:46 -06:00
2026-06-20 18:30:05 -06:00
2026-06-24 15:29:52 -06:00
2026-06-24 16:06:54 -06:00
2026-06-20 23:07:31 -06:00
2026-06-21 10:21:01 -06:00
2026-06-19 15:36:01 -06:00
2026-06-20 08:22:31 -06:00
2026-06-22 11:01:58 -06:00
2026-06-20 08:03:37 -06:00
2026-06-20 19:27:24 -06:00
2026-06-29 11:43:58 -06:00
2026-06-24 23:23:46 -06:00
2026-06-24 22:05:55 -06:00
2026-07-02 08:47:03 -06:00
2026-06-29 14:32:10 -06:00
2026-06-29 12:21:34 -06:00
2026-06-29 14:32:10 -06:00
2026-07-02 08:45:19 -06:00
2026-06-24 22:05:55 -06:00
2026-06-20 18:10:07 -06:00
2026-07-07 11:10:10 -06:00
2026-06-20 23:07:31 -06:00
2026-06-19 17:01:57 -06:00
2026-06-21 10:46:10 -06:00
2026-06-19 15:56:09 -06:00