1.14.0
- 新增「受控设备」：可以把插件要看的流量限定在选定设备上，其余设备的流量根本不进插件。
  面板首页新增一张卡片（设备范围：全部设备 / 仅选定设备；设备清单支持 IP、网段、MAC，
  一行一个或用逗号分隔）。这是上游面板里 device_routing 那一档，本插件补上它，
  因为在此之前"只想盯住某一台设备"只能全量接管，代价是整个网络的每个包都要过用户态。
  实现：给选定设备的连接打一个 connmark（0x400，与引擎自己的 1001/1002 及爱快
  自身使用的连接标记都不冲突），入队规则再加一条 connmark 匹配。标记打在连接上
  而不是报文上，所以两个方向、后续每个报文都跟着走 —— 回程流量不需要再按
  "目的地址是内网设备"去猜。规则插在引擎入队跳转之前，与绕过名单同一位置。
- MAC 与 IP 都支持：MAC 扛得住 DHCP 换 IP（盯住"那台电脑"不会因为续租就断掉），
  IP/网段适合按用户组划范围。
- 选「仅选定设备」却留空设备清单会被拒绝，面板直接说明后果：这样一条流量都不会
  进入插件。本机模式下也拒绝这一档（本机模式处理的是设备自身的流量，没有"设备"可选）。
- 面板会提示口径差别：「仅选定设备」＋「辅助增强」下，内核已识别的流本来就不进插件，
  按设备也看不到它们的识别结果；要看全量流量要把 ikuai.scope 改成 full。
- 状态接口新增设备范围、设备清单、连接标记值与内核里实际装了几条标记规则
  （device_rules），能分清"设置存下来了"和"内核真的装上了"。
- config.yaml 的 ikuai 段新增 deviceScope / deviceList，手改文件同样生效。
- 绕过规则的计数不再把设备标记规则算进去（两者在面板上是两个数字，含义不同）。

1.13.4
- 修一个"开着但什么都没监测到"的静默失效：「仅透视」一条规则都不生成。
  面板三个协议按钮（全加密流 / TLS 伪装 / SSH）发的是 audit，后端只认 block，
  于是设成「仅透视」后 rules.yaml 里没有对应规则 —— 而 OpenGFW 只加载规则里用到
  的分析器，所以这类流量压根不进分析流程：面板上「异常流量」卡片恒为 0，
  「实时流量透视看板」永远空白，操作者看到的是"没有异常流量"。
  更糟的是面板自己在教操作者用这个模式：「把协议设为仅透视即可在此实时查看」。
  现在「仅透视」生成一条只记录不拦截的规则（log: true，不写 action），
  命中即记录、流量原样放行；面板上三个协议卡片与看板因此才有数据。
  不认识模式值（拼错、上游新值）只会"少拦"，绝不会变成拦截。
- 「流量透视看板」不再拿日志当数据源。原来它读日志环再按文本猜协议，
  而日志环按等级与每秒预算裁剪：日志等级一调到 warn，或者一秒超过 500 条，
  看板就整页空白 —— 这跟"确实没有异常流量"长得一模一样，是测量功能最坏的错。
  现在引擎在日志门禁之前写入独立的透视缓冲（500 条，记录双向 IP 与端口、动作、
  命中规则、单调递增 id），记录不再受日志等级影响；新增的 SSE 事件让看板实时更新；
  「清空记录」只清看板，不再顺手动日志。「总分析包」等统计磁贴的计数行为不变。
- 辅助增强下的「仅透视」规则同样静默无效（内核分类过的流不再进插件，插件只看得到
  握手、看不到载荷），面板警告与启动日志现在把这类规则一并列出，而不是只报拦截类。
- 验证方式补强：新增端到端测试，用内存合成报文（裸全加密流 / SSH / 正常 TLS）
  跑真实的内嵌引擎，走「面板保存 → 生成 rules.yaml → 引擎编译 → 实际识别」全链路，
  断言「仅透视」下识别出全加密流量与 SSH、正常 TLS 不误报、且不切断任何流量。
  修好前该测试失败并直接指出"仅透视没有生成任何规则"。
