Files
fire-safety-ymd/PROJECT_STATE.md
2026-09-07 12:55:43 +08:00

31 KiB
Raw Permalink Blame History

fire-safety-ymd 项目当前状态

项 内容
最近更新 2026-09-07
当前分支 main
当前阶段 对话、SuperAgent、空间 MCP、默认关闭的测试页面、无 Trace 兼容模式、测试环境容器部署基线与兼容 Chat 403 Origin 诊断日志已完成代码基线;7 个 MCP 工具的统一分页代码和自动化验证已完成,真实 PostGIS、公网分页与目标机 Origin 白名单验收待完成
当前重点 在目标机用受限 403 诊断日志确认发送方精确 Origin 并完成白名单联调,再部署验证 MCP 分页契约、发布“小牟”消防 Profile,核对具体方案的多工具调用、分页提示和 WGS84 坐标输出

1. 当前 Checkpoint

  • 名称:fire-safety-ymd-chat-origin-diagnostic-logging-v1
  • 状态:代码、针对性自动化与本地全量验证已完成,待提交和测试服务器部署验收
  • 目标:在兼容 completion 返回 403 时提供可复制精确 Origin 的受限日志;普通拒绝记录有界 origin,预检拒绝再记录有界方法、请求头名称集合和稳定原因,同时不暴露任何 Secret、请求正文、会话或 Provider 数据。
  • 非目标:改变 Origin 白名单默认拒绝、放开 *、删除或改写 Origin、恢复旧 DashScope 全路径代理、修改 Nginx 保存 Secret、实现真实用户认证、动态授权、持久审计或直接修改远程服务器。

当前进展:

  • 兼容 Chat 的普通 Origin 拒绝记录 dashscope_chat_request result=forbidden_origin 和经过引用/ASCII 转义的有界 origin;每个请求 Header 最多保留前 256 个输入字节,超长值追加 [truncated] 后再转义。CORS 预检拒绝记录 result=preflight_forbidden、有界 origin、preflight_method、preflight_headers 和 reason(origin_missing、origin_not_allowed、method_not_allowed 或 headers_not_allowed)。成功请求不记录 Origin,日志不记录 xtoken、Authorization、Cookie、prompt/body、会话或 Provider 数据。
  • 受限部署排障已补充:按 request_id 关联 403 响应和 Go 日志;从完整 Origin 确认后,以英文逗号分隔写入 FIRE_SAFETY_CHAT_ALLOWED_ORIGINS,每项规范形式为 scheme://host[:port],不含非根路径、查询或片段,禁止 *;单个末尾 / 会被接受并规范化移除,配置时建议省略。修改代码需 build + recreate,修改环境值也需 recreate;目标服务器仍待实测。
  • 7 个 MCP 工具均已增加 limit/offset schema、服务端校验和稳定 SQL 分页;响应 data 仍为数组,metadata 已区分当前页数量与过滤后总量。自动化、竞态、vet 和 Linux 构建通过;开发机当前无法连接 .env 中的 PostGIS,分页版真实 SQL 尚未实库复验。
  • 用户报告测试页面已经能够正常输出内容,并确认对外身份应为“山东省烟台市牟平区森林防火平台 AI 助手小牟”。现有 Profile 更像泛化模板生成器,没有主动形成数据支撑的演练方案,也没有稳定展示工具坐标。仓库已新增可直接粘贴的消防 Profile 提示词 v2,明确“小牟”身份、“数据库事实 + 通用专业规划”的能力定位、坐标输出硬规则、纯文本结果格式、综合方案结构和能力边界;真实 Profile 尚未由用户发布和验收。
  • Dockerfile 使用显式 Go/Alpine 版本的多阶段构建,在构建阶段执行全部 Go 测试,最终镜像只包含静态服务二进制、CA 和时区数据,并以非 root 用户运行。
  • Docker build 支持通过 FIRE_SAFETY_BUILD_GOPROXY 选择目标机可达的可信 Go module proxy;默认仍为官方代理并保留 checksum database,git 只存在于 builder,构建代理配置在运行容器中强制清空。
  • compose.yaml 只运行一个 API 实例,从未提交的 .env 注入配置,强制清空一次性迁移 DSN,把容器内 8080 发布到宿主机 127.0.0.1:16587,并设置健康检查、只读文件系统、权限收紧和日志轮转。
  • 现有 PostgreSQL/PostGIS 不进入 Compose;同宿主机数据库需要使用容器可达的宿主机地址,且仍需受 listen_addresses、pg_hba.conf 和防火墙约束。
  • Nginx 示例增加 HTTP 到 HTTPS 跳转和 HTTP 429 JSON 限流响应,精确反代 /chat、/chat/、/chat/app.css、/chat/app.js、兼容 completion 和 /mcp,仍不比较、保存或注入 Chat、MCP、SuperAgent 或数据库 Secret;代理必须保留客户端 Origin 交给 Go。
  • 运维手册记录 Git 前置条件、服务器目录、Secret 权限、Compose/Nginx 启停、页面开关、Chat/MCP 冒烟、403 Origin 排障、SuperAgent 回调、更新和回滚。
  • SuperAgent 无法在其配置中指定 MCP 协议版本;同一 SuperAgent 中 th-hotel-simple-superagent 已稳定启用/调用,现场实现不读取 initialize.params.protocolVersion,不读取或校验 MCP-Protocol-Version Header,并固定返回 2025-06-18。消防 MCP 按该 proven profile 兼容:版本字段和 Header 不作为拒绝门禁,响应固定为 2025-06-18。这不表示支持任意其他版本,也不是追求最新协议;日志只使用 direct_success/compatibility_success,不记录原始版本值。
  • SuperAgent Open API 现在由 FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE 控制消息流查询参数,默认 false。无 Trace 严格成功要求最终 AI 消息 finish_reason=stop、非空顶层 message.final 和顶层 end;Trace=true 时仍要求 run.completed(status=success)。无 Trace 不返回公开工具/步骤轨迹,但不等于禁止 Agent 调 MCP。受控诊断中,同一 Key 的 include_trace=true 因应用策略返回 HTTP 403 open_agent_trace_disabled;改用 false 后,真实探针返回严格成功,兼容 Chat 本地 SSE 也完成 null -> stop。公网完整 MCP 对话仍待验证。

