浅念
|
fff4f27e98
|
feat: 测试端点限流(每租户5次/15分钟)
- email/test 与 push/test 复用 LoginLimiter 滑动窗模式: (kind, tenant_slug)
键每租户 15 分钟 5 次真实出站,超限 429——guard 在端点最前(鉴权后),
被限流的租户连 400 预检也不触发;record 只落在通过全部预检真正出站
的那次(校验失败/未配置不消耗预算,两端口预算按 kind 互不挤占)
- conftest autouse 复位限流器(跨测试隔离);新增三测: 第 6 次 429+
不同租户独立+email/push 互不挤占、校验失败不耗预算
- 回归: 后端 630 passed(627+3)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-14 10:17:52 +08:00 |
|
浅念
|
d734ed6d2a
|
feat: resolver回退链接入platform_settings(三级回退/快照热刷新)
- app/platform/settings_store.py 新模块: lifespan 启动把 platform_settings
全表快照进进程内存(load_snapshot/get/refresh,workers=1 单进程纪律);
PUT /api/platform/settings 提交后 refresh 热刷新,回退链即时生效
- config_views email/ai 两组改三级回退: 租户槽位 → 平台设置快照
(键名对齐平台设置页推荐键 ai.*/smtp.*)→ env settings(env 键名
不变做最终兜底);push 无平台推荐键保持两级;smtp.port 自由 KV 容错
归一(数字串转 int,脏值视同未设置落 env)
- conftest autouse 复位快照(resolver 直调测试隔离);新增
test_platform_settings_fallback 六测(启动装载/三级链/端口容错/
push 不接线钉死/PUT 即时生效)
- 平台设置页"仅存储"注记移除(CLAUDE.md 与前端页头同步改为已接线)
- 回归: 后端 627 passed(621+6)/ 前端 vitest 156 / build 零错误
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-14 10:10:52 +08:00 |
|
浅念
|
6af8c186d8
|
fix: Phase3 终审修复(env入库/通用配置组面板/锁屏通知摘除/记档修正)
- I-2: admin/.env(被根 .gitignore 误伤)删除,内容并入入库的
.env.development/.env.production(公共块两份都写,PORT 仅 dev)
- I-1: 配置中心补 contact/engine/misc 三组通用 JSON 编辑面板
(JsonGroupPane:等宽 textarea 整组编辑 + JSON.parse 预检 +
PUT 整组 + 重置出厂 + 顶部字段说明;挂进 GROUP_NAV 三入口);
修组键缺失租户的禁存 bug(父层快照加载后挂载,空组可建组)
- I-3: config_routes.py docstring 改「接线归 Phase 4」;
CLAUDE.md Phase 4 清理单补 resolver 回退链与 email/push test 限流
- M-1: 锁屏摘除入口(用户菜单项删 + 全局组件 enabled:false)
- M-2: 顶栏通知铃铛隐藏(headerBar notification.enabled:false)
- M-5/M-8: admin/README 换三行指针(删模板 README.zh-CN.md);
quickLinks 删「登录」项
- M-3/M-4 不做记档入 Phase 4 清理单
- 测试基线:后端 pytest 595 / 前端 vitest 156(+3 通用 JSON 组)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-14 00:05:40 +08:00 |
|
浅念
|
bf923d9cf7
|
feat: 配置中心-凭据(邮件推送AI表单/掩码交互/SMTP测试/推送探测端点)
- 后端 POST /tenants/{slug}/email/test:resolve_email_settings 当前配置
真发测试邮件(主题 [all-kefu] SMTP 测试邮件+租户名+UTC+8 时间);
回退后 host/user 仍空 → 400;成败如实返回 {sent, error},密钥不进响应
- 后端 POST /tenants/{slug}/push/test:连通性探测——与 _do_post 同款
连接形态 POST 空 messages 批量(红线:绝不携带线索数据);不可达
reason 分类 dns/timeout/connect(Windows 裸 ConnectError 文案兜底),
auth_ok 三态(2xx 真 / 401·403 假 / 其余 null),单次无重试
- email_service 抽 _smtp_send 共用连接逻辑(_send 契约不变)+
send_test_email(成败+错误串如实返回,不走吞异常 bool)
- 前端 CredsPane:邮件/推送/AI 三组凭据表单(数值/邮箱前端预检 +
后端 400 双层);密钥哨兵交互(__SET__ 占位符/不动保存保持库值/
清除按钮显式清空可撤销);SMTP 测试与推送探测三态内联展示
- 测试:pytest 新增 18(email/test 7 + push/test 11),全量 595 通过;
vitest 新增 20(model 哨兵往返/预检边界 + API 调用形态),107 通过
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 20:55:40 +08:00 |
|
浅念
|
0c25287c19
|
feat: 密钥掩码哨兵(__SET__)四处响应 + 站点管理权限放开租户管理员
- config_routes: push.api_key/ai.api_key/email.smtp.password 掩码助手
(MASKED="__SET__";非空才掩,空串/None 原样)。作用于 GET config、
GET versions/{n}、POST rollback 响应、GET settings(计划四处),并盖
PUT/reset/PUT settings 的写回显——哨兵还原后的库值不经任何响应外泄。
- PUT 哨兵还原: 密钥字段收到 __SET__ → 当前快照原值替换后再写版本
(前端"不改就原样传回");传新值照常覆盖;空串传回仍=清空(既有语义
不变)。settings 同款(密钥名含 key/password/secret,递归嵌套 dict;
设置 key 本身命中也算)。库行/版本历史永远存原值。
- tenant_routes: 站点/域名四端点(POST sites/PATCH sites/POST domains/
DELETE domains)require_super → _tenant_guard;租户生命周期三端点
(POST /tenants/GET 列表/PATCH /tenants/{slug})保持超管专属。
- 测试: 掩码四处响应+落库分离断言(_current_snapshot 直查库)、哨兵
往返/新值/清空/嵌套路径/未设还原 None、settings 标量+嵌套+非密钥
字面量;租户管理员四端点自助(201/200)+他租户 403+生命周期仍 403。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 13:39:23 +08:00 |
|
浅念
|
6839cb94d2
|
fix: 终审修复——站点停用接线/prefix查重补创建reset/默认凭据警示+取舍补录
- I-1 站点停用全链接线: Site 数据类加 status 字段; DB 源 _load_one 与
文件源 read_tenant 均只输出 active 站点(停用站点域名不进 registry
索引 → 该域名 404;全停用=合法运营状态输出空 sites;文件源无 status
键默认 active 兼容)。E2E: PATCH 站点 disabled → 其域名 404、复启用
恢复;源级直测两源过滤。
- I-3 prefix 跨租户查重补两口: db.other_push_prefixes 共用助手
(MAX(version) 逐租户当前前缀,排除自身);创建向导(出厂档案前缀被占
→ 400 提示改 blank/改占用方)与 reset push(重置回出厂撞车 → 400 提示
走 PUT)接入;PUT 原有查重改用同一助手。rollback 维持豁免(历史不可变
语义优先,取舍清单记档)。既有测试第二租户改 blank profile 避撞。
- I-4 默认凭据警示: lifespan 启动检测 ADMIN_PASSWORD 仍为 Settings 字段
默认值(非硬编码第二份,防双源漂移)→ logger.warning 醒目提示;
CLAUDE.md Phase 4 部署记档补 ADMIN_PASSWORD 生产要求。
- I-2/M-2 取舍补录: 密钥掩码未实现(GET config/settings 明文返回
api_key/smtp 密码,Phase 3 前须定 __SET__ 哨兵方案);站点管理权限现为
仅超管(Phase 3 对接时决策放开或改 spec);取舍清单第 2 条同步刷新
(rollback 现为唯一豁免口)。
全量回归: 571 passed(基线 566 + 新增 5)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 12:40:21 +08:00 |
|
浅念
|
acf5777ff2
|
feat: 统计API(卡片/漏斗/趋势/分布/推送健康,逐库聚合禁ATTACH)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 11:24:30 +08:00 |
|
浅念
|
ec55bc38ab
|
feat: 数据视图API(会话/详情/推送日志/删除,租户scope强制)
查询语义自 jc admin.py 移植,路由多租户化(/api/platform/tenants/{slug}/...):
- runtime 按 slug 取: registry.runtimes() 匹配 + ensure_ready(resolve 需域名,
平台后台只有 slug);未懒建租户首次查询触发建库不炸
- 会话列表: ≥1 消息的会话、created_at 倒序、intent/site(client_info.site)/
日期区间 from-to(边界含,to 日期-only 含全天)筛选,分页 page/page_size≤100,
每行含意向/联系方式/email_sent/IP 归国(ip_service 复用);total 对筛选后
集合计数(修 jc 旧缺陷: 其会话列表 total 不随 intent 变)
- 详情: 元数据+client_info+画像 chips(raw_info 去 _ 前缀键)+消息全量+意向块
- 删除: jc 原序逐表显式删,补齐 lead_push_logs(兑现 FK 声明的 CASCADE,
免孤儿行);不存在 404
- push-logs: load_only 排除 request_payload 大列,payload_size(func.length
服务端算)作省略标记;status/conversation_id 筛选
- 鉴权 _tenant_guard(slug): 他租户 403/未认证 401 有测试钉住;非法筛选值
显性 400(jc 静默忽略)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 11:00:39 +08:00 |
|
浅念
|
a43c654337
|
feat: 头像上传(uuid重命名/魔数校验/2MB/配置版本管线)与三级解析链
- POST /api/platform/tenants/{slug}/brand/avatar(require_tenant):
multipart 收文件,魔数判定类型(\x89PNG/\xff\xd8\xff/RIFF....WEBP,
优先于扩展名——改后缀骗不过,存盘扩展名取自内容)、≤2MB(413,
upload.size 预检免拷贝)、服务端 uuid4 重命名(原始文件名不参与
路径),落 data/uploads/<slug>/(目录懒建,gitignore 已忽略)
- 走 Task 6 配置版本管线(复用 config_routes 内部 helper):读当前
快照 → brand 组只替换 avatar 字段 → validate_group →
write_config_version(comment=头像上传) → registry_reload 热生效
- /api/public/avatar 三级解析链:uploads → seed 资产 → 静态兜底;
Phase 1 文件名穿越防线(拒 / \ . ..)扩到 uploads 段
- registry.uploads_root:自 data_dir.parent 派生(生产=<repo>/data/
uploads;测试注入 tmp data_dir 时自动落 tmp 内,隔离免污染)
- 新依赖 python-multipart(multipart 表单解析)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 10:35:41 +08:00 |
|
浅念
|
7502176190
|
feat: 配置API(分组校验管线/整份版本/回滚/重置出厂/试金石/平台设置)
- config_validation.validate_group: 九组校验管线(类型/键 allowlist/数值
范围/prompts 大小上限 50KB·100KB/wall 全量交 compile_wall/push.prefix
跨租户查重 spec E1),错误清单中文带字段路径
- config_routes: GET/PUT config(整组替换原样入版本,MAX+1,热 reload)/
reset(按 Tenant.profile 取出厂档案组)/versions 列表·详情/rollback
(旧版复制为新版本,历史不可变)/wall/test 试金石(逐句判定,不落库
不 bump)/settings 平台设置 CRUD(仅超管,resolver 接线归 Phase 3)
- db.write_config_version: 版本写入公共路径(创建向导与配置 API 单一
事实源);Tenant 落 profile 列(重置出厂按它取对应档案)
- _profile_snapshot/_blankify 迁 tenant_source(两路由模块共用);
db_source_app/super_client 夹具收拢 conftest(两测试文件共用)
- 测试: 519 → 537 全绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 10:07:40 +08:00 |
|
浅念
|
ec2e17d5e3
|
feat: 租户管理API(创建向导消费出厂档案/blank保留jc墙/域名/停用/slug不可变)
POST /api/platform/tenants: profile ∈ {auto,jiancai,blank}——首版快照复用
FileTenantSource(seed).read_tenant(profile).snapshot(Task 4 审查指定);
blank=jiancai 档案 _blankify 去身份组但保留 wall/prompts(compile_wall/
PromptProvider 的硬要求)。建 Tenant+main 站点+版本1+租户管理员
(must_change_password=True),创建后 registry_reload(upsert)立即可用。
站点 CRUD(brand_overlay 整字典赋值,M-2a)/域名绑定解绑(全局唯一,
撞车 400 带现有归属)/PATCH 租户(name/status;slug 不可变 400;停用走
reload 路径 dispose 引擎)。列表/详情管理员概要显式挑字段,凭据永不外泄。
鉴权: 写操作+列表 require_super;GET 详情放宽 require_tenant(slug)。
测试: db_source_app 夹具(registry 用 DbTenantSource 生产形态指向临时
platform.db,跨循环纪律: 直查走独立 NullPool 连接),16 项全绿,全量 519。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 09:20:28 +08:00 |
|
浅念
|
c5e8dd6ded
|
fix: 认证审查修复(角色依赖连锁409门/停用租户token取舍注记/公共面整理)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 08:29:01 +08:00 |
|
浅念
|
f49e8e92b1
|
feat: 平台认证(scrypt上移/内存token 8h/登录限流/改密/角色依赖/409语义)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-13 08:18:15 +08:00 |
|