- 面板模型新增透传保留上游的 device_routing 段：本版前端没有它的界面，
  但保存时会整体回写模型，之前被丢弃的字段会在操作者动任何一次设置后永久丢失。

1.13.3
- 修 1.13.2 没生效的 worker 上限：配置文件加载阶段把 workers.count 钳在 1-64
  （沿用旧值 + 记一条说明），而校验函数里的新上限 1-256 永远看不到这个值 ——
  实测在真机上把 count 改成 128 保存，接口回"已保存并重新加载"，但实际仍是 2。
  现在上下限抽成 spec.WorkersMin / WorkersMax 一处定义，加载与校验共用；
  新增测试同时钉住"128 原样保留、999 沿用旧值且有说明、加载结果能过校验"。

1.13.2
- 工作线程数上限从 64 放宽到 256：插件也部署在 128 核的机器上，64 线程把引擎
  卡在硬件之下（仍是合理性边界，不是推荐值 —— 家用路由远在到达上限前就先 CPU 瓶颈了）。
- readme 增加「全灭」模式的推荐配置与实测开销（约 17000 包/秒·核），并写明该模式
  能拦什么、拦不住什么：非 TLS 的全加密流量与 SSH 能拦；TLS 伪装的 Trojan / VMess
  按设计豁免（否则会误杀全部 HTTPS）；UDP 不处理（fet 只处理 TCP）。

1.13.1
- 识别范围警告补上「更省 CPU」的改法：不必把全部流量都拉进插件，可以 ikuai.scope=full
  配 ikuai.queueOnly=custom + ikuai.queuePorts（如 "53,80,443" 或某协议的服务端口），
  只让这些端口的流量进插件 —— 内核不再替这些端口做判断，于是插件能看到流的开头，
  载荷类规则就能生效。1.13.0 的警告只给了"全量接管"一条路。
  已在真机确认该组合生成的队列规则只含端口条件（不含 appmark/ikverdict 限制）。

1.13.0
- 修一个"开了但不会生效"的静默失效：识别范围为「辅助增强」时，依赖报文载荷的拦截
  规则根本不会命中，而界面上完全看不出来。现在会明确提示：
    * 面板顶部显示黄色警告条，列出受影响的规则名，并说明改法（改成「全量接管」）。
    * 启动日志里同样打印一条带 ⚠️ 的说明。
    * /api/rules 新增 warnings 字段。
  原因：辅助增强只把「内核未分类」的报文交给插件，而内核是在一条流开始带载荷之后
  才给它分类的 —— 于是这类流只有握手报文会到插件。域名 / SNI / Host / 协议屏蔽都
  要靠载荷才能判断，因此永远匹配不上。
  只对「拦截」类规则报警：只记录不拦截的规则不报警（默认安装不会挂常驻警告），
  IP / 端口这类不依赖载荷的规则也不报警。

1.12.0
- 配置文件位置改到持久分区：/etc/log/opengfw/config.yaml 与 /etc/log/opengfw/rules.yaml。
  原来在 /etc/opengfw，那属于固件分区（实测只有 129MB），固件升级或恢复出厂会把配置抹掉。
  升级时自动迁移：老位置的文件会被复制到新位置并逐字节校验，确认无误后才删除原文件；
  新位置已有文件时不覆盖。迁移会在启动日志里说明。
  另外处理了一个升级陷阱：应用设置里的路径是安装时一次性写入的，升级不会更新，
  所以老安装启动时仍被指向 /etc/opengfw；该路径现在会在读取时自动重定向到新位置
  （只针对恰好等于老默认值的路径，自己改过的路径不动）。
- 「原生配置预览」新增「重置为出厂设置」：把该文件恢复出厂内容。
  重置 rules.yaml 会同时清空面板上配置的规则（否则面板会显示一批不在文件里的规则）；
  重置 config.yaml 会把拦截恢复为关闭。两项都会先确认再执行。
- 发布闸门新增：默认路径必须在 /etc/log 下、迁移与重置逻辑必须存在、重置端点必须注册。

