Skip to content
Work

Developer tool · Static analysis

Patchwork

Detects when a Stripe API change affects a repository, proves the exact usages with the TypeScript compiler, rewrites them only where the fix can be proven safe, and verifies the patch in a sandbox before opening a pull request.

Analysis
TypeScript Compiler APIStripe usages proven against a trusted stub
Verification
E2B sandboxInstall, typecheck and tests, with no secrets
Architecture
Fastify, PostgreSQL, Next.jsGitHub App, leased job queue; not hosted
Benchmark
73 cases, gated in CIFails on any false “not affected”; 45 test files
Patchwork impact report for HamidZ11/stripe-basil-fixture at commit d2b1ca5: the Invoice.subscription removal is marked Affected with two confirmed usages in two files and a prepared fix to review, beside a list of four tracked changes, three affected and one uncertain.
Impact report for one repository at one exact commit: each Stripe change gets its own verdict, the confirmed usages behind it and the next step.

01

The problem

Stripe ships breaking API changes in dated versions. A changelog says what changed, but not whether a particular codebase uses the changed field, method or value. Searching for a property name finds strings, comments and unrelated objects as readily as real usages.

Patchwork answers the narrower question that matters to a team: does this change affect this repository, at this commit, and exactly where? When the answer is yes and a safe rewrite exists, it prepares the fix, proves it builds and tests in isolation, and only then opens a pull request. It never merges and never deploys.

02

Proving impact

Patchwork snapshots the default branch at an exact SHA and resolves the stripe-node version per workspace from package-lock.json or pnpm-lock.yaml. A cheap text search only nominates candidate files; it never decides anything. Each candidate is then compiled in a small in-memory TypeScript Program alongside a hand-written Stripe type stub, and the TypeChecker decides whether a reference really resolves to the changed Stripe symbol.

Compiling against a trusted stub instead of the installed SDK means Patchwork never has to run npm install on code it does not trust just to analyse it.

Verdicts are deliberately asymmetric
Affected requires positive evidence. Not affected requires explicit negative proof: an applicable SDK version, full coverage of the files, and zero matches. Anything unresolved, such as an any-typed client, an unknown SDK version or a file that failed to load, becomes Uncertain rather than a confident guess in either direction.
Applicability before matching
A usage only counts if the workspace is on an affected SDK major or pins an affected API version. Conflicting version evidence makes applicability unknown, which also resolves to Uncertain.
A benchmark that gates CI
73 cases (44 control, 26 realistic, 3 taken from real public repositories) run inside the test suite. The safety gate fails the build on a single false Not affected or any unsafe certainty.
benchmark cases in CI
73
benchmark cases in CI
false “not affected” allowed by the gate
0
false “not affected” allowed by the gate
Stripe change rules encoded
4
Stripe change rules encoded
test files across API, worker and web
45
test files across API, worker and web
Patchwork repositories overview: two repositories watched for Stripe API changes, stripe-basil-fixture needing attention with confirmed usages across three of four tracked changes and one uncertain, and trading-journal clear.
Every watched repository against every tracked Stripe change: one needs attention, one is clear.

03

Fixing only what is provably safe

Remediation is deterministic, not generated by a model. The current recipe rewrites invoice.subscription to invoice.parent?.subscription_details?.subscription ?? null; the recipe registry records why the other three rules have no automatic fix yet.

After rewriting, the same compiler engine re-checks the result: the source still parses, the old pattern is gone and the replacement is present. If any single finding cannot be rewritten safely, the whole attempt is refused and the reason is shown, for example destructuring, optional chaining, a write position, an ambiguous access, a forbidden path such as a lockfile or .github/, or an oversized diff.

Code impact listing invoice.subscription at invoiceService.ts line 15 and subscriptionService.ts line 18, Stripe's migration note, and the generated candidate patch replacing it with invoice.parent?.subscription_details?.subscription ?? null in both files.
Each confirmed usage by file and line, Stripe’s migration note, then the deterministic rewrite for both files. Where no safe rewrite exists, Patchwork refuses instead of guessing.

04

Verification and trust boundaries

  • Web

    Next.js · TypeScript

    Repositories, impact reports, findings, patches, verification and pull request state.

  • API

    Fastify · PostgreSQL

    GitHub App integration, analysis and patch generation, and the only place jobs are enqueued.

  • Analysis engine

    TypeScript Compiler API

    In-memory programs against a trusted type stub; tri-state verdicts with file and line findings.

  • Worker

    E2B · GitHub App

    Claims verification and pull request jobs from a Postgres queue, runs the sandbox, publishes branches.

Repository code never runs in Patchwork’s processes
The API and worker only read and parse text. Install, typecheck and tests run in an E2B sandbox built from a fixed template, whose only environment is CI=1 and NODE_ENV=test: no GitHub token, database credentials or Patchwork secrets. Install traffic is limited to the default registries, then the network switches to deny-all.
A Postgres queue with leases, not silent retries
Jobs are claimed with FOR UPDATE SKIP LOCKED and a renewed 20-minute lease. An expired lease is recorded as an infrastructure error rather than retried. Duplicate verification runs are blocked, and an existing branch is reconciled, never overwritten.
Pull requests are gated twice
Both the API and the worker require a generated patch, a passed verification, a verified diff whose hash matches the current diff, and no forbidden paths. The worker also refuses if the default branch has moved since analysis. The PR body lists only the checks that actually ran.
AI explains; it never decides
An optional explanation layer summarises established verdicts in plain English. It receives server-built evidence, never source code, returns schema-checked output, and writes to its own table, so it cannot change a verdict, a safety decision or a verification result.
AI explanation of the Issuing Authorization 'expired' status change, with In plain English, Why it matters here and Next step sections, supporting evidence showing no automatic fix, and a follow-up question about which files to change answered from Patchwork's evidence.
A plain-English explanation of one verdict, and a follow-up question answered only from the evidence Patchwork already established. The deterministic verdict stays the source of truth.

05

Limits

  • Four hand-encoded Stripe rules and one automatic fix recipe. GitHub, TypeScript and stripe-node only, one repository at a time, with analysis triggered by the user.
  • Alias resolution is same-file and there is no interprocedural analysis, so a Stripe client imported from another file is reported as Uncertain rather than guessed.
  • One documented false-negative path remains: data passed into a call from another file can slip past the argument filter.
  • Verification can only run the typecheck and test scripts a repository defines; a repository without them gets a weaker check.
  • Not hosted: running it needs the GitHub App, PostgreSQL, the API, the worker and an E2B key.