agentleFS
SajidisrarSajidisrar/ios-claude-skills/skills/ios-api-contract-migration/SKILL.md

ios-api-contract-migration

Skill1 starsChanged 14 days agoMITView on GitHub

Adapt this iOS app to a changed backend contract — renamed or removed fields, changed types, new required parameters, a new error shape, a version bump or a breaking response change. Use when told the API has changed, when given an OpenAPI or Swagger diff, when decoding starts failing after a backend release, or when the app must support both an old and a new response shape during a rollout.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If old and new shapes are both live, do not fork the model.

    line 43
  2. Very specific:

    If both shapes must be understood, write a custom init(from:) that tries the new key then the old one, with a comment naming the date or …

    line 47
  3. Distinctive:

    Never version the model by duplicating the type.

    line 51

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Migrate an API contract change

The failure mode to avoid: patching one decode error, shipping, and discovering the next three in production. Work from the contract, not from the crash.

1. Establish the change precisely

For each affected endpoint, write down: field name before and after, type before and after, whether it is now optional or required, and whether the change is already live in each environment.

Then classify it, because the handling differs:

ChangeHandling
Field renamedUpdate the model property; check snake_case conversion still lines up
Field now optionalProperty becomes Optional; find every use and decide what absence means
Field removedRemove it and every use — do not keep a dead property "for safety"
Type changedUpdate and check every call site; add a decoding test with a real payload
New required request fieldAdd to the draft or request model; decide the default and whether the user must supply it
New enum caseEnums decoded from the wire need a fallback, or a new case ships a crash on old builds
Error shape changedUpdate APIErrorPayload and check AppError.from still produces sensible copy

2. Beware the key-conversion trap

JSONDecoder.api uses .convertFromSnakeCase and the encoder uses .convertToSnakeCase. This round-trips cleanly for ordinary camelCase, but not for trailing acronyms: localID encodes to local_id and decodes back to localId, which does not match. If a property must carry an acronym, either name it localIdentifier or declare explicit CodingKeys. Queued outbox payloads avoid the issue entirely by using the .cache coders.

Enum raw values are values, not keys, so they are never converted: they must match the wire exactly (case inProgress = "in_progress").

3. Handle a staged rollout

If old and new shapes are both live, do not fork the model. Prefer, in order:

  1. Make the new field Optional and treat absence as the old behaviour. Simple, and it deletes cleanly later.
  2. If both shapes must be understood, write a custom init(from:) that tries the new key then the old one, with a comment naming the date or release when the fallback can be deleted.

Never version the model by duplicating the type. Two nearly identical models diverge within a sprint.

4. Update in this order

  1. Wire models and domain models.
  2. Endpoints — new parameters, changed paths.
  3. Repository — anything that read a removed field.
  4. Cache compatibility. Cached JSON was written with the old shape. FileCacheStore and KeychainTokenStorage both drop unreadable data rather than failing, so a shape change is survivable — but confirm the new model really does fail to decode the old payload rather than decoding it wrongly. If a stale cache could decode into something misleading, bump the cache directory name or clear it on upgrade.
  5. Outbox compatibility. A queued payload written by the previous app version must still replay, or the user silently loses work. If a queued payload shape changes, keep the old decode path for one release.
  6. View models and views.

5. Test with real payloads

Take actual response bodies from the new API (with any personal data replaced by invented values) and use them as test fixtures. A hand-written fixture that matches your assumption proves nothing.

Cover: the new shape decodes; the old shape either decodes correctly during rollout or fails cleanly; a stale cache does not produce wrong data; a queued write from the previous version still replays.

Verification

  • Every changed endpoint has a decoding test against a realistic payload.
  • No property kept alive "just in case".
  • Key-conversion checked for any property with an acronym.
  • New enum cases have a decoding fallback, or the change is confirmed safe.
  • Cache and outbox compatibility considered explicitly, and the conclusion written in the summary.
  • Fixtures contain no real client, production or personal data.
  • Any temporary dual-shape support carries a comment saying when to remove it.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.