feat(routers): migrate hosted_file hash lookup to V3 actions
Ported the legacy '/hosted_file/hash/{hash}' endpoint to the V3 actions router.
The new endpoint '/v3/action/hosted_file/hash/{hosted_file_hash}' supports:
- ID Vision: returns random string IDs instead of internal integers
- Local Check: verifies physical file existence on disk (check_for_local=True)
- Deduplication: enables frontend to check for existing files before upload
Also added PROJECT document for AE Hosted Files migration tracking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
124
documentation/PROJECT__AE_hosted_files_uploads_util.md
Normal file
124
documentation/PROJECT__AE_hosted_files_uploads_util.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# PROJECT: AE Hosted Files — Upload Util & V3 Actions Migration
|
||||
|
||||
**Status:** In Progress
|
||||
**Date:** 2026-03-25
|
||||
**Affected systems:** Frontend (aether_app_sveltekit), Backend (aether_api_fastapi)
|
||||
|
||||
---
|
||||
|
||||
## Background
|
||||
|
||||
The legacy `hosted_file.router` (registered at prefix `/hosted_file`) was commented out
|
||||
in `app/routers/registry.py` as part of the V3 migration:
|
||||
|
||||
```python
|
||||
# app.include_router(hosted_file.router, prefix='/hosted_file', tags=['Hosted File'])
|
||||
app.include_router(api_v3_actions_hosted_file.router, prefix='/v3/action/hosted_file', ...)
|
||||
```
|
||||
|
||||
This broke several frontend features that were still calling the old endpoints.
|
||||
Three endpoints have been fixed on the frontend side (already committed and pushed).
|
||||
One endpoint still needs a backend fix.
|
||||
|
||||
---
|
||||
|
||||
## Endpoints: Status Summary
|
||||
|
||||
### FIXED (frontend updated to call new V3 path)
|
||||
|
||||
| Old endpoint | New endpoint | Frontend file |
|
||||
|---|---|---|
|
||||
| `POST /hosted_file/upload_files` | `POST /v3/action/hosted_file/upload` | `src/lib/ae_core/ae_comp__hosted_files_upload.svelte`, `src/routes/events/ae_comp__event_files_upload.svelte` |
|
||||
| `GET /hosted_file/{id}/clip_video` | `GET /v3/action/hosted_file/{id}/clip_video` | `src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte` |
|
||||
|
||||
### NEEDS BACKEND ACTION — Hash Lookup Endpoint
|
||||
|
||||
**Missing endpoint:** `GET /hosted_file/hash/{hosted_file_hash}`
|
||||
|
||||
This endpoint existed in the legacy `hosted_file.py` router (line 233) and has **not** been
|
||||
ported to `api_v3_actions_hosted_file.py`.
|
||||
|
||||
**What it does:**
|
||||
1. Looks up a `hosted_file` record by its `hash_sha256` field
|
||||
2. Optionally checks that the physical file actually exists on disk (`check_for_local=true`)
|
||||
3. Returns the full hosted_file object with two extra flags:
|
||||
- `hosted_file_found_check: true` — file record exists AND physical file confirmed on disk
|
||||
- `hosted_file_size_check: <bytes>` — file size from disk
|
||||
|
||||
**Legacy implementation (hosted_file.py:233):**
|
||||
```python
|
||||
@router.get('/hash/{hosted_file_hash}', response_model=Resp_Body_Base)
|
||||
async def check_hosted_file_obj_w_hash(
|
||||
hosted_file_hash: str = Path(min_length=64, max_length=64),
|
||||
check_for_local: Optional[bool] = True,
|
||||
commons: Common_Route_Params = Depends(common_route_params),
|
||||
):
|
||||
if hfid := lookup_file_hash(file_hash=hosted_file_hash):
|
||||
obj = load_hosted_file_obj(hosted_file_id=hfid, model_as_dict=True)
|
||||
if check_for_local and obj:
|
||||
if check := check_for_hosted_file_hash_file(file_hash=hosted_file_hash, sub_dir=obj.get('subdirectory_path', '')):
|
||||
obj['hosted_file_found_check'] = True
|
||||
obj['hosted_file_size_check'] = check['file_size']
|
||||
return mk_resp(data=obj, response=commons.response)
|
||||
return mk_resp(data=False, status_code=404, response=commons.response)
|
||||
```
|
||||
|
||||
**Where it's called on the frontend:**
|
||||
- `src/lib/ae_core/core__check_hosted_file_obj_w_hash.ts` — thin wrapper, calls `GET /hosted_file/hash/{hash}`
|
||||
- `src/lib/elements/element_input_file.svelte` — calls this before uploading (dedup check)
|
||||
- `src/lib/elements/element_input_files_tbl.svelte` — same (dedup check in the table file input)
|
||||
- Exported via `src/lib/ae_core/ae_core_functions.ts` as `core_func.check_hosted_file_obj_w_hash`
|
||||
|
||||
**Current impact:** The 404 causes a null return. The frontend checks
|
||||
`result && result.hosted_file_found_check` — so if null, it silently skips the dedup check
|
||||
and proceeds to upload anyway. Uploads still work, but duplicate files may be created rather
|
||||
than reusing existing records.
|
||||
|
||||
**Requested fix (backend):**
|
||||
Port this endpoint to `api_v3_actions_hosted_file.py` as:
|
||||
|
||||
```
|
||||
GET /v3/action/hosted_file/hash/{hosted_file_hash}
|
||||
```
|
||||
|
||||
Parameters and response shape should match the legacy implementation exactly.
|
||||
The `check_for_local` query param (default `True`) must be preserved — the frontend
|
||||
passes `check_for_local=true` and expects `hosted_file_found_check` in the response.
|
||||
|
||||
**After backend deploys the new endpoint**, the frontend needs one line changed in
|
||||
`src/lib/ae_core/core__check_hosted_file_obj_w_hash.ts`:
|
||||
```ts
|
||||
// Before:
|
||||
const endpoint = `/hosted_file/hash/${hosted_file_hash}`;
|
||||
// After:
|
||||
const endpoint = `/v3/action/hosted_file/hash/${hosted_file_hash}`;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Other Legacy Endpoints — Audit Notes
|
||||
|
||||
The following were also in `hosted_file.py` but appear to either have V3 equivalents already
|
||||
or are not currently called by the frontend. Backend should confirm:
|
||||
|
||||
| Legacy endpoint | V3 equivalent | Notes |
|
||||
|---|---|---|
|
||||
| `GET /hosted_file/{id}/download` | `GET /v3/action/hosted_file/{id}/download` | Exists in V3 router |
|
||||
| `DELETE /hosted_file/{id}` | `DELETE /v3/action/hosted_file/{id}` | Exists in V3 router |
|
||||
| `GET /hosted_file/{id}/convert_file` | `GET /v3/action/hosted_file/{id}/convert_file` | Exists in V3 router |
|
||||
| `GET /hosted_file/{id}/stream` | Unknown | Not confirmed in V3 router — verify |
|
||||
| `GET /hosted_file/directory_check` | Unknown | Admin/dev utility — verify if still needed |
|
||||
| `GET /hosted_file/hash/{hash}/download` (via V3) | `GET /v3/action/hosted_file/hash/{sha256}/download` | Exists in V3 router (hash-based download) |
|
||||
| `GET /hosted_file/tmp/{subdir}/{filename}/download` | Unknown | Temp file download — verify if still needed |
|
||||
| `POST /hosted_file/create_video` | Unknown | Verify if still needed |
|
||||
|
||||
---
|
||||
|
||||
## Coordinator Notes
|
||||
|
||||
- Frontend commits fixing upload and clip_video are on branch `ae_app_3x_llm`
|
||||
(commits `a5a806e2` and `362136e6`)
|
||||
- Once the backend adds the hash lookup endpoint, the frontend one-line fix in
|
||||
`core__check_hosted_file_obj_w_hash.ts` can be committed alongside it
|
||||
- The `check_for_local` flag is important — it verifies the physical file exists on disk,
|
||||
not just the DB record. Don't drop it in the V3 port.
|
||||
Reference in New Issue
Block a user