DEV Community

Cover image for Inherited an Unmaintained or Vibe-Coded App? A 7-Point Takeover Check Before You Touch the Code
Omni Care
Omni Care

Posted on Edited on Originally published at care.omniai.one AI-assisted

Inherited an Unmaintained or Vibe-Coded App? A 7-Point Takeover Check Before You Touch the Code

When a developer leaves — or an AI-assisted "vibe-coded" prototype suddenly has to go to production — someone inherits a codebase they didn't write. The instinct is to start fixing things: reformat the code, upgrade the dependencies, "just clean this up a bit." That instinct is usually the expensive mistake. Before you change a single line, you need to know what you actually inherited, who really controls it, and where it will blow up under real load. The checklist below is the exact sequence I use when taking over an unknown app. Work it top to bottom — each point gates the next, and skipping ahead is how a two-week stabilisation turns into a two-month firefight.

1. Do you actually control it?

Repo access is not control. Being able to read the code tells you nothing about whether your company can keep the product alive tomorrow. Control means you hold the production hosting account, the domain and DNS, the DNS registrar, the database, the email/sending domain, and the deploy pipeline — under accounts your company owns, not a personal login belonging to the person who left. This is the single most common failure in a takeover: the code looks fine, but production runs on someone's personal Vercel/Render/Firebase project, the domain is in a founder's private registrar account, and the only admin on the database is an ex-contractor. If any of those sit in an account you don't own, getting control back is step zero and everything else waits.

Judge it by asking "if this person disappeared and changed their passwords tonight, what breaks and what can't I recover?" If the honest answer is "the site" or "the database," you don't have a code problem yet — you have an ownership emergency.

Checklist:

  • [ ] Production hosting, domain, DNS registrar, database, and email/sending domain are all under company-owned accounts with at least two admins.
  • [ ] You have removed or rotated every access grant tied to the person who left, and confirmed nothing broke — proving those grants were not load-bearing.

2. Can you build and run it from a clean machine?

Clone the repo into a completely fresh environment and follow whatever docs exist — no shortcuts, no "I'll just copy my old .env." If you cannot get a working local build in an afternoon, you have an onboarding problem before you have a code problem, and that problem will hit every future hire and every incident-response moment when someone needs to reproduce a bug fast. Vibe-coded apps are especially prone to hidden local state: an undocumented global npm package, a specific runtime version, a database seeded by hand, or a secret that only ever lived on one laptop.

The valuable output of this step is not just "it runs" — it's the written record of how you made it run. Capture every command, every missing variable, every version pin as you go. That transcript becomes the README that never existed, and it is often the first genuinely useful artefact a takeover produces.

Checklist:

  • [ ] A brand-new machine (or clean container) can go from git clone to a running local instance using only written steps.
  • [ ] Runtime versions, required services, and seed/fixture data are pinned and documented, not tribal knowledge.

3. Where do the secrets live?