已实现验收项:

  • 镜像构建上下文排除 .env、密钥、证书、SQL、Excel、文档和本机构建产物;运行时镜像不包含 Go 工具链或源码。
  • Compose 配置不包含明文 Secret,且没有数据库容器、数据卷或迁移命令;现有业务数据库不会被部署动作重建。
  • Nginx 上游固定为宿主机回环地址,兼容 Chat SSE 禁用缓冲和自动重试,未列出路径固定 404。
  • 目标机执行步骤包含不渲染 .env 内容的 Compose 检查、nginx -t 前置门禁和可恢复的配置替换。
  • 目标服务器已开始部署:Nginx 配置语法检查和 Docker 镜像构建已通过;曾因 Chat 短凭证门禁发生重启,随后公网 MCP 请求已到达 Go,页面、容器稳定运行和独立 16587/health 通过证据仍待提供。
  • SuperAgent 现场日志已证明公网 MCP 完成 initialize、notifications/initialized、tools/list,并于 2026-09-05 22:35 成功调用 fire_safety_search_place_candidates;这只证明地点候选工具成功,其他消防工具和完整多工具链仍待验收。

2. 当前优先级

  1. 由用户审查本 checkpoint 变更后提交并推送 origin/main;服务器只部署明确提交的 revision。
  2. 在 /home/firee-safety-ymd 重建 Compose,确认宿主机 16587 只绑定回环地址、容器内 8080 健康可达且数据库连接正常。
  3. 按部署手册对同一地名执行 offset=0/1 相邻页真实冒烟,核对 total_count 一致、next_offset 可继续且记录不重复;再验证 7 个工具的分页版 tools/call 和 warning。
  4. 分页契约部署通过后,将 docs/project/integrations/superagent-fire-safety-profile-prompt.md 的“可直接粘贴版本”发布为消防测试 Profile 新版本。
  5. 用全新会话验证地名候选、继续展示和综合演练问题;同时核对自然语言结果与 MCP 日志,坐标只来自 location/nearest_point,责任队伍、集结点和路线能力不得被补造。
  6. 页面测试保持 FIRE_SAFETY_CHAT_PAGE_ENABLED=false 默认边界;需要开启时配置精确 Origin,验证页面入口和静态资源;Nginx 只公开约定路径。
  7. 使用项目专属测试 Key 验证兼容 completion 首轮/多轮、会话复用和无 Trace 严格完成;仅在外部应用策略允许时测试 Trace 模式。
  8. 使用 SuperAgent 实际握手验证 initialize → notifications/initialized → tools/list → 7 个工具的 tools/call;版本字段/Header 不作为配置或拒绝门禁。
  9. 为所有查询表补齐适用 GiST 索引并验证查询计划;当前小数据可做联调,但生产前必须完成索引与并发验证。
  10. 设计真实用户身份、动态角色/区域授权、共享会话、限流、Secret 轮换、指标和持久审计。

