跳到正文

Blog

AI Agent 生成了静态站点,接下来该怎么上线?

Appaloft 如何把 agent 产出的 dist 变成可审计的 static artifact publishing 流程,而不是让 AI 直接拿云厂商密钥上传文件。

AppaloftAIStatic Artifacts部署控制面Agents

AI agent 现在很容易生成一个静态站点。

你给它一个需求,它改代码、跑构建,最后留下一个 dist/build/.zip。如果只是做本地 demo,这已经够了。但如果下一句话是“帮我上线”,问题就变了:agent 该把这些文件交给谁?用什么权限?上线之后怎么证明地址可访问?如果要撤回,撤回的是一批文件、一个路由,还是某个云厂商控制台里的临时部署?

很多时候,静态站点发布被讲成一个上传问题。选择一个对象存储、一个 CDN、一个 Pages 产品,把文件丢进去,然后拿到 URL。这个体验很重要,Cloudflare Pages Direct Upload、Netlify Drop 这类产品都证明了它的价值。Appaloft 关心的是另一层:当上传动作由 AI、CLI、Web UI 或 CI 共同触发时,它不应该绕开部署控制面。

这篇文章接着面向 AI 时代的部署控制面Skill 不是 MCPAI Agent 登录不该复制 Cookie往下讲:AI 可以生成文件,但发布仍然应该是一个可审计、可 readback、可回滚的产品流程。

dist/ 不是部署状态

一个静态构建产物通常很简单:HTML、CSS、JavaScript、图片、字体、manifest.json,有时还有 404.html 或 SPA fallback 需要的 index.html

真正麻烦的是这些文件离开本机之后的状态。

  • 这次发布包含哪些文件?
  • 每个文件的 digest 是什么?
  • 路由是普通静态文件,还是 SPA fallback?
  • 哪个 project、resource、environment 拥有这次发布?
  • 有没有扫描过危险路径、重复路径、可疑 secret、超限文件或已知恶意 fixture?
  • URL 是 immutable deployment URL,还是 current alias?
  • 回滚会切 alias,还是重新上传旧文件?
  • 存储、带宽和清理责任记在哪里?

如果这些答案只存在于 provider UI 或 terminal log 里,AI agent 很快会被诱导去猜。它可能直接调用云厂商 API,或者让用户贴 token,或者把“文件上传成功”当成“应用可用”。这就是我们想避免的地方。

Appaloft 的判断很窄:dist/ 是输入,不是最终事实。部署控制面需要把它变成 static artifact publication。

先把发布入口做成公共边界

Appaloft public core 不应该知道 Appaloft Cloud 的商业域名、对象存储、CDN、计费策略或 abuse 流程。但它应该拥有中性的静态 artifact 发布语义。

这就是 public Appaloft 里的 StaticArtifactPublisherPortStaticArtifactStorePortStaticArtifactRouteProviderPort 的位置。应用层接收 source path、inline file payload 或 zip archive,然后通过 port 编排 manifest、payload、store、route 和 publication readback。

对调用方来说,入口应该能保持朴素:

appaloft static-artifacts publish ./dist
appaloft static-artifacts publish ./dist.zip

HTTP/API 也需要同一组语义,而不是给 Web 或 agent 单独开一条上传捷径:

  • POST /api/static-artifacts/publish
  • POST /api/static-artifacts/publish-payload
  • POST /api/static-artifacts/publish-archive
  • GET /api/static-artifacts/publications

这些入口不决定 Cloud 最终使用 R2、S3、MinIO、Cloudflare Pages、IPFS gateway,还是本地 filesystem adapter。它们只定义产品问题:这里有一批静态文件,请发布成一个可 readback 的 artifact publication。

这个边界对 AI 很重要。agent 可以读取项目、构建产物、选择 dist/ 或 zip archive,然后调用同一条 CLI/API/operation catalog 路径。它不需要知道 Cloud 私有 bucket、provider account、DNS route index 或 cache purge 细节。

上传之前先做难看的检查

静态文件听起来安全,但上传入口一旦对浏览器、CI 或 agent 开放,就会出现一堆不太浪漫的问题。

路径可能包含 ../。同一个 path 可能重复出现。文件大小可能超过策略。base64 可能损坏。一个 demo 里可能意外打进 .env、private key、database URL 或 provider credential。也可能有人上传 credential harvesting 页面、恶意脚本、伪装的 archive entry。

所以 Appaloft Cloud 把 static artifact publishing 拆成 policy、scan、store、route、readback 几步。当前仓库里已经有 code-owned fake readiness 和生产形状的 guard scanner 边界:安全 fixture 可以发布,危险或超限 fixture 会被拒绝,scan 输出不会回显 raw secret/path。真实第三方 malware scanner、URL reputation、object storage readback、CDN route、DNS/TLS 和 cache purge 仍然需要 go-live evidence,不应该在 blog 里写成“已经全部完成”。

