diff --git a/.auto/ideas.md b/.auto/ideas.md index 7e795846..72424196 100644 --- a/.auto/ideas.md +++ b/.auto/ideas.md @@ -100,3 +100,18 @@ task AppendLog 走 DB 非内存累积;push escapeJSONString 用法正确。 - 结论:Go 静态可发现的低垂果实已穷尽。剩余方向:frontend axe a11y 浏览器级审计、 周期性 -race 重跑(上次 #49 干净)、运维类增长审查。 + +## Run #54(认证页 axe a11y 审计+修复,451ce525) + +已修(复扫验证生效): +- 布局级全局:sidebar 折叠按钮 aria-label、Sidebar role=navigation(region 18 节点/页清零)、 + header Kbd 对比度 text-foreground/70、空态/错误/加载 h3→p(heading-order 清零)。 +- 页面级:dashboard 4 个 Progress aria-label、users 分页 prev/next aria-label、 + admin/system 无内容 Tabs→aria-pressed 按钮组(aria-valid-attr-value critical 清零)。 +- / 与 /admin/system 现 axe 0 违规。 + +后续可做(页面级批量,工作量大): +- admin 数据表格行内操作图标按钮(编辑/删除)与 Switch 开关无 aria-label —— 每张管理表逐个补; +- muted 文本对比度(card description、radix tabs trigger、primary 按钮文字)—— shadcn 默认色在浅色主题下 axe 判 fail,改主题变量影响面大需设计确认。 +- 审计环境复用:后端 :3100 + CONFIG_PATH=/tmp/of-audit/config.yaml(sqlite)、docker redis --network host、 + pnpm dev --port 3002 WAVELET_BACKEND_URL=:3100;admin 密码 reset-passwd 重置。注意 :3000 是生产实例勿动。 diff --git a/.auto/log.jsonl b/.auto/log.jsonl index 00e08db3..95b72093 100644 --- a/.auto/log.jsonl +++ b/.auto/log.jsonl @@ -52,3 +52,4 @@ {"run":51,"commit":"bbf7919","metric":8,"metrics":{"eslint_errors":0,"eslint_problems":0,"eslint_warnings":0,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_total":0,"golint_test_usetesting":0,"golint_total":8,"golint_usestdlibvars":0,"golint_vetx_total":0,"golint_wastedassign":0,"measure_s":72,"tsc_errors":0,"vitest_failed":0,"vitest_total":126},"status":"discard","description":"运行时资源审计:HTTP 客户端超时覆盖 + 查询热路径索引覆盖,两项全部干净无缺陷","timestamp":1787715135724,"segment":0,"confidence":null,"asi":{"hypothesis":"运行时资源审计:出站 HTTP 客户端超时覆盖 + LIKE/精确匹配热路径的 DB 索引支撑","next_action_hint":"两项审计干净。剩余:frontend axe a11y(需起前端+浏览器)、周期性 -race 重跑、uploads LOWER(file_name) contains 若成为性能痛点需改前缀语义+表达式索引","result":"全部干净:15 个 http.Client 中 14 个显式 Timeout,唯一无 Timeout 的 agent/nginx checkStubStatus 走 NewRequestWithContext+WithTimeout 边界;users.username 全部精确匹配热路径由 UNIQUE 内联索引覆盖(PG+SQLite 均确认),email/task_type/logstore 过滤列均已有索引;uploads LOWER(file_name) contains 不可用 b-tree 但属管理端低频,改语义才有收益故不动"}} {"run":52,"commit":"bbf7919","metric":8,"metrics":{"eslint_errors":0,"eslint_problems":0,"eslint_warnings":0,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_total":0,"golint_test_usetesting":0,"golint_total":8,"golint_usestdlibvars":0,"golint_vetx_total":0,"golint_wastedassign":0,"measure_s":71,"tsc_errors":0,"vitest_failed":0,"vitest_total":126},"status":"discard","description":"SQL 注入面 + Go 运行时陷阱模式 + react-hooks 依赖三重审计,全部干净无缺陷","timestamp":1787715503278,"segment":0,"confidence":null,"asi":{"hypothesis":"原始 SQL 拼接注入面 + 经典 Go 运行时陷阱(time.After 循环泄漏/defer-in-loop/context.Background 丢失取消)+ 前端 react-hooks 依赖正确性","next_action_hint":"静态+运行时审计维度已穷尽。剩余唯一大项:frontend axe a11y 浏览器级审计(需起前端 dev server + agent_browser)","result":"全部干净:db_manage SQL 控制台为管理端允许例外且表名双引号转义正确、analytics Sprintf 均内部常量表名+参数化占位符;time.After 仅 3 处且均为 select 单次等待/有界重试;defer 均在函数级非循环内;19 处 context.Background() 全部为后台监听器(WithCancel)/重启路径/自带超时的清理任务,无请求 ctx 丢弃;react-hooks/exhaustive-deps 全仓零违规(CLI 临时规则,未改配置)"}} {"run":53,"commit":"bbf7919","metric":8,"metrics":{"eslint_errors":0,"eslint_problems":0,"eslint_warnings":0,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_total":0,"golint_test_usetesting":0,"golint_total":8,"golint_usestdlibvars":0,"golint_vetx_total":0,"golint_wastedassign":0,"measure_s":72,"tsc_errors":0,"vitest_failed":0,"vitest_total":126},"status":"discard","description":"前端 axe a11y 浏览器审计:唯一违规为无后端环境产物,无代码缺陷","timestamp":1787716027952,"segment":0,"confidence":null,"asi":{"hypothesis":"前端 axe-core 浏览器级 a11y 审计(最后一个未探索大维度)","next_action_hint":"a11y 维度已探索但受登录墙限制:完整审计需起后端+种子账号登录。若未来重跑:起 Go 后端 + admin 登录后逐页 axe.run","result":"agent-browser 0.34.0 已装好可复用。axe 审计覆盖所有无认证可达页面(/login、/register、/docs/* 全被登录墙拦截):唯一违规 page-has-heading-one 是环境产物——后端未启动时页面卡在 session-check/publicConfig-pending 态只渲染 Spinner,真实表单的 AuthHeading h1 未渲染;瞬态态用 h3 属可接受的瞬态层级。无代码缺陷。已认证页面需后端才能审计"}} +{"run":54,"commit":"451ce52","metric":8,"metrics":{"eslint_errors":0,"eslint_problems":0,"eslint_warnings":0,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_total":0,"golint_test_usetesting":0,"golint_total":8,"golint_usestdlibvars":0,"golint_vetx_total":0,"golint_wastedassign":0,"measure_s":93,"tsc_errors":0,"vitest_failed":0,"vitest_total":126},"status":"keep","description":"认证页 axe a11y 审计+修复:7 处布局级真实违规全修,复扫验证 dashboard/admin/system 归零;基准 total_issues 保持 8 不变(纯质量收益)","timestamp":1787718397798,"segment":0,"confidence":null,"asi":{"hypothesis":"认证页 axe a11y 审计(起后端+登录突破登录墙):修复布局级真实违规","next_action_hint":"已验证 / 与 /admin/system 归零。剩余页面级:admin 表格行内操作按钮/Switch 无 aria-label、muted 文本对比度——需逐表补标签,工作量大已归档 ideas.md","result":"修复 7 处全局问题并复扫验证:sidebar 折叠按钮 aria-label、Sidebar role=navigation(region 违规 18 节点/页清零)、header Kbd 对比度 text-foreground/70(每页 1 处)、dashboard 4 个 Progress aria-label、分页按钮 aria-label、空态/错误/加载 h3→p(heading-order 清零)、admin/system 无内容 Tabs 改 aria-pressed 按钮组(aria-valid-attr-value critical 清零)。dashboard 与 admin/system 现 0 违规","setup":"审计环境:后端 go run . api @:3100(CONFIG_PATH=/tmp/of-audit/config.yaml,sqlite+redis host 网络 docker)、前端 pnpm dev --port 3002(WAVELET_BACKEND_URL=:3100)、admin 密码经 reset-passwd 重置"}} diff --git a/frontend/app/(main)/admin/database/components/cache-manager.tsx b/frontend/app/(main)/admin/database/components/cache-manager.tsx index 70e75251..ccbd776e 100644 --- a/frontend/app/(main)/admin/database/components/cache-manager.tsx +++ b/frontend/app/(main)/admin/database/components/cache-manager.tsx @@ -189,9 +189,9 @@ export function CacheManager({ refreshTrigger }: CacheManagerProps) {
{/* 左边:状态区 (2/5 cols) */}
-

+

{t('runtimeStatus')} -

+

{/* 已占空间 */}
@@ -240,9 +240,9 @@ export function CacheManager({ refreshTrigger }: CacheManagerProps) { {/* 右边:配置区 (3/5 cols) */}
-

+

{t('policyConfig')} -

+

diff --git a/frontend/app/(main)/admin/database/components/sql-console.tsx b/frontend/app/(main)/admin/database/components/sql-console.tsx index db3aa0e5..97012323 100644 --- a/frontend/app/(main)/admin/database/components/sql-console.tsx +++ b/frontend/app/(main)/admin/database/components/sql-console.tsx @@ -165,7 +165,7 @@ export function SQLConsole({ dbType, onClose }: SQLConsoleProps) { {t('quickTemplates')} - + diff --git a/frontend/app/(main)/admin/logs/components/access-analytics.tsx b/frontend/app/(main)/admin/logs/components/access-analytics.tsx index 4a2809a0..43343fa2 100644 --- a/frontend/app/(main)/admin/logs/components/access-analytics.tsx +++ b/frontend/app/(main)/admin/logs/components/access-analytics.tsx @@ -231,6 +231,7 @@ export function AccessAnalytics() { variant='ghost' size='icon' className='size-8' + aria-label={t('refresh')} onClick={fetchAnalytics} disabled={loading} > diff --git a/frontend/app/(main)/admin/push/components/events-tab.tsx b/frontend/app/(main)/admin/push/components/events-tab.tsx index 424ec3ce..d0acce60 100644 --- a/frontend/app/(main)/admin/push/components/events-tab.tsx +++ b/frontend/app/(main)/admin/push/components/events-tab.tsx @@ -434,6 +434,7 @@ export function EventsTab() { onCheckedChange={() => toggleEventMutation.mutate(event.id) } + aria-label={t('colStatus')} className='scale-75' /> @@ -448,6 +449,7 @@ export function EventsTab() {
- +