3. 已确认事实

  • 仓库已初始化 Git,当前分支是 main,已有远程 origin;当前已推送基线为 801c0af。
  • docs/import/字段组.xlsx 和 docs/import/数据表映射.xlsx 是用户已有、已暂存的变更,本 checkpoint 未修改。
  • 用户已使用项目只读 probe 成功连接数据库 fire_safety_ymd;PostGIS 报告版本 3.3 USE_GEOS=1 USE_PROJ=1 USE_STATS=1,8 表合计 4,055 条记录。
  • 实库 4,048 条非空几何已在 2026-09-05 的受控事务中从 SRID 0 补齐为 SRID 4326;坐标 extent 约为经度 121.16 至 121.93、纬度 37.07 至 37.49,类型与预期一致且未发现 WGS84 数值越界。数据提供方确认 8 表源数据均为 EPSG:4326 且无坐标偏移,严格 readiness 已通过。
  • 实库包含 7 条空几何;防火网格 4 条、林区工矿企业 4 条、墓地坟区 27 条无效面几何。用户决定首版不修复原始几何,由 MCP 排除并明确告警。
  • 实库仅防火网格表报告存在 GiST 几何索引,其余 7 张表尚未发现 GiST 几何索引。
  • 防火通道首次重导在约第 256 条因 Geometry has Z dimension but column does not 中止,证明源数据混合二维与 Z 维度;用户将 st_2_xianyoufanghuotongdao.geom 改为不限定 typmod 的 geometry 后报告重导成功。原始列不得无审查改回二维 geometry(GEOMETRY),也不得静默 ST_Force2D 丢弃 Z。
  • 每张表的 2 条本地样例足以确定首版字段映射;样例不能证明全库质量或实时状态。
  • 原始导出样例的 geom 列均声明为 geometry(GEOMETRY),但该声明不兼容防火通道中的 Z 记录;防火通道实库导入列已按用户现场操作改为裸 geometry。数据提供方允许当前二维算法忽略 Z,但原始 Z 仍须保留,不能对原始表执行 ST_Force2D。
  • Go module 当前使用临时名称 fire-safety-ymd,本地工具链为 Go 1.26.6。
  • 直接第三方依赖为 github.com/jackc/pgx/v5 v5.10.0;HTTP、JSON-RPC/MCP 和测试仍使用 Go 标准库。
  • 服务默认监听 :8080;GET /health 仍只是 liveness,不访问外部依赖。
  • 用户对话 API、SuperAgent Open API Adapter、默认关闭的 /chat 测试页面和 MCP endpoint 都默认关闭;Chat Bearer、页面手动输入的 xtoken、Open API Key 和 MCP Token 属于三个独立信任方向并禁止复用。
  • /api/chat 已实现单进程内存会话映射、同会话并发 Run 冲突和严格 SSE 最终回答;模拟 Provider 端到端测试通过,真实 SuperAgent 尚未通过该入口联调。
  • 可选兼容入口已实现截图所示路径、xtoken、input.prompt/session_id 和 event: result 外形;正文仍只在严格成功的 stop 事件中出现,不是 DashScope 全量 API。403 Origin/预检拒绝仅记录有界、引用/转义的诊断字段,不记录 Secret、正文或会话/Provider 数据。
  • 可选 /chat 测试页面已纳入 Go 路由边界:页面开关默认关闭,关闭时 /chat、/chat/、/chat/app.css、/chat/app.js 均直接 404;开启时 /chat 返回 308 到 /chat/,/chat/ 与 /chat/app.css、/chat/app.js 提供同源页面资源。页面不嵌入或持久化 Token,用户手动输入 xtoken,页面仅在内存中复用 session_id。
  • Dockerfile、.dockerignore 和 compose.yaml 已建立测试部署基线;容器单实例运行,容器内 8080 仅发布到宿主机 127.0.0.1:16587,一次性迁移 DSN 在服务容器中强制为空。
  • deploy/nginx/fire-safety-ymd.conf.example 已将公网页面/资源、兼容对话和 MCP 调用指向宿主机 127.0.0.1:16587,再由 Docker 映射到容器 8080;配置不保存或注入任何 Provider/Chat/MCP Secret。目标机仅 nginx -t 语法检查已通过,reload、页面资源和 HTTPS 实际响应尚未验证。
  • 用户确认真实数据包含大量镇街,环境变量不适合枚举全量值;MCP 现支持显式数据库全范围 all 和默认镇街白名单 town_allowlist 两种服务端范围。
  • 用户选择先实现简单地名能力、后续再优化;当前只查询既有森林防火记录,不调用外部地图服务,也不把候选代表点自动认定为演练点。
  • 消防 Profile 的对外身份已确认为“山东省烟台市牟平区森林防火平台 AI 助手小牟”,能力不限于复述系统字段,可用通用专业知识补全演练方案;本地地点和资源事实仍必须来自用户确认或 MCP,相关工具返回坐标时默认展示 WGS84 经度、纬度。当前实现是授权 MCP 查询,不得表述为业务数据已经训练进模型或 Agent 会在对话中自行学习。
  • 本地真实 MCP 冒烟已完成:7 个工具均成功访问实库,响应和错误边界符合契约;该结果不等于公网、SuperAgent 或生产并发已验证。
  • SuperAgent 无法配置 MCP 协议版本;已稳定接通的 th-hotel-simple-superagent 作为 proven profile 参照,不读取/校验 initialize 版本字段或 MCP-Protocol-Version Header,并固定返回 2025-06-18。消防服务按该 profile 处理,版本字段/Header 不作为拒绝门禁;固定返回不等于支持任意其他版本,也不是追求最新协议。
  • 防火通道现有字段不能支持可靠路线规划;防火网格现有字段不能支持实时队伍位置或正式集结点。

