consent-flow
Generates GDPR/CCPA/DPDP privacy consent flows with granular category preferences, consent state persistence, audit logging, and ATT (App Tracking Transparency) integration. Use when user needs privacy consent UI, cookie/tracking consent, or compliance management.
Best use case
consent-flow is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Generates GDPR/CCPA/DPDP privacy consent flows with granular category preferences, consent state persistence, audit logging, and ATT (App Tracking Transparency) integration. Use when user needs privacy consent UI, cookie/tracking consent, or compliance management.
Teams using consent-flow should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/consent-flow/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How consent-flow Compares
| Feature / Agent | consent-flow | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Generates GDPR/CCPA/DPDP privacy consent flows with granular category preferences, consent state persistence, audit logging, and ATT (App Tracking Transparency) integration. Use when user needs privacy consent UI, cookie/tracking consent, or compliance management.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Consent Flow Generator
Generate a production privacy consent system with granular category-based consent, persistent state management, a consent banner and preferences UI, audit logging for compliance, and App Tracking Transparency integration.
## When This Skill Activates
Use this skill when the user:
- Asks about "privacy consent" or "consent management"
- Mentions "GDPR consent" or "GDPR compliance"
- Wants "cookie consent" or "tracking consent"
- Mentions "ATT prompt" or "App Tracking Transparency"
- Asks for "privacy preferences" or "consent preferences"
- Mentions "CCPA compliance" or "DPDP compliance"
- Wants to "manage user consent" or "consent banner"
- Asks about "consent audit log" or "consent records"
## Pre-Generation Checks
### 1. Project Context Detection
- [ ] Check Swift version (requires Swift 5.9+)
- [ ] Check deployment target (iOS 16+ / macOS 13+)
- [ ] Check for @Observable support (iOS 17+ / macOS 14+)
- [ ] Identify source file locations
### 2. Conflict Detection
Search for existing consent or privacy code:
```
Glob: **/*Consent*.swift, **/*Privacy*.swift, **/*Tracking*.swift, **/*GDPR*.swift
Grep: "ATTrackingManager" or "ConsentManager" or "trackingAuthorizationStatus"
```
If third-party library found (OneTrust, Usercentrics, CookieBot):
- Ask if user wants to replace or keep it
- If keeping, don't generate — advise on integration best practices instead
### 3. ATT Framework Availability
Check for App Tracking Transparency framework:
```
Grep: "AppTrackingTransparency" in project files
Grep: "NSUserTrackingUsageDescription" in Info.plist
```
If `NSUserTrackingUsageDescription` is missing from Info.plist, warn the user that ATT requires this key and offer to add it.
### 4. Platform Detection
Determine if generating for iOS (primary ATT target) or macOS (ATT not applicable) or both.
## Configuration Questions
Ask user via AskUserQuestion:
1. **Target regulations?**
- GDPR only (EU — opt-in model)
- CCPA only (California — opt-out model)
- DPDP only (India — consent-based)
- All regulations (recommended for global apps)
2. **Consent categories?** (multi-select)
- Essential (always on, cannot be disabled)
- Analytics (usage tracking, crash reporting)
- Marketing (advertising, attribution)
- Personalization (recommendations, content tailoring)
- Functional (preferences, saved settings beyond essential)
3. **Include ATT integration?**
- Yes — request ATT permission before any tracking (recommended for iOS)
- No — handle consent without ATT (macOS, or no IDFA usage)
4. **Consent UI style?**
- Bottom banner with manage preferences (recommended)
- Full-screen consent view (for first launch)
- Settings-embedded (preferences in app settings, no banner)
- Banner + Settings (banner on first launch, preferences in settings)
## Generation Process
### Step 1: Read Templates
Read `templates.md` for production Swift code.
Read `patterns.md` for compliance rules, regulation differences, and UX guidance.
### Step 2: Create Core Files
Generate these files:
1. `ConsentCategory.swift` — Enum of consent categories with metadata
2. `ConsentDecision.swift` — Per-category consent state with timestamp
3. `ConsentManager.swift` — @Observable manager with persistence and ATT integration
4. `ConsentAuditLog.swift` — Compliance audit trail with JSON export
### Step 3: Create UI Files
5. `ConsentBannerView.swift` — Animated slide-up consent banner
6. `ConsentPreferencesView.swift` — Detailed toggle list for each category
### Step 4: Create Optional Files
Based on configuration:
- `ConsentRegulationConfig.swift` — If multiple regulations selected
- `ConsentATTBridge.swift` — If ATT integration selected (extracted for testability)
### Step 5: Determine File Location
Check project structure:
- If `Sources/` exists → `Sources/Consent/`
- If `App/` exists → `App/Consent/`
- Otherwise → `Consent/`
## Output Format
After generation, provide:
### Files Created
```
Consent/
├── ConsentCategory.swift # Consent category enum with metadata
├── ConsentDecision.swift # Per-category decision with timestamp
├── ConsentManager.swift # @Observable manager with persistence
├── ConsentAuditLog.swift # Compliance audit trail
├── ConsentBannerView.swift # Animated consent banner
├── ConsentPreferencesView.swift # Granular preferences UI
├── ConsentRegulationConfig.swift # Multi-regulation rules (optional)
└── ConsentATTBridge.swift # ATT integration bridge (optional)
```
### Integration Steps
**Show consent on first launch:**
```swift
@main
struct MyApp: App {
@State private var consentManager = ConsentManager()
var body: some Scene {
WindowGroup {
ContentView()
.environment(consentManager)
.overlay(alignment: .bottom) {
if consentManager.needsConsent {
ConsentBannerView()
.environment(consentManager)
.transition(.move(edge: .bottom).combined(with: .opacity))
}
}
.animation(.easeInOut(duration: 0.3), value: consentManager.needsConsent)
}
}
}
```
**Check consent before tracking:**
```swift
func trackEvent(_ event: AnalyticsEvent) {
guard consentManager.hasConsent(for: .analytics) else { return }
analyticsService.track(event)
}
func showPersonalizedAd() {
guard consentManager.hasConsent(for: .marketing) else {
showGenericAd()
return
}
adService.showPersonalized()
}
```
**Open preferences from settings:**
```swift
NavigationLink("Privacy Preferences") {
ConsentPreferencesView()
.environment(consentManager)
}
```
**Export audit log for data requests:**
```swift
func handleDataRequest() async throws -> Data {
let auditLog = ConsentAuditLog.shared
return try auditLog.exportJSON()
}
```
### Testing
```swift
@Test
func consentGrantedPersistsAcrossLaunches() async {
let defaults = UserDefaults(suiteName: "test")!
defaults.removePersistentDomain(forName: "test")
let manager = ConsentManager(defaults: defaults)
manager.updateConsent(for: .analytics, granted: true)
let manager2 = ConsentManager(defaults: defaults)
#expect(manager2.hasConsent(for: .analytics) == true)
}
@Test
func essentialConsentCannotBeRevoked() {
let manager = ConsentManager()
manager.updateConsent(for: .essential, granted: false)
#expect(manager.hasConsent(for: .essential) == true) // Always granted
}
@Test
func auditLogRecordsDecisions() {
let log = ConsentAuditLog(directory: tempDirectory)
log.record(category: .analytics, granted: true, regulation: .gdpr)
let entries = log.allEntries()
#expect(entries.count == 1)
#expect(entries[0].category == .analytics)
#expect(entries[0].granted == true)
}
@Test
func denyAllRevokesNonEssentialCategories() {
let manager = ConsentManager()
manager.grantAll()
manager.denyAllNonEssential()
#expect(manager.hasConsent(for: .essential) == true)
#expect(manager.hasConsent(for: .analytics) == false)
#expect(manager.hasConsent(for: .marketing) == false)
}
```
## Common Patterns
### Show Consent on First Launch
```swift
.onAppear {
if consentManager.needsConsent {
// Banner auto-shows via overlay
}
}
```
### Update Preferences Later
```swift
Button("Privacy Settings") {
showPreferences = true
}
.sheet(isPresented: $showPreferences) {
ConsentPreferencesView()
.environment(consentManager)
}
```
### Check Consent Before Any Tracking Call
```swift
extension ConsentManager {
func executeIfConsented(
category: ConsentCategory,
action: () -> Void
) {
guard hasConsent(for: category) else { return }
action()
}
}
```
### Export Audit Log for Data Subject Requests
```swift
let jsonData = try consentManager.auditLog.exportJSON()
// Attach to email or upload to compliance endpoint
```
## Gotchas
### ATT Must Be Requested Before Any Tracking
Apple rejects apps that access IDFA before calling `ATTrackingManager.requestTrackingAuthorization`. Always request ATT first, then enable tracking SDKs based on the result.
### GDPR Requires Opt-In (Not Opt-Out)
Under GDPR, all non-essential tracking requires explicit opt-in consent. Pre-checked boxes or implied consent are not valid. The default state for all non-essential categories must be `.notDetermined`, not `.granted`.
### Consent Must Be As Easy to Withdraw As to Grant
GDPR Article 7(3): "It shall be as easy to withdraw as to give consent." If consent is granted with one tap on a banner, it must be revocable with equal ease — not buried 5 screens deep in settings.
### Different Regulations Have Different Age Thresholds
- GDPR: 16 years (member states can lower to 13)
- CCPA: 16 years for sale of data, 13 for minors
- DPDP: 18 years (parental consent required below)
If your app serves minors, you need age verification before consent collection.
### Don't Block the UI on ATT
`ATTrackingManager.requestTrackingAuthorization` is async and shows a system dialog. Never call it during app launch or in a way that blocks the main UI. Show your own consent banner first, then request ATT as a secondary step.
### Consent State Must Survive App Reinstall (GDPR)
For GDPR compliance, consider syncing consent state to a server. UserDefaults is deleted on app uninstall. If a user reinstalls, you must re-request consent — never assume prior consent.
## References
- **templates.md** — All production Swift templates for consent flow
- **patterns.md** — Regulation comparison, ATT details, UX best practices, anti-patterns
- Related: `generators/permission-priming` — Pre-permission UI patterns (ATT priming)
- Related: `generators/analytics-setup` — Analytics that respects consent state
- Related: `generators/settings-screen` — Embedding consent preferences in settingsRelated Skills
auth-flow
Generates authentication infrastructure with Sign in with Apple, biometrics, and Keychain storage. Use when user wants to add authentication, login, or Sign in with Apple.
watchOS
watchOS development guidance including SwiftUI for Watch, Watch Connectivity, complications, and watch-specific UI patterns. Use for watchOS code review, best practices, or Watch app development.
visionos-widgets
visionOS widget patterns including mounting styles, glass/paper textures, proximity-aware layouts, and spatial widget families. Use when creating or adapting widgets for visionOS.
test-data-factory
Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.
test-contract
Generate protocol/interface test suites that any implementation must pass. Define the contract once, test every implementation. Use when designing protocols or swapping implementations.
tdd-refactor-guard
Pre-refactor safety checklist. Verifies test coverage exists before AI modifies existing code. Use before asking AI to refactor anything.
tdd-feature
Red-green-refactor scaffold for building new features with TDD. Write failing tests first, then implement to pass. Use when building new features test-first.
tdd-bug-fix
Fix bugs using red-green-refactor — reproduce the bug as a failing test first, then fix it. Use when fixing bugs to ensure they never regress.
snapshot-test-setup
Set up SwiftUI visual regression testing with swift-snapshot-testing. Generates snapshot test boilerplate and CI configuration. Use for UI regression prevention.
integration-test-scaffold
Generate cross-module test harness with mock servers, in-memory stores, and test configuration. Use when testing networking + persistence + business logic together.
characterization-test-generator
Generates tests that capture current behavior of existing code before refactoring. Use when you need a safety net before AI-assisted refactoring or modifying legacy code.
testing
TDD and testing skills for iOS/macOS apps. Covers characterization tests, TDD workflows, test contracts, snapshot tests, and test infrastructure. Use for test-driven development, adding tests to existing code, or building test infrastructure.