API keys, access tokens, database URLs, and webhook signing secrets that are hard-coded in the repo, committed in an old .env, or living only in one person's shell history are a time bomb. In an inherited app you must assume every secret is already compromised: you don't know who has seen the repo history, who forked it, or which third-party the previous owner pasted a key into. Inventory every secret, rotate the ones that could have walked out the door, and move them into a real secret store (your host's env manager, a vault, or at minimum a locked-down manager) so they are never again committed to source.

Judge severity by blast radius: a rotated analytics key is a shrug; a leaked payment-processor secret or a database admin credential is a same-day priority. Grep the full git history, not just the current tree — secrets that were "removed" in a later commit are still sitting in the history for anyone with clone access.

Checklist:

  • [ ] Every secret is inventoried, classified by blast radius, and the high-risk ones are rotated.
  • [ ] git log/history has been scanned for committed credentials, and secrets now live in a real store rather than the repo.

4. What happens on deploy — and can you roll back?

Trace exactly one change from commit to production and write down every stage it passes through. Is there CI? Any tests that actually run? A staging step, or does main push straight to live? Most importantly: when something breaks at 2am, can you get back to the last known-good state in about 60 seconds? A takeover without a rollback path is how a routine one-line fix becomes a multi-hour outage — because the moment you touch anything, you own whatever breaks, and "I can't undo it" is the worst sentence to say during an incident.

If there is no rollback path, building one is almost always a higher-value first move than any code cleanup. An immutable previous deploy you can re-point to, or a tagged last-good release, buys you the confidence to change everything else safely.

Checklist:

  • [ ] You have traced one commit end-to-end and documented the real deploy path (CI, staging, promotion to production).
  • [ ] A tested rollback exists — you have actually reverted to a previous version in a safe environment and confirmed it works.

5. What's the blast radius of the data?

Find the database, confirm backups actually run — and, crucially, that they restore — and check whether personal or sensitive data is handled sanely. "We have backups" is meaningless until you have performed a restore into a scratch environment and seen real rows come back. Vibe-coded apps love to log everything and secure nothing: full request bodies with passwords in plaintext logs, PII in analytics events, no retention policy, and a single unencrypted production dump sitting in someone's Downloads folder.

Judge this by imagining a breach or a bad migration: what is the worst data that could leak or be destroyed, and could you prove to a customer what happened? If the app touches payments, health, or identity data, this point can outrank everything above it. Data mistakes are the ones you cannot roll back.

Checklist:

  • [ ] You have run a real backup → restore drill and confirmed the data comes back intact.
  • [ ] You know exactly what personal/sensitive data is stored and logged, and obvious leaks (plaintext secrets in logs, PII in analytics) are closed.

6. Which parts are load-bearing vs. decorative?

AI-generated and hastily built code is full of plausible-looking functions that are never called, "features" held together with copy-paste, and abstractions that wrap a single call site. If you trust the file names and folder structure, you will spend days hardening code that no user ever reaches while the one fragile path that handles every real request goes unnoticed. Map the actual request flows: instrument the running app, watch the logs under real usage, and follow the two or three journeys that actually matter (sign-up, the core action, payment) from entry point to database.

Judge each module by "what happens to a paying user if this breaks right now?" Load-bearing code earns tests and monitoring first; decorative code can be quarantined, feature-flagged off, or deleted. Deleting confidently is a superpower here — dead code is not free, it is a place bugs hide.

Checklist:

  • [ ] The two or three critical user journeys are traced end-to-end from request to database, with the load-bearing modules named.
  • [ ] Obvious dead/unreachable code is identified and either removed or clearly quarantined, so effort goes where users actually are.

7. Rescue, rebuild, or bring in a lead?

With points 1–6 answered, the decision is usually no longer a gut call — the evidence makes it for you. A small, controllable surface with recoverable data and a working rollback → rescue in place and iterate. No control, no tests, unknown data integrity, critical business dependency → contain the damage first, then rebuild the core deliberately rather than patching in the dark. Strategically important but chronically under-owned → bring in a fractional lead to stabilise ownership, deploy, and data before you try to scale features on top.

The trap at this stage is sunk cost: "we've already put six months into this" is a reason people keep pouring effort into an app that should be contained and rebuilt. Let the answers to points 1–5 — not the effort already spent — pick the path. The cheapest month is the one where you decide correctly instead of fixing symptoms.

Checklist:

  • [ ] You have written down the rescue / rebuild / bring-in-a-lead decision with the specific evidence from points 1–6 behind it.
  • [ ] The decision is driven by current control, data, and deploy risk — not by how much time has already been spent.

Score your own situation (free, no signup)

I built the full version of this into a free browser self-check — it scores your takeover risk across these seven dimensions and points you to the right next move. Nothing to install, no email required, and your answers stay in your browser:

👉 https://care.omniai.one/software-takeover/?utm_source=devto&utm_medium=referral&utm_campaign=software_takeover

If you're staring at an inherited or AI-built app right now, do the control check (point 1) first. Most "the code is a mess" emergencies are really "we don't own our own production" emergencies in disguise — and until ownership, deploy, and data are solid, cleaning the code just rearranges the risk.

Top comments (0)