Appearance
storage — 存储管理(STS 直传链路)(7 action)
前缀:
/api/v1/admin/storage/权限:读 =STORAGE_READ(super + operator + it);删 =STORAGE_DELETE(super + operator,it 删除一律 403) 代码:src/app/admin/interface/api/storage_mgmt.py+application/usecase/storage_mgmt.py规划/设计:.claude/plan/admin-storage-management{,-design}.md⚠️ App 端四端点(/api/v1/storage/{sts,complete,download-url,delete})契约零变化 — 本域为 admin 跨用户视角
1. records —— 上传记录列表(时间流)
GET /api/v1/admin/storage/records · 权限 STORAGE_READ
Query 参数:
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
page | int | ⬜ | 1 | ≥1 |
page_size | int | ⬜ | 20 | 1~100 |
user_id | string | ⬜ | — | 用户 ID(精确匹配) |
type | string | ⬜ | — | 数据包类型(如 xiaomi_zip / coros_fit) |
status | string | ⬜ | — | pending / parsing / parsed / failed |
date_from / date_to | string | ⬜ | — | ISO 日期(含当日 00:00:00 / 23:59:59) |
响应 data:{ total, items: [UploadRecord] }(created_at 倒序;筛选 AND 语义) UploadRecord 字段:id(up-N)/ user_id / type / cos_url / object_key / mime / size / status / password / parsed_result / error_msg / created_at
2. records/{id} —— 记录详情
GET /api/v1/admin/storage/records/{record_id} · 权限 STORAGE_READ
响应 data:{ record: UploadRecord }(全字段 — 抽屉渲染用)
错误码:40201004 记录不存在(HTTP 404 — 与权限码同值别名,靠 HTTP 状态区分)。
3. records/{id} —— 删除(对象 + 记录双删)
DELETE /api/v1/admin/storage/records/{record_id} · 权限 STORAGE_DELETE
语义:查记录 → COS 对象删除(幂等)→ 记录删除 → admin_audit 留痕(action=STORAGE_RECORD_DELETE)。 ⚠️ 与 App 端属主删除不同:admin 跨用户,无属主校验(RBAC 已收口)。
响应 data:{ ok, object_deleted, record_deleted, object_key }
错误码:40201004 记录不存在(HTTP 404;已删过再删同样 404,前端提示「记录不存在」)。
4. stats —— 统计看板
GET /api/v1/admin/storage/stats · 权限 STORAGE_READ
响应 data:
json
{
"total_count": 12480,
"total_size": 92644487168,
"type_dist": {"xiaomi_zip": 7740, "coros_fit": 3870},
"status_dist": {"parsed": 12410, "pending": 52, "parsing": 18, "failed": 37},
"trend_30d": [{"date": "2026-09-11", "count": 12}, "…共 30 项逐日补零升序"]
}实时 SQL 聚合(generate_series 逐日补零)——前端免补点。
5. config-health —— 配置健康 + 自检
GET /api/v1/admin/storage/config-health[?self_check=true] · 权限 STORAGE_READ
| 档位 | 行为 |
|---|---|
| 默认(轻档) | env 五键脱敏现状 + 规则常量 + checks: [] / all_ok: null |
self_check=true(重档) | 真发 STS AssumeRole 冒烟(探针身份 __health_probe__)+ 桶列举探测,逐项 {name, ok, detail, elapsed_ms} |
响应 data:{ env, env_missing, rules, checks, self_check, all_ok } ⚠️ env.STS_SECRET_KEY 恒 "******"(密钥永不回显);rules 为代码常量只读快照(max_size/allowed_mime/allowed_exts/rate_limit/sts_duration/download_ttl)。
6. orphan-scan —— 孤儿对账(桶 ↔ 记录双向)
POST /api/v1/admin/storage/orphan-scan · 权限 STORAGE_READ
同步扫描(最长约 30s — 前端需 60s timeout):COS uploads/ 前缀列举(上限 1000 对象)↔ upload_record 全量 object_key。
⚠️ 竞态防护:桶侧排除最近修改 1 小时内的对象(「已 PUT 未 complete」的上传中文件会被误判为孤儿,直接删会打断真实用户上传)= recent_excluded 计数。 ⚠️ truncated=true(达 1000 上限)时不返回 record_orphans(桶 key 集不完整,记录侧差集不可信)。
响应 data:
json
{
"bucket_orphans": [{"object_key": "uploads/…", "size": 812, "last_modified": "…"}],
"record_orphans": [{"record_id": "up-1239", "object_key": "uploads/…", "type": "…", "created_at": "…"}],
"scanned_objects": 342,
"truncated": false,
"recent_excluded": 2,
"elapsed_ms": 8210
}7. orphan-delete —— 批量删桶孤儿
POST /api/v1/admin/storage/orphan-delete · 权限 STORAGE_DELETE
Body:{ "object_keys": ["uploads/…", "…"] }(≤ 50/次) 语义:逐个 cz_delete_object(幂等);单项失败不中断,逐项回报;聚合 admin_audit 留痕(action=STORAGE_ORPHAN_DELETE)。
响应 data:{ requested, deleted: [{object_key, ok}], failed: [{object_key, error}] }
错误码:40201001 object_keys 非数组/为空/超 50 上限(HTTP 400)。
错误码一览
| 码 | 场景 | HTTP |
|---|---|---|
40201002 | 未登录 / token 无效 | 401 |
40201004 | RBAC 权限不足(无 storage:read / storage:delete) | 403 |
40201001 | 参数非法(object_keys 形态/上限) | 400 |
40201004 | 记录不存在(详情/删除 miss — 与权限码同值别名) | 404 |
审计动作登记
| action | 触发 | target |
|---|---|---|
STORAGE_RECORD_DELETE | 端点 3 | upload_record / record_id(before 含 object_key+user_id) |
STORAGE_ORPHAN_DELETE | 端点 7 | cos_object / batch:Nok/Mfail(before 含 object_keys 全量) |