v0.4.4 — 8 auto-fixers, MCP server, REST API, agent loop, executed verification

Your APIs are rotting.
Catch it before production does.

Integration-rot scans your repos for deprecated third-party API usage, drafts the migration with a contract test, and opens the pull request — so a vendor sunset never becomes your 2 a.m. incident.

integration-rot check demo/sample-app
$ integration-rot check demo/sample-app

Integration-rot report for demo/sample-app
  critical=0 high=0 medium=2 low=0

  [MEDIUM  ] SendGrid: SendGrid v2 API deprecated — migrate to v3 (no sunset published) (no sunset date) [auto-fix available]
             - dependency `@sendgrid/mail` ^6.5.0 (npm, package.json)
             - app.py:28: `"https://api.sendgrid.com/api/mail.send.json",` (matches sendgrid-v2-api)
  [MEDIUM  ] Stripe: Legacy Charges API superseded by PaymentIntents (SCA-ready) (no sunset date) [auto-fix available]
             - dependency `stripe` ^8.0.0 (npm, package.json)
             - app.py:16: `charge = stripe.Charge.create(` (matches stripe-charges-api)

The problem: integration rot

Every third-party API you ship against is a liability with a timer on it. The blast radius hides across repos until a vendor flips the switch.

πŸ•΅οΈ

Deprecations hide in plain sight

Sunset notices live in changelogs nobody reads. The deprecated call sits in billing/worker.py for two years — until it starts returning 410s.

🧩

Migrations are toil, not engineering

Each vendor migration is the same shape: find every call site, rewrite args, prove the new contract. It's mechanical work that eats senior-engineer weeks.

πŸ«₯

Silent drift breaks you first

Vendors change fields and endpoints without a formal deprecation. Your integration keeps "working" while the data it returns quietly changes shape.

How it works

Four stages, one pipeline. Every transcript below is real output captured from running the tool — no mockups.

01

Scan

integration-rot scan

Inventory every third-party dependency and find hardcoded vendor API calls. Parses package.json, requirements.txt, go.mod, Gemfile and pom.xml, maps 76 SDK packages to vendors (plus 13 API hostnames), and heuristically spots vendor hostnames in source.

scan
$ integration-rot scan demo/sample-app
Dependencies found in demo/sample-app:
  npm      @sendgrid/mail ^6.5.0 [SendGrid]  (package.json)
  npm      stripe ^8.0.0 [Stripe]  (package.json)
  pypi     requests 2.28.0  (requirements.txt)
  pypi     stripe 2.56.0 [Stripe]  (requirements.txt)

Direct vendor API calls:
  [SendGrid] app.py:28: "https://api.sendgrid.com/api/mail.send.json",
02

Match & rank

integration-rot check

Cross-reference the inventory against a curated knowledge base of 17 deprecations β€” each linked to its vendor source, with dates only where the vendor published them. Risk is ranked by days-to-sunset and severity; exit code 1 on critical/high — built for CI gates and Markdown/JSON reporting.

check
$ integration-rot check demo/sample-app

Integration-rot report for demo/sample-app
  critical=0 high=0 medium=2 low=0

  [MEDIUM  ] SendGrid: SendGrid v2 API deprecated — migrate to v3 (no sunset published) (no sunset date) [auto-fix available]
             - dependency `@sendgrid/mail` ^6.5.0 (npm, package.json)
             - app.py:28: `"https://api.sendgrid.com/api/mail.send.json",` (matches sendgrid-v2-api)
  [MEDIUM  ] Stripe: Legacy Charges API superseded by PaymentIntents (SCA-ready) (no sunset date) [auto-fix available]
             - dependency `stripe` ^8.0.0 (npm, package.json)
             - app.py:16: `charge = stripe.Charge.create(` (matches stripe-charges-api)
03

Draft the fix

integration-rot fix

Generate a real unified diff plus a contract test that proves the new API contract. Eight migration drafters ship today: Stripe Charges→PaymentIntents, Twilio Authy→Verify v2, SendGrid v2→v3, Plaid /transactions/get→/transactions/sync, Slack RTM→Socket Mode, GitHub ?access_token=→Authorization header, Salesforce retired API versions→v59.0, and Mailchimp API 2.0→3.0 (migration draft — v3 operations need manual endpoint mapping).

fix
$ integration-rot fix demo/sample-app --entry stripe-charges-api --file app.py
--- a/app.py
+++ b/app.py
@@ -13,11 +13,20 @@

 def create_charge(amount_cents, currency, token, description=""):
     """Charge a card using the legacy Charges API (deprecated pattern)."""
