Simon Willison · 博客

Datasette Apps:在 Datasette 中托管自定义 HTML 应用

Datasette Apps: Host custom HTML applications inside Datasette

二〇二六年六月十九日 · 英文原文

Datasette 发布插件 `datasette-apps`,允许在 Datasette 实例上运行自包含的 HTML+JavaScript 应用,这些应用运行在 `<iframe sandbox>` 与 CSP 标头构成的严格沙箱中,无法访问 cookie、localStorage 或向外部主机发起 HTTP 请求。应用可通过 `postMessage()` 和 `MessageChannel()` 对指定数据库执行只读 SQL 查询,并支持通过 Datasette 的存储查询(stored queries)执行写入操作。该插件最初源于为 Datasette Agent 构建 Claude Artifacts 机制的尝试,后独立为顶级概念。创建应用的表单末尾包含可复制提示词,便于 LLM(如 ChatGPT、Claude、Gemini)生成代码。安全方面,通过 `apps-set-csp` 权限和 `allowed_csp_origins` 配置限制 CSP 允许列表,防止低权限用户窃取数据。

今天我们为 Datasette 发布了一个新插件 datasette-apps,并在 Datasette 项目博客上发布了这篇发布公告。那篇文章介绍了“是什么”,但我想在这里进一步展开,说明“为什么”。

TL;DR Datasette Apps 是自包含的 HTML+JavaScript 应用程序,运行在 Datasette 应用上严格受限的沙箱中。它们可以使用 JavaScript 对 Datasette 中的数据执行只读 SQL 查询,如果你配置了一些存储查询(stored queries),它们也可以执行写入查询。这里有一个非常简单的示例和一个更复杂的自定义时间线示例——后者看起来像这样:

Apps 允许运行 JavaScript 并渲染 HTML 和 CSS。它们在访问权限上受到限制——它们运行的 <iframe sandbox> 阻止它们访问 cookie 或 localStorage,并且它们还有一个注入的 CSP 标头(感谢这项研究),阻止它们向外部主机发起 HTTP 请求,从而防止恶意或有缺陷的 app 泄露私有数据。

Datasette Apps 最初是我尝试为 Datasette Agent 构建一个 Claude Artifacts 机制,但我很快意识到,这种沙箱模式不仅限于为界面表面添加自定义 app,它的用途要广泛得多,于是我将其提升为 Datasette 生态系统中的一个顶级概念。它们也是一种有趣的方式,将我多年来在 vibe-coded HTML 工具上的实验转化为我主要项目的核心功能!

你可以通过使用 GitHub 登录 agent.datasette.io 演示实例来试用 Datasette Apps。

为什么要构建这个?

从第一个版本开始,Datasette 就通过其 JSON API 提供了一个灵活的 backend,用于创建自定义 HTML 应用。我最早的 Datasette 项目之一是在 Eventbrite 工作时为文档构建的内部搜索引擎——它的工作方式是通过 cron 将不同系统的文档导入 SQLite,然后通过一个 Datasette 实例提供服务,该实例带有一个自定义的 HTML+JavaScript 搜索界面,直接查询 Datasette API。我使用客户端 JavaScript 构建 SQL 查询,这最初只是一个工程玩笑,但后来证明是迭代应用的一种非常高效的方式!

那个项目,加上我构建 HTML 工具集的经验以及我对 Claude Artifacts 的实验,让我确信,为自包含的 HTML 前端添加一个 Datasette 风格的 backend 是一种极其强大的组合。想象一下,如果 Claude Artifacts 能够访问一个持久的关系数据库,它们会变得多么有用。这就是我正在用 Datasette Apps 构建的东西!

Datasette Apps 中的巧妙想法

以下是我在构建这个过程中发现的一些我认为具有持久价值的想法和模式。

借助大量 AI 辅助构建

Datasette Apps 最初于四月份以 datasette-agent-artifacts 的形式诞生,这是一个我后来重命名为 datasette-agent-edit 的插件,只保留了其编辑工具。我将其构建为 Datasette Agent 的首批插件之一,以帮助将插件钩子调整到正确的形状。第一个原型主要使用 Claude Code 中的 Claude Opus 4.6 构建。

当我转向 Datasette Apps 时,我首先使用 Codex Desktop 和 GPT-5.5 xhigh 制定了一个计划,基于广泛的对话并输入了 datasette-agent-artifacts 和我构建的其他原型。后续的大部分工作都坚持使用 Codex,但在我们能够访问 Claude Fable 5 的短短几天里,我让它对该产品进行了一次安全评估(这项能力不久后就会导致它被美国政府封禁),它发现了一个非常真实的问题。

我允许用户为他们的 app 将 CSP 主机加入允许列表,但 Fable 指出了以下攻击:一个拥有 create-app 权限的低权限用户创建一个 app,该 app 查询 SQLite 以获取所有可用表,并选择所有数据,然后将其窃取到他们通过 CSP 加入允许列表的主机。然后,他们诱骗一个有权访问私有数据的管理员用户访问他们的 app。……然后该 app 可以以该用户的身份运行查询并窃取他们的私有数据!这显然是不可接受的。我通过将对任何域进行允许列表的能力限制在一个新的 apps-set-csp 权限中来解决这个问题,该权限仅供受信任的工作人员使用。站点管理员还可以使用一个 allowed_csp_origins 列表来配置 Datasette,普通用户随后可以选择这些来源。这意味着你可以做诸如允许 cdnjs.cloudflare.com 之类的事情,你的用户将能够构建从 cdnjs CDN 加载额外 JavaScript 库的 app。

我已经非常仔细地审查了 Datasette Apps,特别是与安全相关的部分。关键的沙箱和 CSP 配置基于多个 AI 辅助的原型和测试。

目前看来不错

我对这个初始版本非常满意。Datasette 正在超越其作为提供只读数据应用的起源,发展成为一个更丰富的生态系统,其中包含各种工具,用于在数据收集后利用这些数据做有用的事情。Datasette 的根源在于数据新闻。我一直对一个问题感兴趣:当记者拿到大量关于世界的数据转储后,接下来会发生什么?Datasette 支持探索和发布这些数据。Datasette Agent 增加了借助 AI 进行审问的能力。现在,Datasette Apps 将其扩展到构建自定义界面和可视化,以帮助解锁隐藏在数据中的故事。

标签:iframes, javascript, projects, sandboxing, ai, datasette, generative-ai, llms, ai-assisted-programming, content-security-policy

译自 Simon Willison · 博客 · 录于 二〇二六年六月十九日