Phase 302 — Liv AI "Upload from device" fix
AionUi's composer "+ → Upload from device" and drag-drop POST files to /api/fs/upload, which 404'd because the vendored aionui-web build has no filesystem backend (same class as the Phase 299 /api/fs/browse bug). Both surfaces were broken: the navbar AionUi iframe and the LivOS command bar.
- Added
POST /api/fs/uploadto livinityd implementing AionUi's exact contract (multipartfile/file_name/conversation_id→{success, data:"<path>"}), reusing the existing Busboy upload pattern with a sandboxed temp write. - Hardened per adversarial review: traversal-proof filename (separators + NUL stripped),
..-rejecting conversation_id, atomic O_EXCL create, active-user auth, 110MB cap. - Pointed the LivOS command bar's upload at the apex route (was the backend-less
/liv/api/fs/upload).
Gates: livinityd tsc 385 (zero net-new) · ui build 0 · adversarial review (routing, Busboy race, response shape confirmed).
Full Changelog: v44.86...v44.87