claude-code-pilot 3.1.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +16 -11
- package/bin/install.js +127 -11
- package/manifest.json +20 -1
- package/package.json +4 -3
- package/src/agents/a11y-architect.md +141 -0
- package/src/agents/code-architect.md +71 -0
- package/src/agents/code-explorer.md +69 -0
- package/src/agents/code-simplifier.md +47 -0
- package/src/agents/comment-analyzer.md +45 -0
- package/src/agents/csharp-reviewer.md +101 -0
- package/src/agents/dart-build-resolver.md +201 -0
- package/src/agents/django-build-resolver.md +252 -0
- package/src/agents/django-reviewer.md +169 -0
- package/src/agents/fastapi-reviewer.md +79 -0
- package/src/agents/fsharp-reviewer.md +109 -0
- package/src/agents/pr-test-analyzer.md +45 -0
- package/src/agents/silent-failure-hunter.md +50 -0
- package/src/agents/swift-build-resolver.md +170 -0
- package/src/agents/swift-reviewer.md +116 -0
- package/src/agents/type-design-analyzer.md +41 -0
- package/src/available-rules/README.md +3 -1
- package/src/available-rules/dart/coding-style.md +159 -0
- package/src/available-rules/dart/hooks.md +66 -0
- package/src/available-rules/dart/patterns.md +261 -0
- package/src/available-rules/dart/security.md +135 -0
- package/src/available-rules/dart/testing.md +215 -0
- package/src/available-rules/web/coding-style.md +105 -0
- package/src/available-rules/web/design-quality.md +72 -0
- package/src/available-rules/web/hooks.md +129 -0
- package/src/available-rules/web/patterns.md +88 -0
- package/src/available-rules/web/performance.md +73 -0
- package/src/available-rules/web/security.md +66 -0
- package/src/available-rules/web/testing.md +64 -0
- package/src/commands/ccp/ai-integration-phase.md +36 -0
- package/src/commands/ccp/audit-fix.md +33 -0
- package/src/commands/ccp/code-review-fix.md +52 -0
- package/src/commands/ccp/cost-report.md +107 -0
- package/src/commands/ccp/eval-review.md +32 -0
- package/src/commands/ccp/extract_learnings.md +22 -0
- package/src/commands/ccp/import.md +37 -0
- package/src/commands/ccp/ingest-docs.md +42 -0
- package/src/commands/ccp/intel.md +179 -0
- package/src/commands/ccp/mvp-phase.md +45 -0
- package/src/commands/ccp/plan-prd.md +160 -0
- package/src/commands/ccp/plan-review-convergence.md +58 -0
- package/src/commands/ccp/pr-ecc.md +184 -0
- package/src/commands/ccp/scan.md +26 -0
- package/src/commands/ccp/security-scan.md +74 -0
- package/src/commands/ccp/sketch-wrap-up.md +31 -0
- package/src/commands/ccp/sketch.md +54 -0
- package/src/commands/ccp/spec-phase.md +62 -0
- package/src/commands/ccp/spike-wrap-up.md +31 -0
- package/src/commands/ccp/spike.md +51 -0
- package/src/commands/ccp/ultraplan-phase.md +33 -0
- package/src/hooks/ccp-bash-hook-dispatcher.js +96 -0
- package/src/hooks/ccp-context-monitor.js +23 -0
- package/src/hooks/ccp-doc-file-warning.js +93 -0
- package/src/hooks/ccp-pre-bash-dispatcher.js +24 -0
- package/src/hooks/ccp-read-injection-scanner.js +152 -0
- package/src/hooks/ccp-write-gateguard.js +868 -0
- package/src/hooks/kit-check-update.js +59 -7
- package/src/hooks/run-with-flags-shell.sh +1 -0
- package/src/hooks/run-with-flags.js +48 -1
- package/src/hooks/session-end.js +88 -1
- package/src/lib/hook-flags.js +14 -0
- package/src/lib/project-detect.js +0 -2
- package/src/lib/shell-substitution.js +499 -0
- package/src/pilot/references/agent-contracts.md +79 -0
- package/src/pilot/references/ai-evals.md +156 -0
- package/src/pilot/references/ai-frameworks.md +186 -0
- package/src/pilot/references/doc-conflict-engine.md +91 -0
- package/src/pilot/references/execute-mvp-tdd.md +81 -0
- package/src/pilot/references/gate-prompts.md +100 -0
- package/src/pilot/references/gates.md +70 -0
- package/src/pilot/references/mandatory-initial-read.md +2 -0
- package/src/pilot/references/mvp-concepts.md +49 -0
- package/src/pilot/references/planner-graphify-auto-update.md +67 -0
- package/src/pilot/references/planner-human-verify-mode.md +57 -0
- package/src/pilot/references/planner-mvp-mode.md +53 -0
- package/src/pilot/references/project-skills-discovery.md +19 -0
- package/src/pilot/references/revision-loop.md +97 -0
- package/src/pilot/references/skeleton-template.md +48 -0
- package/src/pilot/references/sketch-interactivity.md +41 -0
- package/src/pilot/references/sketch-theme-system.md +94 -0
- package/src/pilot/references/sketch-tooling.md +45 -0
- package/src/pilot/references/sketch-variant-patterns.md +81 -0
- package/src/pilot/references/spidr-splitting.md +69 -0
- package/src/pilot/references/thinking-models-debug.md +44 -0
- package/src/pilot/references/thinking-models-execution.md +50 -0
- package/src/pilot/references/thinking-models-planning.md +62 -0
- package/src/pilot/references/thinking-models-research.md +50 -0
- package/src/pilot/references/thinking-models-verification.md +55 -0
- package/src/pilot/references/user-story-template.md +58 -0
- package/src/pilot/references/verify-mvp-mode.md +85 -0
- package/src/pilot/references/worktree-path-safety.md +89 -0
- package/src/pilot/templates/AI-SPEC.md +246 -0
- package/src/pilot/templates/spec.md +307 -0
- package/src/pilot/workflows/ai-integration-phase.md +284 -0
- package/src/pilot/workflows/audit-fix.md +175 -0
- package/src/pilot/workflows/code-review-fix.md +497 -0
- package/src/pilot/workflows/eval-review.md +155 -0
- package/src/pilot/workflows/extract_learnings.md +242 -0
- package/src/pilot/workflows/help.md +5 -0
- package/src/pilot/workflows/import.md +246 -0
- package/src/pilot/workflows/ingest-docs.md +328 -0
- package/src/pilot/workflows/mvp-phase.md +199 -0
- package/src/pilot/workflows/plan-review-convergence.md +329 -0
- package/src/pilot/workflows/scan.md +102 -0
- package/src/pilot/workflows/sketch-wrap-up.md +285 -0
- package/src/pilot/workflows/sketch.md +360 -0
- package/src/pilot/workflows/spec-phase.md +262 -0
- package/src/pilot/workflows/spike-wrap-up.md +306 -0
- package/src/pilot/workflows/spike.md +452 -0
- package/src/pilot/workflows/ultraplan-phase.md +189 -0
- package/src/skills/accessibility/SKILL.md +146 -0
- package/src/skills/agent-architecture-audit/SKILL.md +256 -0
- package/src/skills/agent-eval/SKILL.md +145 -0
- package/src/skills/agent-harness-design/SKILL.md +73 -0
- package/src/skills/agent-introspection-debugging/SKILL.md +153 -0
- package/src/skills/android-clean-architecture/SKILL.md +339 -0
- package/src/skills/angular-developer/SKILL.md +154 -0
- package/src/skills/angular-developer/references/angular-animations.md +160 -0
- package/src/skills/angular-developer/references/angular-aria.md +410 -0
- package/src/skills/angular-developer/references/cli.md +86 -0
- package/src/skills/angular-developer/references/component-harnesses.md +59 -0
- package/src/skills/angular-developer/references/component-styling.md +91 -0
- package/src/skills/angular-developer/references/components.md +117 -0
- package/src/skills/angular-developer/references/creating-services.md +97 -0
- package/src/skills/angular-developer/references/data-resolvers.md +69 -0
- package/src/skills/angular-developer/references/define-routes.md +67 -0
- package/src/skills/angular-developer/references/defining-providers.md +72 -0
- package/src/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/src/skills/angular-developer/references/e2e-testing.md +56 -0
- package/src/skills/angular-developer/references/effects.md +83 -0
- package/src/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/src/skills/angular-developer/references/host-elements.md +80 -0
- package/src/skills/angular-developer/references/injection-context.md +63 -0
- package/src/skills/angular-developer/references/inputs.md +101 -0
- package/src/skills/angular-developer/references/linked-signal.md +59 -0
- package/src/skills/angular-developer/references/loading-strategies.md +61 -0
- package/src/skills/angular-developer/references/mcp.md +108 -0
- package/src/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/src/skills/angular-developer/references/outputs.md +86 -0
- package/src/skills/angular-developer/references/reactive-forms.md +122 -0
- package/src/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/src/skills/angular-developer/references/resource.md +77 -0
- package/src/skills/angular-developer/references/route-animations.md +56 -0
- package/src/skills/angular-developer/references/route-guards.md +52 -0
- package/src/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/src/skills/angular-developer/references/router-testing.md +87 -0
- package/src/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/src/skills/angular-developer/references/signal-forms.md +795 -0
- package/src/skills/angular-developer/references/signals-overview.md +94 -0
- package/src/skills/angular-developer/references/tailwind-css.md +69 -0
- package/src/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/src/skills/angular-developer/references/testing-fundamentals.md +65 -0
- package/src/skills/api-connector-builder/SKILL.md +120 -0
- package/src/skills/code-tour/SKILL.md +236 -0
- package/src/skills/compose-multiplatform-patterns/SKILL.md +299 -0
- package/src/skills/csharp-testing/SKILL.md +321 -0
- package/src/skills/dart-flutter-patterns/SKILL.md +563 -0
- package/src/skills/dashboard-builder/SKILL.md +108 -0
- package/src/skills/dotnet-patterns/SKILL.md +321 -0
- package/src/skills/error-handling/SKILL.md +376 -0
- package/src/skills/fastapi-patterns/SKILL.md +327 -0
- package/src/skills/flox-environments/SKILL.md +496 -0
- package/src/skills/frontend-design/SKILL.md +145 -0
- package/src/skills/frontend-slides/SKILL.md +184 -0
- package/src/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/src/skills/fsharp-testing/SKILL.md +280 -0
- package/src/skills/gateguard/SKILL.md +121 -0
- package/src/skills/github-ops/SKILL.md +144 -0
- package/src/skills/hookify-rules/SKILL.md +128 -0
- package/src/skills/ios-icon-gen/SKILL.md +157 -0
- package/src/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/src/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/src/skills/knowledge-ops/SKILL.md +154 -0
- package/src/skills/liquid-glass-design/SKILL.md +279 -0
- package/src/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/src/skills/mysql-patterns/SKILL.md +412 -0
- package/src/skills/nestjs-patterns/SKILL.md +230 -0
- package/src/skills/plan-orchestrate/SKILL.md +220 -0
- package/src/skills/prisma-patterns/SKILL.md +371 -0
- package/src/skills/production-audit/SKILL.md +206 -0
- package/src/skills/security-bounty-hunter/SKILL.md +99 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/candidate-playbook.md +49 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/report.json +35 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/scenario.json +62 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/trace.json +45 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/verifier-result.json +35 -0
- package/src/skills/swift-actor-persistence/SKILL.md +143 -0
- package/src/skills/swift-protocol-di-testing/SKILL.md +190 -0
- package/src/skills/swiftui-patterns/SKILL.md +259 -0
- package/src/skills/terminal-ops/SKILL.md +109 -0
- package/src/skills/ui-demo/SKILL.md +465 -0
- package/src/skills/vite-patterns/SKILL.md +449 -0
- package/src/skills/windows-desktop-e2e/SKILL.md +887 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: production-audit
|
|
3
|
+
description: Local-evidence production readiness audit for shipped apps, pre-launch reviews, post-merge checks, and "what breaks in prod?" questions without sending repo data to an external audit service.
|
|
4
|
+
origin: community
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Production Audit
|
|
8
|
+
|
|
9
|
+
Use this skill when the user asks whether an application is ready to ship, what
|
|
10
|
+
could break in production, or what must be fixed before a launch. This is a
|
|
11
|
+
maintainer-safe rewrite of the stale community production-audit idea: it keeps
|
|
12
|
+
the useful production-readiness lens and removes unpinned external execution and
|
|
13
|
+
third-party data sharing.
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
|
|
17
|
+
- The user asks "is this production-ready", "what would break in prod", "what
|
|
18
|
+
did we miss", "audit this repo", or "ready to ship?"
|
|
19
|
+
- A feature was merged and needs a pre-deploy or post-merge risk pass.
|
|
20
|
+
- A public launch, demo, customer rollout, or investor walkthrough is close.
|
|
21
|
+
- CI is green but the user wants production risk, not only test status.
|
|
22
|
+
- A deployed URL, release branch, PR, or current checkout is available for
|
|
23
|
+
evidence gathering.
|
|
24
|
+
|
|
25
|
+
## When Not to Use
|
|
26
|
+
|
|
27
|
+
- During active implementation when the right lens is line-level secure coding;
|
|
28
|
+
use `security-review` first.
|
|
29
|
+
- For pure libraries, templates, docs-only repos, or scaffolds unless the user
|
|
30
|
+
wants packaging/release readiness rather than application readiness.
|
|
31
|
+
- When the user asks for a formal compliance audit. This skill is engineering
|
|
32
|
+
triage, not legal, financial, medical, or regulatory certification.
|
|
33
|
+
- When the only available evidence is a product idea with no repo, deployment,
|
|
34
|
+
CI, or runtime surface.
|
|
35
|
+
|
|
36
|
+
## How It Works
|
|
37
|
+
|
|
38
|
+
Build the audit from local and user-authorized evidence. Do not run unpinned
|
|
39
|
+
remote code, upload repository contents to third-party services, or call
|
|
40
|
+
external scanners unless the user explicitly approves that specific tool and
|
|
41
|
+
data flow.
|
|
42
|
+
|
|
43
|
+
Use this order:
|
|
44
|
+
|
|
45
|
+
1. Establish the release surface.
|
|
46
|
+
2. Read recent changes and current branch state.
|
|
47
|
+
3. Inspect runtime, auth, data, payment, background-job, AI, and deployment
|
|
48
|
+
boundaries that actually exist in the repo.
|
|
49
|
+
4. Check CI, tests, migrations, environment documentation, and rollback path.
|
|
50
|
+
5. Produce a short ship/block recommendation with specific fixes.
|
|
51
|
+
|
|
52
|
+
## Evidence Checklist
|
|
53
|
+
|
|
54
|
+
Start with cheap, local signals:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
git status --short --branch
|
|
58
|
+
git log --oneline --decorate -20
|
|
59
|
+
git diff --stat origin/main...HEAD
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then inspect the project-specific surface:
|
|
63
|
+
|
|
64
|
+
- Package scripts, CI workflows, release scripts, Docker files, and deployment
|
|
65
|
+
manifests.
|
|
66
|
+
- API routes, webhooks, auth middleware, background workers, cron jobs, and
|
|
67
|
+
database migrations.
|
|
68
|
+
- Environment variable documentation and startup checks.
|
|
69
|
+
- Observability hooks, error reporting, logs, health checks, and dashboards.
|
|
70
|
+
- Rollback, seed, migration, and backfill instructions.
|
|
71
|
+
- E2E coverage for the user paths that matter most.
|
|
72
|
+
|
|
73
|
+
If a deployed URL is in scope, use browser or HTTP checks only against that URL
|
|
74
|
+
and avoid credentialed actions unless the user supplies a safe test account.
|
|
75
|
+
|
|
76
|
+
## Risk Lenses
|
|
77
|
+
|
|
78
|
+
### Security And Auth
|
|
79
|
+
|
|
80
|
+
- Are public routes, API routes, and admin routes clearly separated?
|
|
81
|
+
- Are auth and authorization enforced server-side?
|
|
82
|
+
- Are secrets kept out of client bundles, logs, example output, and checked-in
|
|
83
|
+
files?
|
|
84
|
+
- Are rate limits, CSRF protections, CORS policy, and upload validation present
|
|
85
|
+
where the app needs them?
|
|
86
|
+
- Does the AI or agent surface defend against prompt injection, tool abuse, and
|
|
87
|
+
untrusted content crossing into privileged actions?
|
|
88
|
+
|
|
89
|
+
### Data Integrity
|
|
90
|
+
|
|
91
|
+
- Do migrations run forward cleanly and have a rollback or recovery plan?
|
|
92
|
+
- Are destructive migrations, backfills, and data imports staged safely?
|
|
93
|
+
- Do database policies, grants, and service-role boundaries match the app's
|
|
94
|
+
tenancy model?
|
|
95
|
+
- Are retries idempotent for writes, jobs, and webhook handlers?
|
|
96
|
+
|
|
97
|
+
### Payments And Webhooks
|
|
98
|
+
|
|
99
|
+
- Are webhook signatures verified before parsing trusted payload fields?
|
|
100
|
+
- Is each payment, subscription, or fulfillment webhook idempotent?
|
|
101
|
+
- Are replay, duplicate delivery, and out-of-order delivery handled?
|
|
102
|
+
- Are test-mode and live-mode credentials separated?
|
|
103
|
+
|
|
104
|
+
### Operations
|
|
105
|
+
|
|
106
|
+
- Can the app start from a clean checkout using documented commands?
|
|
107
|
+
- Are required environment variables named, validated, and fail-fast?
|
|
108
|
+
- Is there a health check that proves dependencies are reachable?
|
|
109
|
+
- Are deploy, rollback, and incident-owner paths documented?
|
|
110
|
+
- Are logs useful without leaking secrets or personal data?
|
|
111
|
+
|
|
112
|
+
### User Experience
|
|
113
|
+
|
|
114
|
+
- Are the launch-critical paths covered on desktop and mobile?
|
|
115
|
+
- Are forms usable on mobile without input zoom, layout overlap, or blocked
|
|
116
|
+
submission states?
|
|
117
|
+
- Do loading, empty, error, and permission-denied states tell the user what
|
|
118
|
+
happened?
|
|
119
|
+
- Is there a support or recovery path when a critical operation fails?
|
|
120
|
+
|
|
121
|
+
## Scoring
|
|
122
|
+
|
|
123
|
+
Use scores to force prioritization, not to imply mathematical certainty.
|
|
124
|
+
|
|
125
|
+
| Band | Score | Meaning |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| Blocked | 0-49 | Do not ship until the top risks are fixed |
|
|
128
|
+
| Risky | 50-69 | Ship only behind a small rollout or internal beta |
|
|
129
|
+
| Launchable With Caveats | 70-84 | Ship if owners accept the listed risks |
|
|
130
|
+
| Strong | 85-100 | No obvious launch blockers from available evidence |
|
|
131
|
+
|
|
132
|
+
Cap the score at `69` if any of these are true:
|
|
133
|
+
|
|
134
|
+
- Authentication or authorization is missing on sensitive data.
|
|
135
|
+
- Payment or fulfillment webhooks are not idempotent.
|
|
136
|
+
- Required migrations cannot be run safely.
|
|
137
|
+
- Secrets are exposed in client bundles, logs, or committed files.
|
|
138
|
+
- There is no rollback path for a high-impact release.
|
|
139
|
+
|
|
140
|
+
Cap the score at `84` if CI is not green or the launch-critical path was not
|
|
141
|
+
tested end to end.
|
|
142
|
+
|
|
143
|
+
## Output Format
|
|
144
|
+
|
|
145
|
+
Lead with one sentence:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
Production audit: 76/100, launchable with caveats, with webhook idempotency and rollback docs as the two risks to fix before public launch.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Then list:
|
|
152
|
+
|
|
153
|
+
- `Blockers`: must-fix items before deploy.
|
|
154
|
+
- `High-value fixes`: next fixes if the user wants to improve the score.
|
|
155
|
+
- `Evidence checked`: files, commands, CI, deployed URL, or PRs inspected.
|
|
156
|
+
- `Evidence missing`: what would change confidence if provided.
|
|
157
|
+
- `Next action`: one concrete fix or verification step.
|
|
158
|
+
|
|
159
|
+
Keep strengths short. The user asked for readiness, so the useful answer is the
|
|
160
|
+
remaining risk and the next action.
|
|
161
|
+
|
|
162
|
+
## Example
|
|
163
|
+
|
|
164
|
+
User:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
is this ready to ship?
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Response:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
Production audit: 68/100, risky, because Stripe webhooks are verified but not idempotent and there is no rollback note for the pending migration.
|
|
174
|
+
|
|
175
|
+
Blockers:
|
|
176
|
+
- Add idempotency for `checkout.session.completed` before fulfilling orders.
|
|
177
|
+
- Write and test the rollback path for `20260511_add_billing_state.sql`.
|
|
178
|
+
|
|
179
|
+
High-value fixes:
|
|
180
|
+
- Add a health check that verifies database and payment-provider reachability.
|
|
181
|
+
- Add one E2E path for upgrade, webhook fulfillment, and billing-page refresh.
|
|
182
|
+
|
|
183
|
+
Evidence checked:
|
|
184
|
+
- `api/stripe/webhook.ts`
|
|
185
|
+
- `db/migrations/20260511_add_billing_state.sql`
|
|
186
|
+
- GitHub Actions run for the release branch
|
|
187
|
+
|
|
188
|
+
Next action: Want me to patch webhook idempotency first?
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Anti-Patterns
|
|
192
|
+
|
|
193
|
+
- Running `npx <package>@latest` or a remote scanner as the default audit path.
|
|
194
|
+
- Uploading source, secrets, customer data, or private topology to an external
|
|
195
|
+
audit service without explicit approval.
|
|
196
|
+
- Producing a score without naming the evidence checked.
|
|
197
|
+
- Treating green CI as production readiness.
|
|
198
|
+
- Ending with a generic "let me know what you want to do."
|
|
199
|
+
|
|
200
|
+
## See Also
|
|
201
|
+
|
|
202
|
+
- Skill: `security-review`
|
|
203
|
+
- Skill: `deployment-patterns`
|
|
204
|
+
- Skill: `e2e-testing`
|
|
205
|
+
- Skill: `tdd-workflow`
|
|
206
|
+
- Skill: `verification-loop`
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-bounty-hunter
|
|
3
|
+
description: Hunt for exploitable, bounty-worthy security issues in repositories. Focuses on remotely reachable vulnerabilities that qualify for real reports instead of noisy local-only findings.
|
|
4
|
+
origin: ECC direct-port adaptation
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Security Bounty Hunter
|
|
9
|
+
|
|
10
|
+
Use this when the goal is practical vulnerability discovery for responsible disclosure or bounty submission, not a broad best-practices review.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
- Scanning a repository for exploitable vulnerabilities
|
|
15
|
+
- Preparing a Huntr, HackerOne, or similar bounty submission
|
|
16
|
+
- Triage where the question is "does this actually pay?" rather than "is this theoretically unsafe?"
|
|
17
|
+
|
|
18
|
+
## How It Works
|
|
19
|
+
|
|
20
|
+
Bias toward remotely reachable, user-controlled attack paths and throw away patterns that platforms routinely reject as informative or out of scope.
|
|
21
|
+
|
|
22
|
+
## In-Scope Patterns
|
|
23
|
+
|
|
24
|
+
These are the kinds of issues that consistently matter:
|
|
25
|
+
|
|
26
|
+
| Pattern | CWE | Typical impact |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| SSRF through user-controlled URLs | CWE-918 | internal network access, cloud metadata theft |
|
|
29
|
+
| Auth bypass in middleware or API guards | CWE-287 | unauthorized account or data access |
|
|
30
|
+
| Remote deserialization or upload-to-RCE paths | CWE-502 | code execution |
|
|
31
|
+
| SQL injection in reachable endpoints | CWE-89 | data exfiltration, auth bypass, data destruction |
|
|
32
|
+
| Command injection in request handlers | CWE-78 | code execution |
|
|
33
|
+
| Path traversal in file-serving paths | CWE-22 | arbitrary file read or write |
|
|
34
|
+
| Auto-triggered XSS | CWE-79 | session theft, admin compromise |
|
|
35
|
+
|
|
36
|
+
## Skip These
|
|
37
|
+
|
|
38
|
+
These are usually low-signal or out of bounty scope unless the program says otherwise:
|
|
39
|
+
|
|
40
|
+
- Local-only `pickle.loads`, `torch.load`, or equivalent with no remote path
|
|
41
|
+
- `eval()` or `exec()` in CLI-only tooling
|
|
42
|
+
- `shell=True` on fully hardcoded commands
|
|
43
|
+
- Missing security headers by themselves
|
|
44
|
+
- Generic rate-limiting complaints without exploit impact
|
|
45
|
+
- Self-XSS requiring the victim to paste code manually
|
|
46
|
+
- CI/CD injection that is not part of the target program scope
|
|
47
|
+
- Demo, example, or test-only code
|
|
48
|
+
|
|
49
|
+
## Workflow
|
|
50
|
+
|
|
51
|
+
1. Check scope first: program rules, SECURITY.md, disclosure channel, and exclusions.
|
|
52
|
+
2. Find real entrypoints: HTTP handlers, uploads, background jobs, webhooks, parsers, and integration endpoints.
|
|
53
|
+
3. Run static tooling where it helps, but treat it as triage input only.
|
|
54
|
+
4. Read the real code path end to end.
|
|
55
|
+
5. Prove user control reaches a meaningful sink.
|
|
56
|
+
6. Confirm exploitability and impact with the smallest safe PoC possible.
|
|
57
|
+
7. Check for duplicates before drafting a report.
|
|
58
|
+
|
|
59
|
+
## Example Triage Loop
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
semgrep --config=auto --severity=ERROR --severity=WARNING --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then manually filter:
|
|
66
|
+
|
|
67
|
+
- drop tests, demos, fixtures, vendored code
|
|
68
|
+
- drop local-only or non-reachable paths
|
|
69
|
+
- keep only findings with a clear network or user-controlled route
|
|
70
|
+
|
|
71
|
+
## Report Structure
|
|
72
|
+
|
|
73
|
+
```markdown
|
|
74
|
+
## Description
|
|
75
|
+
[What the vulnerability is and why it matters]
|
|
76
|
+
|
|
77
|
+
## Vulnerable Code
|
|
78
|
+
[File path, line range, and a small snippet]
|
|
79
|
+
|
|
80
|
+
## Proof of Concept
|
|
81
|
+
[Minimal working request or script]
|
|
82
|
+
|
|
83
|
+
## Impact
|
|
84
|
+
[What the attacker can achieve]
|
|
85
|
+
|
|
86
|
+
## Affected Version
|
|
87
|
+
[Version, commit, or deployment target tested]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Quality Gate
|
|
91
|
+
|
|
92
|
+
Before submitting:
|
|
93
|
+
|
|
94
|
+
- The code path is reachable from a real user or network boundary
|
|
95
|
+
- The input is genuinely user-controlled
|
|
96
|
+
- The sink is meaningful and exploitable
|
|
97
|
+
- The PoC works
|
|
98
|
+
- The issue is not already covered by an advisory, CVE, or open ticket
|
|
99
|
+
- The target is actually in scope for the bounty program
|
package/src/skills/security-scan/references/agentshield-policy-exception/candidate-playbook.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# AgentShield Policy Exception Playbook
|
|
2
|
+
|
|
3
|
+
Candidate id: `sarif-backed-timeboxed-exception-review`
|
|
4
|
+
|
|
5
|
+
Use this playbook when AgentShield organization-policy output produces a
|
|
6
|
+
finding that may need remediation, a time-boxed exception, or explicit
|
|
7
|
+
enforcement.
|
|
8
|
+
|
|
9
|
+
## Accepted Path
|
|
10
|
+
|
|
11
|
+
1. Identify the AgentShield finding id, category, severity, affected file or
|
|
12
|
+
MCP/hook surface, and policy pack or organization baseline.
|
|
13
|
+
2. Retrieve scanner evidence before judgment:
|
|
14
|
+
- SARIF/code-scanning result, especially `agentshield-policy/*`
|
|
15
|
+
- JSON/HTML report evidence
|
|
16
|
+
- terminal or GitHub Action job-summary counts
|
|
17
|
+
3. Record lifecycle fields for any exception request: owner, ticket, scope,
|
|
18
|
+
expiry, rationale, and whether it is active, expiring soon, or expired.
|
|
19
|
+
4. Keep expired exceptions rejected or enforced until new evidence exists.
|
|
20
|
+
5. Decide whether immediate remediation is possible. If not, only promote a
|
|
21
|
+
narrow time-boxed exception tied to the named owner, ticket, scope, and
|
|
22
|
+
expiry.
|
|
23
|
+
6. Keep AgentShield code, policy packs, enforcement settings, release state,
|
|
24
|
+
and live security posture out of the read-only evaluator run.
|
|
25
|
+
|
|
26
|
+
## Rejected Path
|
|
27
|
+
|
|
28
|
+
Do not blanket suppress a policy category, policy pack, or organization gate
|
|
29
|
+
because a finding is inconvenient.
|
|
30
|
+
|
|
31
|
+
Do not downgrade critical/high findings without SARIF or report evidence and a
|
|
32
|
+
current owner, ticket, scope, and expiry.
|
|
33
|
+
|
|
34
|
+
Do not treat expired exceptions as active. Expired means the policy gate should
|
|
35
|
+
remain enforced until a maintainer creates a fresh, bounded exception or fixes
|
|
36
|
+
the underlying issue.
|
|
37
|
+
|
|
38
|
+
## Minimum Validation
|
|
39
|
+
|
|
40
|
+
- `npx ecc-agentshield scan --format json`
|
|
41
|
+
- AgentShield SARIF/code-scanning artifact or report evidence
|
|
42
|
+
- `npx ecc-agentshield scan --format html` when executive review evidence is
|
|
43
|
+
needed
|
|
44
|
+
- Current exception lifecycle fields: owner, ticket, scope, expiry, status
|
|
45
|
+
- `node tests/docs/evaluator-rag-prototype.test.js`
|
|
46
|
+
- `git diff --check`
|
|
47
|
+
|
|
48
|
+
Record the scanner evidence, lifecycle state, policy-pack source, and
|
|
49
|
+
remediation-versus-exception decision in the maintainer PR body or handoff.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "ecc.evaluator-rag.report.v1",
|
|
3
|
+
"scenario_id": "agentshield-policy-exception",
|
|
4
|
+
"run_id": "2026-05-12-agentshield-policy-exception-prototype",
|
|
5
|
+
"result": "prototype_passed",
|
|
6
|
+
"read_only": true,
|
|
7
|
+
"scores": {
|
|
8
|
+
"sarif_report_evidence": 0.95,
|
|
9
|
+
"exception_lifecycle": 0.93,
|
|
10
|
+
"ownership_specificity": 0.9,
|
|
11
|
+
"remediation_decision": 0.88,
|
|
12
|
+
"blanket_suppression_safety": 1
|
|
13
|
+
},
|
|
14
|
+
"findings": [
|
|
15
|
+
{
|
|
16
|
+
"id": "sarif-report-match-required",
|
|
17
|
+
"severity": "warning",
|
|
18
|
+
"summary": "AgentShield policy exceptions must name SARIF or report evidence before a remediation or exception playbook can be promoted."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "expired-exception-enforcement",
|
|
22
|
+
"severity": "warning",
|
|
23
|
+
"summary": "Expired exceptions must remain rejected or enforced; the evaluator cannot treat stale approvals as active evidence."
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "bounded-owner-fields",
|
|
27
|
+
"severity": "info",
|
|
28
|
+
"summary": "Accepted exceptions preserve owner, ticket, scope, expiry, policy-pack source, and affected surface fields."
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"recommended_next_action": {
|
|
32
|
+
"candidate_id": "sarif-backed-timeboxed-exception-review",
|
|
33
|
+
"action": "Use the promoted playbook for future AgentShield policy exception requests before changing gates, suppressing categories, or accepting security risk."
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "ecc.evaluator-rag.scenario.v1",
|
|
3
|
+
"scenario_id": "agentshield-policy-exception",
|
|
4
|
+
"title": "Gate AgentShield policy exceptions with report and SARIF evidence",
|
|
5
|
+
"mode": "read_only_prototype",
|
|
6
|
+
"objective": "Given an AgentShield organization-policy finding or proposed exception, retrieve report, SARIF, lifecycle, and ownership evidence before promoting a remediation or time-boxed exception playbook.",
|
|
7
|
+
"sources": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "repo_doc",
|
|
10
|
+
"path": "docs/ECC-2.0-GA-ROADMAP.md",
|
|
11
|
+
"purpose": "Durable record of AgentShield policy gates, SARIF output, policy packs, reports, corpus benchmark, and exception lifecycle audit evidence"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"kind": "repo_command",
|
|
15
|
+
"path": "commands/security-scan.md",
|
|
16
|
+
"purpose": "ECC command contract for running AgentShield and separating scanner facts from follow-up judgment"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "repo_skill",
|
|
20
|
+
"path": "skills/security-scan/SKILL.md",
|
|
21
|
+
"purpose": "Operator-facing AgentShield scan workflow and output-format guidance"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "external_pr_evidence",
|
|
25
|
+
"repo": "affaan-m/agentshield",
|
|
26
|
+
"prs": [
|
|
27
|
+
55,
|
|
28
|
+
56,
|
|
29
|
+
57,
|
|
30
|
+
59,
|
|
31
|
+
60,
|
|
32
|
+
62
|
|
33
|
+
],
|
|
34
|
+
"purpose": "Policy gate, SARIF, policy-pack, HTML report, corpus benchmark, and exception lifecycle implementation evidence"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"retrieval_questions": [
|
|
38
|
+
"Which AgentShield policy finding, category, severity, and affected file or MCP/hook surface triggered the request?",
|
|
39
|
+
"Is there SARIF/code-scanning evidence for an `agentshield-policy/*` result, and does it match the report finding?",
|
|
40
|
+
"Is the exception active, expiring soon, or expired?",
|
|
41
|
+
"Does the exception include owner, ticket, scope, expiry, and rationale fields?",
|
|
42
|
+
"Which policy pack or organization baseline produced the finding?",
|
|
43
|
+
"Is remediation possible now, or is a bounded exception safer than a blanket suppression?"
|
|
44
|
+
],
|
|
45
|
+
"forbidden_actions": [
|
|
46
|
+
"approving policy exceptions without SARIF or report evidence",
|
|
47
|
+
"treating expired exceptions as active",
|
|
48
|
+
"blanket-suppressing AgentShield policy packs or organization-policy gates",
|
|
49
|
+
"downgrading critical/high findings without owner, ticket, scope, and expiry",
|
|
50
|
+
"editing AgentShield code or policy files from this ECC evaluator run",
|
|
51
|
+
"publishing or enforcing new security policy from this read-only evaluator run"
|
|
52
|
+
],
|
|
53
|
+
"acceptance_gates": [
|
|
54
|
+
"SARIF or report evidence is named",
|
|
55
|
+
"finding id, category, severity, and affected surface are preserved",
|
|
56
|
+
"policy pack or organization baseline is named",
|
|
57
|
+
"owner, ticket, scope, and expiry state are recorded",
|
|
58
|
+
"expired exceptions stay rejected or enforced",
|
|
59
|
+
"remediation versus time-boxed exception decision is explicit",
|
|
60
|
+
"at least one blanket suppression candidate is rejected"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "ecc.evaluator-rag.trace.v1",
|
|
3
|
+
"scenario_id": "agentshield-policy-exception",
|
|
4
|
+
"run_id": "2026-05-12-agentshield-policy-exception-prototype",
|
|
5
|
+
"read_only": true,
|
|
6
|
+
"events": [
|
|
7
|
+
{
|
|
8
|
+
"phase": "observation",
|
|
9
|
+
"summary": "A policy finding or exception request references AgentShield organization-policy output. The evaluator records the affected finding without editing AgentShield code, policy packs, or enforcement settings.",
|
|
10
|
+
"evidence": [
|
|
11
|
+
"docs/ECC-2.0-GA-ROADMAP.md",
|
|
12
|
+
"commands/security-scan.md"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"phase": "retrieval",
|
|
17
|
+
"summary": "Retrieved SARIF/report evidence, policy-pack source, exception lifecycle state, owner, ticket, scope, expiry, and whether remediation is immediately available.",
|
|
18
|
+
"evidence": [
|
|
19
|
+
"agentshield-policy/* SARIF result",
|
|
20
|
+
"AgentShield report exception counts",
|
|
21
|
+
"skills/security-scan/SKILL.md"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"phase": "proposal",
|
|
26
|
+
"summary": "Generated two candidate playbooks: SARIF-backed time-boxed exception review, and blanket policy suppression for the affected category.",
|
|
27
|
+
"candidate_ids": [
|
|
28
|
+
"sarif-backed-timeboxed-exception-review",
|
|
29
|
+
"blanket-policy-suppression"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"phase": "verification",
|
|
34
|
+
"summary": "Accepted the evidence-backed exception review because it preserves finding details and lifecycle fields. Rejected blanket suppression because it bypasses policy gates and ignores expired exceptions.",
|
|
35
|
+
"evidence": [
|
|
36
|
+
"examples/evaluator-rag-prototype/agentshield-policy-exception/verifier-result.json"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"phase": "promotion",
|
|
41
|
+
"summary": "Promoted only the read-only AgentShield policy exception playbook. The evaluator does not modify AgentShield code, policy packs, enforcement settings, release state, or live security posture.",
|
|
42
|
+
"promoted_candidate_id": "sarif-backed-timeboxed-exception-review"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "ecc.evaluator-rag.verifier.v1",
|
|
3
|
+
"scenario_id": "agentshield-policy-exception",
|
|
4
|
+
"run_id": "2026-05-12-agentshield-policy-exception-prototype",
|
|
5
|
+
"read_only": true,
|
|
6
|
+
"candidates": [
|
|
7
|
+
{
|
|
8
|
+
"candidate_id": "sarif-backed-timeboxed-exception-review",
|
|
9
|
+
"decision": "accepted",
|
|
10
|
+
"score": 0.93,
|
|
11
|
+
"reasons": [
|
|
12
|
+
"names SARIF/code-scanning or report evidence for the AgentShield finding",
|
|
13
|
+
"preserves finding id, category, severity, affected surface, and policy-pack source",
|
|
14
|
+
"records owner, ticket, scope, expiry, and active/expiring/expired lifecycle state",
|
|
15
|
+
"rejects expired exceptions and requires remediation or a time-boxed exception",
|
|
16
|
+
"keeps AgentShield code, policy packs, enforcement settings, and release actions out of the read-only evaluator run"
|
|
17
|
+
],
|
|
18
|
+
"rollback": "Do not apply the future exception or suppression; re-run AgentShield, restore the prior organization policy, and keep the finding enforced until owner/ticket/scope/expiry evidence is current."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"candidate_id": "blanket-policy-suppression",
|
|
22
|
+
"decision": "rejected",
|
|
23
|
+
"score": 0.11,
|
|
24
|
+
"reasons": [
|
|
25
|
+
"has no SARIF or report evidence",
|
|
26
|
+
"blanket-suppresses AgentShield policy packs and organization-policy gates",
|
|
27
|
+
"treats expired exceptions as active",
|
|
28
|
+
"drops owner, ticket, scope, and expiry fields",
|
|
29
|
+
"would edit AgentShield or policy gate behavior from an ECC evaluator run"
|
|
30
|
+
],
|
|
31
|
+
"rollback": "Do not suppress the policy category; restart from scanner evidence, lifecycle state, and a bounded remediation or exception request."
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"promoted_candidate_id": "sarif-backed-timeboxed-exception-review"
|
|
35
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: swift-actor-persistence
|
|
3
|
+
description: Thread-safe data persistence in Swift using actors — in-memory cache with file-backed storage, eliminating data races by design.
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Swift Actors for Thread-Safe Persistence
|
|
8
|
+
|
|
9
|
+
Patterns for building thread-safe data persistence layers using Swift actors. Combines in-memory caching with file-backed storage, leveraging the actor model to eliminate data races at compile time.
|
|
10
|
+
|
|
11
|
+
## When to Activate
|
|
12
|
+
|
|
13
|
+
- Building a data persistence layer in Swift 5.5+
|
|
14
|
+
- Need thread-safe access to shared mutable state
|
|
15
|
+
- Want to eliminate manual synchronization (locks, DispatchQueues)
|
|
16
|
+
- Building offline-first apps with local storage
|
|
17
|
+
|
|
18
|
+
## Core Pattern
|
|
19
|
+
|
|
20
|
+
### Actor-Based Repository
|
|
21
|
+
|
|
22
|
+
The actor model guarantees serialized access — no data races, enforced by the compiler.
|
|
23
|
+
|
|
24
|
+
```swift
|
|
25
|
+
public actor LocalRepository<T: Codable & Identifiable> where T.ID == String {
|
|
26
|
+
private var cache: [String: T] = [:]
|
|
27
|
+
private let fileURL: URL
|
|
28
|
+
|
|
29
|
+
public init(directory: URL = .documentsDirectory, filename: String = "data.json") {
|
|
30
|
+
self.fileURL = directory.appendingPathComponent(filename)
|
|
31
|
+
// Synchronous load during init (actor isolation not yet active)
|
|
32
|
+
self.cache = Self.loadSynchronously(from: fileURL)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// MARK: - Public API
|
|
36
|
+
|
|
37
|
+
public func save(_ item: T) throws {
|
|
38
|
+
cache[item.id] = item
|
|
39
|
+
try persistToFile()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func delete(_ id: String) throws {
|
|
43
|
+
cache[id] = nil
|
|
44
|
+
try persistToFile()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public func find(by id: String) -> T? {
|
|
48
|
+
cache[id]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public func loadAll() -> [T] {
|
|
52
|
+
Array(cache.values)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MARK: - Private
|
|
56
|
+
|
|
57
|
+
private func persistToFile() throws {
|
|
58
|
+
let data = try JSONEncoder().encode(Array(cache.values))
|
|
59
|
+
try data.write(to: fileURL, options: .atomic)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private static func loadSynchronously(from url: URL) -> [String: T] {
|
|
63
|
+
guard let data = try? Data(contentsOf: url),
|
|
64
|
+
let items = try? JSONDecoder().decode([T].self, from: data) else {
|
|
65
|
+
return [:]
|
|
66
|
+
}
|
|
67
|
+
return Dictionary(uniqueKeysWithValues: items.map { ($0.id, $0) })
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Usage
|
|
73
|
+
|
|
74
|
+
All calls are automatically async due to actor isolation:
|
|
75
|
+
|
|
76
|
+
```swift
|
|
77
|
+
let repository = LocalRepository<Question>()
|
|
78
|
+
|
|
79
|
+
// Read — fast O(1) lookup from in-memory cache
|
|
80
|
+
let question = await repository.find(by: "q-001")
|
|
81
|
+
let allQuestions = await repository.loadAll()
|
|
82
|
+
|
|
83
|
+
// Write — updates cache and persists to file atomically
|
|
84
|
+
try await repository.save(newQuestion)
|
|
85
|
+
try await repository.delete("q-001")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Combining with @Observable ViewModel
|
|
89
|
+
|
|
90
|
+
```swift
|
|
91
|
+
@Observable
|
|
92
|
+
final class QuestionListViewModel {
|
|
93
|
+
private(set) var questions: [Question] = []
|
|
94
|
+
private let repository: LocalRepository<Question>
|
|
95
|
+
|
|
96
|
+
init(repository: LocalRepository<Question> = LocalRepository()) {
|
|
97
|
+
self.repository = repository
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func load() async {
|
|
101
|
+
questions = await repository.loadAll()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func add(_ question: Question) async throws {
|
|
105
|
+
try await repository.save(question)
|
|
106
|
+
questions = await repository.loadAll()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Key Design Decisions
|
|
112
|
+
|
|
113
|
+
| Decision | Rationale |
|
|
114
|
+
|----------|-----------|
|
|
115
|
+
| Actor (not class + lock) | Compiler-enforced thread safety, no manual synchronization |
|
|
116
|
+
| In-memory cache + file persistence | Fast reads from cache, durable writes to disk |
|
|
117
|
+
| Synchronous init loading | Avoids async initialization complexity |
|
|
118
|
+
| Dictionary keyed by ID | O(1) lookups by identifier |
|
|
119
|
+
| Generic over `Codable & Identifiable` | Reusable across any model type |
|
|
120
|
+
| Atomic file writes (`.atomic`) | Prevents partial writes on crash |
|
|
121
|
+
|
|
122
|
+
## Best Practices
|
|
123
|
+
|
|
124
|
+
- **Use `Sendable` types** for all data crossing actor boundaries
|
|
125
|
+
- **Keep the actor's public API minimal** — only expose domain operations, not persistence details
|
|
126
|
+
- **Use `.atomic` writes** to prevent data corruption if the app crashes mid-write
|
|
127
|
+
- **Load synchronously in `init`** — async initializers add complexity with minimal benefit for local files
|
|
128
|
+
- **Combine with `@Observable`** ViewModels for reactive UI updates
|
|
129
|
+
|
|
130
|
+
## Anti-Patterns to Avoid
|
|
131
|
+
|
|
132
|
+
- Using `DispatchQueue` or `NSLock` instead of actors for new Swift concurrency code
|
|
133
|
+
- Exposing the internal cache dictionary to external callers
|
|
134
|
+
- Making the file URL configurable without validation
|
|
135
|
+
- Forgetting that all actor method calls are `await` — callers must handle async context
|
|
136
|
+
- Using `nonisolated` to bypass actor isolation (defeats the purpose)
|
|
137
|
+
|
|
138
|
+
## When to Use
|
|
139
|
+
|
|
140
|
+
- Local data storage in iOS/macOS apps (user data, settings, cached content)
|
|
141
|
+
- Offline-first architectures that sync to a server later
|
|
142
|
+
- Any shared mutable state that multiple parts of the app access concurrently
|
|
143
|
+
- Replacing legacy `DispatchQueue`-based thread safety with modern Swift concurrency
|