关于 fasten-ehr-integration
fasten-ehr-integration 是面向开发者的分步技能,指导通过 Fasten Connect 将数字健康应用连接到患者授权的 EHR 数据。它涵盖经过验证的只读 FHIR 导入,并要求记录隐私与架构决策。
主要功能
- 01指导配置 Fasten Connect
- 02导入患者授权的 FHIR 数据
- 03通过 Webhook 下载导出文件
- 04逐阶段验证集成
- 05生成隐私与架构简报
适用场景
- 01将患者记录导入健康应用
- 02使用 EHR 沙盒测试集成
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ stanfordspezi/ spezivibe --skill fasten-ehr-integration安装后在 Claude Code 中输入/fasten-ehr-integration确认已加载。
详细介绍
Fasten EHR 集成
引导用户通过 Fasten Connect 将应用连接到真实的电子健康记录(EHR)数据,逐步完成从开发者账户到可正常运行且经过测试的集成:将患者的 FHIR 记录下载到应用自己的存储中,并保存一份隐私与架构决策摘要(docs/planning/ehr-connection-brief.md)。在这种架构中,健康数据最终会存储在用户的应用中,因此责任也由用户承担——隐私指导流程未完成前,切勿发布此集成。
适用场景
当用户希望:
- 让患者将自己的医疗记录导入数字健康应用
- 无需针对每个医疗系统单独集成,即可获取真实的 FHIR 数据(病症、药物、化验结果、文档)
- 在正式上线前,基于逼真的 EHR 沙盒进行原型开发
以下情况不要使用此技能:
- 应用必须向 EHR 写入数据,或由临床医生在 EHR 内启动应用——这属于 SMART on FHIR / 供应商市场的范畴
- 数据源是可穿戴设备或 HealthKit——请使用
health-data-model-planning - 合成 FHIR 数据已足够——Fasten 发布了一个示例 EHI 导出(Epic 沙盒,JSONL),而 Synthea 或公共 SMART 沙盒无需任何账户
背景
Fasten Connect 是一个基于患者同意的记录聚合服务。应用无需逐个集成 EHR 供应商和医疗系统,只需嵌入一个小组件,由患者自行授权访问:
Patient ──logs into their own patient portal──▶ Provider EHR
│ │
▼ ▼
Your app ◀──FHIR records (webhook + download)── Fasten Connect
- 应用嵌入 Fasten 的 Stitch 小组件。患者查找自己的医疗系统,并登录自己的患者门户(例如 MyChart)。凭据只会发送给医疗服务提供方,不会发送给应用。
- 授权后的连接会以
org_connection_id的形式返回,由后端存储——这是持久的同意凭证。 - 后端请求批量 EHI 导出。Fasten 检索记录,并将其打包为 NDJSON/JSONL 格式的 FHIR 资源(每行一个资源;主要 EHR 患者访问 API 实际使用的是 R4)。
- Fasten 通过 webhook 向后端发送下载链接通知;后端下载文件。Fasten 会在 24 小时后从其存储中删除导出文件——在此流程中,应用中的副本将成为唯一副本。
这是由消费者主导的数据交换:患者行使 HIPAA 赋予的访问权,并指示将记录发送到应用。此流程为只读,不会向 EHR 回写数据。Fasten 还支持通过 TEFCA Individual Access Services 实现的身份验证流程,使用身份核验(CLEAR / ID.me)代替门户登录;其 API 接口相同。
规划优先流程
如果此技能在规划阶段运行——即应用尚不存在时(build-an-app 编排器会执行此操作)——步骤 2–7 中的验证关卡暂时无法执行。在这种模式下:尽可能完成步骤 1,完整走完“数据隐私”部分,并生成包含 Current mode: not started 的输出摘要。开发者账户和步骤 2–7 将在计划为此集成安排的实现里程碑中稍后完成——届时请再次使用此技能,完成全部流程及验证关卡。
工作方式
你是一位专业的集成指导人员。请逐步操作,确认每个阶段都能正常运行后再继续——此集成的核心是异步、由 webhook 驱动的流程,最后再统一调试远比逐步验证每个环节困难。不要一开始就抛出一堆问题。遇到令人意外的情况时,请对照官方文档进行核实——API 细节可能发生变化,应以文档为准。
步骤 1:了解应用
针对无法从项目中推断的信息,向用户询问:
- “你的后端技术栈是什么?它能接收公共 HTTPS 请求吗,还是我们在本地开发?”
- “下载的记录会存放在哪里——本地磁盘、数据库,还是云存储桶?哪些人应该能查看这些记录?”
- “先用沙箱,还是你已经可以使用实时模式?”
| 答案 | 影响范围 |
|---|---|
| 后端技术栈和可访问性 | 所有 Fasten API 调用和私钥都在服务器端;Webhook 投递需要公共 URL 或本地开发备用方案(步骤 5) |
| 记录的存储位置 | “数据隐私”部分中的隐私讨论——存储、加密、访问和删除 |
| 测试模式还是实时模式 | 测试密钥可访问约 24 个沙箱(FooClinic、Epic、Cerner、付款方沙箱);实时密钥可访问真实医疗系统 |
始终从测试模式开始。除可访问的医疗系统不同外,流程与实时模式完全相同。
**继续前请确认:**你已了解后端、存储位置,并且将从测试模式开始。
步骤 2:开发者账户和密钥
让用户自行完成这些操作——这是他们的账户,你绝不能接触他们的凭据:
- 在 Fasten Connect 开发者门户注册。
- 复制测试模式密钥对:公开 ID(
public_test_…)和私钥(private_test_…)。私钥只显示一次——请立即保存。 - 门户要求提供重定向 URL——Fasten 在成功连接后重定向到的 URL,它也会通过查询参数接收连接参数。在标准 Stitch 弹出窗口/模态框流程中,结果还会通过组件事件在页面内传递,因此大多数集成会根据这些事件执行操作;应用的基础 URL 是合适的填写值。(重定向模式和移动设备深层链接流程会直接使用该 URL——如果应用采用这类流程,请参阅文档。)
然后配置项目:
- 将两个密钥都放入服务器端环境配置(例如
.env.local),并确保文件已加入 gitignore。请给值加上引号——私钥可能包含特殊 shell 字符,环境文件解析器或dotenv-expand可能会错误处理这些字符。 - 公开 ID 本来就是公开的(它会嵌入客户端组件)。私钥绝不能传到客户端:不得使用
NEXT_PUBLIC_/EXPO_PUBLIC_风格的前缀,不得包含在客户端构建包或移动应用二进制文件中。
API 使用 HTTP Basic 认证,认证地址为 https://api.connect.fastenhealth.com/v1——公开 ID 作为用户名,私钥作为密码。测试模式和实时模式使用相同的基础 URL;由密钥选择模式。
**继续前请验证:**使用任意经过认证的 GET 请求对密钥进行冒烟测试(例如,使用虚构 ID 调用导出状态端点):401 表示密钥错误或格式被破坏;404/JSON 错误表示认证成功。这可以提前两步发现引号配置错误,避免问题之后才暴露。
步骤 3:嵌入 Connect 组件
在患者需要连接医疗服务提供方的位置添加 Stitch v4 组件。Web 组件(适用于任何框架):
<link rel="stylesheet" href="https://cdn.fastenhealth.com/connect/v4/fasten-stitch-element.css">
<script type="module" src="https://cdn.fastenhealth.com/connect/v4/fasten-stitch-element.js"></script>
<fasten-stitch-element public-id="public_test_…">Connect a provider</fasten-stitch-element>
提供 React SDK(@fastenhealth/fasten-stitch-element-react)和 React Native 支持——请参阅 Stitch v4 文档。
监听元素的 eventBus DOM 事件。载荷以 JSON 字符串的形式放在 event.detail.data 中——请对其进行解析:
document.querySelector('fasten-stitch-element')
.addEventListener('eventBus', (event) => {
const payload = JSON.parse(event.detail.data);
if (payload.event_type === 'widget.complete') {
// payload.data: [{ org_connection_id, platform_type, connection_status, … }]
// POST it to YOUR backend and persist org_connection_id
}
});
在服务器端保存每个 org_connection_id,并记录时间戳和连接元数据——它既是导出的 API 句柄,也是应用同意审计跟踪的起点。(更丰富的连接元数据,包括 EHR 提供时的 consent_expires_at,会通过 patient.connection_success Webhook 到达——步骤 5。)
**继续前请验证:**连接一个沙箱服务提供方——使用步骤 7 表格中的 FooClinic 账号 [email protected] / f00clinic 是最快的首次测试方式——并确认 org_connection_id 已保存到后端存储中。
第 4 步:请求导出
仅从后端执行:
POST https://api.connect.fastenhealth.com/v1/bridge/fhir/ehi-export
Authorization: Basic base64(public_id:private_key)
Content-Type: application/json
{"org_connection_id": "…"}
响应中包含 task_id;处理是异步的(耗时从几秒到几分钟不等,任务也可能超时——随后会收到 patient.ehi_export_failed webhook,因此请规划有上限的重试:由于 failure_reason 往往会被隐藏,请进行少量重试并逐步延长间隔,然后停止,并将情况告知用户或 Fasten 支持团队)。
确保用户了解:
- 下载链接仅通过 webhook 发送。 状态端点(
GET /v1/bridge/fhir/ehi-export/{task_id})仅供查询信息,会返回pending/success/failed,不会返回链接;Fasten 的文档明确不建议轮询。若未注册 webhook 端点,就无法获取导出内容。 - 该端点对每个
org_connection_id都是幂等的——再次请求会返回现有任务。对于遗漏的 webhook 投递,文档说明的恢复方式包括 Fasten 的自动重试(约 24 小时内最多重试 4 次)、门户中的 Delivery Logs(可查看 15 天内的负载)以及测试模式下的 Webhook Simulator。(实际上,有人观察到再次请求会重新投递完成 webhook,但文档并未说明这一行为——不要依赖它来构建功能。) - 顺序说明: 请在首次导出前注册 webhook 端点(第 5 步),否则首次完成通知可能无处投递——在沙盒环境中,可通过幂等的再次请求安全地恢复。
继续前请验证: 已记录 task_id,且该任务对应的状态端点返回 pending 或 success。
步骤 5:接收 Webhook 并下载
实现一个 webhook 端点(例如 POST /api/webhooks/fasten),以便:
- 验证签名。 Fasten 遵循 Standard Webhooks 规范——使用任意 Standard Webhooks 库和门户中该端点的签名密钥进行验证。这是任何 webhook 端点的基础安全措施,适用于两种模式。注意:密钥按端点和模式区分——Fasten 的常见问题要求测试和正式环境使用不同的 webhook URL,且每个 URL 都有自己的签名密钥。
- 处理以下事件(每个负载信封都包含
api_mode、用于幂等处理的稳定id、type和data):patient.ehi_export_success—data包含task_id、org_connection_id、download_links[](url、export_type、content_type),以及按资源类型统计数量的stats。自动订阅。patient.ehi_export_failed— 由于真实错误可能包含 PHI,failure_reason通常为suppressed_please_contact。自动订阅。patient.connection_success和patient.authorization_revoked— 默认未启用;请在门户中为该端点开启。撤销事件可能会批量发送。
- 立即下载。 使用相同的 Basic auth 获取每个
download_links[].url;API 会回复一个指向签名 URL 的重定向(有效期约为 10 分钟——如需新的 URL,请重新请求)。链接自 webhook 发送起 24 小时内有效;Fasten 会在 24 小时后删除导出文件。应将 webhook 视为应用接管文件的时刻。导出文件大小从数 MB 到数 GB 不等(取决于记录的丰富程度),请流式写入存储,而不要缓存在内存中。 - 尽快返回 2xx,并在确认后再进行耗时处理;投递失败时会使用相同的事件
id重试。
在门户的 webhook 设置中注册端点 URL。
本地开发——webhook 必须能够访问开发者的机器:
| 选项 | 方法 | 说明 |
|---|---|---|
| 隧道(首选) | cloudflared tunnel --url http://localhost:PORT(无需账户)或 ngrok http PORT;注册 https://<tunnel>/api/webhooks/fasten | 全自动。Quick tunnel 的 URL 每次重启都会变化——请更新门户中的 URL;另请注意,新端点会有新的签名密钥(也要更新环境变量;直接编辑现有端点的 URL 会保留密钥) |
| 手动粘贴 | 在门户中注册端点 URL,即使无法访问也可以(系统仍会尝试投递并记录日志),然后从 Webhooks → Delivery Logs 复制 patient.ehi_export_success 负载,粘贴到应用中一个运行相同下载逻辑的小型接收端点 | 无需隧道;足以用于沙盒开发 |
| 托管收件箱(smee.io、requestbin) | Fasten 自己的文档建议将这些服务用于临时测试 | 仅限沙盒——切勿通过第三方收件箱转发真实患者的 webhook 流量 |
**继续之前请先验证:**在门户的 Webhook Simulator 中发送 webhook.test 事件,并确认端点收到事件(模拟器事件会走正常投递流程,因此会验证签名)。如果采用手动粘贴方式,则应改为将复制的负载传入接收端点,并确认文件已写入存储。然后端到端运行一次真实的沙盒导出。
第 6 步:解析和展示
导出文件采用 NDJSON/JSONL 格式:每行一个 FHIR 资源。请宽容地解析——现实中的记录往往杂乱无章:
- 跳过格式错误的行,而不是让整个文件解析失败;防御性地将任何
Bundle解包为其条目。 - 按
resourceType分组。典型的导出包含Patient、Condition、MedicationRequest、AllergyIntolerance、Observation(通常占大多数,包括实验室检查和生命体征)、DiagnosticReport、Immunization、Procedure、Encounter、DocumentReference/Binary(通常是 PDF),以及作为参考数据的Practitioner/Organization/Location。 - 防御性地呈现名称、代码和日期:优先使用
.text,其次依次回退到coding[].display→code;日期可能分散在effectiveDateTime、onsetDateTime、authoredOn、issued、period.start中。 - 在密钥就绪前,你可以基于 Fasten 的示例导出 gist,构建并测试这一整层。
- 如果应用需要正式的架构,请运行
fhir-data-model-design,并将传入的资源映射到其输出。
第 7 步:端到端测试
测试模式下可用的沙箱(完整的凭据列表:测试患者凭据):
| 沙箱 | 凭据 | 适用场景 |
|---|---|---|
| FooClinic(Sandbox)—— Fasten 自有沙箱,包含 16 个角色 | [email protected] / f00clinic(11 个资源);[email protected] / f00clinic(包含 3,500 多个资源的肿瘤病历) | 首次运行;容量测试 |
| Epic 沙箱 | fhircamila / epicepic1 | 模拟真实的 Epic 格式数据 |
| Cerner、athenahealth、支付方沙箱(Aetna、Cigna、Medicare、VA) | 请参阅凭据指南 | 覆盖多种平台类型 |
端到端验证——集成完成前,以下每项都必须通过:
- 小组件连接到沙箱提供方;
org_connection_id已在服务端持久化 - 已从后端请求导出;已记录
task_id - 已收到 Webhook,并验证签名;文件已流式传输到应用存储
- 记录已解析,并在应用 UI 中可见
- 已处理
patient.ehi_export_failed:通过门户的 Webhook Simulator 测试处理程序(或向端点发送带签名的模拟负载);存在有界重试路径 - 已在门户中启用
patient.authorization_revoked,并按照应用的同意政策进行处理——以相同方式测试(模拟器是沙箱测试路径;无法按需触发真实撤销事件) - 客户端包和版本控制中均不包含私钥
数据隐私:健康数据的去向
请明确地带用户逐项了解下表——这是创新者常常忽略、之后又追悔莫及的部分。这是产品指导,不构成法律建议;请说明,在正式上线前,应由法律顾问、合规负责人或机构隐私团队进行审查。
| 阶段 | 健康数据由谁持有 | 备注 |
|---|---|---|
| 门户登录 | 仅服务提供方 | 患者凭据会输入服务提供方自己的门户;在此流程中,应用和 Fasten 都不会存储这些凭据 |
| 检索与打包 | Fasten 的云(AWS;子处理方列于 trust.fastenhealth.com,均标注为美国) | Fasten 表示,数据在传输中和静态存储时均经过加密,并且成功传输后,临时副本会在 24 小时内自动删除 |
| 导出文件静态存储(Fasten) | Fasten,≤ 24 小时 | 保留期限结束后删除;下载链接也会随之失效 |
| Webhook 负载 | 应用的后端(以及路径中的任何隧道或收件箱) | 包含标识符、统计数据和下载链接——链接仍需 API 密钥才能使用,但应将负载视为敏感信息;实时模式下不使用第三方收件箱 |
| 下载 | 应用的后端 | 基本身份验证 + 短时有效的签名 URL(约 10 分钟) |
| 应用中的静态存储 | 应用团队——无限期 | 这是该架构的核心:应用持有这些记录。加密、访问控制、保留、删除和泄露响应现在都由应用承担 |
启用实时模式前必须做出的决定(在简报的「输出」部分记录):
- 下载时转移保管责任。 24 小时后,此流程中唯一留存的副本就是应用中的副本。在真实记录进入系统之前,先决定记录存放在哪里、谁可以访问、如何加密,以及患者如何要求删除记录。
- 监管框架取决于应用服务对象。 需要梳理以下三个分支:
- 由消费者主导: 根据 HHS OCR 关于访问权和健康应用的指导,个人指定发送至既非受监管实体也非业务伙伴的应用的记录,不再受 HIPAA 规则约束;但 FTC《健康数据泄露通知规则》和州健康隐私法(例如,将消费者健康记录应用视为医疗保健提供者的 California CMIA,以及 Washington My Health My Data)很可能适用;此外,FTC Act Section 5 也适用于应用作出的任何隐私承诺。Fasten 的材料未涉及 HBNR;此项分析由应用团队自行负责。
- 代表受监管实体行事: 该应用很可能属于需要签署 BAA 的业务伙伴,包括评估是否与 Fasten 签署 BAA。Fasten 的政策称,对于部分客户,Fasten“可能符合业务伙伴的定义”;Fasten 是否签署 BAA 尚未公开说明——请直接询问 Fasten。
- 研究用途: 如果记录将用于研究,请在启用实时模式前联系 IRB,使连接和同意环节与研究知情同意流程保持一致,并检查所在机构的受监管实体身份和数据治理规则(数据风险分类、获批的存储环境——学术医疗中心通常都有此类规则)是否会改变存储和访问要求。
运行
digital-health-compliance-planning,查看完整分析。
- 需要核实供应商声明。 Fasten 自称已通过 SOC 2 鉴证,并在营销材料中宣称“SOC2 & HIPAA-compliant”;但其隐私政策称其为“not directly subject to HIPAA”的 IAS 提供商。SOC 2 报告和 HIPAA 评估需通过其信任中心申请获取。对于正式部署,请索取这些材料;不要在应用自身的隐私说明中复述营销声明。
- 同意由患者控制且会过期。 连接元数据可能包含
consent_expires_at——根据 Fasten 文档,仅当 EHR 提供该信息时才会包含(他们提到 HTI-2 的规定将于 2026 年 1 月生效,但 EHR 的支持仍不均衡)。患者可以撤销同意;撤销会停止后续数据获取,但不会撤销此前已披露的数据。对于已下载的数据,撤销同意后的现实选择是删除或归档并停止使用(例如因法律保全或审计需要):无论是否已披露,继续在产品中使用已撤销同意所涉数据,都可能与下文“停止后续使用”的义务相冲突。 - Fasten 的同意条款会延伸至应用。 Fasten 的隐私政策称,作为 CARIN Alliance Code of Conduct 的签署方,它会对所有客户“强制执行”以下要求:仅在获得同意后使用、便于撤销同意,以及披露 AI/ML 的使用情况和与第三方共享的情况。请在注册时确认 Fasten Connect 协议中的具体延伸义务——应用的隐私政策和行为必须切实满足这些要求。
- 密钥就是安全边界。 私钥授权每次导出和下载。仅在服务端保存,加入 gitignore;如发生泄露则轮换,并为每个环境使用单独的密钥对。
- 尽量减少留存的数据。 导出内容往往超出大多数产品的需求,尤其是自由文本笔记和
Binary文档。数据也可能包含敏感程度更高的类别(源自 42 CFR Part 2 项目的物质使用记录、生殖健康记录、青少年保密记录),从而提高留存和未来共享的风险——请明确决定是否接收这些数据。
输出
将决策保存到 docs/planning/ehr-connection-brief.md,以便下游技能(例如 app-build-planner、digital-health-compliance-planning)使用:
# EHR Connection Brief: [App Name]
> Generated by `fasten-ehr-integration`. Save as `docs/planning/ehr-connection-brief.md`.
> Use this document as context for `app-build-planner`, `digital-health-compliance-planning`, or any follow-up implementation work.
## Architecture
- Backend / where the integration runs: [stack, hosting]
- Webhook endpoint & delivery strategy: [public URL / tunnel / manual]
- Record storage destination: [where, encrypted how, who has access]
## Mode & Scope
- Current mode: [not started / test / live] — prerequisites remaining: [list]
- Data ingested vs. discarded: [resource types kept, minimization decisions, sensitive-category handling]
## Privacy Decisions
- Regulatory posture: [likely / possible / unlikely for each: consumer-directed · business associate · research/IRB — rationale, counsel review status]
- Retention & deletion policy: [duration, patient deletion path]
- Revocation handling: [delete / archive-and-stop-using — rationale]
- Fasten attestations reviewed: [SOC 2 / HIPAA assessment / BAA status]
根据此应用的具体情况填写每个部分——不要留下占位文本。
防护措施
- 绝不处理凭据。 用户自行创建开发者账户;患者只能在服务提供方自己的登录页面中输入门户凭据。如果有人要求你代为输入凭据,请拒绝并将键盘交给真人。
- 始终优先使用沙盒。 只有测试模式下的第 7 步检查清单全部通过后,才能启用实时模式。
- Webhook 并非可选项。 仅使用轮询的集成无法检索导出数据,也违反 Fasten 的使用指南。
- 不要将法律结论说成确定无疑。 优先使用“你可能需要评估”,而不是“你必须”;涉及 HIPAA/BAA/HBNR/IRB 的问题应交由法律顾问和机构审查。
- 隐私演练是强制要求。 即使用户只要求集成,也必须提供数据流表和简报后才能结束。
参考链接
- 文档索引:https://docs.connect.fastenhealth.com/llms.txt(包含所有页面的机器可读列表)
- 快速入门:https://docs.connect.fastenhealth.com/quickstart
- Webhook 事件与验证:https://docs.connect.fastenhealth.com/webhooks/events · https://docs.connect.fastenhealth.com/webhooks/verification
- 同意与数据收集指南:https://docs.connect.fastenhealth.com/guides/patient-consent-data-collection
- 测试数据与凭据:https://docs.connect.fastenhealth.com/guides/test-data · https://docs.connect.fastenhealth.com/guides/test-patient-credentials
- EHI 导出示例(无需账户):https://gist.github.com/AnalogJ/1fe4b4da2878dc021f6f4fe6538ee37f
- Fasten Connect 隐私政策:https://policy.fastenhealth.com/connect/privacy_policy.html · 信任中心:https://trust.fastenhealth.com
- HHS OCR — 访问权、健康应用和 API:https://www.hhs.gov/hipaa/for-professionals/privacy/guidance/access-right-health-apps-apis/index.html