feat(meowpanel): 通知中心+文件管理后端补全 (agent-182) — /api/notifications(读TF归档,环形200条)+单删+dismiss_all(保留媒体/进度活动通知); 文件域修4bug(normalize_path丢前导/致白名单必失败、upload multipart 文件名截断恒NULL、rename拼错路径恒ENOTDIR、read>1MB改truncated) + 上传8MB上限+文件名净化+双重白名单防逃逸
meowpanel 8108852f→58a7b186; mipsel/host -Wall -Wextra 0 warning; 宿主 curl 自测全过 需launcher配合项(已记录): MSG_NOTIFY_QUERY 查询帧 + dismiss 广播 IPC
This commit is contained in:
1 parent
c187b7bce3
commit
563a9be1d6
5 files changed
+438
-75
No files matched your search
@@ -102,18 +102,22 @@ http://<host>.local:8080/
|
||||
| POST | `/api/key` | 批量/顺序注入 | ✅ |
|
||||
| GET | `/api/logs` | `MeowOS/logs` 文件列表 | ✅(无卡→503) |
|
||||
| GET | `/api/logs/read?file=&lines=` | 读日志(上限 1000 行;`..`/绝对→403;敏感名→403) | ✅ |
|
||||
| GET | `/api/notifications` | **501** | ⚠️ |
|
||||
| DELETE | `/api/notifications/:id` | **501** | ⚠️ |
|
||||
| POST | `/api/notifications/dismiss_all` | **501** | ⚠️ |
|
||||
| GET | `/api/notifications` | 通知列表(读 TF 转储日志;见 §5.8) | ✅(无源→空态 `source:none`,不 503) |
|
||||
| DELETE | `/api/notifications/:id` | 单条删除(重写日志移除该 id) | ✅(不存在→404) |
|
||||
| POST | `/api/notifications/dismiss_all`(别名 `/api/notifications/clear`) | 一键清空:**保留活动中的媒体/进度通知**,移除其余 | ✅ |
|
||||
| GET | `/api/files/read?path=` | 读文本:预览上限 1MB,超限 `truncated:true`(不再 404);二进制→415 | ✅ |
|
||||
|
||||
### 返回 501 `NOT_IMPLEMENTED` 的端点(诚实标注)
|
||||
|
||||
| 端点 | 原因 |
|
||||
|---|---|
|
||||
| `/api/notifications`、`/api/notifications/:id`、`/api/notifications/dismiss_all` | 通知存储为 **launcher 进程内存**(`meow_notif.c g_slots[]`,NOTIFICATION_SYSTEM §4),后端为独立 svcd 子进程,**跨进程不可达**那批内存槽;框架只在关机前 dump 到 TF `MeowOS/notifications/notifications.log`(CSV 追加,非活跃快照)。**需为通知后端另开 IPC 查询/清撤通道**(如 `MSG_NOTIFY_LIST` 应答)或持久化活跃集,见 MEOWPANEL_PROTOCOL §6 待定案。 |
|
||||
| `/api/key/:code` 的 `press:"hold"` | `hold` 需常驻持续注入通道(阶段 D),后端未实现;`tap`/`long` 已实现。 |
|
||||
| OTA 升级模式(`/api/system/ota` 带 `url`) | 升级为草案(MEOWPANEL_PROTOCOL §6 待定案);当前 `POST /api/system/ota` 空 body 触发 `meow_svc_power` 的 `POWER_UPGRADE`(写 mtd5 进升级模式),带 `url` 的下载+升级未实现。 |
|
||||
|
||||
> 通知端点已从 501 落地为「读 TF 卡通知转储日志」实现。因 launcher 侧 **`MSG_NOTIFY_LIST` 为下行推送(守护→App),
|
||||
> 无「客户端查询通知清单」请求类型**(launcher `util.c` `case MSG_NOTIFY_LIST: "not dispatched here"`),后端(svcd 独立进程)
|
||||
> 无法经 IPC 取活跃清单,故回退到 TF 转储文件。详见 §5.8 与输出「需 launcher 侧配合项」。
|
||||
|
||||
> 前端对 `501` 显示「该功能后端尚未实现」(`ok:false,error.code=NOT_IMPLEMENTED`)。
|
||||
|
||||
---
|
||||
@@ -189,9 +193,23 @@ http://<host>.local:8080/
|
||||
- `GET /api/logs/read?file=&lines=`:`file` 必须相对 `MeowOS/logs/`,**禁 `..`/绝对路径 → 403**,敏感名 → 403;
|
||||
缺省 `lines=200`,上限 `1000`;返回 `{file,lines[],total,truncated}`。
|
||||
|
||||
### 5.8 通知(501 及其依据)
|
||||
见 §4 501 表:通知存储为 launcher 进程内存,后端跨进程不可读/清撤。已在源码 `api_notifications*` 注释「为何未实现 +
|
||||
后续如何接」(通知后端加 `MSG_NOTIFY_LIST` 查询/清撤 IPC,或持久化活跃集到 TF `MeowOS/notifications/` 供只读)。
|
||||
### 5.8 通知(数据源 = TF 卡通知转储日志)
|
||||
- **数据源优先级**:① launcher IPC 查询 →② TF 转储文件 →③ 空态。当前 ① 不可用(launcher 侧 `MSG_NOTIFY_LIST` 仅下行推送、
|
||||
无客户端查询请求类型,见「需 launcher 侧配合项」),故以 ② 为准。
|
||||
- **TF 转储文件**:`<卡根>/MeowOS/notifications/notifications.log`(launcher `meow_notif_dump_tf` 一行一条 CSV,
|
||||
字段 `timestamp,id,app_id,app_icon,category,urgency,progress,title,body,target_activity,ongoing,media,dismissed`;
|
||||
`meow_notif_clear_tf` 开机清空 → 会话级归档)。后端逐行流式读取(环形保留最新 `NOTIF_PREVIEW_MAX=200` 条,不全量进内存)。
|
||||
- **`GET /api/notifications`**:返回 `{count, items:[...], notifications:[...], source}`;`items`= `notifications` 别名
|
||||
(兼容前端读 `.notifications` 与任务约定空态 `items:[]`)。字段含 `id/app_id/app_name/app_icon/category/summary/body/
|
||||
urgency/ts/progress/ongoing/media/target_activity/dismissed`。`progress<0`→`null`;`app_name` 对 `system`→`系统`,其余用 `app_id` 兜底。
|
||||
无源(无卡/文件不存在)→ `{count:0,items:[],notifications:[],source:"none"}`(**不 503、不伪造数据**)。
|
||||
- **`DELETE /api/notifications/:id`**:从日志移除该行(重写临时文件后 rename)。不存在 → 404。
|
||||
- **`POST /api/notifications/dismiss_all`(别名 `/api/notifications/clear`)**:重写日志,**只保留活动中的媒体/进度通知**
|
||||
(`ongoing||media||progress>=0||category=="media"`),移除其余;返回 `{dismissed:<移除数>}`。
|
||||
- **语义边界**:日志是**归档快照**(归档时 `dismissed` 尚未置 1,故该列恒 ≈0 不可靠),非活跃快照;且面板清空只改
|
||||
日志视图,**不联动 launcher 进程内存**(launcher 通知中心仍显示其内存活跃集)。无 launcher 查询/清撤 IPC 前的诚实降级。
|
||||
- **并发**:面板清空/删除用「写临时 + rename」重写日志;launcher 侧仍以 `O_APPEND` 追加,二者为竞写(低并发、会话级日志,
|
||||
可接受),已写入「已知边界」(§7)。
|
||||
|
||||
---
|
||||
|
||||
@@ -208,6 +226,17 @@ http://<host>.local:8080/
|
||||
5. **`/api/files` 上传/删除/重命名等 path**:前端对这些操作传**绝对路径**(`d.path/子项`),列表传**相对 root**;
|
||||
后端 `normalize_path` 对两者均容错(相对则拼 root,绝对则直用),符合协议「白名单根 + 规范化」。
|
||||
6. **`GET /api/files` 返回值**:`files_list` 返回 `500` 语义时以 500 封装(协议未定义 `root` 之外错误枚举,用通用错误信封)。
|
||||
7. **通知清单数据源**:协议 §3.8 称后端「经通知后端读取」;因 launcher 无「客户端查询通知清单」IPC(`MSG_NOTIFY_LIST` 仅下行),
|
||||
后端**改读 TF 卡通知转储日志**(`MeowOS/notifications/notifications.log`)。响应额外带 `source`(`tf`/`none`)与 `items` 别名
|
||||
(与 `notifications` 同内容);`items` 为任务约定空态形状,`notifications` 为前端实际读取字段,二者并存。`clear` 语义为
|
||||
「保留活动中的媒体/进度通知」(`ongoing||media||progress>=0`),对应通知中心既定语义。
|
||||
8. **`/api/files/read` 文本截断**:协议 §3.4 称「仅文本(<1MB)→ 二进制 415」;现实现为「预览上限 1MB,超限 `truncated:true`,
|
||||
不再整体 404」,二进制仍 415(比协议更友好,返回文件真实 `size` + `truncated`)。
|
||||
9. **`/api/files/upload`/`rename` 修正**:上传文件名经 `safe_filename` 取 basename、拒绝 `..`/分隔符(防 `../../etc/passwd` 逃逸),
|
||||
落盘前对 dir 与拼接后路径双重 `normalize_path`+白名单校验;rename 的新路径 = **原路径父目录** + `new_name`(原实现误拼到文件尾部,
|
||||
恒 ENOTDIR 失败)。上传体上限 `MAX_UPLOAD_BODY`=8MB,超限 → 413 `PAYLOAD_TOO_LARGE`。
|
||||
10. **TF 卡根可覆盖(宿主测试)**:`env MEOW_TF_ROOT` 覆盖卡根(设备上不设,恒用 `/usr/data/mnt/sd_0`);`env MEOW_NOTIF_LOG`
|
||||
覆盖通知转储日志路径。设 `MEOW_TF_ROOT` 时 `tf_present()` 恒真(测试用)。
|
||||
|
||||
---
|
||||
|
||||
@@ -223,6 +252,12 @@ http://<host>.local:8080/
|
||||
- **`/api/files/upload` 上传路径**:multipart 需要 `path` 字段(目标目录);缺失时上传文件会被忽略(前端总是带着 `path`)。
|
||||
- **数据一致性**:设置直接写 `settings.conf`;`display.brightness`/`boot.default` 的 clamp/同步与 launcher `meow_settings_*` 同口径。
|
||||
若 launcher 未来改 clamp 逻辑,需同步本表。
|
||||
- **通知视图为「会话级归档」**:TF 转储日志由 launcher 开机清空、每通知归档时追加一次;非活动(非 ongoing/无进度)通知
|
||||
10s TTL 自动归档后仍留在日志,故面板会**显示已自动过期但未手动清理的历史通知**(直到 clear)。媒体/进度/ongoing 通知
|
||||
持续保留。无 launcher 查询 IPC 前的诚实降级(见 §5.8)。
|
||||
- **通知清空不联动 launcher 内存**:面板 clear/delete 只重写日志视图,launcher 通知中心内存活跃集不受影响(两者数据源分离)。
|
||||
- **上传为「限长缓冲」非全流式**:multipart 请求体整体读入(上限 8MB,超限 413),下载为流式(8KB 分块)。严格「socket 逐字节流式上传
|
||||
解析」未实现(需增量 multipart 解析器),列为后续;14MB 内存约束下 8MB 上限 + 流式下载已覆盖大文件读侧。
|
||||
- **存储为 `meowpanel` 编译时刻写死**的 socket/路径会因 `--sock-perf/--sock-power`(qemu sim)可覆盖,但默认走 `/usr/data/meow_*.sock`。
|
||||
|
||||
---
|
||||
@@ -231,9 +266,9 @@ http://<host>.local:8080/
|
||||
|
||||
```
|
||||
patch_v2/meowpanel/
|
||||
├── meowpanel.c # 后端源码(单文件,约 2700 行)
|
||||
├── meowpanel.c # 后端源码(单文件,约 3150 行,-Wall -Wextra 0 warning)
|
||||
├── build_meowpanel.sh # 交叉编译 + host 分支(-Wall -Wextra 0 warning)
|
||||
├── meowpanel # 交叉产物(mipsel 静态,约 166 KB,md5 11ed76ec…)
|
||||
├── meowpanel # 交叉产物(mipsel 静态,约 174 KB,md5 58a7b186…)
|
||||
├── meowpanel_host # 宿主编译(本机 ld,调试用)
|
||||
├── services.d/
|
||||
│ └── meowpanel.conf # 部署到 TF 卡 MeowOS/services.d/meowpanel.conf
|
||||
|
||||
Reference in new issue
Block a user