简要定义
“集成”覆盖三类外部连接:GitHub 仓库授权(作为部署来源)、Provider(基础设施/DNS/通知等能力提供方)、Plugin(扩展 Appaloft 自身行为)。它们都通过统一的 Connection 模型管理授权和撤销。
为什么存在这个概念
部署来源、DNS 自动配置、通知推送和自定义扩展点,本质上都是”Appaloft 代表你使用一个外部系统的能力”。把它们放在同一套 Connection/Connector 模型下,是为了让授权、撤销、审计和安全边界只需要实现一次。
GitHub 仓库
GitHub 仓库把一次部署和一段可追溯的源码绑定起来:仓库、ref、工作目录和部署身份需要一起记录,这样重试、回滚和预览才能回到同一组输入。
# 查看当前 workspace 的 GitHub App 安装状态
appaloft github status
# 浏览已授权访问的仓库
appaloft github repositories --search web配置一个 GitHub 来源至少需要确认:仓库(owner/repo)、Ref(分支/tag/commit SHA,生产环境用稳定分支,预览用 Pull Request 的 commit SHA)、目录(monorepo 中不要假设仓库根目录就是应用目录)、触发方式(手动/推送自动/Pull Request 预览)。
Pull Request 预览应该使用提交的 commit SHA,而不是会移动的分支名,这样预览页面、日志和后续清理都能对应同一个提交。
Provider
Provider 负责基础设施、DNS 等外部能力。公开文档只解释你能配置和观察什么,不会暴露内部 Provider SDK 类型。
appaloft providers list每个 Provider 会返回安全的诊断信息:稳定的能力标记、启用状态、configured / not configured / partial 等配置状态。诊断信息只服务于可见性判断,不会包含云 SDK 对象、原始响应、access token 或私钥。
Plugin
Plugin 扩展 Appaloft 自身的能力,必须显式声明兼容性、权限和沙箱假设。
appaloft plugins list不兼容的插件会保持”可见但不可激活”,方便你区分”这个扩展点存在但暂时不可用”和”完全不存在的插件”。插件诊断不会暴露实现内部、Provider SDK 对象或密钥引用。
集成方需要用额外运行时行为组合 Appaloft 时,应导入公开的 server 工厂而不是内部源码路径:
import { createAppaloftServer } from "@appaloft/server";
const server = await createAppaloftServer({
extensions: [
{
name: "health-extension",
http: {
routes: [{ method: "GET", path: "/extension/health", handle: () => new Response("ok") }],
},
},
],
});Connection 与 Connector
Connection 是 Appaloft 代表你保存的一次授权关系(例如 GitHub App 安装、DNS Provider 授权、Slack Webhook)。ConnectorDefinition 是目录中具体可连接的项(例如 github-source、cloudflare-dns),你安装、授权、撤销和审计的对象始终是具体 Connector,而不是抽象分类。
appaloft connectors catalog
appaloft connectors list
appaloft connectors connect <connector>
appaloft connectors revoke <connectionId>
appaloft connectors plan --connector <connector> --capability <key> --parameters-json '<json>'
appaloft connectors accept --connector <connector> --capability <key> --plan-id <planId> --risk <risk> --summary <summary> --effects-json '<json>'
appaloft connectors apply --connector <connector> --capability <key> --parameters-json '<json>' --accepted-plan-id <acceptedPlanId>
# 按能力分类的快捷命令(底层仍是同一套 Connection 模型)
appaloft dns plan <domain> --hostname <host> --target <target> --connector cloudflare-dnsDNS 类连接需要经过三层校验才能自动配置:公开 DNS 发现(不需要授权,只是根据域名推断可能的托管商)、Connector 授权(证明你能访问某个 Provider 账号)、Zone 归属匹配(授权账号里必须真的存在覆盖该域名的 Zone)。三层都满足后,Appaloft 才会生成并应用 DNS 变更计划;任何一层不满足都会 fail closed 并提示手动配置。
托管 Kubernetes 与多集群容量也复用同一套 Connector 协议。具体 Connector 可以声明 infrastructure.cluster.provision、import、inspect、readiness、state-eligibility、drain、delete、place、failover、recover、cleanup-orphans、handoff-traffic、failback-traffic 和 traffic-status 能力。公共合同只返回目标池、确定性的放置理由、placement epoch、fencing token、安全状态/恢复/路由/端点/健康证明、成本/支持级别和残留资源计数;Provider 凭证、计费、配额、租户策略和商业拓扑由组合该 Connector 的 Cloud/Enterprise 实现持有。
创建、删除和故障转移属于外部基础设施变更:先运行 connectors plan,检查成本、支持和 cleanup 证据,再接受该精确 plan 并将返回的 acceptedPlanId 传给 connectors apply。应用参数若与已接受的 plan 不一致会在 Provider 副作用前失败;容量不足或 failover 次数超限也不会静默回退到其他拓扑。
托管容量 Cell 生命周期
托管容量 Cell 是目标池中一个可独立识别的托管集群目标。它记录该集群是由 Appaloft 创建还是从既有集群导入,当前处于 accepting、draining、drained、deleted 或 failed,并提供安全的 failure domain、可用容量、活跃 placement 数、成本/支持等级,以及删除 Appaloft 管理关系时如何处置 Provider 资源。
provision 与 import 创建托管视图,inspect 无需接受计划即可返回同一份安全快照。执行 delete 前必须先 drain:drain 会立即把可用容量设为零,阻止新的 placement;仍有活跃 placement 时保持 draining,数量归零后才成为 drained。Cell 未 drained 或活跃 placement 不为零时,delete 会失败。删除 imported Cell 只从 Appaloft 注销,必须保留外部集群;provisioned Cell 只有在精确计划已接受且 Provider adapter 获准变更时才能请求删除 Provider 资源。
Web Console 在“账号设置 → 连接”中显示这些操作。Import 需要既有集群引用,以及 provider-neutral 的名称、规格和所需能力;drain/delete 只绑定精确集群引用。计划与回读显示来源、生命周期、Provider 资源处置、容量、活跃 placement、failure domain、成本/支持和 Appaloft 自有残留资源,但不会返回凭据、私有 binding 或原始 Provider 对象。
独立替代容量就绪检查
infrastructure.cluster.readiness 是只读的 connectors plan 能力。它针对精确的当前目标、placement epoch、工作负载策略与目标池快照,返回类型化的 ready 或 blocked 结果。结果包含可用候选、独立 failure domain、总可用容量、预计成本、支持等级和稳定原因码;当前目标缺失、共享/缺少 failure domain、容量为零、状态非 ready、缺少能力或被策略排除都属于可诊断的 blocked 数据,而不是传输错误。
这个检查不需要接受计划,也没有 connectors apply 路径;它不会预留容量、增加 placement epoch、生成 fencing token 或更改集群、工作负载、Provider、路由和 DNS。结果只说明该不可变快照在检查时是否存在替代容量,真正的流量切换仍需重新检查新鲜状态、完成 fencing 并接受精确的切换计划。
Stateful 故障转移资格与 RPO/RTO 证据
infrastructure.cluster.state-eligibility 是只读的 connectors plan 能力。每个工作负载必须显式声明 stateless、external-durable、restorable 或 local-pvc;省略状态不会被当成 stateless。结果是类型化的 eligible 或 blocked,绑定精确的工作负载、当前目标、替代目标和评估时间,并返回稳定原因码。
Stateless 可以直接通过资格检查。External durable 状态必须提供有有效期的独立持久性证据;restorable 状态必须同时提供现有 Storage Volume backup 与已完成 restore rehearsal 的安全引用,并证明 source target 与 recovery target 不同。两类 stateful profile 都分别声明最大 recovery-point age(RPO 目标)和最大 recovery time(RTO 目标),证据则记录实际观测值;缺证据、证据过期、恢复到同一 target 或观测值超过目标都会得到 blocked。
local-pvc 始终返回 state_local_pvc_not_portable。资格检查没有 apply 路径,也不会执行备份、恢复、fencing、Provider 或路由变更。Failover/recover 与 Cloud 托管的流量切换必须重新绑定同一 workload/current/replacement 的新鲜 eligible decision;既有 Storage Volume 操作仍是备份/恢复生命周期的唯一真相,资格合同不会复制它。
Fenced 流量切换与显式 failback
infrastructure.cluster.handoff-traffic 把一份精确的当前路由权威、安全端点引用、新鲜健康证明、当前和下一 placement epoch、轮换后的 fencing token 与回滚端点绑定进高风险计划。接受后,Connector 在任何副作用前重新读取当前路由与替代端点健康:路由、目标、epoch、token、端点或健康有效期任一漂移都会 fail closed。
执行顺序固定为读取路由、读取健康、fence 旧 actor、移动路由、验证新权威、清理临时资源。移动前失败必须保持旧路由;移动后验证失败只能尝试一次回滚,并且只有回滚也被验证后才能返回 rolled-back。无法证明回滚时返回 manual-intervention,绝不把不确定状态报告为成功。infrastructure.cluster.traffic-status 只有 plan/readback;infrastructure.cluster.failback-traffic 不是旧 receipt 的反向重放,而是必须重新规划并接受更晚 epoch 与新 fencing token 的独立变更。
公共响应只包含路由、端点、健康证明引用、执行步骤、结果、回滚次数和残留自有资源。凭据、Provider binding、账号/Zone 标识与原始 Provider 响应不进入公共合同。真正的 DNS、负载均衡或 CDN 写入仍取决于具体 Connector 是否获准 apply。
Cloud 组合提供托管集群 Connector 时,Web Console 的“账号设置 → 连接”会从 Connector 目录发现这些能力。变更能力提供 plan → 接受 → apply 流程;readiness、state-eligibility 与 traffic-status 只提供 plan/readback。Web 只提交安全的集群/工作负载/状态证据/路由/端点引用、健康证明、所需能力和放置意图;Provider 凭据、私有 binding 与原始 Provider 对象不会进入表单。修改任何计划绑定输入都会立即废弃旧接受状态,apply 在新的精确计划被接受前保持禁用。计划和回读只显示成本、支持等级、选中区域/目标、placement epoch、状态资格/RPO/RTO/原因、流量结果/回滚、替代容量和残留自有资源等安全字段。
常见误区
- 把 GitHub 登录当成仓库访问授权:登录只代表身份,浏览仓库、接收 Webhook 或回写部署状态需要单独完成 GitHub 集成授权。
- 认为 Provider/Plugin 诊断会暴露密钥:诊断信息按设计只包含安全的能力和状态标记。
- 把”DNS”当成一个可安装的东西:
dns是能力分类,真正被安装和撤销的是具体 Connector(如cloudflare-dns)。