1.11.0
- 「原生配置预览」现在可以直接在面板里编辑并保存（原来只能看）。
  两个文件（config.yaml / rules.yaml）各自有「编辑 / 保存 / 取消」；保存先过校验：
  配置文件要能解析成有效设置（例如 log.level 只能是 debug/info/warn/error），
  规则要能被引擎编译。不通过就不写盘，并把原文件还原、把引擎的错误原文回给你，
  所以贴坏内容不会把插件弄成起不来的状态。保存成功即时生效（热加载）。
  上游那份面板的这块本来是只读的，编辑功能是本插件加的（独立脚本，上游前端保持原样）。

1.10.0
- 管理面板换成上游 OpenGFW 面板的前端（ccqwertyui/luci-app-opengfw），本插件自研面板退役。
  为什么：自研面板是与上游并行的第二套界面与第二套参数定义；上游那套是现成的、功能更全的
  中文界面（域名/IP/端口规则、屏蔽、流量透视、实时日志、环境诊断、规则仿真测试）。
  做法：把它的前端资产（index.html / css / js / i18n）原样内置进本插件，并按它前端实际调用的
  21 个 /api/* 端点实现后端 —— 底层是**本插件自己的引擎**，不是上游的 dashboard 二进制。
  为什么不直接跑上游的 dashboard 二进制：它在启动引擎前检查 /sys/module/nft_queue，
  而 iKuai 把 NFQUEUE 编进内核（不是模块），该前置条件在本固件上永远不成立（实测被拒）；
  它还会用 nftables 自己写防火墙规则，而 iKuai 没有 nftables。
- 调度方式沿用本插件的「内核优先」：内核 DPI 先判，只有内核未能识别的流量才进入本插件队列
  （爱快自身的 appmark/ikverdict 语义），与云防火墙那类内核调度一致，不是把全部转发流量
  都搬到用户态。
- 面板的规则模型（域名/协议开关、IP、端口、屏蔽）由本插件翻译成引擎的表达式规则：
  域名按 DNS 名称 / TLS SNI / HTTP Host 分别生成，子域用 hasSuffix（DNS 名称带末尾点、
  SNI 与 Host 不带，写错就会静默不命中）；生成的规则经引擎编译器校验通过才落盘。
- 面板生成的规则写在 rules.yaml 的标记行之后，标记之前的操作者规则**逐字保留**（含注释与
  格式），面板只重写自己那一段。
- 面板里的「DNS 污染」「反诈 HTTP 跳转」以及屏蔽的「仅记录」模式，本引擎没有对应实现：
  设置会被保存但**在面板上明确说明不生效**，不会假装生效。
- 「安装内核模块」按钮在本固件上如实回答「NFQUEUE 已内建」——上游那一版正是卡在这里。
- 环境诊断给出 iKuai 实际相关的检查项（NFQUEUE 内核接口、iptables 可读性、挂载一致性、
  当前调度方式），只诊断不改内核。
- 原始配置编辑（config.yaml / rules.yaml）保存前先校验，内容非法则拒绝并**还原原文件**。
- 本插件自己的 /api/v1/* 保持不变：发布闸门与验收脚本用它，且它带有面板放不下的字段。
- 面板头部的版本徽标改为显示**本插件**的版本（原来显示上游 dashboard 自己的 v1.1.2-14）。
- 面板总览的统计磁贴接上真实数据，不再恒为 0：
    * 「总分析包」= 内核交给本插件的报文数（读 iKuai iptables 规则自带的 -c 计数，
      读不到时不显示 0 而是保持 0 并在 status 里以 queue_counters_ok 标明"未测到"）；
    * 「已拦截流量包」= 引擎的拦截判定数（本引擎按流判定，用户态拿不到逐包拦截数，
      因此这里给的是判定次数，不是编造出来的包数）；
    * 「全加密代理 / Trojan / SSH」等卡片 = 引擎识别并命中的次数。
  计数在日志等级门禁**之前**累加：否则把日志调到 warn 就会让面板数字变成 0，
  看起来像"没有流量"，这是最坏的一种错。
  说明：fet（全加密流量）无法区分裸 VMess 与 Shadowsocks，两者合并计入
  「全加密代理 (SS / 裸 VMess)」这一张卡，不编造拆分。

1.9.0
