fix: 终审微修(admin no-cache/PII挂账/死配置清理)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-14 14:03:50 +08:00
parent dcf9d4b54c
commit a20d53887d
5 changed files with 38 additions and 8 deletions
+1
View File
@@ -151,6 +151,7 @@
7. ~~锁屏功能已摘除入口~~ + ~~通知组件摘除~~(锁屏 Phase 3 摘入口,Phase 4 Task 5F 删代码:art-screen-lock/art-notification 组件目录、component.ts/headerBar.ts 配置项、useHeaderBar.shouldShowNotification、类型字段、components.d.ts 条目、crypto-js 依赖(env.d.ts 声明/package.json/optimizeDeps/lockfile)、en/zh 孤儿语言键全部清除,grep 零残留)。
8. ~~租户切换器 composable 收拢~~(Phase 4 Task 5E 完成:`admin/src/composables/useTenantOptions.ts` 收拢会话/配置/统计三页租户下拉(默认形态选中首个 + bootstrapTenantContext 引导;stats 用 selectFirst:false 纯数据源);dashboard 卡片墙形态不在此列)。
9. ~~ECharts 按需收窄~~(Phase 4 Task 5D 完成:echarts.use 收窄为 Bar/Line/Pie + Title/Tooltip/Grid/Legend + CanvasRenderer——全仓 grep 证实存活消费方仅 stats 页与 useChart;echarts chunk 767,864 B → 559,737 B(-27%),dist 总体积 -273 KB)。
10. **引擎日志含会话摘录 vs spec §9 承诺**(终审挂账)——观察期收口为 session_id 索引(手册 §6.2 有详述;收口前日志文件按含 PII 对待,备份/外发注意)。
## Phase 4 完成状态(2026-10-14 收尾核对)
-3
View File
@@ -23,9 +23,6 @@ VITE_WITH_CREDENTIALS = false
# 是否打开路由信息
VITE_OPEN_ROUTE_INFO = false
# 锁屏加密密钥(锁屏入口已摘除——Phase 3 终审 M-1;密钥保留防遗留代码异常)
VITE_LOCK_ENCRYPT_KEY = s3cur3k3y4adpro
# API 请求基础路径(开发环境使用 / 走 Vite 代理,见 vite.config.ts 的 server.proxy)
VITE_API_URL = /
-3
View File
@@ -22,9 +22,6 @@ VITE_WITH_CREDENTIALS = false
# 是否打开路由信息
VITE_OPEN_ROUTE_INFO = false
# 锁屏加密密钥(锁屏入口已摘除——Phase 3 终审 M-1;密钥保留防遗留代码异常)
VITE_LOCK_ENCRYPT_KEY = s3cur3k3y4adpro
# API 地址前缀(生产由反代把 /api 与 /static 指向后端,前端同源相对路径)
VITE_API_URL = /
+7 -2
View File
@@ -257,9 +257,14 @@ app.mount("/admin", AdminSPA(), name="admin")
async def static_no_cache(request, call_next):
"""静态资源协商缓存(2026-09-30 线上事件): 无 Cache-Control 时浏览器对
widget.js 走启发式缓存,修复部署后用户端仍跑旧脚本。no-cache=每次用
etag 轻量协商,有更新即时生效,未变则 304 几乎零开销。"""
etag 轻量协商,有更新即时生效,未变则 304 几乎零开销。
/admin 同覆盖(终审微修): SPA 的 index.html 引用带 hash 的 assets——
管理员端旧 index 被启发式缓存会引旧 assets 白屏(与 widget.js 事件
同类);index 每次协商,hash 资源未变则 304,开销可忽略。"""
resp = await call_next(request)
if request.url.path.startswith("/static/"):
path = request.url.path
if (path.startswith("/static/")
or path == "/admin" or path.startswith("/admin/")):
resp.headers["Cache-Control"] = "no-cache"
return resp
+30
View File
@@ -80,6 +80,36 @@ def test_admin_assets_served(admin_client):
assert "admin bundle" in r.text
# ---- no-cache 协商缓存(终审微修) --------------------------------------------
def test_admin_responses_no_cache(admin_client):
# /admin 全前缀(含重定向、index、hash assets)带 no-cache: SPA 的
# index.html 引用带 hash 的 assets,发版后管理员端旧 index 被启发式
# 缓存会引旧 assets 白屏——与 2026-09-30 widget.js 线上事件同类,
# 协商缓存让 index 每次轻量校验(未变 304)
r = admin_client.get("/admin", follow_redirects=True)
assert r.status_code == 200
assert r.headers["cache-control"] == "no-cache"
r = admin_client.get("/admin/")
assert r.status_code == 200
assert r.headers["cache-control"] == "no-cache"
r = admin_client.get("/admin/assets/app.js")
assert r.status_code == 200
assert r.headers["cache-control"] == "no-cache"
def test_platform_api_not_no_cache(admin_client):
# 负面钉位: 中间件只覆盖静态面(/static/ 与 /admin),/api/platform
# 响应不带 no-cache——API 的缓存语义归端点自己
r = admin_client.post(
"/api/platform/auth/login",
json={"username": "nope", "password": "bad"},
)
assert r.status_code == 401
assert "cache-control" not in r.headers
# ---- SPA fallback 边界 -------------------------------------------------------