4. Known Issues 与未确认项

  • 目标 PostgreSQL 的只读连接和 PostGIS 3.3 已由 probe 验证;数据库版本、TLS/网络生产拓扑、凭证轮换和审计仍未确认。
  • 35 条无效面几何和 7 条空几何会被查询排除;尤其 4 条无效防火网格可能造成所属网格和责任中队结果缺口,27 条无效墓地面可能造成风险区域漏项。
  • 除防火网格外 7 张表缺少 GiST 几何索引;当前 geography 距离表达式的生产索引方案需根据实库查询计划确认。
  • 水源/设施 syzt、水源 hc_datetime 等字段的枚举、单位、时区和更新责任人尚未确认。
  • SuperAgent MCP 的公网 URL 已有现场成功证据:Bearer、Content-Type、JSON-RPC 通过,随后记录了 initialize、notifications/initialized、tools/list,并于 2026-09-05 22:35 成功调用 fire_safety_search_place_candidates。同一 SuperAgent 的 th-hotel 服务已稳定调用,为 proven profile 参照;消防服务其余 6 个工具、完整多工具链、TLS、网络白名单和 Token 轮换仍待联调。是否发送协议 Header 不构成兼容阻塞。
  • /api/chat 静态 Bearer、兼容路径 xtoken 和 /chat 测试页面只适用于受控联调,浏览器用户可以看到手动输入的 Token;页面默认关闭,开启时要求 FIRE_SAFETY_CHAT_ALLOWED_ORIGINS 包含精确 https://agent.nianxx.com,复杂网络下其他浏览器来源须按 403 诊断日志和 Network 面板确认后追加。真实用户身份、动态授权、生产速率限制和滥用防护尚未实现。Chat 短凭证仅可通过默认关闭的显式 legacy 开关在受控测试/迁移窗口使用,MCP Token 仍要求至少 32 个可打印 ASCII 字符,三凭证必须不同。
  • SuperAgent Trace 策略当前不对本项目开放:同一 Key 请求 include_trace=true 返回 403 open_agent_trace_disabled;改为 include_trace=false 后真实探针已严格成功。无 Trace 只影响工具/步骤轨迹返回和成功判定,不禁止 Agent 调用 MCP;实际消防 Profile 的无 Trace 多工具对话和工具轨迹替代证据仍待公网验收。
  • 目标公网机器的 Docker/Compose 和 Nginx 版本、配置 include 层级、证书、DNS、安全组及 PostgreSQL 网络拓扑尚未完整验证;用户已开始远程部署,仓库资产与服务器现场配置仍需完成一致性核验。
  • 目标服务器此前连续两次访问 proxy.golang.org:443 均在约 91 秒后超时,随后已通过可达的构建路径完成 Docker 镜像构建;该事实不代表所有外部 HTTPS 都可达。
  • 目标机曾因已交付的 Chat 短凭证未通过默认配置门禁而反复重启;801c0af 已包含显式兼容方案。最新公网 /mcp 请求已完成地点候选工具调用,说明该启动阻塞已不再是当前首要问题;但独立 health、页面公网响应、兼容 Chat 多轮、MCP 其余工具和完整链路仍未形成通过证据。
  • Chat 会话只在单个 Go 进程内存中保存;重启或多实例切换会丢失上下文,且当前没有历史查询、持久审计或主动取消 Provider Run。
  • 当前 all/town_allowlist 都是服务账号静态范围,不是最终用户级授权;all 会授权当前数据库中 MCP 固定查询表内所有镇街和镇街字段为空的记录,身份提供方、角色、租户和精确位置权限尚未确定。
  • 地名搜索是无索引的有界包含匹配;真实数据量下的耗时、重名率和名称字段质量尚未验证,生产优化可能需要标准地名表、别名词典或 pg_trgm 索引。
  • 镇街或村庄名称可能匹配多条资源/网格;线面只返回只读计算的代表点,不能直接作为真实演练点。
  • 仅实现结构化运行日志和兼容 Chat 拒绝场景的有界诊断字段,没有持久审计、指标、限流网关或数据源版本;403 日志不是最终审计方案。
  • 路线规划缺少路网拓扑、坡度、路面、宽度、车辆限制、封路、实时火场和天气数据。
  • 队伍集结缺少正式集结点、实时定位、战备状态、人员/车辆/装备和容量数据。
  • fire-safety-ymd 正式 module path 与 CI/部署 Go 版本仍待确认。
  • 新提示词尚未发布到真实消防 Profile;坐标展示、地名确认、多点不串线、综合问题多工具调用以及建议/事实分层均待全新会话验收。

