docs: 补 skill/SKILL.md(模块规范 MANDATORY 项)

This commit is contained in:
yumoqing 2026-08-14 13:42:28 +08:00
parent d38e26ffff
commit d5feff2042

48
skill/SKILL.md Normal file
View File

@ -0,0 +1,48 @@
---
name: app_audit
description: 全局审计日志模块。append-only 审计owner.audit 角色隔离防自删。Use when 写入/查询/备份/删除审计日志,或为关键操作接入审计。
---
# app_audit — 审计日志全局模块
## 架构
独立仓库 + 独立 Python 包。其他模块通过 `from app_audit import audit_log` 在关键操作时写入审计。
```
app_audit/
├── app_audit/
│ ├── __init__.py # 导出 audit_log / is_audit_role / list/backup/delete
│ ├── audit_service.py # 核心逻辑(纯函数,只依赖 sqlor/appPublic
│ └── init.py # load_app_auditadd_startup 建表 + owner.audit 角色
├── models/sd_audit_logs.json
├── wwwroot/index.ui # DataGrid 审计日志列表界面
├── wwwroot/api/audit.dspy # list/backup/delete
└── scripts/load_path.py # RBAC 权限注册(仅 owner.audit
```
## 数据模型
`sd_audit_logs`id, user_id, username, action, target, detail(text), result, client_ip, created_at。append-only只 INSERT 不 UPDATE
## 关键端点
`/app_audit/api/audit.dspy`action 参数):
- `list`:分页查询,返回 `{rows, total}`DataGrid 兼容)。过滤参数 user_id/username/act/from/to分页 page/rows。
- `backup`:导出 JSON支持过滤 + limit上限 50000
- `delete`:按 `before` 时间戳删除(`audit_delete` 留痕永不删)。
## 审计事件清单VALID_ACTIONS 白名单)
认证 login/login_fail/logout权限 role_change/perm_change/user_role_change工作环境 work_env_set/org_key_gen/remote_bwrap部署账号 account_create/account_remove/sandbox_run用户机构 user_create/user_disable/user_delete/org_change审计自身 audit_delete/audit_backup。非白名单 action 归 `unknown`detail 保留原始值)。
## Pitfalls
- **审计独立性**owner.audit 与 owner.superuser 完全隔离superuser 也无权看审计。双层校验RBAC path 挂 owner.audit + audit.dspy 内 is_audit_role应用层是兜底独立 app 的 RBAC 对未注册路径可能放行)。
- **审计写入是旁路**audit_log 内 try/except失败不阻断主流程。
- **run 类接口 result 判断用 `rc == 0`**run_in_sandbox/run_in_work_env 返回 `{rc, stdout, stderr}`,没有 `ok` 键,不能 `r.get('ok')`(会恒判 fail
- **sqlor `%` 是占位符**LIKE 要写 `%%`
- **INSERT IGNORE 在 aiomysql 打 Duplicate entry 警告**(无害噪音)。
- **RBAC 缓存 600s TTL**:注册新权限后要重启服务才生效。
- **审计员用户 user_status='0' 才是启用**basic_auth 判断 `user_status != '0'` 为禁用。
- **owner.audit 角色的 role 表 id 是 'owner.audit' 字符串**(非随机 IDuserrole.roleid 直接存 'owner.audit'。