diff --git a/suites-help/系统使用手册/平台架构文档.md b/suites-help/系统使用手册/平台架构文档.md index b00a102..2d2dddd 100644 --- a/suites-help/系统使用手册/平台架构文档.md +++ b/suites-help/系统使用手册/平台架构文档.md @@ -1,392 +1,208 @@ -# AgentGIS Cloud Platform — 实际部署架构 +# 平台架构文档 -> **本文档反映当前实际运行状态(2026-07-16 验证)。** -> 基于阿里云 ECS(39.107.238.22)+ 腾迅云 ECS(106.54.216.234)部署情况编写。 +> 面向平台运维的架构描述,反映 **2026-07-16** 实际部署状态。 +> 阿里云 ECS(39.107.238.22)生产环境,腾迅云 ECS(106.54.216.234)备份。 --- -## 一、总体拓扑 +## 一、总览 ``` -用户 - │ - ▼ - Nginx Proxy Manager (mercator-npm) ← HTTPS 统一入口 - │ ┌───────────────────────────────────────────┐ - │ │ www.mercator.cn → homepage:3000 │ - │ │ auth.mercator.cn → auth-front:3000 │ - │ │ suites.mercator.cn → suite-front:3302 │ - │ │ discussions.mercator.cn → discuss:3001 │ - │ │ git.mercator.cn → gitea:3000 │ - │ └───────────────────────────────────────────┘ - │ - ├── mercator-homepage — 官网首页 - ├── mercator-auth-center-frontend — 认证前端 (Next.js) - ├── mercator-auth-center-backend — 认证后端 (FastAPI, :8000) - ├── mercator-suite-market-frontend — 套件市场前端 (Next.js) - ├── suite-market — 套件市场后端 (FastAPI, :8001) - ├── mercator-discussions-frontend — 讨论区前端 (Next.js) - ├── mercator-discussions-backend — 讨论区后端 (FastAPI, :8005) - ├── mercator-gitea — Gitea 代码托管 / Packages 存储 - ├── minio-nginx — MinIO 对象存储 - ├── mercator-postgres — PostgreSQL (统一元数据) - └── mercator-redis — Redis (缓存) +用户 / AI Agent + │ + ▼ +Nginx Proxy Manager (mercator-npm) ← HTTPS 统一入口 + │ + ├── www.mercator.cn → homepage:3000 + ├── auth.mercator.cn → auth-center-frontend:3000 (→ backend :8000) + ├── suites.mercator.cn → suite-market-frontend:3302 (→ backend :8001) + ├── discussions.mercator.cn → discussions-frontend:3001 (→ backend :8005) + └── git.mercator.cn → gitea:3000 ``` -### 物理部署 +**核心原则:执行在本地,云端只做管理和分发。** -| 服务器 | IP | 角色 | 运行内容 | -|--------|-----|------|---------| -| 阿里云 ECS | 39.107.238.22 | **生产环境** | 全部平台服务容器 + Gitea(SuiteHub & AgentGIS 两个组织) | -| 腾迅云 ECS | 106.54.216.234 | 备份 | Gitea(备份实例,角色待确认) | +``` +云端:套件市场 → 认证 → Gitea Packages(脚本包/镜像) + ↑ +本地(用户机器):gis-actions (agc) → 下载脚本包 → docker run 执行 → 结果留在本地 +``` --- -## 二、容器清单 +## 二、生产环境容器清单 -### 2.1 认证中心 — Auth Center +全部运行在阿里云 ECS(39.107.238.22),Docker 网络 `mercator-net`。 + +### 2.1 认证中心 — auth-center | 项目 | 说明 | |------|------| -| **前端** | `mercator-auth-center-frontend:20260715a`,Next.js,端口 3000 | -| **后端** | `mercator-auth-center-backend:20260630h`,FastAPI,端口 8000 | -| **数据库** | `auth_center_db`(PostgreSQL) | +| 前端 | `mercator-auth-center-frontend:20260715a`,Next.js,:3000 | +| 后端 | `mercator-auth-center-backend:20260630h`,FastAPI,:8000 | +| 数据库 | `auth_center_db`(PostgreSQL,表前缀 `auth_`) | -**后端 API:** +后端 API 分组:登录注册、企业微信 OIDC 扫码、API Key 管理(`mk_` 前缀)、服务账户 Token(HS256 JWT,1h)、MFA TOTP、OAuth2/OIDC 服务端、用户管理、会话管理、审计日志。 -| 分组 | 路由 | 功能 | -|------|------|------| -| 公开认证 | `POST /api/v1/public/login/` | 密码登录 | -| | `POST /api/v1/public/mfa/verify-login/` | MFA 二次验证 | -| | `POST /api/v1/public/refresh/` | Token 刷新 | -| | `POST /api/v1/public/register/` | 注册 | -| | `POST /api/v1/public/forgot-password/` | 忘记密码 | -| | `POST /api/v1/public/reset-password/` | 重置密码 | -| 企业微信 OAuth | `GET /api/v1/public/oauth/wecom/qrcode/` | 扫码登录 | -| | `GET /api/v1/public/oauth/wecom/qrcode/status/{state}/` | 扫码状态轮询 | -| | `GET /api/v1/public/oauth/providers/` | 支持的 OAuth 提供商 | -| API Key | `POST/GET /api/v1/auth/api-keys/` | API Key 管理 | -| | `POST /api/v1/auth/api-keys/verify/` | API Key 校验 | -| 服务认证 | `POST /api/v1/service-auth/token/` | 服务账户 Token(HS256 JWT) | -| 用户管理 | `GET /api/v1/profile/me/` | 个人信息 | -| | `GET /api/v1/roles/me/` | 当前角色 | -| MFA | `GET /api/v1/mfa/status/` | MFA 状态 | -| | `POST /api/v1/mfa/totp/enable/` | 启用 TOTP | -| Session | `GET /api/v1/sessions/` | 会话列表 | -| OAuth2 服务端 | `GET /.well-known/openid-configuration` | OIDC 发现 | -| | `GET /.well-known/jwks.json` | JWKS | -| | `GET /oauth2/authorize/` | OAuth2 授权 | -| | `POST /oauth2/token` | Token 颁发 | -| 管理后台 | `GET /api/v1/admin/users/` | 用户管理 | -| 运维 | `GET /health` | 健康检查 | -| | `GET /health/detailed` | 详细健康状态 | - -**数据库表(`auth_` 前缀):** - -``` -auth_users, auth_user_roles, auth_api_keys, auth_service_accounts, -auth_login_history, auth_audit_logs, auth_notifications, -auth_jwt_secrets, auth_jwt_secret_audit_log, -auth_email_verifications, auth_faqs, auth_system_configs, -auth_third_party_accounts, -oauth_clients, oauth_authorization_codes, oauth_refresh_tokens -``` - -### 2.2 套件市场 — Suite Market +### 2.2 套件市场 — suite-market | 项目 | 说明 | |------|------| -| **前端** | `mercator-suite-market-frontend:20260715a`,Next.js,端口 3302 | -| **后端** | `suite-market`(镜像 `mercator/suite-market-backend:20260630i`),FastAPI,端口 8001 | -| | 代码内标题为 "Scheduler Service",版本 2.3.9 | -| **数据库** | `suite_market_db`(PostgreSQL) | +| 前端 | `mercator-suite-market-frontend:20260715a`,Next.js,:3302 | +| 后端 | `mercator/suite-market-backend:20260630i`,FastAPI,:8001,v2.3.9 | +| 数据库 | `suite_market_db`(PostgreSQL,表前缀 `suite_`) | -**后端 API:** +**API 概览:** -| 分组 | 路由 | 功能 | -|------|------|------| -| 套件 CRUD | `GET /api/v1/suites` | 套件列表 | -| | `POST /api/v1/suites` | 创建套件 | -| | `GET /api/v1/suites/search?q=` | 搜索套件 | -| | `GET /api/v1/suites/{id}` | 套件详情 | -| | `PATCH /api/v1/suites/{id}` | 更新套件 | -| | `DELETE /api/v1/suites/{id}` | 删除套件 | -| | `POST /api/v1/suites/{id}/versions` | 发布版本 | -| | `POST /api/v1/suites/{id}/execute` | 执行套件 | -| 发布 | `POST /publish` | Git 仓库发布 | -| | `POST /publish/upload` | 文件上传发布 | -| 参数校验 | `POST /api/v1/parameters/validate` | 参数校验 | -| 合规检测 | `POST /api/v1/compliance/check` | 合规检测 | -| 类型 | `GET /api/v1/types` | 数据类型定义 | -| 分类 | `GET /api/v1/categories` | 分类列表 | -| 用户 | `POST /api/v1/users` | 创建用户 | -| | `POST /api/v1/users/apply-developer` | 申请开发者 | -| 管理 | `GET /api/v1/admin/...` | 管理员接口 | -| 配置 | `GET /api/v1/config` | 系统配置 | -| 健康 | `GET /api/v1/health` | 健康检查 | +| 路由 | 功能 | +|------|------| +| `GET/POST /api/v1/suites` | 套件 CRUD | +| `GET /api/v1/suites/search?q=` | 搜索 | +| `POST /api/v1/suites/{id}/versions` | 发布版本 | +| `POST /publish` / `POST /publish/upload` | 发布套件(Git 仓库 / 文件上传) | +| `POST /api/v1/compliance/check` | 合规检测 | +| `POST /api/v1/parameters/validate` | 参数校验 | +| `GET /api/v1/categories` | 分类管理 | +| `GET /api/v1/health` | 健康检查 | -**数据库表(`suite_` 前缀):** - -``` -suite_suites — 套件主表 -suite_versions — 版本记录 -suite_categories — 分类 -suite_executions — 执行记录 -suite_user_roles — 用户角色 -suite_developer_applications — 开发者申请 -suite_business_types — 业务类型 -suite_data_types — 数据类型 -suite_file_type_mappings — 文件类型映射 -``` - -**后端内部模块:** - -| 模块 | 文件 | 功能 | -|------|------|------| -| 模块 | 文件 | 实际功能 | -|------|------|---------| -| Workflow 引擎 | `services/workflow.py` | DAG 拓扑排序 + `$inputs.xxx` / `$steps.xxx.yyy` 参数引用解析。**不执行节点**,仅套件发布时预处理用,实际执行在 GIS Actions 本地完成| -| 参数解析 | `services/param_resolver.py` | 根据 `params_mapping` 解析 `$inputs.xxx` / `$steps.xxx.yyy` 引用,用于任务下发前预处理 | -| 合规检测 | `services/compliance.py` + `routers/compliance.py` | `POST /api/v1/compliance/check` — 仅基础格式检查(params_schema 有无 properties、steps 有无、type 合法性),**不扫代码、不验引用** | -| ~~任务队列~~ | ~~`services/queue.py`~~ | **已废弃** — 仅存内存空壳字典(`_tasks: dict = {}`),无实际功能 | -| 角色守卫 | `services/role_guard.py` | 角色等级校验(user → developer → admin),支持 JWT roles 回退 | -| 认证守卫 | `auth_guard.py` | JWT / API Key 统一认证中间件 | - -**关于 Skills 层:** 架构文档中规划的独立 Skills 微服务已被移除。旧表 `suite_skills` 和 `scripts` 已在迁移中删除。技能注册在发布流程中自动完成,不独立暴露 API。 - -### 2.3 讨论区 — Discussions +### 2.3 讨论区 — discussions | 项目 | 说明 | |------|------| -| **前端** | `mercator-discussions-frontend:20260630q`,Next.js,端口 3001 | -| **后端** | `mercator-discussions-backend:20260715a`,FastAPI,端口 8005 | -| **数据库** | `discussions_db`(PostgreSQL) | +| 前端 | `mercator-discussions-frontend:20260630q`,Next.js,:3001 | +| 后端 | `mercator-discussions-backend:20260715a`,FastAPI,:8005 | +| 数据库 | `discussions_db`(PostgreSQL,表前缀 `discussions_`) | -**后端 API:** +**API 概览:** 话题 CRUD + 关闭/重开,评论 CRUD,标签管理。 -| 路由 | 方法 | 功能 | -|------|------|------| -| `/api/v1/topics` | GET | 话题列表 | -| `/api/v1/topics` | POST | 创建话题 | -| `/api/v1/topics/{id}` | GET | 话题详情 | -| `/api/v1/topics/{id}` | PATCH | 更新话题 | -| `/api/v1/topics/{id}` | DELETE | 删除话题 | -| `/api/v1/topics/{id}/close` | POST | 关闭话题 | -| `/api/v1/topics/{id}/reopen` | POST | 重新打开话题 | -| `/api/v1/topics/{topic_id}/comments` | GET | 评论列表 | -| `/api/v1/topics/{topic_id}/comments` | POST | 发表评论 | -| `/api/v1/comments/{comment_id}` | PATCH | 编辑评论 | -| `/api/v1/comments/{comment_id}` | DELETE | 删除评论 | -| `/api/v1/labels` | GET | 标签列表 | -| `/api/v1/labels` | POST | 创建标签 | +**种子标签:** bug, feature, question, discussion, announcement, suggestion -**种子标签:** bug (#ef4444), feature (#22c55e), question (#3b82f6), discussion (#a855f7), announcement (#f59e0b), suggestion (#06b6d4) - -**数据库表(`discussions_` 前缀):** - -``` -discussions_topics — 话题 -discussions_comments — 评论 -discussions_labels — 标签 -discussions_topic_labels — 话题-标签关联 -``` - -### 2.4 Gitea - -| 实例 | 域名 | 组织 | 用途 | 部署位置 | -|------|------|------|------|---------| -| 主实例 | `git.mercator.cn` | **SuiteHub** + **AgentGIS** | 平台仓库 + Packages(镜像/脚本包分发)+ 源代码 | 阿里云 ECS | -| 备份实例 | `gitea.mercator.cn` | 待确认 | 备份 Gitea | 腾迅云 ECS | - -**AgentGIS 组织仓库(源码):** -- `auth-center` — 认证中心 -- `suite-market` — 套件市场 -- `discussions` — 用户交流平台 -- `gis-actions` — 本地执行器 -- `gis-base-image` — 基础镜像 -- `mercator-homepage` — 官网首页 - -**Gitea Packages 用途:** -- OCI Registry:基础镜像存储与分发(`docker pull`) -- Generic Packages:脚本包存储与分发(Publish API 自动上传) - -### 2.5 基础设施 +### 2.4 基础设施 | 服务 | 容器 | 版本 | |------|------|------| | PostgreSQL | mercator-postgres | postgres:16-alpine | | Redis | mercator-redis | redis:7-alpine | | NPM | mercator-npm | jc21/nginx-proxy-manager:latest | -| MinIO | minio-nginx | nginx:alpine(MinIO 反代,端口 9000) | +| MinIO | minio-nginx | nginx:alpine(MinIO 反代,:9000) | --- -## 三、认证体系 +## 三、Gitea -### 3.1 凭证类型 +### 3.1 实例 -| 类型 | 获取方式 | 有效期 | 使用场景 | -|------|---------|--------|---------| -| **JWT (Access Token)** | 密码登录 / 企业微信扫码 | 15 分钟 | 浏览器 Web UI | -| **API Key (`mk_`)** | Auth Center Dashboard 创建 | 自定义(默认 90 天) | AI Agent 自动化调用 | -| **服务账户 Token (HS256 JWT)** | `POST /api/v1/service-auth/token/` | 1 小时 | 微服务间内部通信 | -| **Gitea Token** | Gitea 设置页面生成 | 自定义 | Publish API 上传脚本包 | +| 域名 | 位置 | 用途 | +|------|------|------| +| `git.mercator.cn` | 阿里云 ECS **生产环境** | 源码托管 + Packages(OCI 镜像仓库 + Generic 脚本包存储) | +| `gitea.mercator.cn` | 腾迅云 ECS **备份** | 待确认角色 | -### 3.2 认证流程 +### 3.2 组织与仓库 -``` -用户浏览器 → auth.mercator.cn - ├── 密码登录 → JWT - ├── 企业微信扫码 → OIDC → JWT - └── MFA (TOTP) 二次验证 +**AgentGIS 组织**(源码仓库): -AI Agent (OpenClaw) → API Key (mk_...) → suite-market API - -微服务通信 → HS256 JWT (1h) → Auth Center 签发 -``` - -### 3.3 OAuth2 / OIDC 支持 - -Auth Center 内置 OAuth2 服务端,支持: -- 企业微信作为 OIDC 身份源 -- 自签发 RS256 签名的 JWT(通过 `/.well-known/jwks.json` 暴露公钥) -- 设备授权流程(OAuth 2.0 Device Code) - ---- - -## 四、套件发布与执行 - -### 4.1 发布流程 - -``` -开发者上传 zip/tgz 包 → POST /publish 或 POST /publish/upload - │ - ┌────┴────┐ - │ 解析 workflow.yaml - │ 合规检测 (compliance) - │ 参数校验 (parameters) - │ 打包 scripts/ → .tar.gz - │ 上传至 Gitea Packages - │ 注册版本至 suite_versions - └─────────┬──┘ - │ - 返回发布结果 -``` - -发布入口:`suites.mercator.cn/publish` - -### 4.2 GIS Actions 本地执行流程 - -**平台上没有任务队列,没有 Worker。** GIS Actions 直接从套件市场获取套件并本地执行: - -``` -GIS Actions (用户本地): - python cli.py run --suite-id - │ - ▼ - 1. 请求 GET suites.mercator.cn/api/v1/suites/{id} - → 返回 params_schema / package_url 等元信息 - │ - ▼ - 2. 从 package_url 下载脚本包(Gitea Generic Packages) - → wget https://git.mercator.cn/api/packages/... - │ - ▼ - 3. 解压 → 读取 workflow.yaml - │ - ▼ - 4. steps_executor.execute_steps() - ├── 解析依赖拓扑(depends_on) - ├── 每个步骤:docker run --rm gis-base ... - └── 传递步骤间输出 - │ - ▼ - 5. 清理:删除下载的 tgz 和解压的套件目录 -``` - -**用户也可以通过 CLI 直接指定 --package-url 跳过市场查询。** - -### 4.3 基础镜像 - -``` -gis-base:latest -├── Linux OS (Debian/Ubuntu slim) -├── Python 3.11 -├── GDAL, Shapely, GeoPandas, Fiona, PyProj, Rasterio -└── 入口脚本 run.sh -``` - -基础镜像存储在 Gitea Packages(OCI Registry),由管理员构建维护。 - ---- - -## 五、数据库概览 - -### 5.1 数据库分布 - -| 数据库 | 用途 | 表前缀 | -|--------|------|--------| -| `gitea_db` | Gitea 元数据 | Gitea 自有 | -| `auth_center_db` | 认证、用户、API Key、MFA、OAuth、审计 | `auth_`、`oauth_` | -| `suite_market_db` | 套件、版本、执行记录、分类 | `suite_` | -| `discussions_db` | 话题、评论、标签 | `discussions_` | - -### 5.2 跨服务数据共享 - -Auth Center 与 Suite Market / Discussions 通过 API 调用互通: -- Suite Market 调用 Auth Center 验证 JWT / API Key -- Discussions 调用 Auth Center 验证用户身份 -- 各服务通过 `DATABASE_URL` 连接各自的数据库 - ---- - -## 六、安全防护(当前实现) - -| 层面 | 措施 | +| 仓库 | 说明 | |------|------| -| 认证 | JWT 15m + API Key + 服务账户 Token 三级凭证 | -| 速率限制 | `slowapi` 限流,全局速率控制 | -| CSRF | `fastapi-csrf-protect`(Auth Center) | -| CORS | 全部服务设置 `allow_origins=["*"]`(NPM 层控制) | -| 密码 | 支持 MFA TOTP 二次验证 | -| 日志 | 操作审计日志 (`auth_audit_logs`) | -| 镜像 | Gitea Packages 私有 Registry,需认证拉取 | +| `auth-center` | 认证中心后端源码 | +| `suite-market` | 套件市场后端源码 | +| `discussions` | 讨论区后端源码 | +| `gis-actions` | 本地执行器源码(`cli.py` + `steps_executor.py`) | +| `gis-base-image` | 基础镜像 Dockerfile | +| `mercator-homepage` | 官网首页源码 | -**尚未实现的规划项:** 脚本包内存擦除、反调试探针、数字水印、强制心跳校验(标注在旧架构文档中,待 GIS Actions 实现时同步落地)。 +**SuiteHub 组织**(项目文档): + +| 仓库 | 说明 | +|------|------| +| `agent-profiles` | Agent 认知文件 + 用户/开发者文档 + 平台架构文档 | +| `land-remediation-settlement` | 土地整治项目竣工结算套件 | --- -## 七、当前的架构缺口 / 待办 +## 四、认证体系 + +### 4.1 凭证 + +| 类型 | 有效期 | 用途 | +|------|--------|------| +| JWT(密码/OIDC 登录) | 15 分钟 | 浏览器 Web UI | +| API Key(`mk_`) | 自定义(默认 90 天) | AI Agent 自动化 | +| 服务账户 Token(HS256 JWT) | 1 小时 | 微服务间通信 | +| Gitea Token | 自定义 | 上传脚本包到 Gitea Packages | + +### 4.2 认证流程 + +``` +浏览器 → auth.mercator.cn → 密码登录 / 企业微信扫码 → JWT +AI Agent → API Key (mk_...) → suite-market API +微服务 → HS256 JWT → Auth Center 签发 +``` + +### 4.3 OAuth2 / OIDC + +Auth Center 内置 OAuth2 服务端,企业微信为 OIDC 身份源,RS256 签名。 + +--- + +## 五、套件生命周期 + +### 5.1 发布 + +``` +开发者打包 workflow.yaml + scripts/ → .tar.gz + → POST /publish/upload(需 API Key) + → 合规检测(格式检查) + → 参数校验 + → 上传到 Gitea Packages + → 注册版本到 suite_versions +``` + +### 5.2 本地执行 + +gis-actions 是用户本地的 Python CLI,通过 `agc` 命令使用: + +``` +agc run --suite-id --input key=value + │ + ├── GET suites.mercator.cn/api/v1/suites/{id}(查 package_url) + ├── wget 从 Gitea Packages 下载脚本包 + ├── 解压 → 读取 workflow.yaml + ├── steps_executor: 按 depends_on 拓扑序 + │ └── 每步 docker run --rm gis-base 隔离执行 + ├── 脚本包清理(删除下载和解压目录) + └── 结果留在本地 work_dir/_step_outputs/ +``` + +**平台上没有任务队列、没有 Worker。** 执行完全在用户本地完成,数据不离开用户机器。 + +### 5.3 基础镜像 + +`gis-base:latest` 存储在 Gitea Packages(OCI Registry),由管理员维护。内置 Python 3.11 + GDAL + Shapely + GeoPandas + numpy + openpyxl 等。 + +--- + +## 六、架构缺口 | 缺口 | 影响 | 优先级 | |------|------|--------| | **用户反馈通道缺失** | 本地使用套件出问题,没有渠道报给开发者 | 高 | -| **未验证 GIS Actions 就绪状态** | 套件市场已上线,但 GIS Actions(本地执行器)的发布通道、用户安装流程未验证 | 中 -| **无任务 Worker** | 平台上根本不存在任务队列和 Worker,执行全靠 GIS Actions 本地直连 Gitea 下载 | 中 | -| **合规检测基本是空壳** | 仅检查 params_schema/output_schema/steps 格式,不扫代码、不验引用(系统中已无独立的 skill 概念) | 中 | +| **合规检测基本是空壳** | 仅检查 params_schema/steps 格式,不扫代码、不验引用 | 中 | | **无监控告警** | 服务挂了没人知道 | 中 | -| **脚本清理未落地** | 知识产权保护机制待实现 | 低(GIS Actions 未跑之前无需) | +| **未验证 gis-actions 就绪状态** | 发布通道、用户安装流程未验证 | 中 | +| **脚本清理未落地** | 知识产权保护机制待实现(gis-actions 未跑之前无需) | 低 | --- -## 八、技术栈总览 +## 七、技术栈 -| 层级 | 技术选型 | -|------|---------| -| 前端框架 | Next.js(全部前端) | -| 后端框架 | FastAPI(全部后端) | -| 数据库 | PostgreSQL 16 | -| 缓存 | Redis 7 | -| 反向代理 | Nginx Proxy Manager (jc21/nginx-proxy-manager) | +| 层级 | 选型 | +|------|------| +| 前端 | Next.js | +| 后端 | FastAPI | +| 数据库 | PostgreSQL 16 + Redis 7 | +| 反向代理 | Nginx Proxy Manager | +| 代码托管 / Packages | Gitea | | OIDC 身份源 | 企业微信 | -| Token 签名 | RS256 (OIDC) / HS256 (服务内部) | -| 代码托管 | Gitea | -| 镜像仓库 | Gitea Packages (OCI) | -| 脚本包存储 | Gitea Generic Packages | | 对象存储 | MinIO | -| 容器管理 | Docker (原生,非编排) | -| 邮件推送 | 阿里云 DirectMail | - ---- - -*本文档反映 2026-07-16 实际部署状态。随平台演进持续更新。* +| 邮件 | 阿里云 DirectMail | +| 本地执行器 | gis-actions(Python CLI + Docker) |