安全设计
记忆系统里存的不只是普通业务数据,它往往还包含用户偏好、项目约定、技术决策,甚至可能混入密钥、令牌和敏感背景。安全能力如果不是从第一阶段就纳入主链路,后面几乎不可能“顺手补齐”。
双凭证模型
当前阶段采用两套并行但边界清晰的认证方式:
| 凭证 | 面向对象 | 典型场景 |
|---|---|---|
| 管理员 Session Cookie | 浏览器工作台 | 登录后台、管理 Token、查看审计 |
| API Token | CLI / MCP / 自动化 | 非浏览器客户端长期访问 |
这样拆分的原因是浏览器和终端的安全模型天然不同。让浏览器继续手填长期 Token,只会把凭证暴露面扩大;让 CLI 依赖 Session 又不现实。
管理员初始化
第一阶段默认通过环境变量引导首个管理员初始化:
MEMORY_BOOTSTRAP_ADMIN_USERNAMEMEMORY_BOOTSTRAP_ADMIN_PASSWORD
只有在数据库里没有用户时才执行初始化,避免后续实例重启时重复注入默认账号。
Token 生命周期管理
Token 至少要支持:
- 创建
- 列表查看
- 设置过期时间
- 吊销
- 区分客户端类型和访问级别
并且必须只保存哈希,不保存明文。这条约束看起来基础,但在记忆系统里尤其重要,因为 Token 很可能被多个宿主长期使用,一旦泄露影响范围会很大。
Provider 密钥存储
Embedding 和 LLM Provider 的 API Key 不能明文入库。控制台里维护的 provider 凭证,必须先用应用级主密钥加密再落库,例如:
MEMORY_EMBEDDING_MASTER_KEYMEMORY_LLM_MASTER_KEY
这样做是为了把“环境变量中的进程内默认 provider”和“持久化到数据库的控制台 provider”两条安全链路区分开。
传输安全
生产环境必须通过 HTTPS 提供服务。推荐使用 Caddy 或 Nginx 作为 TLS 终结层,服务端本身运行在内网 HTTP 即可。
这个约束不能因为“是自托管环境”就放松。只要涉及浏览器登录、Token 管理和远端 Agent 访问,明文传输就是不必要的风险。
数据隔离
最基本的隔离策略包括:
- 请求身份映射后自动附加
user_id过滤 project_id参与作用域边界校验- 不允许通过参数伪造跨用户读取
- 第一阶段不启用跨用户共享和多租户互访
敏感内容防护
写入前必须做第一层敏感内容扫描,重点拦截:
- API Key / Secret Key
- Bearer Token
- 私钥块
- 显式凭证赋值片段
- 已知格式的内部 Token 字面量
这里的策略要尽量倾向“高置信拦截”,避免因为只出现了 token、password 这类概念词就误杀正常讨论内容。
日志与审计
日志至少要保证:
- 不记录完整记忆正文
- 不记录 Token 原文
- 不记录被拦截的敏感内容原文
- 关键操作有最小审计链路
第一阶段建议重点审计:
- 登录 / 登出
- Token 创建与吊销
- 记忆创建与删除
- 状态变更
- 模式切换
这样用户才有能力回看“谁在什么时候做了什么关键操作”。
限流与错误暴露
记忆系统通常会被多种自动化客户端访问,因此基础限流必须存在。与此同时,错误响应也要避免把数据库异常、堆栈细节直接回显给外部调用方,以免把内部结构暴露出去。