portaly-sentry
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePortaly Sentry — Payment Integration Health Check
Portaly Sentry — 支付集成健康检查
Use this skill to run a comprehensive security and reliability health check on a Portaly Vibe payment integration. This skill is designed for non-engineers using vibe coding tools who want to ship with confidence. Keep output human and actionable: lead with a plain-language summary and let the user drill in — reserve the 26-row technical table for when they ask for it.
This skill works alongside . It uses the same API contract as the canonical source of truth for what a correct integration looks like.
portaly-payment使用该技能对Portaly Vibe支付集成执行全面的安全与可靠性健康检查。本技能专为使用vibe编码工具的非工程师设计,帮助他们放心发布产品。输出内容需通俗易懂且具备可操作性:先用平实语言给出总结,让用户按需深入了解——仅在用户要求时展示包含26项检查的技术表格。
本技能与配合使用,采用与正确集成标准一致的API协议。
portaly-paymentQuick Start
快速开始
Step 1 — Confirm integration exists
步骤1 — 确认集成存在
- Confirm the project has a Portaly Vibe payment integration (look for ,
portaly,callbackSecret, or checkout session creation code).x-portaly-signature - If no integration is found, tell the user and stop.
- 确认项目包含Portaly Vibe支付集成(查找、
portaly、callbackSecret或结账会话创建代码)。x-portaly-signature - 若未找到集成,告知用户并终止流程。
Step 2 — Introduce what Sentry checks, in plain language
步骤2 — 用平实语言介绍Sentry的检查内容
Before asking anything else, show the user this intro so they understand what Sentry actually does. Do not skip this step — the first-time user has no idea what "SIG" or "SUB" means.
Template:
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.在询问其他问题前,先向用户展示以下介绍,让他们了解Sentry的实际功能。请勿跳过此步骤——首次使用的用户不清楚“SIG”或“SUB”的含义。
模板:
Portaly Sentry从3个维度检查您的支付集成:
🏦 支付流程是否合规? 签名、回调、订阅
🔐 商户凭证是否安全? 环境变量、凭证管理
🛡️ 其他环节是否加固? 依赖项、Web安全、数据处理
共26项检查,按严重程度分级:CRITICAL(严重)/ WARNING(警告)/ INFO(提示)。Step 3 — Ask which project and which scan standard
步骤3 — 询问项目和扫描标准
Do not pick a default — ask the user both questions and wait for an answer. Phrase it as a checkpoint, not a suggestion.
Template:
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 nowStandard → scope mapping (agent-internal; do not show this table to the user):
| User choice | Report includes | Blocking severity | Fix workflow |
|---|---|---|---|
| 🚀 Pre-launch | all 26 checks | CRITICAL only | offered |
| 🔧 Routine check | all 26 checks | CRITICAL + WARNING | offered |
| 🏆 Gold standard | all 26 checks | all severities | offered |
| 📄 Report only | all 26 checks | n/a | never offered |
| ⏰ Weekly auto | skip scan → jump to Step 16 | n/a | n/a |
All four non-scheduled standards run all 26 checks. The first three differ only in the pass/fail threshold used in the Layer 1 summary's "Status" line (see Step 14). 📄 Report only runs the same scan but skips Layer 2 (the fix-mode prompt) and ends after Layer 3 — use it for audits, code-review handoffs, or when the user just wants to see results without committing to fixes now.
Advanced. If the user explicitly asks to scan only one category (e.g. "only scan signatures" or "re-run SIG"), accept that as a single-category mode using one of: SIG, SUB, CBK, ENV, SEC, WEB, DEP, DATA. Do not surface this as a main option — category codes overwhelm first-time users.
请勿默认选择——向用户询问这两个问题并等待回复。以确认点的方式表述,而非建议。
模板:
开始扫描前需确认两项信息:
① 要扫描哪个项目?(例如:~/gratitude-app)
② 选择扫描标准:
🚀 预发布标准 — 所有CRITICAL项必须通过
🔧 常规检查标准 — 所有CRITICAL + WARNING项必须通过
🏆 黄金标准 — 通过全部26项检查(包括INFO)
📄 仅生成报告 — 扫描并展示报告,跳过修复流程
⏰ 每周自动扫描 — 安排定期扫描,不立即执行标准→范围映射(仅内部使用;请勿向用户展示此表格):
| 用户选择 | 报告包含内容 | 阻塞性严重程度 | 修复流程 |
|---|---|---|---|
| 🚀 预发布标准 | 全部26项检查 | 仅CRITICAL | 提供修复 |
| 🔧 常规检查标准 | 全部26项检查 | CRITICAL + WARNING | 提供修复 |
| 🏆 黄金标准 | 全部26项检查 | 所有严重程度 | 提供修复 |
| 📄 仅生成报告 | 全部26项检查 | 无 | 绝不提供修复 |
| ⏰ 每周自动扫描 | 跳过扫描→跳转至步骤16 | 无 | 无 |
所有四种非定期扫描标准都会执行全部26项检查。前三种标准仅在步骤14的第一层总结“状态”行中使用的通过/失败阈值不同(见步骤14)。📄仅生成报告模式执行相同扫描,但跳过第二层(修复模式提示),在第三层后结束——适用于审计、代码审查交接,或用户仅想查看结果而不立即修复的场景。
高级功能。如果用户明确要求仅扫描某一类别(例如“仅扫描签名”或“重新运行SIG”),接受此要求并使用单一类别模式,可选类别代码:SIG、SUB、CBK、ENV、SEC、WEB、DEP、DATA。请勿将此作为主要选项展示——类别代码会让首次用户感到困惑。
Prerequisites
前置条件
- Static analysis checks (SIG, SUB, CBK, ENV, SEC, WEB, DATA) do not require credentials.
- For DEP checks, the project must have a .
package.json - For reporting results to Portaly, the user needs a .
PORTALY_API_KEY
- 静态分析检查(SIG、SUB、CBK、ENV、SEC、WEB、DATA)无需凭证。
- 执行DEP检查时,项目必须包含。
package.json - 如需向Portaly上报结果,用户需要。
PORTALY_API_KEY
Health Check Categories
健康检查类别
SIG — Signature Verification
SIG — 签名验证
Checks that callback signature verification matches Portaly's canonical implementation.
| ID | Check | Severity |
|---|---|---|
| SIG-001 | Stable JSON sort order uses | CRITICAL |
| SIG-002 | HMAC algorithm is SHA-256 | CRITICAL |
| SIG-003 | Timestamp replay protection rejects callbacks older than 5 minutes | WARNING |
| SIG-004 | Signature comparison uses | CRITICAL |
检查回调签名验证是否符合Portaly的标准实现。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| SIG-001 | 使用 | CRITICAL |
| SIG-002 | HMAC算法为SHA-256 | CRITICAL |
| SIG-003 | 时间戳重放防护拒绝超过5分钟的回调 | WARNING |
| SIG-004 | 使用 | CRITICAL |
SUB — Subscription Lifecycle
SUB — 订阅生命周期
Checks that subscription identifiers are stored and used correctly across the checkout-to-cancel flow.
| ID | Check | Severity |
|---|---|---|
| SUB-001 | | CRITICAL |
| SUB-002 | Duplicate callback handling via idempotency key | WARNING |
| SUB-003 | Cancel/resume APIs use the persisted | CRITICAL |
检查订阅标识符在结账至取消流程中的存储和使用是否正确。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| SUB-001 | 结账完成后持久化 | CRITICAL |
| SUB-002 | 通过幂等键处理重复回调 | WARNING |
| SUB-003 | 取消/恢复API使用持久化的 | CRITICAL |
CBK — Callback Endpoint
CBK — 回调端点
Checks callback endpoint configuration and behavior.
| ID | Check | Severity |
|---|---|---|
| CBK-001 | | CRITICAL |
| CBK-002 | Signature verification failure is logged with diagnostics | WARNING |
| CBK-003 | Callback handler returns explicit 200 on success | INFO |
检查回调端点的配置和行为。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| CBK-001 | | CRITICAL |
| CBK-002 | 签名验证失败时记录诊断信息 | WARNING |
| CBK-003 | 回调处理成功时返回明确的200状态码 | INFO |
ENV — Environment & Credentials
ENV — 环境与凭证
Checks credential management and environment configuration.
| ID | Check | Severity |
|---|---|---|
| ENV-001 | | CRITICAL |
| ENV-002 | | CRITICAL |
| ENV-003 | No API key or callback secret hardcoded in source files | CRITICAL |
检查凭证管理和环境配置。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| ENV-001 | | CRITICAL |
| ENV-002 | | CRITICAL |
| ENV-003 | 源代码中未硬编码API密钥或回调密钥 | CRITICAL |
SEC — Security Best Practices
SEC — 安全最佳实践
Checks for security hygiene in the integration.
| ID | Check | Severity |
|---|---|---|
| SEC-001 | No callback secret or API key in client-side / browser-accessible code | CRITICAL |
| SEC-002 | Raw callback body persisted for audit trail | INFO |
| SEC-003 | Secrets read from environment variables (rotation-ready) | INFO |
| SEC-004 | Callback endpoint has no overly permissive CORS ( | WARNING |
| SEC-005 | Payment-related pages set | INFO |
检查集成中的安全卫生情况。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| SEC-001 | 客户端/浏览器可访问的代码中无回调密钥或API密钥 | CRITICAL |
| SEC-002 | 原始回调体被持久化用于审计追踪 | INFO |
| SEC-003 | 从环境变量读取密钥(支持轮换) | INFO |
| SEC-004 | 回调端点未设置过于宽松的CORS( | WARNING |
| SEC-005 | 支付相关页面设置 | INFO |
WEB — Web Security Fundamentals
WEB — Web安全基础
Checks for common web security issues in payment flows.
| ID | Check | Severity |
|---|---|---|
| WEB-001 | | CRITICAL |
| WEB-002 | Error responses do not expose stack traces, internal paths, or DB schema | WARNING |
| WEB-003 | Callback endpoint validates | WARNING |
| WEB-004 | Callback endpoint enforces request body size limit | WARNING |
检查支付流程中的常见Web安全问题。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| WEB-001 | | CRITICAL |
| WEB-002 | 错误响应未暴露堆栈跟踪、内部路径或数据库模式 | WARNING |
| WEB-003 | 回调端点验证 | WARNING |
| WEB-004 | 回调端点强制设置请求体大小限制 | WARNING |
DEP — Dependency Security
DEP — 依赖项安全
Checks for known vulnerabilities in project dependencies.
| ID | Check | Severity |
|---|---|---|
| DEP-001 | | CRITICAL |
| DEP-002 | Lock file ( | WARNING |
检查项目依赖项中的已知漏洞。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| DEP-001 | | CRITICAL |
| DEP-002 | 锁文件( | WARNING |
DATA — Data Handling Security
DATA — 数据处理安全
Checks for safe data handling practices.
| ID | Check | Severity |
|---|---|---|
| DATA-001 | Callback payload fields validated (type/length) before database writes | WARNING |
| DATA-002 | Logs do not contain full API keys, callback secrets, or raw customer PII | WARNING |
检查安全的数据处理实践。
| ID | 检查内容 | 严重程度 |
|---|---|---|
| DATA-001 | 回调负载字段在写入数据库前已验证(类型/长度) | WARNING |
| DATA-002 | 日志中不包含完整API密钥、回调密钥或原始客户PII | WARNING |
Workflow
工作流程
Step 4 — Discover integration files
步骤4 — 发现集成文件
Search the project for files related to Portaly payment integration:
- Files importing or containing HMAC operations
crypto - Files containing ,
portaly,x-portaly-signature,x-portaly-timestamp,callbackSecretPORTALY_CALLBACK_SECRET - Callback route handlers (Express routes, Next.js API routes, Cloud Functions HTTP triggers)
- Files containing ,
subscriptionIdin the context of checkout completionsessionId - Files containing ,
successRedirectUrlcancelRedirectUrl
Build a file inventory and map each file to the relevant check categories.
在项目中搜索与Portaly支付集成相关的文件:
- 导入或包含HMAC操作的文件
crypto - 包含、
portaly、x-portaly-signature、x-portaly-timestamp、callbackSecret的文件PORTALY_CALLBACK_SECRET - 回调路由处理器(Express路由、Next.js API路由、Cloud Functions HTTP触发器)
- 在结账完成上下文中包含、
subscriptionId的文件sessionId - 包含、
successRedirectUrl的文件cancelRedirectUrl
构建文件清单,并将每个文件映射到相关检查类别。
Step 5 — Run SIG checks
步骤5 — 执行SIG检查
For each signature-related file:
- Check sort order pattern — compare against canonical implementation in .
../portaly-payment/scripts/sign_callback.mjs - Check HMAC algorithm — verify .
createHmac('sha256', ...) - Check timestamp validation — look for comparison of against current time with a 5-minute window.
x-portaly-timestamp - Check comparison method — verify is used, not
crypto.timingSafeEqualor===.==
Reference: can automate this step.
scripts/check_signature_sort.mjs对于每个签名相关文件:
- 检查排序模式——与中的标准实现对比。
../portaly-payment/scripts/sign_callback.mjs - 检查HMAC算法——验证使用。
createHmac('sha256', ...) - 检查时间戳验证——查找将与当前时间对比并设置5分钟窗口的逻辑。
x-portaly-timestamp - 检查比较方法——验证使用而非
crypto.timingSafeEqual或===。==
参考:可自动化此步骤。
scripts/check_signature_sort.mjsStep 6 — Run SUB checks
步骤6 — 执行SUB检查
Trace the subscription ID lifecycle:
- In the callback handler, after , check what gets persisted. The stored value should be
status === 'completed'(which equalssessionIdper Portaly's current contract).subscriptionId - Check for idempotency — does the handler check if this was already processed before fulfilling?
sessionId - Trace the cancel/resume code path — verify it reads the same field that the callback wrote and passes it to
subscriptionIdor/subscriptions/{subscriptionId}/cancel./resume
Reference: can automate this step.
scripts/check_subscription_lifecycle.mjs追踪订阅ID的生命周期:
- 在回调处理器中,当后,检查持久化的内容。存储的值应为
status === 'completed'(根据Portaly当前协议,其等于sessionId)。subscriptionId - 检查幂等性——处理器是否在执行前检查该是否已处理过?
sessionId - 追踪取消/恢复代码路径——验证其读取回调写入的同一字段,并将其传递给
subscriptionId或/subscriptions/{subscriptionId}/cancel。/resume
参考:可自动化此步骤。
scripts/check_subscription_lifecycle.mjsStep 7 — Run CBK checks
步骤7 — 执行CBK检查
- Check if is constructed with
callbackUrl.https:// - Check the signature verification failure branch — does it log diagnostic info (timestamp, payload hash, expected vs actual)?
- Check that the success branch returns an explicit status.
200
- 检查是否使用
callbackUrl构建。https:// - 检查签名验证失败分支——是否记录诊断信息(时间戳、负载哈希、预期值与实际值)?
- 检查成功分支是否返回明确的状态码。
200
Step 8 — Run ENV checks
步骤8 — 执行ENV检查
- Read (or
.env,.env.example) — check for.env.localandPORTALY_API_KEY.PORTALY_CALLBACK_SECRET - Read — check that
.gitignoreis listed..env - Grep source files (excluding ,
node_modules) for literal.env,pcs_live_, or any string that looks like a callback secret.pcs_test_
- 读取(或
.env、.env.example)——检查是否包含.env.local和PORTALY_API_KEY。PORTALY_CALLBACK_SECRET - 读取——检查是否包含
.gitignore。.env - 在源代码中搜索(排除、
node_modules)字面量.env、pcs_live_或任何类似回调密钥的字符串。pcs_test_
Step 9 — Run SEC checks
步骤9 — 执行SEC检查
- Check for API key or callback secret in files under directories typically served to the browser (,
src/,public/,app/for client components). Watch forpages/prefixed env vars containing secrets.NEXT_PUBLIC_ - Check if the raw callback body is saved to the database for auditing.
- Verify secrets are read from or equivalent, not hardcoded.
process.env - Check for CORS middleware on the callback endpoint — flag .
Access-Control-Allow-Origin: * - Check for CSP headers on success/cancel redirect pages.
- 检查浏览器可访问目录(、
src/、public/、客户端组件的app/)下的文件中是否存在API密钥或回调密钥。注意包含pages/前缀的环境变量是否包含密钥。NEXT_PUBLIC_ - 检查原始回调体是否保存到数据库用于审计。
- 验证密钥从或等效方式读取,而非硬编码。
process.env - 检查回调端点的CORS中间件——标记。
Access-Control-Allow-Origin: * - 检查成功/取消重定向页面是否设置CSP头。
Step 10 — Run WEB checks
步骤10 — 执行WEB检查
- Check if and
successRedirectUrlare validated against an allowlist of trusted domains before being used in redirects.cancelRedirectUrl - Check error handling in the callback route — ensure blocks do not send full error stacks in the response body.
catch - Check that the callback endpoint validates header.
Content-Type - Check for body parser size limits (e.g., or equivalent).
express.json({ limit: '1mb' })
- 检查和
successRedirectUrl在用于重定向前是否已针对可信域名白名单验证。cancelRedirectUrl - 检查回调路由中的错误处理——确保块不在响应体中发送完整错误堆栈。
catch - 检查回调端点是否验证头。
Content-Type - 检查是否设置了解析器大小限制(例如或等效配置)。
express.json({ limit: '1mb' })
Step 11 — Run DEP checks
步骤11 — 执行DEP检查
- If exists, run
package.jsonornpm audit --jsonand parse the output for critical/high severity vulnerabilities.pnpm audit --json - Check if or
package-lock.jsonexists and is not inpnpm-lock.yaml..gitignore
- 如果存在,运行
package.json或npm audit --json并解析输出,查找严重或高危漏洞。pnpm audit --json - 检查或
package-lock.json是否存在且未包含在pnpm-lock.yaml中。.gitignore
Step 12 — Run DATA checks
步骤12 — 执行DATA检查
- Check if callback payload fields are validated before database writes (type checks, length limits, sanitization).
- Grep log statements (,
console.log,console.error) for potential secret or PII exposure — flag any that log the full callback payload, API key, or callback secret.logger.
- 检查回调负载字段在写入数据库前是否已验证(类型检查、长度限制、清理)。
- 在日志语句(、
console.log、console.error)中搜索潜在的密钥或PII泄露——标记任何记录完整回调负载、API密钥或回调密钥的日志。logger.
Step 13 — Sync results to Portaly (optional)
步骤13 — 将结果同步到Portaly(可选)
After running all checks but before presenting the summary, offer to sync the scan to the user's Portaly dashboard. Doing this now means Step 14's Layer 1 summary can include a shareable report link.
There are two transports — prefer MCP when available:
Path A — MCP (preferred, zero extra config). If the agent is connected to Vibe MCP, the tool is available. It uses the agent's existing MCP connection — no needed. Briefly ask consent, then call the tool with the scan payload. Capture and from the response and use as in the Layer 1 dashboard link. See § "MCP reporting" for the input schema.
vibe_report_health_checkPORTALY_API_KEYreportIddashboardUrlreportId{scan_id}references/health-check-contract.mdPath B — REST API (fallback). When MCP is not connected and the user has set in their environment, fall back to running — it reads the key from and POSTs to for you. Prefer this over hand-rolling a / with the key inline. Capture from the script's stdout. See § "Report API Contract" for the full request/response schema.
PORTALY_API_KEYscripts/report.mjsprocess.env.PORTALY_API_KEYhttps://portaly.ai/api/creator-subscription/health-check-reportscurlfetchreportIdreferences/health-check-contract.mdRules:
- Do not call either path without explicit user consent.
- If both paths are unavailable (no MCP, no key) or the call fails (e.g., 404 on REST), skip the sync silently and continue to Step 14 without a dashboard link. Do not block the summary on this.
- Do not call both paths for the same scan — pick one.
在完成所有检查但展示总结前,询问用户是否要将扫描结果同步到其Portaly仪表板。此时同步可让步骤14的第一层总结包含可分享的报告链接。
有两种传输方式——优先使用MCP:
路径A — MCP(优先,无需额外配置)。如果代理已连接到Vibe MCP,则工具可用。它使用代理现有的MCP连接——无需。简要询问用户同意后,调用该工具并传入扫描负载。从响应中捕获和,并在第一层仪表板链接中使用作为。参考 § "MCP reporting"获取输入 schema。
vibe_report_health_checkPORTALY_API_KEYreportIddashboardUrlreportId{scan_id}references/health-check-contract.md路径B — REST API(备选)。当未连接MCP且用户环境中已设置时,退而使用——它从读取密钥并POST到。优先使用此方式而非手动编写包含密钥的/。从脚本标准输出中捕获。参考 § "Report API Contract"获取完整请求/响应schema。
PORTALY_API_KEYscripts/report.mjsprocess.env.PORTALY_API_KEYhttps://portaly.ai/api/creator-subscription/health-check-reportscurlfetchreportIdreferences/health-check-contract.md规则:
- 未经用户明确同意,请勿调用任何路径。
- 如果两种路径都不可用(无MCP、无密钥)或调用失败(例如REST返回404),静默跳过同步并继续到步骤14,不展示仪表板链接。请勿因同步问题阻塞总结展示。
- 请勿对同一扫描调用两种路径——选择其一。
Step 14 — Present the summary (not the full table)
步骤14 — 展示总结(而非完整表格)
The first thing the user sees must be a plain-language summary, not a 26-row table. The full technical report lives on the dashboard — only show it locally when the user picks , when the user is in 📄 Report only mode, or when dashboard reporting is unavailable.
[C]Output up to three layers, in this order (📄 Report only mode emits Layer 1 + Layer 3 only — see below):
用户首先看到的必须是平实语言的总结,而非包含26行的表格。完整技术报告在仪表板上——仅当用户选择、处于📄仅生成报告模式,或仪表板报告不可用时,才在本地展示。
[C]按以下顺序输出最多三层内容(📄仅生成报告模式仅输出第一层 + 第三层——见下文):
Layer 1 — Plain-language summary (always show)
第一层 — 平实语言总结(始终展示)
Load titles from — do not invent new phrasing. Compute the health score from the per-check results using the formula in § "Health Score Formula" — the same number the dashboard shows.
references/fix-explanations.mdreferences/health-check-contract.mdTemplate:
📊 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)
https://portaly.ai/dashboard/sentry-scans/{scan_id}Score banding (must match the dashboard):
| Score | Band |
|---|---|
| 90–100 | Healthy |
| 70–89 | Needs attention |
| 0–69 | At risk |
{status_line}| Standard | Condition for "safe to launch" |
|---|---|
| 🚀 Pre-launch | 0 CRITICAL failures |
| 🔧 Routine check | 0 CRITICAL and 0 WARNING failures |
| 🏆 Gold standard | 0 failures across all 26 checks |
Use or — nothing in between. If the Step 13 sync was skipped and there is no , drop the whole block (both the label line and the URL line); do not show a broken or placeholder link.
✅ Safe to launch❌ Not safe to launch yetscan_id🔗 Full reportFor 📄 Report only, omit the line entirely (there is no launch gate in this mode) and replace it with . Everything else in Layer 1 stays the same.
Status:Mode: 📄 Report only — fix workflow disabled从加载标题——请勿自行创造表述。使用 § "Health Score Formula"中的公式根据每项检查结果计算健康分数——与仪表板显示的分数一致。
references/fix-explanations.mdreferences/health-check-contract.md模板:
📊 支付集成健康检查 — {projectName}
健康分数: {score}/100 ({等级: 健康 | 需要关注 | 存在风险})
🟢 通过 {passedCount}项检查 表现良好
🟡 待审核 {warnedCount}项警告 本周内处理
🔴 严重问题 {failedCount}项阻塞 发布前必须修复
状态: {status_line}
最需修复的{min(3, failures)}个问题:
1. {来自fix-explanations.md的平实标题} ({ID})
2. ...
3. ...
🔗 完整报告(全部26项检查、修复指南、历史记录)
https://portaly.ai/dashboard/sentry-scans/{scan_id}分数等级(必须与仪表板一致):
| 分数 | 等级 |
|---|---|
| 90–100 | 健康 |
| 70–89 | 需要关注 |
| 0–69 | 存在风险 |
{status_line}| 标准 | "可安全发布"条件 |
|---|---|
| 🚀 预发布标准 | 0项CRITICAL失败 |
| 🔧 常规检查标准 | 0项CRITICAL 且 0项WARNING失败 |
| 🏆 黄金标准 | 26项检查全部通过 |
使用或——无中间状态。如果步骤13同步被跳过且无,则删除整个块(包括标签行和URL行);请勿展示无效或占位链接。
✅ 可安全发布❌ 暂不可安全发布scan_id🔗 完整报告对于📄仅生成报告模式,完全省略行(此模式无发布门限),替换为。第一层的其他内容保持不变。
Status:模式: 📄 仅生成报告 — 修复流程已禁用Layer 2 — Fix mode choice (show right after summary, except in 📄 Report only)
第二层 — 修复模式选择(总结后立即展示,📄仅生成报告模式除外)
In 📄 Report only mode, skip Layer 2 entirely and go straight to Layer 3. Do not render the prompt — the user has already opted out of fixes.
[A] / [B] / [C]Template:
─────────────────────────────────────
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 firstThe user's answer routes to:
- [A] → Interactive Fix Workflow with all failures, ordered CRITICAL → WARNING → INFO
- [B] → Interactive Fix Workflow with CRITICAL failures only
- [C] → Layer 3
在📄仅生成报告模式下,完全跳过第二层直接进入第三层。请勿显示提示——用户已选择不修复。
[A] / [B] / [C]模板:
─────────────────────────────────────
是否现在开始修复?
[A] 是,按顺序引导我修复所有问题(推荐)
[B] 仅修复🔴严重问题(最快发布路径)
[C] 先展示完整报告用户的回复将导向:
- [A] → 交互式修复流程,处理所有失败项,按严重程度排序(CRITICAL → WARNING → INFO)
- [B] → 交互式修复流程,仅处理CRITICAL失败项
- [C] → 第三层
Layer 3 — Full technical report (on [C], in 📄 Report only mode, or when dashboard reporting is unavailable)
第三层 — 完整技术报告(选择[C]时、📄仅生成报告模式下,或仪表板报告不可用时)
Render the full 26-row table, grouped by category. Format:
undefined按类别分组展示完整的26行表格。格式:
undefinedPortaly Sentry — Health Check Report
Portaly Sentry — 健康检查报告
Project: {project_name} | Scan: {ISO timestamp} | Mode: {manual|scheduled}
项目: {project_name} | 扫描时间: {ISO时间戳} | 模式: {手动|定期}
SIG — Signature Verification
SIG — 签名验证
| # | Check | Severity | Status |
|---|---|---|---|
| SIG-001 | Stable JSON sort order | CRITICAL | [PASS] |
| ... | ... | ... | ... |
| # | 检查内容 | 严重程度 | 状态 |
|---|---|---|---|
| SIG-001 | 稳定JSON排序 | CRITICAL | [PASS] |
| ... | ... | ... | ... |
SUB — Subscription Lifecycle
SUB — 订阅生命周期
| # | Check | Severity | Status |
|---|---|---|---|
| ... | ... | ... | ... |
(repeat for CBK / ENV / SEC / WEB / DEP / DATA)
Summary: X/26 passed | Y CRITICAL failures | Z warnings | W skipped
| # | 检查内容 | 严重程度 | 状态 |
|---|---|---|---|
| ... | ... | ... | ... |
(CBK / ENV / SEC / WEB / DEP / DATA类别重复上述格式)
总结: X/26通过 | Y项CRITICAL失败 | Z项警告 | W项跳过
Fix: {ID} — {Check Name}
修复: {ID} — {检查名称}
File: {file_path}:{line}
{description of the issue}
{code diff showing the fix}
undefined文件: {file_path}:{line}
{问题描述}
{显示修复的代码差异}
undefinedStep 15 — Interactive Fix Workflow (per-item confirmation)
步骤15 — 交互式修复流程(逐项确认)
Enter this workflow only after the user explicitly picks [A] (fix all) or [B] (fix CRITICAL only) from Layer 2. For each failure, in order of severity (CRITICAL → WARNING → INFO), present exactly one item at a time and wait for confirmation before touching any file.
In 📄 Report only mode this step is unreachable by design — Layer 2 is never shown, so [A]/[B] are never picked. If the user later changes their mind and asks to start fixing, treat that as a new request and re-prompt with the Layer 2 choices before entering this workflow.
仅当用户明确从第二层选择**[A](修复全部)或[B]**(仅修复CRITICAL)后,才进入此流程。对于每个失败项,按严重程度顺序(CRITICAL → WARNING → INFO),每次仅展示一项,等待用户确认后再修改文件。
在📄仅生成报告模式下,此步骤不可达——第二层从未显示,因此[A]/[B]从未被选择。如果用户之后改变主意并要求开始修复,将其视为新请求,在进入此流程前重新提示第二层选择。
Per-item template
逐项模板
Render the block below for each failure. All plain-language copy comes from — do not paraphrase on the fly. Keep IDs, file paths, code in the diff, and the keys as-is.
references/fix-explanations.md[Y]/[N]/[?]/[STOP]Template:
🔴 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为每个失败项渲染以下内容。所有平实语言文案来自——请勿即兴改写。保持ID、文件路径、代码差异中的代码,以及选项不变。
references/fix-explanations.md[Y]/[N]/[?]/[STOP]模板:
🔴 第{n}项,共{m}项 | 进度 {progress_bar} {percent}%
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
修复: {平实标题} ({ID})
📍 涉及文件:
{file_path} ({变更摘要,例如"添加1个导入,修改3行"})
❓ 为什么这很重要?
{来自fix-explanations.md的原因说明}
🔧 预览:
{统一差异格式,- 旧代码 / + 新代码}
✅ 影响范围: {来自fix-explanations.md的影响说明}
✅ 不影响: {来自fix-explanations.md的非影响说明}
─────────────────────────────────────
是否应用此修复?
[Y] 确认,应用修复
[N] 跳过此项
[?] 我想了解更多细节
[STOP] 暂停,稍后再继续Rules
规则
- One item at a time. Never batch multiple fixes into one confirmation. Even if [B] has 3 CRITICAL items, ask Y/N for each.
- Match severity icon to the header: 🔴 for CRITICAL, 🟡 for WARNING, ⚪ for INFO.
- Progress bar: use filled and
▓empty, 7 blocks total. Example at 3/7:░.▓▓▓░░░░ - Use the user's own code style in the diff. Match their module system (ESM vs CommonJS), variable names, and framework idioms. Pull canonical fix patterns from and
references/common-pitfalls.md, then adapt to the user's style.../portaly-payment/scripts/sign_callback.mjs - Never show raw CRITICAL/WARNING/INFO labels in user-facing text. Use natural phrasing like "Critical / Should fix / Nice to have", and let the 🔴/🟡/⚪ icons carry severity visually.
- 逐项处理。切勿将多个修复合并为一次确认。即使[B]有3项CRITICAL问题,也要逐项询问Y/N。
- 标题图标匹配严重程度:🔴对应CRITICAL,🟡对应WARNING,⚪对应INFO。
- 进度条:使用填充,
▓空白,共7个区块。示例:3/7进度为░。▓▓▓░░░░ - 代码差异匹配用户代码风格。匹配其模块系统(ESM vs CommonJS)、变量名和框架习惯。从和
references/common-pitfalls.md获取标准修复模式,然后适配用户风格。../portaly-payment/scripts/sign_callback.mjs - 用户可见文本中请勿显示原始CRITICAL/WARNING/INFO标签。使用自然表述如“严重问题 / 建议修复 / 优化项”,并通过🔴/🟡/⚪图标直观展示严重程度。
Handling each response
回复处理
Match the user's reply to intent rather than an exact string. The key-letter triggers are canonical; equivalent words in English or the user's own language count as the same intent.
| Intent | Canonical trigger | Action |
|---|---|---|
| Apply | | Apply the edit, confirm success in one line (e.g. |
| Skip | | Do not modify the file. Mark as |
| Explain | | Load the corresponding pitfall entry from |
| Stop | | Stop immediately. Show a resume summary: |
根据用户回复的意图而非精确字符串匹配。关键字母触发为标准;英文或用户本地语言的等效表述视为同一意图。
| 意图 | 标准触发词 | 操作 |
|---|---|---|
| 应用 | | 应用修改,用一行确认成功(例如 |
| 跳过 | | 不修改文件。标记为 |
| 解释 | | 从 |
| 停止 | | 立即停止。展示恢复总结: |
After the last item
最后一项处理完成后
Template:
🎉 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模板:
🎉 修复会话完成
✅ 已应用: {X}项
⏭️ 已跳过: {Y}项
─────────────────────────────────────
建议后续步骤:
1. 运行常规测试或尝试端到端结账流程
2. 重新运行Sentry确认所有问题已解决
3. 如果您有Portaly API密钥,将结果同步到仪表板Step 16 — Set up automated scanning (optional)
步骤16 — 设置自动扫描(可选)
Three options, from simplest to most rigorous. Present all three and let the user choose.
Option A — GitHub Actions (recommended for any project with a GitHub repo)
Tell the user to create with the template in
. Then add as a GitHub repository secret.
This runs on every push to main AND weekly on Monday — blocks merges if CRITICAL issues are found.
.github/workflows/portaly-sentry.ymlreferences/ci-setup-guide.mdPORTALY_API_KEYOption B — Pre-push git hook (local machine enforcement)
Run once to install:
bash
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-pushOption C — Automated script runner via
scripts/report.mjsFor any CI system or scheduled task, point at the automation script directly. The script reads from the environment — set it through the CI's secret store, your shell profile, or a loader rather than inlining the value.
PORTALY_API_KEY.envbash
undefined提供三种选项,从简单到严格。展示所有选项让用户选择。
选项A — GitHub Actions(推荐给所有GitHub仓库项目)
告知用户创建,使用中的模板。然后将添加为GitHub仓库密钥。此配置会在每次推送到main分支时运行,且每周一自动运行——如果发现CRITICAL问题,将阻止合并。
.github/workflows/portaly-sentry.ymlreferences/ci-setup-guide.mdPORTALY_API_KEY选项B — Git预推送钩子(本地机器强制执行)
运行一次完成安装:
bash
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系统或定时任务,直接指向自动化脚本。脚本从环境读取——通过CI密钥存储、shell配置文件或加载器设置,而非硬编码值。
PORTALY_API_KEY.envbash
undefinedPORTALY_API_KEY exported via CI secret / shell / .env
PORTALY_API_KEY通过CI密钥/shell/.env导出
node .claude/skills/portaly-sentry/scripts/report.mjs
--dir . --scan-type scheduled --fail-on critical
--dir . --scan-type scheduled --fail-on critical
`--fail-on critical` makes the command exit 1 when CRITICAL issues are found,
which any CI system will treat as a build failure.
See `references/ci-setup-guide.md` for the full CLI reference and setup instructions.node .claude/skills/portaly-sentry/scripts/report.mjs
--dir . --scan-type scheduled --fail-on critical
--dir . --scan-type scheduled --fail-on critical
`--fail-on critical`参数会在发现CRITICAL问题时让命令以1退出,任何CI系统都会将其视为构建失败。
参考`references/ci-setup-guide.md`获取完整CLI参考和设置说明。Output Style
输出风格
- Lead with the plain-language summary (Layer 1), not the table. The 26-row table is Layer 3, shown only on request.
- Use the plain title from when naming a failed check — never surface raw IDs like "SIG-004" as the headline. Put the ID in parentheses after the title.
references/fix-explanations.md - Use ,
[PASS],[FAIL],[WARN]status indicators only inside Layer 3 tables.[SKIP] - Group Layer 3 checks by category (SIG, SUB, CBK, ENV, SEC, WEB, DEP, DATA).
- Per-failure fix instructions belong in the Interactive Fix Workflow (one at a time, with explicit confirmation), not in a dumped list after the table.
- Static analysis is read-only. Only enter fix mode after the user picks [A] or [B].
- 先展示平实语言总结(第一层),而非表格。26行表格属于第三层,仅在用户要求时展示。
- 命名失败检查时,使用中的平实标题——切勿将“SIG-004”等原始ID作为标题。将ID放在标题后的括号中。
references/fix-explanations.md - 仅在第三层表格中使用、
[PASS]、[FAIL]、[WARN]状态标识。[SKIP] - 第三层检查按类别分组(SIG、SUB、CBK、ENV、SEC、WEB、DEP、DATA)。
- 每项失败的修复说明属于交互式修复流程(逐项展示,需明确确认),而非表格后的批量列表。
- 静态分析为只读模式。仅在用户选择[A]或[B]后进入修复模式。
Preferred Response Shape
首选响应结构
Standard modes (🚀 Pre-launch / 🔧 Routine check / 🏆 Gold standard):
- Plain-language summary with 🔴/🟡/⚪ counts, status line, TOP 3 failures, dashboard link (Layer 1)
- Fix mode choice prompt: [A] / [B] / [C] (Layer 2)
- Then one of:
- [A] or [B] → enter Interactive Fix Workflow (one failure at a time)
- [C] → show full Layer 3 report grouped by category
- Optional: report-to-Portaly confirmation
📄 Report only mode:
- Plain-language summary (Layer 1, with line in place of
Mode:)Status: - Full Layer 3 report grouped by category
- Stop. Do not show Layer 2, do not enter the Interactive Fix Workflow.
- Optional: report-to-Portaly confirmation
标准模式(🚀预发布 / 🔧常规检查 / 🏆黄金标准):
- 平实语言总结,包含🔴/🟡/⚪计数、状态行、前3个失败项、仪表板链接(第一层)
- 修复模式选择提示:[A] / [B] / [C](第二层)
- 然后进入以下之一:
- [A]或[B] → 进入交互式修复流程(逐项处理失败项)
- [C] → 展示按类别分组的完整第三层报告
- 可选:向Portaly上报确认
📄仅生成报告模式:
- 平实语言总结(第一层,用行替换
Mode:行)Status: - 按类别分组的完整第三层报告
- 停止。不展示第二层,不进入交互式修复流程。
- 可选:向Portaly上报确认
Guardrails
防护规则
- Read-only until the user enters fix mode. Discovery, scanning, and the Layer 1/3 reports must not touch user code. Only after the user picks or
[A]in Layer 2 may you enter the Interactive Fix Workflow, and within it only apply an edit after a[B]for that specific item. Never batch-apply multiple fixes from a single confirmation.[Y] - 📄 Report only stays read-only, period. When the user picks Report only in Step 3, do not show Layer 2 and do not enter the Interactive Fix Workflow — even if the report surfaces CRITICAL failures. If the user later asks to fix, treat that as a new request and re-prompt with [A]/[B]/[C] before applying anything.
- Don't surface secret values in your own output. When generating example commands, headers, snippets, logs, PR/commit content, or anything else you write, refer to the credential by variable name only () — never with a literal value like
$PORTALY_API_KEY. Preferpcs_live_...or the MCPscripts/report.mjstool over hand-rollingvibe_report_health_check/curlwith the key in the header. If a check surfaces a secret found in the user's source, mask it asfetchbefore displaying. Helping the user when they explicitly provide a key (e.g. "save this to***", "test this key") is fine — this rule is about what you generate on your own initiative..env - Cross-reference portaly-payment. Load for the authoritative callback verification spec and subscription lifecycle contract.
../portaly-payment/references/api-contract.md - Do not assume the user's stack. Check for Express, Next.js (App Router / Pages Router), Cloud Functions, Fastify, or vanilla Node.js before recommending fixes.
- Match the user's code style. When recommending fixes, generate code that matches the user's existing patterns, variable naming, and module system (ESM vs CommonJS).
- If no integration is found, stop. Tell the user the project does not appear to have a Portaly payment integration and ask if they want to set one up using .
portaly-payment - Report API is optional. Do not call the health-check report API without user consent. If the API returns 404, skip silently and show results locally.
- DEP checks require package.json. If no exists, skip DEP checks and mark them as
package.json.[SKIP] - Windows encoding. On Windows, run before any API calls containing non-ASCII text.
chcp 65001
- 进入修复模式前为只读。发现、扫描及第一层/第三层报告不得修改用户代码。仅在用户从第二层选择或
[A]后,才可进入交互式修复流程,且仅在用户对特定项选择[B]后才可应用修改。切勿通过一次确认批量应用多个修复。[Y] - 📄仅生成报告模式始终保持只读。当用户在步骤3选择仅生成报告时,不展示第二层,不进入交互式修复流程——即使报告发现CRITICAL问题。如果用户之后要求修复,将其视为新请求,在应用任何修改前重新提示[A]/[B]/[C]选择。
- 输出中请勿暴露密钥值。生成示例命令、头信息、代码片段、日志、PR/提交内容或任何其他内容时,仅通过变量名引用凭证()——切勿使用
$PORTALY_API_KEY等字面量值。优先使用pcs_live_...或MCP的scripts/report.mjs工具,而非手动编写包含密钥的vibe_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 vs CommonJS)一致的代码。
- 未找到集成则停止。告知用户项目似乎不包含Portaly支付集成,并询问是否要使用设置集成。
portaly-payment - 上报API为可选。未经用户同意,请勿调用健康检查上报API。如果API返回404,静默跳过并在本地展示结果。
- DEP检查需要package.json。如果不存在,跳过DEP检查并标记为
package.json。[SKIP] - Windows编码。在Windows上,运行包含非ASCII文本的API调用前,执行。
chcp 65001
Resources
资源
- Use for the full checklist item definitions, severity levels, pass/fail criteria, and the report API contract.
references/health-check-contract.md - Use for detailed descriptions of known bugs found in real integrations, with wrong vs correct implementations and detection methods. Load this when a user picks
references/common-pitfalls.md(explain more) in the Interactive Fix Workflow.[?] - Use for user-facing plain-language copy of all 26 checks: plain title, why it matters, affects, doesn't affect. Load during Layer 1 summary rendering and during each Interactive Fix Workflow item. Do not paraphrase on the fly — keep the canonical phrasing consistent across summary and per-item views.
references/fix-explanations.md - Use for fully automated CI/CD scanning — runs all 26 checks, prints a formatted report, and POSTs results to portaly.ai. Accepts
scripts/report.mjsfor CI exit code control.--fail-on critical - Canonical implementation of the 0–100 health score formula. Imported by
scripts/computeHealthScore.mjsand mirrored by the Vibe dashboard so the skill terminal and the dashboard always show the same number.report.mjs - Use for automated signature sort pattern verification across project files. Called internally by
scripts/check_signature_sort.mjs.report.mjs - Use for automated subscription ID lifecycle tracing. Called internally by
scripts/check_subscription_lifecycle.mjs.report.mjs - Use when the user wants to set up GitHub Actions, pre-push hooks, or npm scripts for automated scanning.
references/ci-setup-guide.md - Cross-reference: Canonical Portaly callback signature implementation. Use as the reference for what correct looks like.
../portaly-payment/scripts/sign_callback.mjs - Cross-reference: Authoritative API contract. Use for callback payload fields, subscription lifecycle endpoints, and the
../portaly-payment/references/api-contract.mdcontract.subscriptionId === sessionId
- 用于获取完整检查项定义、严重程度、通过/失败标准,以及上报API协议。
references/health-check-contract.md - 用于获取真实集成中发现的已知Bug的详细说明,包括错误与正确实现及检测方法。当用户在交互式修复流程中选择
references/common-pitfalls.md(了解更多)时加载此文件。[?] - 用于获取所有26项检查的用户可见平实语言文案:平实标题、重要性说明、影响范围、非影响范围。在第一层总结渲染和每个交互式修复流程项中加载。请勿即兴改写——保持总结和逐项视图中的标准表述一致。
references/fix-explanations.md - 用于完全自动化的CI/CD扫描——执行全部26项检查,打印格式化报告,并将结果POST到portaly.ai。支持
scripts/report.mjs参数控制CI退出码。--fail-on critical - 0–100健康分数公式的标准实现。被
scripts/computeHealthScore.mjs导入,并与Vibe仪表板同步,确保技能终端和仪表板始终显示相同分数。report.mjs - 用于自动化验证项目文件中的签名排序模式。被
scripts/check_signature_sort.mjs内部调用。report.mjs - 用于自动化追踪订阅ID生命周期。被
scripts/check_subscription_lifecycle.mjs内部调用。report.mjs - 当用户想要设置GitHub Actions、预推送钩子或npm脚本进行自动扫描时使用。
references/ci-setup-guide.md - 交叉参考:Portaly回调签名的标准实现。用作正确实现的参考。
../portaly-payment/scripts/sign_callback.mjs - 交叉参考:权威API协议。用于获取回调负载字段、订阅生命周期端点,以及
../portaly-payment/references/api-contract.md协议。subscriptionId === sessionId