这个说法没有那么漂亮,但它更像真实平台。

AI 生成速度越快,平台越不能默认相信产物。控制面要在写入 store 或激活 route 之前拦下明显不该发布的东西。

路由意图也要进模型

静态站点并不只有一种路由行为。

普通文档站点可以按路径找文件:/docs/start 对应某个 HTML 文件。SPA 往往需要未知路径 fallback 到 index.html。某些 content-addressed 或 hash-routing 场景则不需要 provider rewrite。

如果这个差异只藏在 Cloud provider adapter 里,发布记录就解释不清。Appaloft 使用 provider-neutral 的 routeBehavior 来记录调用方意图:

  • static-files
  • single-page-app
  • hash-routing

这不是 Cloudflare、R2、Pages 或 IPFS 的字段。它只是说,这批 artifact 希望怎样被服务出来。之后真实 provider adapter 再把它翻译成 CDN rewrite、Pages route rule、object gateway fallback,或者 hash route 提示。

这里也能看出 public/private 边界。Public Appaloft 可以理解 route behavior。Cloud 可以决定官方默认域名、Worker route index、对象存储 provider 和 cache strategy。二者不需要互相泄漏。

Readback 比 URL 更重要

发布成功后,最容易返回的是一个 URL。最容易误导人的也是它。

一个 URL 可能已经分配,但文件没写完;alias 可能还指向旧版本;CDN 可能还没刷新;默认域名 route index 可能存在但 edge readback 失败;某个 provider API 返回成功,但实际对象读不回来。

所以 static artifact publication 需要 readback evidence。Appaloft 在 Cloud 侧记录 manifest digest、storage ref、store provider key、route provider key、resource id、route behavior 和 provider readback evidence。这个 evidence 不暴露 bucket、endpoint、account id 或 credential;它只告诉控制面:这个 provider 步骤是 verified、deferred,还是 blocked,并关联外部系统 gap。

这让 UI、CLI 和 AI agent 都能更诚实地回答用户:“文件已经进入 publication 记录,但真实 CDN readback 还没完成。”或者:“immutable URL 已经 verified,current alias rollback 只会切换 route,不会重新上传文件。”

AI 不需要假装自己看懂了 provider 控制台。它应该读 Appaloft 的 readback。

回滚不是重新发一遍

静态站点通常很适合 versioned publication:每次发布都有 immutable artifact,当前地址只是指向其中一个版本。

这让 rollback 可以变成 alias/route decision,而不是“重新构建、重新上传、祈祷旧依赖还能安装”。Appaloft 的 fake publisher 已经把 versioned URL、alias rollback dry-run、cache purge deferred gap 和 usage attribution 放进模型里。真实 provider 之后怎么执行 cache purge、route activation 或 object lifecycle,是 adapter 和运维证据问题。

这个差异对 agent 也很实用。用户说“回滚刚才那个静态站点”,agent 不应该去仓库里猜上一个 commit,也不应该手工删除一批 object。它应该查询 publications,选择已验证版本,生成 rollback plan,再走控制面的 accepted action。

这和 Blueprint 部署不是一回事

Appaloft 已经支持把静态站点当成普通 workload 部署:创建 static-site resource,通过 deployment pipeline 构建成可运行的静态服务器,部署到用户自己的 server。

Static artifact publishing 是另一条路径。它更像“我已经有了构建产物,请把这些文件发布到托管静态 surface”。它适合 AI agent、浏览器上传、CI artifact、设计工具导出的站点、文档构建产物,或者一个只需要 public URL 的前端 demo。

两条路径都应该接控制面,但它们解决的问题不同:

  • BYOS static-site deployment 更接近 runtime workload。
  • Static artifact publishing 更接近 managed file publication。

把它们混在一起会让模型变糊。把它们分开,agent 才能根据用户意图选择入口:是部署一个 resource,还是发布一批 artifact。

我们还没磨平的地方

这条路还有不少真实工作。

Cloud 默认的 R2/S3-compatible object store、Worker default-domain gateway、DNS/TLS、cache purge、abuse takedown、外部 malware/URL reputation provider、生命周期清理和生产 run evidence,都不能靠一句“以后接上”糊过去。它们需要 provider config、readback、fail-closed policy 和清理边界。

我们现在能确定的是产品形状:AI agent 产出的静态文件不应该直接越过 Appaloft。它应该进入一个可解释的 publication workflow。Public Appaloft 定义中性入口,Cloud 注入私有 policy、scan、store、route、audit 和 provider evidence。

AI 让“生成站点”这件事变得很快。上线这一步不该因此变得更随意。一个好的上传体验可以很轻,但它仍然需要留下清楚的事实:发布了什么、谁发布的、路由到哪里、怎么验证、怎么撤回。