5. Next Checkpoint

建议:fire-safety-ymd-container-public-entry-live-smoke-test。

完成条件:

  • 用户提交并推送本 checkpoint 后,目标机能在 /home/firee-safety-ymd clone 或 git pull --ff-only 到明确 revision。
  • docker compose build --pull、up -d 和容器健康检查通过,宿主机 16587 只绑定 127.0.0.1,运行容器中没有迁移凭证。
  • 在目标机替换安全 App ID、执行 nginx -t 后 reload,并验证 TLS、HTTP 到 HTTPS 跳转、429 和未列出路径 404。
  • 验证页面开关关闭时 /chat、/chat/、/chat/app.css 和 /chat/app.js 均直接返回 404;开启并 recreate 后 /chat 返回 308、/chat/ 返回 200,两个资源也返回 200;页面 Origin 白名单包含 https://agent.nianxx.com。
  • 使用无敏感信息的问题验证兼容首轮 null -> stop、后续 session_id 复用、错误 xtoken、断流和超时。
  • 验证兼容 Chat 403 Origin/预检日志:仅拒绝场景记录有界、引用/转义后的 Origin;预检附有界方法、请求头名称集合和原因;日志不出现 Token、Cookie、prompt/body、会话或 Provider 数据。
  • 使用浏览器测试页面手动输入静态测试 xtoken,确认页面不写入 Token、同源发送兼容 completion SSE,并在第二轮复用内存 session_id;页面不作为生产认证。
  • 配置 SuperAgent 对公网 /mcp 的独立 Bearer,验证真实工具调用、TLS 和 warning 保留。
  • 不在输出、命令历史、Nginx、镜像层或 Git 中记录任何 Secret。

