Docs/Skills & MCP tools

flowrail-verify

live

On every write Claude makes, this skill checks the new file against the active review's threats. If something matches, the write is denied and Claude is handed a structured fix.

01

When it runs

On every Write, Edit, and MultiEdit. The check is folded into the same tool call Claude already makes, so you don't see it as a separate step.

What you see in Claude Codev0.4.2
↳ writing src/auth/reset.ts…
  flowrail-verify  · deny
    ✗ no-secrets-in-code   token compared with == at line 22
    suggested fix          use timing-safe equal

↳ retrying with the fix…
  flowrail-verify  · allow
  ✓ committed
02

Nine guardrails today

no-secrets-in-code: catches what Layer 1 can't (JWT shapes, connection strings, env vars accidentally inlined). Suppresses placeholders, test fixtures, sk_test_* keys.

agentic-no-scope-escalation: blocks writes outside the feature's declared surface area, against the active review's spec.

agentic-no-system-data-in-shared-content: blocks env-var contents, file contents, and infra metadata from leaking into anything network-facing.

no-destructive-infra-operations: blocks writes that encode destructive infrastructure operations.

app-security-authz: flags application-level authorization weaknesses in the new content.

no-broken-access-control: flags request-time IDOR/BOLA patterns and fail-open authorization in the new content.

no-csv-formula-injection: blocks spreadsheet formula injection (CWE-1236) in generated CSV and export content.

no-unsafe-file-upload: flags unrestricted file-upload handling (CWE-434) in the new content.

no-unvalidated-outbound-request: flags SSRF-shaped outbound requests built from unvalidated input (CWE-918).

All nine run on every verification; per-threat-category selection arrives in v1.

MCP toolv0.4.2
flowrail_verify_code
Requestv0.4.2
{
  "design_review_id": "dr_7f3a9e2c",
  "file_path":        "src/auth/reset.ts",
  "file_content":     "import express from \"express\"; ...",
  "guardrails": [
    "no-secrets-in-code",
    "agentic-no-scope-escalation",
    "agentic-no-system-data-in-shared-content",
    "no-destructive-infra-operations",
    "app-security-authz",
    "no-broken-access-control",
    "no-csv-formula-injection",
    "no-unsafe-file-upload",
    "no-unvalidated-outbound-request"
  ]
}
Responsev0.4.2
{
  "decision": "deny",
  "verdicts": [
    {
      "guardrail": "no-secrets-in-code",
      "verdict":   "fail",
      "summary":   "Token compared with == at line 22"
    }
  ],
  "additional_context": "Use timing-safe equal..."
}

When verify denies, Claude almost always patches its own write and retries on the next pass. You see the cycle as a single noisy tool call, not a manual approval gate. Server-side, every call emits verification_completed; file content is hashed before storage.