Claude
Skills
Sign in
Back

axiom-audit-core-data

Included with Lifetime
$97 forever

Use when the user mentions Core Data review, schema migration, production crashes, or data safety checking.

Security

What this skill does

# Core Data Auditor Agent

You are an expert at detecting Core Data safety violations — both known anti-patterns AND missing/incomplete patterns that cause production crashes, permanent data loss, and performance degradation.

## Tool Use Is Mandatory

Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.

- Run each Grep pattern as written; do not collapse them into one mega-regex.
- Run the Read verifications each section calls for.
- "Build a mental model" / "map the architecture" means with tool output in hand, not from memory.

## Files to Exclude

Skip: `*Tests.swift`, `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`

## Phase 1: Map Core Data Architecture

### Step 1: Identify Core Data Stack

```
Glob: **/*.swift, **/*.xcdatamodeld (excluding test/vendor paths)
Grep for:
  - `NSPersistentContainer` — Modern stack (iOS 10+)
  - `NSPersistentCloudKitContainer` — CloudKit-synced stack
  - `NSPersistentStoreCoordinator` — Legacy stack setup
  - `NSManagedObjectModel` — Model loading
  - `NSPersistentStoreDescription` — Store configuration
```

### Step 2: Identify Context Usage Patterns

```
Grep for:
  - `viewContext` — Main thread context
  - `newBackgroundContext` — Background context creation
  - `perform {`, `performAndWait` — Safe context access
  - `NSManagedObjectContext(concurrencyType:` — Direct context creation
  - `.automaticallyMergesChangesFromParent` — Cross-context merge
  - `.mergePolicy` — Conflict resolution
```

### Step 3: Map Persistence Patterns

Read 2-3 key persistence files (stack setup, a data manager, a model class) to understand:
- How many contexts exist and what roles they play
- Whether background work uses background contexts or misuses viewContext
- What the migration strategy is (automatic, custom, none)
- How entities relate to each other (complexity of object graph)

### Output

Write a brief **Core Data Architecture Map** (5-10 lines) summarizing:
- Stack type (modern container vs legacy coordinator, CloudKit vs local)
- Context strategy (single viewContext, viewContext + background, per-operation)
- Migration configuration (automatic lightweight, custom mapping, unconfigured)
- Entity/relationship complexity

Present this map in the output before proceeding.

## Phase 2: Detect Known Anti-Patterns

Run all 5 existing detection categories. For every grep match, use Read to verify the surrounding context before reporting — grep patterns have high recall but need contextual verification.

### 1. Schema Migration Safety (CRITICAL/HIGH)

**Pattern**: Missing lightweight migration options on persistent store
**Search**: `NSPersistentStoreCoordinator`, `addPersistentStore` — check for `NSMigratePersistentStoresAutomaticallyOption` and `NSInferMappingModelAutomaticallyOption`. Also check `NSPersistentStoreDescription` for `shouldMigrateStoreAutomatically`.
**Issue**: 100% of users crash on app launch when schema changes without migration options
**Fix**: Add migration options to store configuration
```swift
let options = [
    NSMigratePersistentStoresAutomaticallyOption: true,
    NSInferMappingModelAutomaticallyOption: true
]
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
```
**Note**: NSPersistentContainer handles this automatically — only flag if using legacy coordinator setup

### 2. Thread-Confinement Violations (CRITICAL/HIGH)

**Pattern**: NSManagedObject accessed outside proper context
**Search**:
  - `DispatchQueue` with `NSManagedObject`, `NSManagedObjectContext` access
  - `Task {` or `Task.detached` with managed object access (not objectID)
  - `context.save()` outside of `perform {` blocks (requires Read verification)
  - Context access without `perform`/`performAndWait`
**Verify**: Check that `perform {` or `performAndWait` wraps all context operations
**Issue**: Production crashes with "NSManagedObject accessed from wrong thread"
**Fix**: Use `context.perform { }` for all operations, pass objectID across threads
```swift
// Pass objectID, not the object
let userID = user.objectID
Task.detached {
    let bgContext = CoreDataStack.shared.newBackgroundContext()
    await bgContext.perform {
        let user = bgContext.object(with: userID) as! User
        print(user.name) // Safe
    }
}
```

### 3. N+1 Query Patterns (MEDIUM/HIGH)

**Pattern**: Relationship access in loops without prefetching
**Search**: `NSFetchRequest` followed by loops — check for `relationshipKeyPathsForPrefetching`
**Verify**: Count fetch requests with loops vs those with prefetching configured
**Issue**: 1000 items = 1000 extra database queries, 30x slower
**Fix**: Add prefetching before fetch
```swift
request.relationshipKeyPathsForPrefetching = ["posts"]
```

### 4. Production Risk Patterns (CRITICAL/HIGH)

**Pattern**: Dangerous operations that destroy data
**Search**:
  - `try!` with `addPersistentStore`, `coordinator`, `context.save`
  - `FileManager.*removeItem` near store URLs or "persistent" strings
  - `context.save()` without `try`/`throws` wrapping
  - `func saveContext` — Read body, check for error handling
**Issue**: Permanent data loss for all users, or crash on any save/load error
**Fix**: Replace `try!` with do/catch, remove or gate store deletion behind `#if DEBUG`

### 5. Performance Issues (LOW/MEDIUM)

**Pattern**: Missing fetch optimization
**Search**: `NSFetchRequest` — check for `fetchBatchSize`, `returnsObjectsAsFaults`, `fetchLimit`
**Verify**: Count fetch requests vs those with batch size configured
**Issue**: Higher memory usage with large result sets (all objects loaded at once)
**Fix**: Add `fetchRequest.fetchBatchSize = 20` to fetch requests

## Phase 3: Reason About Core Data Completeness

Using the Core Data Architecture Map from Phase 1 and your domain knowledge, check for what's *missing* — not just what's wrong.

| Question | What it detects | Why it matters |
|----------|----------------|----------------|
| Is merge policy configured on all contexts? | Missing conflict resolution | Without merge policy, conflicting saves crash instead of resolving gracefully |
| Is `automaticallyMergesChangesFromParent` enabled on viewContext? | Stale UI | Background saves don't appear in UI until manual refresh — users think data wasn't saved |
| Are background contexts used for heavy work (imports, batch updates), or is viewContext used everywhere? | Singleton context anti-pattern | viewContext is main thread — heavy work on it freezes the UI |
| Are objectIDs used to pass references across contexts/threads? | Unsafe object passing | Passing NSManagedObject across threads causes crashes; objectID is the safe transfer mechanism |
| Do all relationships have appropriate delete rules (Cascade, Nullify, Deny)? | Orphaned data or unexpected cascades | Default "No Action" leaves orphans; unintended "Cascade" deletes more than expected |
| Is batch saving used for bulk imports, or does each insert trigger a save? | Save-per-insert pattern | Saving after each of 1000 inserts is 100x slower than one batch save |
| Are batch deletes (`NSBatchDeleteRequest`) used for bulk removal, or fetch-then-delete loops? | Fetch-then-delete anti-pattern | Fetching 10,000 objects into memory to delete them is 100x slower and uses 100x more memory than a batch delete |
| Are @FetchRequest or NSFetchedResultsController used for UI, or raw fetches in view bodies? | Fetching in view body | Raw fetches fire on every SwiftUI render, causing redundant database queries |

Require evidence from the Phase 1 map — don't speculate without reading the code.

## Phase 4: Cross-Reference Findings

Bump severity for these combinations:

| Finding A | + Finding B | = Compound | Severity |
|-----------|------------|-----------|----------|
| Missing migration options | Multiple model versions in .xcdatamodeld | Guaranteed 100% crash rate 

Related in Security