6. 验证记录

  • MCP 分页:gofmt、GOCACHE=/private/tmp/fire-safety-ymd-pagination-go-cache go test -count=1 ./...、go vet ./...、go test -race -count=1 ./... 和 Linux 静态服务构建通过;覆盖 7 个工具的 schema、默认值、边界校验、透传、当前页/总量元数据、末页、超尾页、稳定排序与只读 SQL 参数化。开发机使用现有 .env 尝试真实分页冒烟时无法连接已配置 PostGIS,因此分页版真实 SQL 和公网链路仍待测试服务器验证。
  • gofmt -w ./cmd ./internal:通过。
  • GOCACHE=/private/tmp/fire-safety-ymd-go-cache go test -count=1 ./...:通过;新增覆盖页面开关依赖、开启/关闭路由、HTML/静态资源、安全响应头和应用装配;原有 Chat、SuperAgent、MCP/PostGIS 覆盖继续通过。
  • GOCACHE=/private/tmp/fire-safety-ymd-origin-log-go-cache go test -count=1 ./internal/handler -run 'TestDashScopeChatForbidden(OriginLogIsActionableAndSafe|PreflightLogIdentifiesCause)$':通过;覆盖 403 Origin 日志的引用/转义、前 256 个输入字节截断边界、恶意换行隔离、预检方法/请求头/原因和 Token/Cookie/prompt 不落日志。
  • 403 Origin 诊断日志全量回归:go test -count=1 ./...、go vet ./...、go test -race -count=1 ./...、gofmt -l ./cmd ./internal、Linux amd64 静态服务构建和 git diff --check 均通过;沙箱内完整测试因既有 httptest 无权绑定回环端口失败,获准在沙箱外重跑后通过。
  • GOCACHE=/private/tmp/fire-safety-ymd-go-cache go vet ./...:通过。
  • GOCACHE=/private/tmp/fire-safety-ymd-go-cache go test -race -count=1 ./...:通过。
  • SuperAgent 无 Trace:自动化覆盖 include_trace=false 请求参数、最终 AI 消息 finish_reason=stop + 非空顶层 message.final + 顶层 end 成功,以及 Trace=true 仍要求 run.completed(status=success);真实同一 Key 诊断为 true=403 open_agent_trace_disabled,false 模式下 cmd/superagent-probe 严格成功并返回最终回答,本地兼容 Chat SSE 也完成 finish_reason=null -> stop,公网完整 MCP 对话仍待验证。
  • node --check internal/handler/chatpage/app.js:通过。
  • 本地真实浏览器:首轮兼容 SSE、第二轮 session_id 复用、错误凭证、Nginx 风格 429、未完成 SSE 断流后清会话、恶意 HTML 纯文本显示均通过;375px 视口无横向溢出,4 个按钮高度均为 44px,控制台无错误。
  • ruby -e 'require "yaml"; YAML.load_file("compose.yaml")':通过基础 YAML 解析;开发机没有 Docker CLI,未执行 docker compose config --quiet。
  • Chat legacy 短凭证回归:默认仍拒绝少于 32 个字符的 Chat Token;仅在 FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN=true 时接受非空、最多 4096 字节且仅含 ASCII 0x21-0x7e 的短值;原生与兼容入口均通过,MCP 至少 32 字符和三凭证分离门禁保持不变。
  • 模拟 SuperAgent Chat 端到端:原生与兼容入口均通过;应用创建 Provider Session、发送消息、解析严格完成事件,原生返回 conversation/message/done,兼容入口返回 result 且最终 finish_reason=stop。
  • Nginx:配置已完成静态检查且未包含真实 Secret;开发机未安装 Nginx。据用户截图,目标机 nginx -t 已通过,reload 和 HTTPS 实际响应尚未验证。
  • 测试页面:已补齐默认关闭开关、/chat 规范化入口、/chat/ HTML、/chat/app.css、/chat/app.js、同源兼容 SSE、手动 xtoken/内存 session_id 以及开启/关闭/回滚文档;Go 自动化测试、JavaScript 语法检查和本地真实浏览器首轮/续轮、错误凭证、429、断流、纯文本注入与 375px 移动端验收通过,公网静态资源和真实 SuperAgent 多轮仍待部署验收。
  • Docker/Compose:部署文件已通过 YAML/静态安全断言;开发机未安装 Docker。目标机 Docker 镜像构建已成功,曾因 Chat 短凭证默认门禁反复重启;最新公网 /mcp 请求证明服务随后已恢复处理请求,但 docker compose config --quiet、独立 health 和完整公网链路仍待现场确认。
  • 构建代理回归检查:修复前静态反馈命令返回 RED: Docker build has no configurable GOPROXY;修复后确认 Compose build arg、Dockerfile GOPROXY 和运行容器清空边界,返回 GREEN。
  • CGO_ENABLED=0 GOOS=linux go build -buildvcs=false -trimpath ./cmd/server:通过,生成 Linux 静态服务二进制;不替代目标机真实 Docker build。
  • 目标机首次 Docker 构建:失败;go mod download 获取 github.com/jackc/pgpassfile@v1.0.0 时连接 proxy.golang.org:443 超时,镜像/容器未生成,随后 curl http://127.0.0.1:16587/health 得到 connection refused,符合前置构建失败。
  • 目标机后续 Docker 构建:成功;但 docker compose logs --tail=100 api 报 FIRE_SAFETY_CHAT_AUTH_TOKEN must contain at least 32 printable ASCII characters,容器因配置校验失败重启,故 curl http://127.0.0.1:16587/health 仍未形成通过证据。
  • 目标机 Nginx:用户截图显示 nginx -t 配置语法检查成功;是否已 reload 以及 HTTPS 实际响应仍待确认。
  • SuperAgent MCP 公网现场:用户提供的 2026-09-05 22:35 日志证明请求已到达 Go 服务,Bearer、Content-Type 和 JSON-RPC 校验通过,完成 initialize/notifications/tools-list 后,fire_safety_search_place_candidates 已返回 success。该证据只覆盖地点候选工具;数据库 readiness 虽已在本地通过,但其余 6 个工具和完整公网多工具链仍待验收。
  • MCP proven-profile 回归:旧实现对 SuperAgent 请求返回截图中的 MCP_PROTOCOL_VERSION_UNSUPPORTED(RED);兼容实现对版本字段缺失、空值、非字符串、直接匹配或其他值均固定返回 2025-06-18,并覆盖带/不带/不同值 Header;同一 Handler 内的 initialize → notifications/initialized → tools/list → tools/call 回归通过,日志仅输出 direct_success 或 compatibility_success(GREEN)。公网完整链路仍待部署验证。
  • SRID 迁移预检:通过;使用临时 admin 连接确认 4,048 条候选、8 表 UPDATE 权限和 7 表 ALTER 权限,未输出 DSN 或业务记录。
  • SRID 数据迁移:通过;事务更新 4,048 条非空几何,7 张二维表改为 geometry(Geometry,4326),防火通道保持裸 geometry,迁移前后几何载荷指纹与维度一致。
  • 真实 PostGIS 严格 audit:通过;运行时只读账号报告 8 表 SRID 均为 4326、类型与范围门禁通过。预期保留 7 条空几何、35 条无效面几何和 7 张缺 GiST 索引表 warning。
  • 本地真实 MCP 冒烟:通过;health、鉴权、Origin、方法限制、协议初始化、7 工具发现、7 tools/call、无结果、非法参数、响应一致性、字段脱敏、warning 和结构化日志均符合契约。第二轮实库查询约 0.35 至 0.99 秒。
  • 数据导入:用户报告 8 份 SQL 已导入,防火通道在使用裸 geometry 保留混合二维/Z 后重导成功;这是现场反馈,不替代项目只读 probe 的最终验证。
  • 真实 SuperAgent 对话与 MCP 联调:对话 API 仅完成模拟 Provider 端到端测试,真实消防 Profile 尚未完成 Chat 页面/多轮验收;MCP readiness 和本地真实工具冒烟已通过。公网 /mcp 已完成一次 fire_safety_search_place_candidates,但其余 6 个工具和完整多工具链尚待验证,不能宣称公网工具联调或部署完成。th-hotel 成功只证明同一 SuperAgent 的兼容档案可行,不替代消防 endpoint 的完整链路验收。
  • 样例 SQL:未执行;含受限数据的 *.sql 已被 Git 忽略。
  • Git:801c0af(Chat 门禁兼容修复)已由用户提交并推送到 origin/main;本次 MCP 协商变更尚未提交,未执行自动 commit/push。