-    charge = stripe.Charge.create(
+    # TODO(manual, required): `token` was a legacy Charges-API card token.
+    # It MUST now be a PaymentMethod ID (pm_...): convert it first β€” e.g. Stripe's
+    # Dashboard data migration tool for saved cards, or the Payment Element /
+    # Checkout for new cards. Stripe documents `payment_method` as a
+    # PaymentMethod, Card, or compatible Source ID β€” NOT a raw tok_... token.
+    # https://stripe.com/docs/api/payment_intents/create
+    # https://stripe.com/docs/payments/payment-methods/transitioning
+    charge = stripe.PaymentIntent.create(
         amount=amount_cents,
         currency=currency,
-        source=token,
+        payment_method=token,
         description=description,
+        confirm=True,
+        automatic_payment_methods={"enabled": True, "allow_redirects": "never"}
     )
     return charge

--- generated contract test: tests/test_stripe_payment_intent_contract.py ---
"""Contract test sketch ... asserts the call *shape* only β€” it does not prove
Stripe accepts the value. payment_method must be a real pm_... ID."""
Notes:
  - rewrote 1 stripe.Charge.create call(s) to stripe.PaymentIntent.create (SCA-ready)
  - `source=token` was a legacy Charges-API card token: convert it to a PaymentMethod
    (pm_...) β€” manual step, e.g. Stripe's Dashboard data migration tool β€” then pass
    the pm_... ID. See https://stripe.com/docs/payments/payment-methods/transitioning
  - verify with stripe-mock or Stripe test clocks before merging
04

Prove & propose

integration-rot verify + drift + propose

Execute the migration, don't just draft it: run the contract tests in an isolated sandbox before anything touches your repo. Catch the changes vendors don't announce: diff a pinned OpenAPI snapshot against the live spec and see changed params and fields on the endpoints you pin — or track drift over time with timestamped snapshot history. Then propose opens the PR from your already-pushed branch, with the risk finding, diff and reviewer notes attached. (It doesn't create the branch, commit, or push, and it doesn't run the contract test — verify runs tests in a sandbox; test-gating propose is on the v0.5 roadmap.)

verify + drift + propose
$ integration-rot verify ./myrepo --entry stripe-charges-api --file app.py

=== evidence: stripe-charges-api on app.py ===
Files changed in sandbox: app.py, tests/test_stripe_payment_intent_contract.py
Contract tests run: 1 (PASS)
--- pytest output ---
.                                                                        [100%]
1 passed in 0.16s
--- end pytest output ---

$ integration-rot drift --vendor stripe --spec ./stripe-spec.json

Schema drift for Stripe: Stripe: 0 endpoint(s) added, 0 removed, 1 changed

  [CHANGED] POST /v1/charges
            - request field `capture` removed
            - response field `amount` type changed: integer -> string

$ export GITHUB_TOKEN=ghp_...   # repo scope, read from env β€” never argv
$ integration-rot propose ./myrepo --entry stripe-charges-api --file app.py \
      --owner myorg --repo-name myrepo --head fix/stripe-payment-intents
Pull request opened: https://github.com/myorg/myrepo/pull/42

What you get

A complete loop from detection to merged PR — not another dashboard that just tells you you're doomed.

πŸ“š

Curated deprecation DB

17 curated deprecations across 13 vendors, each linked to its vendor source (Twitter's links a news report β€” no vendor announcement was published). Dates appear only where the vendor published them — entries without a published date say so. No invented sunsets.

🎯

Risk-ranked findings

Critical/high/medium/low by days-to-sunset and severity. Exit code 1 on serious findings — gate your CI.

πŸ”§

Migration drafters

Real unified-diff patches for 8 migrations: Stripe, Twilio Verify, SendGrid v3, Plaid sync, Slack Socket Mode, GitHub auth headers, Salesforce versions, Mailchimp v3 (draft).

πŸ§ͺ

Contract tests

Every draft ships a pytest contract test asserting the new API's parameter contract. Proof, not vibes.

πŸ”­

Schema-drift detection

Diff pinned OpenAPI snapshots against live vendor specs β€” or keep a timestamped drift history. Catches the changes nobody announced.

πŸ“¬

PR proposer

Opens a GitHub PR from your already-pushed branch, carrying the risk report, diff and reviewer notes. Draft-PR mode included. (It doesn't run the contract test — verify does.)

πŸ€–

MCP server

integration-rot mcp exposes scan, check, draft-fix, DB lookup and the fixer catalog as Model Context Protocol tools over stdio β€” stdlib only, no mcp package. Point any MCP client at it.

🌐

REST API

integration-rot serve serves a JSON API (stdlib http.server): GET /health /deprecations /fixers, POST /scan /check /fix. /fix drafts only β€” it never writes to disk.

πŸ”

Agent loop

integration-rot agent --path ./repo runs scan β†’ draft β†’ sandbox-test β†’ keep-or-revert on a temp copy of your repo. Your repo is never modified; you get a report with diffs to review. The planner is a deterministic risk-first policy β€” no LLM, no API key, works offline.

Deprecation coverage

The knowledge base today — dates only where the vendor published them. Eight ship with auto-fixers; the rest are detection-ready.

VendorEntryTitleAuto-fix
Stripestripe-charges-apiLegacy Charges API β†’ PaymentIntents (SCA-ready)fixer
Stripestripe-legacy-checkoutLegacy Checkout retireddetect
Twiliotwilio-authy-apiAuthy API end-of-life β†’ Verify v2fixer
Twiliotwilio-fax-apiProgrammable Fax deprecateddetect
Slackslack-rtm-apiRTM API deprecated β†’ Socket Mode / Events APIfixer
SendGridsendgrid-v2-apiv2 API sunset β†’ v3fixer
Plaidplaid-legacy-transactions/transactions/get β†’ /transactions/syncfixer
Twittertwitter-free-api-retirementFree API v1.1/v2 β†’ paid Basic tierdetect
Redditreddit-free-api-retirementFree API β†’ paid Data APIdetect
Googlegoogle-plus-api-shutdownGoogle+ API shutdowndetect
Googlegcm-to-fcmGoogle Cloud Messaging β†’ Firebase Cloud Messagingdetect
Googlegoogle-signin-gsigapi.auth2 β†’ Google Identity Servicesdetect
LinkedInlinkedin-api-v1-v2API v1 β†’ v2detect
Mailchimpmailchimp-api-2-retirementAPI 2.0 / Export API 1.0 β†’ API 3.0fixer
Instagraminstagram-legacy-api-shutdownLegacy API Platform shutdowndetect
GitHubgithub-api-query-authQuery-param auth β†’ Authorization headerfixer
Salesforcesalesforce-api-v21-v30Platform API v21.0–v30.0 retirementfixer

Architecture

Thirteen modules, zero runtime dependencies. The fetcher abstraction means live vendor feeds plug in without touching the analyzer.

SCANNER manifests + API-host heuristic DEPRECATIONS 17 curated entries + feed fetchers ANALYZER match + rank risk console/json/md FIXER unified diff + contract test PROPOSER GitHub PR with evidence DRIFT Β· OpenAPI diffing target repo in β†’ ranked findings β†’ patch β†’ pull request

agent Β· analyzer Β· api_server Β· cli Β· deprecations Β· fixer Β· mcp_server Β· models Β· proposer Β· scanner Β· schema_drift Β· vendor_map Β· verifier

Roadmap

v0.4.3 is the working core β€” verified, not just drafted: Windows-safe UTF-8 I/O, auto-detected test functions on every entry point, complete vendor map, honest Reddit framing. Next: deeper fixes, team workflow, vendor partnerships.

v0.4.4 β€” shipped βœ“
  • MCP server, REST API, and autonomous agent loop (deterministic planner)
  • pip install entry point: a real integration-rot command
  • Executed verification: run contract tests in an isolated sandbox
  • 8 migration fixers, 17-entry sourced deprecation DB
  • Manifest-less pattern detection; Twilio-SDK & Plaid-SDK migrations
  • Auto-detected test function on fix / verify / agent / API / MCP
v0.5 β€” deeper fixes
  • Fixers for the long tail (Twitter, Reddit, more auth migrations)
  • Multi-file migrations, not just single-file
  • Drift against observed traffic, not just specs
  • Run the contract test before proposing the PR
v0.6 β€” team workflow
  • GitHub App: install on an org, PRs on a schedule
  • Monorepo-aware scanning + SARIF output
  • Per-repo policy file (rot.toml)

Quickstart

Python β‰₯ 3.10, zero runtime dependencies. Sixty seconds to your first report.

quickstart
$ git clone https://github.com/Kayforkind/integration-rot.git
$ cd integration-rot && python -m pip install -e ".[dev]"
$ integration-rot demo          # full pipeline on the bundled sample app
$ integration-rot check /path/to/your/repo
$ integration-rot agent --path /path/to/your/repo   # autonomous fix loop on a temp copy
Get the code Read the docs

Hosted version β€” early access

The open-source CLI is yours today. We're building a hosted service that watches your repos continuously, opens PRs with proven migrations, and pages you before a deprecation becomes an incident. Join the waitlist β€” … developers already have.