关于 portaly-sentry
portaly-sentry 是面向使用 vibe coding 工具的非工程人员的 Skill,用于检查 Portaly Vibe 支付集成的安全性与可靠性。它按严重级别组织检查,并提供扫描和报告流程。
主要功能
- 01检查支付签名与回调
- 02审查订阅生命周期处理
- 03检查凭据与 Web 安全
- 04检查依赖项和数据处理
- 05按严重级别呈现结果并配置扫描流程
适用场景
- 01上线前评估 Portaly Vibe 集成
- 02在日常维护中检查支付安全
- 03为审计或代码评审生成报告
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ portaly-ai/ portaly-skills --skill portaly-sentry安装后在 Claude Code 中输入/portaly-sentry确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ci-setup-guide.mdcommon-pitfalls.mdfix-explanations.mdhealth-check-contract.mdscripts/check_signature_sort.mjscheck_subscription_lifecycle.mjscomputeHealthScore.mjsreport.mjs详细介绍
Portaly Sentry — 支付集成健康检查
使用此技能,对 Portaly Vibe 支付集成进行全面的安全性和可靠性健康检查。此技能专为使用氛围编程工具、希望放心发布项目的非工程师设计。输出应通俗易懂且可操作:先给出通俗易懂的摘要,方便用户深入了解;只有用户提出要求时,才展示包含 26 行的技术表格。
此技能与 portaly-payment 配合使用。它采用相同的 API 契约,以此作为判断集成是否正确的权威依据。
快速开始
步骤 1 — 确认集成是否存在
- 确认项目中存在 Portaly Vibe 支付集成(查找
portaly、callbackSecret、x-portaly-signature或创建结账会话的代码)。 - 如果未找到集成,请告知用户并继续 — 系统会自动跳过支付专属检查;通用检查(DEP、ENV-002)仍会运行。
步骤 2 — 用通俗语言介绍 Sentry 的检查内容
在询问其他任何问题之前,先向用户展示以下介绍,让他们了解 Sentry 的实际检查内容。不要跳过此步骤 — 首次使用的用户并不了解“SIG”或“SUB”的含义。
模板:
Portaly Sentry checks your payment integration across 3 areas:
🏦 Is the payment flow itself done right? signatures, callbacks, subscriptions
🔐 Are your merchant credentials safe? env vars, credential management
🛡️ Is everything else hardened? dependencies, web security, data handling
26 checks in total, graded by severity: CRITICAL / WARNING / INFO.
步骤 3 — 询问项目和扫描标准
不要选择默认值 — 向用户同时询问这两个问题,然后等待答复。将其作为必须确认的选项,而非建议。
模板:
Two things before I start:
① Which project should I scan? (e.g. ~/gratitude-app)
② Which standard do you want?
🚀 Pre-launch — pass all CRITICAL
🔧 Routine check — pass all CRITICAL + WARNING
🏆 Gold standard — pass all 26 (including INFO)
📄 Report only — scan and show the report, skip the fix workflow
⏰ Weekly auto — schedule a recurring scan instead of scanning now
标准 → 范围映射(仅供 Agent 内部使用;不要向用户展示此表):
| 用户选项 | 报告包含 | 阻断严重级别 | 修复流程 |
|---|---|---|---|
| 🚀 上线前 | 全部 26 项检查 | 仅 CRITICAL | 提供 |
| 🔧 常规检查 | 全部 26 项检查 | CRITICAL + WARNING | 提供 |
| 🏆 黄金标准 | 全部 26 项检查 | 所有严重级别 | 提供 |
| 📄 仅报告 | 全部 26 项检查 | 不适用 | 绝不提供 |
| ⏰ 每周自动运行 | 跳过扫描 → 跳转至步骤 16 | 不适用 | 不适用 |
所有四种非定时标准都会运行全部 26 项检查。前三种的区别仅在于第 1 层摘要中“状态”一行所采用的通过/失败阈值(见步骤 14)。📄 仅报告会运行相同的扫描,但跳过第 2 层(修复模式提示),并在第 3 层结束 — 可用于审计、代码审查交接,或用户只想查看结果、暂不进行修复的情况。
高级选项。 如果用户明确要求只扫描一个类别(例如“只扫描签名”或“重新运行 SIG”),则接受单类别模式,可选类别包括:SIG、SUB、CBK、ENV、SEC、WEB、DEP、DATA。不要将此作为主要选项展示 — 类别代码会让首次使用的用户不知所措。
前提条件
- 静态分析检查(SIG、SUB、CBK、ENV、SEC、WEB、DATA)不需要凭据。
- 要运行 DEP 检查,项目必须包含
package.json。 - 要向 Portaly 报告结果,用户需要
PORTALY_API_KEY。
Provider 配置
报告端点默认为 https://portaly.ai/api/creator-subscription/health-check-reports。可通过 PORTALY_API_HOST 覆盖主机(scripts/report.mjs 已支持此设置)。请参阅仓库根目录中的 PROVIDER.md。
健康检查类别
SIG — 签名验证
检查回调签名验证是否与 Portaly 的规范实现一致。
| ID | 检查项 | 严重级别 |
|---|---|---|
| SIG-001 | 稳定 JSON 排序使用 Object.entries().sort(([a],[b]) => a.localeCompare(b)) | CRITICAL |
| SIG-002 | HMAC 算法为 SHA-256 | CRITICAL |
| SIG-003 | 时间戳重放保护会拒绝超过 5 分钟的回调 | WARNING |
| SIG-004 | 签名比较使用 crypto.timingSafeEqual | CRITICAL |
SUB — 订阅生命周期
检查订阅标识符是否在从结账到取消的整个流程中得到正确存储和使用。
| ID | 检查项 | 严重性 |
|---|---|---|
| SUB-001 | 结账完成后持久化 subscriptionId(= sessionId) | CRITICAL |
| SUB-002 | 通过幂等键处理重复回调 | WARNING |
| SUB-003 | 取消/恢复 API 使用已持久化的 subscriptionId | CRITICAL |
CBK — 回调端点
检查回调端点的配置和行为。
| ID | 检查项 | 严重性 |
|---|---|---|
| CBK-001 | callbackUrl 使用 HTTPS | CRITICAL |
| CBK-002 | 记录签名验证失败及诊断信息 | WARNING |
| CBK-003 | 回调处理程序在成功时明确返回 200 | INFO |
ENV — 环境与凭据
检查凭据管理和环境配置。
| ID | 检查项 | 严重性 |
|---|---|---|
| ENV-001 | 在 .env 文件或源代码中引用 PORTALY_API_KEY 和 PORTALY_CALLBACK_SECRET(证明密钥通过某种机制接入,例如 .env、密钥管理器、运行时环境等) | CRITICAL |
| ENV-002 | 敏感的 .env 文件已加入 Git 忽略规则(通过 git check-ignore 验证;.env.example 除外——它是应当提交的模板) | CRITICAL |
| ENV-003 | 源文件中未硬编码 API 密钥或回调密钥 | CRITICAL |
SEC — 安全最佳实践
检查集成中的安全规范。
| ID | 检查项 | 严重性 |
|---|---|---|
| SEC-001 | 客户端/浏览器可访问的代码中不包含回调密钥或 API 密钥 | CRITICAL |
| SEC-002 | 持久化原始回调正文以供审计追踪 | INFO |
| SEC-003 | 从环境变量读取密钥(便于轮换) | INFO |
| SEC-004 | 回调端点未配置过于宽松的 CORS(Access-Control-Allow-Origin: *) | WARNING |
| SEC-005 | 支付相关页面设置 Content-Security-Policy 标头 | INFO |
WEB — Web 安全基础
检查支付流程中常见的 Web 安全问题。
| ID | 检查项 | 严重性 |
|---|---|---|
| WEB-001 | 根据域名允许列表验证 successRedirectUrl / cancelRedirectUrl | CRITICAL |
| WEB-002 | 错误响应不会泄露堆栈跟踪、内部路径或数据库架构 | WARNING |
| WEB-003 | 回调端点验证 Content-Type: application/json | WARNING |
| WEB-004 | 回调端点强制执行请求正文大小限制 | WARNING |
DEP — 依赖项安全
检查项目依赖项中是否存在已知漏洞。
| ID | 检查项 | 严重性 |
|---|---|---|
| DEP-001 | npm audit / pnpm audit 报告中没有严重或高危 CVE | CRITICAL |
| DEP-002 | 存在锁定文件(package-lock.json / pnpm-lock.yaml)且已提交 | WARNING |
DATA — 数据处理安全
检查安全的数据处理实践。
| ID | 检查项 | 严重性 |
|---|---|---|
| DATA-001 | 写入数据库前验证回调负载字段(类型/长度) | WARNING |
| DATA-002 | 日志中不包含完整的 API 密钥、回调密钥或原始客户个人身份信息 | WARNING |
工作流
第 4 步 — 查找集成文件
在项目中搜索与 Portaly 支付集成相关的文件:
- 导入
crypto或包含 HMAC 操作的文件 - 包含
portaly、x-portaly-signature、x-portaly-timestamp、callbackSecret、PORTALY_CALLBACK_SECRET的文件 - 回调路由处理程序(Express 路由、Next.js API 路由、Cloud Functions HTTP 触发器)
- 在结账完成的上下文中包含
subscriptionId、sessionId的文件 - 包含
successRedirectUrl、cancelRedirectUrl的文件
建立文件清单,并将每个文件对应到相关检查类别。
第 5 步 — 运行 SIG 检查
针对每个与签名相关的文件:
- 检查排序模式——与
../portaly-payment/scripts/sign_callback.mjs中的规范实现进行比较。 - 检查 HMAC 算法——确认使用了
createHmac('sha256', ...)。 - 检查时间戳验证——查找是否将
x-portaly-timestamp与当前时间进行比较,并采用 5 分钟的时间窗口。 - 检查比较方法——确认使用了
crypto.timingSafeEqual,而非===或==。
参考:scripts/check_signature_sort.mjs 可以自动完成此步骤。
第 6 步 — 运行 SUB 检查
追踪订阅 ID 的生命周期:
- 在回调处理程序中,检查
status === 'completed'之后持久化了什么。存储的值应为sessionId(根据 Portaly 当前的约定,它等于subscriptionId)。 - 检查幂等性——处理程序在完成履行操作前,是否会检查此
sessionId是否已处理? - 追踪取消/恢复代码路径——确认它读取回调写入的同一个
subscriptionId字段,并将其传递给/subscriptions/{subscriptionId}/cancel或/resume。
参考:scripts/check_subscription_lifecycle.mjs 可以自动完成此步骤。
第 7 步 — 运行 CBK 检查
- 检查
callbackUrl是否以https://构造。 - 检查签名验证失败分支——是否记录了诊断信息(时间戳、负载哈希、预期值与实际值)?
- 检查成功分支是否返回了明确的
200状态码。
第 8 步 — 运行 ENV 检查
- 在整个目录树中查找
.env*文件(根目录、functions/、apps/*、packages/*等)。 - ENV-001 在同时引用
PORTALY_API_KEY和PORTALY_CALLBACK_SECRET时通过——无论是在.env文件中,还是在源代码中按名称引用。在代码中出现名称(例如process.env.PORTALY_API_KEY、defineSecret('PORTALY_API_KEY')或任何其他用法),都表示项目已通过某种机制(.env、密钥管理器、运行时环境、Shell 导出等)配置了密钥——脚本无需知道使用的是哪个平台。始终需要这两个密钥:PORTALY_API_KEY用于发起出站调用,PORTALY_CALLBACK_SECRET用于验证付款结果。 - ENV-002:验证每个敏感
.env文件都已加入 gitignore。使用git check-ignore,以便遵循分层模式(例如,根目录.gitignore中的**/.env会涵盖functions/.env)。跳过.env.example——它是预期提交的占位模板。如果不存在敏感.env文件,或者项目不是 git 仓库,则检查通过(不存在泄漏风险)。 - 在源文件中搜索字面值
pcs_live_、pcs_test_,或任何看起来像回调密钥的字符串(排除node_modules和.env)。
第 9 步 — 运行 SEC 检查
- 检查通常会提供给浏览器的目录中的文件(客户端组件的
src/、public/、app/、pages/),确认其中没有 API 密钥或回调密钥。留意包含密钥的NEXT_PUBLIC_前缀环境变量。 - 检查是否将原始回调正文保存到数据库以供审计。
- 确认密钥是从
process.env或等效机制读取的,而非硬编码。 - 检查回调端点是否使用了 CORS 中间件——如果存在
Access-Control-Allow-Origin: *,则标记出来。 - 检查成功/取消重定向页面是否设置了 CSP 标头。
第 10 步 — 运行 WEB 检查
- 检查
successRedirectUrl和cancelRedirectUrl在用于重定向之前,是否经过可信域名允许列表验证。 - 检查回调路由的错误处理——确保
catch块不会在响应正文中发送完整的错误堆栈。 - 检查回调端点是否验证了
Content-Type标头。 - 检查是否设置了正文解析器大小限制(例如
express.json({ limit: '1mb' })或等效配置)。
第 11 步 — 运行 DEP 检查
- 如果存在
package.json,运行npm audit --json或pnpm audit --json,并解析输出以检查严重或高危漏洞。 - 检查是否存在
package-lock.json或pnpm-lock.yaml,且未被.gitignore忽略。
步骤 12 — 运行 DATA 检查
- 检查回调负载字段在写入数据库前是否经过验证(类型检查、长度限制、净化)。
- 搜索日志语句(
console.log、console.error、logger.),检查是否可能泄露机密或个人身份信息(PII)——标记任何记录了完整回调负载、API 密钥或回调密钥的日志。
步骤 13 — 将结果同步到 Portaly(可选)
运行完所有检查后、展示摘要前,询问用户是否要将扫描结果同步到其 Portaly 仪表板。现在执行此操作,步骤 14 的第一层摘要即可包含可分享的报告链接。
有两种传输方式——如果 MCP 可用,优先使用 MCP:
路径 A — MCP(首选,无需额外配置)。 如果 Agent 已连接 Vibe MCP,则可使用 vibe_report_health_check 工具。该工具使用 Agent 现有的 MCP 连接——无需 PORTALY_API_KEY。简要征求用户同意,然后使用扫描负载调用该工具。将响应中的 dashboardUrl 用作第一层的仪表板链接。输入架构请参阅 references/health-check-contract.md §“MCP reporting”。
路径 B — REST API(备用)。 如果未连接 MCP,且用户已在其环境中设置 PORTALY_API_KEY,则改为运行 scripts/report.mjs——该脚本会从 process.env.PORTALY_API_KEY 读取密钥,并替你向 https://portaly.ai/api/creator-subscription/health-check-reports 发送 POST 请求。优先使用此方式,不要手动拼接带内联密钥的 curl / fetch。将脚本标准输出中的 dashboardUrl(Dashboard: <url> 这一行)用作第一层的仪表板链接。完整的请求/响应架构请参阅 references/health-check-contract.md §“Report API Contract”。
规则:
- 未经用户明确同意,不得调用任何一种路径。
- 如果两种路径都不可用(无 MCP、无密钥),或调用失败(例如 REST 返回 404),则静默跳过同步,并继续步骤 14,不附带仪表板链接。不要因此阻止摘要展示。
- 同一次扫描不得同时调用两种路径——选择其中一种。
步骤 14 — 展示摘要(不展示完整表格)
用户首先看到的必须是通俗易懂的摘要,而不是 26 行的表格。完整技术报告位于仪表板上——只有在用户选择 [C]、用户处于 📄 仅报告模式,或仪表板报告不可用时,才在本地展示完整报告。
最多输出以下三层,并按此顺序排列(📄 仅报告模式只输出第一层和第三层——见下文):
第一层 — 通俗易懂的摘要(始终展示)
从 references/fix-explanations.md 加载标题——不要编造新措辞。根据各项检查结果,使用 references/health-check-contract.md §“Health Score Formula”中的公式计算健康评分——评分必须与仪表板显示的数字一致。
模板:
📊 Payment integration health check — {projectName}
Health score: {score}/100 ({band: Healthy | Needs attention | At risk})
🟢 Passing {passedCount} checks looking good
🟡 Review {warnedCount} warnings take a look this week
🔴 Critical {failedCount} blockers must fix before launch
Status: {status_line}
Top {min(3, failures)} things to fix:
1. {plain title from fix-explanations.md} ({ID})
2. ...
3. ...
🔗 Full report (all 26 checks, fix guidance, history)
{dashboard_url}
评分分档(必须与仪表板一致):
| 评分 | 分档 |
|---|---|
| 90–100 | 健康 |
| 70–89 | 需要关注 |
| 0–69 | 有风险 |
{status_line} 由步骤 3 选择的扫描标准决定(与评分无关——评分仅供参考,是否符合标准决定能否发布):
| 标准 | “可以安全发布”的条件 |
|---|---|
| 🚀 发布前 | CRITICAL 失败数为 0 |
| 🔧 常规检查 | CRITICAL 和 WARNING 失败数均为 0 |
| 🏆 金标准 | 全部 26 项检查均无失败 |
使用 ✅ 可以安全发布 或 ❌ 暂不可安全发布——不要使用其他表述。{dashboard_url} 是步骤 13 返回的 dashboardUrl。如果跳过步骤 13,或步骤 13 未返回该值,则移除整个 🔗 完整报告 区块(包括标签行和 URL 行)。
对于 📄 仅报告 模式,完全省略 Status: 行(此模式下没有发布门槛),并替换为 Mode: 📄 仅报告 — 修复工作流已禁用。第一层中的其他内容保持不变。
第 2 层 — 选择修复模式(紧接摘要显示,📄 仅报告模式除外)
在 📄 仅报告模式下,完全跳过第 2 层,直接进入第 3 层。不要显示 [A] / [B] / [C] 提示 — 用户已经选择不进行修复。
模板:
─────────────────────────────────────
Want to start fixing now?
[A] Yes, walk me through all of them in order (recommended)
[B] Just the 🔴 critical ones (fastest path to launch)
[C] Show me the full report first
用户的回答将导向:
- [A] → 交互式修复工作流,包含所有失败项,按 CRITICAL → WARNING → INFO 排序
- [B] → 交互式修复工作流,仅包含 CRITICAL 失败项
- [C] → 第 3 层
第 3 层 — 完整技术报告(选择 [C]、处于 📄 仅报告模式,或无法提供仪表板报告时)
按类别分组,呈现完整的 26 行表格。格式:
## Portaly Sentry — Health Check Report
Project: {project_name} | Scan: {ISO timestamp} | Mode: {manual|scheduled}
### SIG — Signature Verification
| # | Check | Severity | Status |
|---|-------|----------|--------|
| SIG-001 | Stable JSON sort order | CRITICAL | [PASS] |
| ... | ... | ... | ... |
### SUB — Subscription Lifecycle
| # | Check | Severity | Status |
|---|-------|----------|--------|
| ... | ... | ... | ... |
(repeat for CBK / ENV / SEC / WEB / DEP / DATA)
---
Summary: X/26 passed | Y CRITICAL failures | Z warnings | W skipped
### Fix: {ID} — {Check Name}
File: {file_path}:{line}
{description of the issue}
{code diff showing the fix}
第 15 步 — 交互式修复工作流(逐项确认)
只有在用户从第 2 层明确选择 [A](修复全部)或 [B](仅修复 CRITICAL)后,才进入此工作流。按严重程度(CRITICAL → WARNING → INFO)排序,每次只呈现一项失败,并等待确认后再修改任何文件。
在 📄 仅报告模式下,按设计无法进入此步骤 — 不会显示第 2 层,因此用户不会选择 [A]/[B]。如果用户之后改变主意并要求开始修复,应将其视为新请求,并在进入此工作流前重新提示第 2 层选项。
逐项模板
针对每项失败呈现以下区块。所有通俗易懂的文案均来自 references/fix-explanations.md — 不要临时改写。ID、文件路径、差异中的代码以及 [Y]/[N]/[?]/[STOP] 按键均保持原样。
模板:
🔴 Item {n} of {m} | Progress {progress_bar} {percent}%
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Fix: {plain title} ({ID})
📍 Which file?
{file_path} ({change summary, e.g. "add 1 import, change 3 lines"})
❓ Why does this matter?
{why it matters, from fix-explanations.md}
🔧 Preview:
{unified diff, - old / + new}
✅ Affects: {affects, from fix-explanations.md}
✅ Doesn't affect: {doesn't affect, from fix-explanations.md}
─────────────────────────────────────
Apply this fix?
[Y] Go ahead, apply it
[N] Skip this one
[?] I'd like to understand more first
[STOP] Pause here, I'll come back later
规则
- 一次只处理一项。 绝不要在一次确认中批量修复多项内容。即使 [B] 下有 3 项 CRITICAL,也要逐项询问 Y/N。
- 严重程度图标须与标题对应: CRITICAL 使用 🔴,WARNING 使用 🟡,INFO 使用 ⚪。
- 进度条: 使用
▓表示已完成,░表示未完成,总计 7 个区块。例如,3/7 时:▓▓▓░░░░。 - 差异代码须遵循用户自己的代码风格。 匹配其模块系统(ESM 或 CommonJS)、变量名称和框架惯用写法。从
references/common-pitfalls.md和../portaly-payment/scripts/sign_callback.mjs中获取规范的修复模式,再调整为符合用户风格的写法。 - 面向用户的文本中绝不显示原始 CRITICAL/WARNING/INFO 标签。 使用自然表达,例如“严重 / 建议修复 / 可以改进”,并通过 🔴/🟡/⚪ 图标直观地表示严重程度。
处理每种回复
根据用户回复表达的意图进行匹配,而不是要求完全一致。按键字母是标准触发词;英文或用户使用的语言中的同义表达均视为相同意图。
| 意图 | 标准触发词 | 操作 |
|---|---|---|
| 应用 | [Y](或“是”/“应用”/“好的”/同义表达) | 应用修改,用一行确认成功(例如 ✅ Applied {ID}),然后继续处理第 n+1 项。 |
| 跳过 | [N](或“跳过”/“不”/同义表达) | 不修改文件。标记为 ⏭️ Skipped {ID},然后继续处理第 n+1 项。 |
| 解释 | [?](或“为什么”/“详细说说”/同义表达) | 从 references/common-pitfalls.md 加载对应的陷阱条目(错误与正确实现及其说明)。解释后,使用相同的 Y/N/?/STOP 选项重新提示 — 不要重新呈现完整模板。 |
| 停止 | [STOP](或“暂停”/“稍后再说”/同义表达) | 立即停止。显示恢复摘要:已应用 X 项 / 已跳过 Y 项 / 剩余 Z 项。随时发送“resume fixing”,我会从第 {n} 项继续。 不要继续处理。 |
处理完最后一项后
模板:
🎉 Fix session complete
✅ Applied: {X}
⏭️ Skipped: {Y}
─────────────────────────────────────
Suggested next steps:
1. Run your usual tests or try a checkout end-to-end
2. Re-run Sentry to confirm everything passes now
3. If you have a Portaly API key, sync the results to your dashboard
步骤 16 — 设置自动扫描(可选)
有三个选项,按从简单到严格的顺序排列。请向用户介绍全部三个选项,并让用户自行选择。
选项 A — GitHub Actions(推荐用于任何拥有 GitHub 仓库的项目)
请用户根据 references/ci-setup-guide.md 中的模板创建 .github/workflows/portaly-sentry.yml。然后,将 PORTALY_API_KEY 添加为 GitHub 仓库机密。
此操作会在每次推送到 main 时运行,并在每周一运行一次——如果发现 CRITICAL 问题,则会阻止合并。
选项 B — Git 推送前钩子(本地计算机强制执行)
运行一次以安装:
cat > .git/hooks/pre-push << 'EOF'
#!/bin/sh
set -e
node "$(git rev-parse --show-toplevel)/.claude/skills/portaly-sentry/scripts/report.mjs" \
--dir "$(git rev-parse --show-toplevel)" --fail-on critical
EOF
chmod +x .git/hooks/pre-push
选项 C — 通过 scripts/report.mjs 运行自动化脚本
对于任何 CI 系统或定时任务,直接指向自动化脚本即可。该脚本会从环境中读取 PORTALY_API_KEY——请通过 CI 的机密存储、shell 配置文件或 .env 加载器进行设置,而不要将值直接写入脚本。
# PORTALY_API_KEY exported via CI secret / shell / .env
node .claude/skills/portaly-sentry/scripts/report.mjs \
--dir . --scan-type scheduled --fail-on critical
--fail-on critical 会在发现 CRITICAL 问题时使命令以状态码 1 退出,任何 CI 系统都会将其视为构建失败。
完整的 CLI 参考和设置说明,请参阅 references/ci-setup-guide.md。
输出风格
- 先提供通俗易懂的摘要(第 1 层),而不是表格。 26 行表格属于第 3 层,仅在用户要求时显示。
- 命名检查失败项时,使用
references/fix-explanations.md中的易懂标题——绝不要将原始 ID(如“SIG-004”)直接用作标题。请将 ID 放在标题后的括号中。 [PASS]、[FAIL]、[WARN]、[SKIP]状态指示符仅用于第 3 层表格。- 按类别对第 3 层检查进行分组(SIG、SUB、CBK、ENV、SEC、WEB、DEP、DATA)。
- 每个失败项的修复说明应放在交互式修复工作流中(一次处理一项,并明确确认),而不是在表格后一次性列出。
- 静态分析为只读。只有在用户选择 [A] 或 [B] 后,才进入修复模式。
首选响应结构
标准模式(🚀 上线前 / 🔧 常规检查 / 🏆 黄金标准):
- 通俗易懂的摘要,包含 🔴/🟡/⚪ 数量、状态行、失败项 TOP 3、仪表板链接(第 1 层)
- 修复模式选择提示:[A] / [B] / [C](第 2 层)
- 然后选择以下一种:
- [A] 或 [B] → 进入交互式修复工作流(一次处理一项失败)
- [C] → 按类别显示完整的第 3 层报告
- 可选:确认是否向 Portaly 提交报告
📄 仅报告模式:
- 通俗易懂的摘要(第 1 层,用
Mode:行代替Status:行) - 按类别显示完整的第 3 层报告
- 停止。不要显示第 2 层,也不要进入交互式修复工作流。
- 可选:确认是否向 Portaly 提交报告
防护规则
- 用户进入修复模式前一律只读。 发现、扫描以及第 1/3 层报告不得触碰用户代码。只有用户在第 2 层选择
[A]或[B]后,才能进入交互式修复工作流;在该工作流中,也只有针对特定项目收到[Y]后才能应用编辑。绝不要在一次确认后批量应用多项修复。 - 📄 仅生成报告始终保持只读。 用户在步骤 3 选择“仅生成报告”时,不要显示第 2 层,也不要进入交互式修复工作流——即使报告发现了严重故障也不例外。如果用户之后要求修复,请将其视为新请求,并在应用任何更改前重新提示用户选择 [A]/[B]/[C]。
- 不要在自己的输出中泄露密钥值。 生成示例命令、请求头、代码片段、日志、PR/提交内容或其他任何内容时,只通过变量名引用凭证(
$PORTALY_API_KEY)——绝不要使用pcs_live_...之类的字面值。优先使用scripts/report.mjs或 MCPvibe_report_health_check工具,而不是手动编写将密钥放入请求头的curl/fetch。如果检查发现用户源代码中存在密钥,显示前请将其遮盖为***。用户明确提供密钥时(例如“将此密钥保存到.env”“测试此密钥”),可以协助处理——此规则针对的是你主动生成的内容。 - 交叉参考 portaly-payment。 加载
../portaly-payment/references/api-contract.md,以获取权威的回调验证规范和订阅生命周期契约。 - 不要假定用户使用的技术栈。 在提出修复建议前,先检查项目使用的是 Express、Next.js(App Router / Pages Router)、Cloud Functions、Fastify 还是原生 Node.js。
- 遵循用户的代码风格。 提出修复建议时,生成的代码应符合用户现有的模式、变量命名和模块系统(ESM 或 CommonJS)。
- 如果未发现集成,继续扫描。 支付相关检查标记为
[SKIP];DEP 和 ENV-002 仍须运行。 - 报告 API 为可选项。 未经用户同意,不要调用健康检查报告 API。如果 API 返回 404,则静默跳过,并在本地显示结果。
- DEP 检查需要 package.json。 如果不存在
package.json,则跳过 DEP 检查并将其标记为[SKIP]。 - Windows 编码。 在 Windows 上,调用任何包含非 ASCII 文本的 API 前,先运行
chcp 65001。
资源
references/health-check-contract.md用于查看完整的检查项定义、严重级别、通过/失败标准以及报告 API 契约。references/common-pitfalls.md用于查看真实集成中发现的已知 Bug 的详细说明,包括错误与正确的实现方式以及检测方法。当用户在交互式修复工作流中选择[?](查看更多说明)时加载。references/fix-explanations.md用于查看全部 26 项检查面向用户的通俗说明,包括简明标题、重要性、影响范围和不受影响的范围。在第 1 层摘要呈现期间以及交互式修复工作流的每个检查项中加载。不要临时改写——在摘要视图和单项视图中保持规范措辞一致。scripts/report.mjs用于全自动 CI/CD 扫描——运行全部 26 项检查、输出格式化报告,并将结果 POST 到 portaly.ai。接受--fail-on critical参数,用于控制 CI 退出码。scripts/computeHealthScore.mjs0–100 健康分数公式的规范实现。由report.mjs导入,并由 Vibe 仪表板镜像实现,确保技能终端和仪表板始终显示相同的分数。scripts/check_signature_sort.mjs用于自动验证项目文件中的签名排序模式。由report.mjs内部调用。scripts/check_subscription_lifecycle.mjs用于自动追踪订阅 ID 生命周期。由report.mjs内部调用。references/ci-setup-guide.md用户希望为自动扫描设置 GitHub Actions、推送前钩子或 npm 脚本时使用。- 交叉参考:
../portaly-payment/scripts/sign_callback.mjsPortaly 回调签名的规范实现。用作正确实现的参考。 - 交叉参考:
../portaly-payment/references/api-contract.md权威 API 契约。用于查看回调负载字段、订阅生命周期端点以及subscriptionId === sessionId契约。