7. 2026-09-06 MCP 分页契约 checkpoint

  • 名称:fire-safety-ymd-mcp-pagination-v1
  • 状态:代码、自动化测试和文档契约已完成;分页版真实 PostGIS 查询与公网 SuperAgent 验收待完成。
  • 统一契约:7 个只读工具均接受可选 limit/offset;limit 范围为 1..20,offset 范围为 0..10000。地名候选、水源、指挥部候选、防火通道和风险区域默认 limit=10;防火网格和责任中队默认 limit=20;offset 默认 0。
  • 结果契约:data 始终为数组;metadata.result_count 为当前页数量,新增 total_count、limit、offset、has_more、next_offset。总量必须在授权范围、有效几何排除和全部业务过滤完成后、分页前计算,并使用稳定排序;末页 next_offset=null。
  • 状态语义:仅 total_count=0 使用 status=no_results;总量大于零但请求超出末页时仍为 status=ok,返回空数组和 has_more=false。
  • Agent 规则:has_more=true 时说明当前展示数/总数;用户要求继续时使用上一页 next_offset;综合方案默认不自动拉取全部页。
  • 实现范围:Domain/Service/Handler/Repository 已统一分页;Repository 使用过滤后的窗口总量、稳定排序和参数化 LIMIT/OFFSET,超尾空页通过相同条件的只读首页探测恢复准确 total_count。同步更新了项目上下文、架构、空间 MCP Spec、SuperAgent 接入指南、演练证据流程、消防 Profile 提示词和本状态记录。

8. 2026-09-07 Chat 403 Origin 诊断日志 checkpoint

  • 名称:fire-safety-ymd-chat-origin-diagnostic-logging-v1
  • 状态:Handler 实现、针对性自动化与本地全量回归已完成;提交、目标机重建和公网 Origin 白名单验收待完成。
  • 诊断契约:普通兼容 Chat POST 仅在非空 Origin 不被允许时记录 result=forbidden_origin 与有界 origin;预检拒绝记录 result=preflight_forbidden、origin、preflight_method、preflight_headers 和稳定 reason。每个请求 Header 最多保留前 256 个输入字节,超长值追加 [truncated] 后再引用/ASCII 转义,不能伪造额外日志行。
  • 安全边界:诊断字段仅用于定位来源,不改变授权;成功请求不记录 Origin,任何场景均不记录 xtoken、Authorization、Cookie、prompt/body、会话或 Provider 数据。日志无持久审计、保留周期和访问角色设计,生产前仍需另行审查。
  • 白名单契约:从完整、可信的浏览器 Network Origin 或未截断日志确认后,才把规范形式 scheme://host[:port] 写入 FIRE_SAFETY_CHAT_ALLOWED_ORIGINS;多个来源英文逗号分隔,不得带非根路径、查询或片段,也不得使用 *;单个末尾 / 会被接受并规范化移除,配置时建议省略。修改 .env 需 recreate;修改代码需 build + recreate;目标服务器真实日志、Nginx 链路和公网联调仍待验证。
  • 本地验证:目标 Handler 回归、全量测试、竞态测试、vet、格式检查、Linux amd64 静态服务构建和 diff 检查均通过;目标机 Docker build/recreate、Nginx reload、浏览器实际 Origin、复杂网络来源和公网 HTTPS 响应尚未形成证据。