mindforge-cc 1.0.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/.agent/CLAUDE.md +462 -0
- package/.agent/forge/help.md +7 -0
- package/.agent/forge/init-project.md +32 -0
- package/.agent/forge/plan-phase.md +30 -0
- package/.agent/mindforge/approve.md +18 -0
- package/.agent/mindforge/audit.md +30 -0
- package/.agent/mindforge/benchmark.md +33 -0
- package/.agent/mindforge/complete-milestone.md +18 -0
- package/.agent/mindforge/debug.md +126 -0
- package/.agent/mindforge/discuss-phase.md +138 -0
- package/.agent/mindforge/execute-phase.md +165 -0
- package/.agent/mindforge/health.md +21 -0
- package/.agent/mindforge/help.md +23 -0
- package/.agent/mindforge/init-org.md +131 -0
- package/.agent/mindforge/init-project.md +155 -0
- package/.agent/mindforge/install-skill.md +15 -0
- package/.agent/mindforge/map-codebase.md +298 -0
- package/.agent/mindforge/metrics.md +22 -0
- package/.agent/mindforge/migrate.md +40 -0
- package/.agent/mindforge/milestone.md +12 -0
- package/.agent/mindforge/next.md +105 -0
- package/.agent/mindforge/plan-phase.md +125 -0
- package/.agent/mindforge/plugins.md +40 -0
- package/.agent/mindforge/pr-review.md +41 -0
- package/.agent/mindforge/profile-team.md +23 -0
- package/.agent/mindforge/publish-skill.md +19 -0
- package/.agent/mindforge/quick.md +135 -0
- package/.agent/mindforge/release.md +10 -0
- package/.agent/mindforge/retrospective.md +26 -0
- package/.agent/mindforge/review.md +157 -0
- package/.agent/mindforge/security-scan.md +233 -0
- package/.agent/mindforge/ship.md +100 -0
- package/.agent/mindforge/skills.md +141 -0
- package/.agent/mindforge/status.md +104 -0
- package/.agent/mindforge/sync-confluence.md +11 -0
- package/.agent/mindforge/sync-jira.md +12 -0
- package/.agent/mindforge/tokens.md +8 -0
- package/.agent/mindforge/update.md +42 -0
- package/.agent/mindforge/verify-phase.md +62 -0
- package/.agent/mindforge/workspace.md +29 -0
- package/.claude/CLAUDE.md +462 -0
- package/.claude/commands/forge/help.md +7 -0
- package/.claude/commands/forge/init-project.md +32 -0
- package/.claude/commands/forge/plan-phase.md +30 -0
- package/.claude/commands/mindforge/approve.md +18 -0
- package/.claude/commands/mindforge/audit.md +30 -0
- package/.claude/commands/mindforge/benchmark.md +33 -0
- package/.claude/commands/mindforge/complete-milestone.md +18 -0
- package/.claude/commands/mindforge/debug.md +126 -0
- package/.claude/commands/mindforge/discuss-phase.md +138 -0
- package/.claude/commands/mindforge/execute-phase.md +165 -0
- package/.claude/commands/mindforge/health.md +21 -0
- package/.claude/commands/mindforge/help.md +23 -0
- package/.claude/commands/mindforge/init-org.md +131 -0
- package/.claude/commands/mindforge/init-project.md +155 -0
- package/.claude/commands/mindforge/install-skill.md +15 -0
- package/.claude/commands/mindforge/map-codebase.md +298 -0
- package/.claude/commands/mindforge/metrics.md +22 -0
- package/.claude/commands/mindforge/migrate.md +40 -0
- package/.claude/commands/mindforge/milestone.md +12 -0
- package/.claude/commands/mindforge/next.md +105 -0
- package/.claude/commands/mindforge/plan-phase.md +125 -0
- package/.claude/commands/mindforge/plugins.md +40 -0
- package/.claude/commands/mindforge/pr-review.md +41 -0
- package/.claude/commands/mindforge/profile-team.md +23 -0
- package/.claude/commands/mindforge/publish-skill.md +19 -0
- package/.claude/commands/mindforge/quick.md +135 -0
- package/.claude/commands/mindforge/release.md +10 -0
- package/.claude/commands/mindforge/retrospective.md +26 -0
- package/.claude/commands/mindforge/review.md +157 -0
- package/.claude/commands/mindforge/security-scan.md +233 -0
- package/.claude/commands/mindforge/ship.md +100 -0
- package/.claude/commands/mindforge/skills.md +141 -0
- package/.claude/commands/mindforge/status.md +104 -0
- package/.claude/commands/mindforge/sync-confluence.md +11 -0
- package/.claude/commands/mindforge/sync-jira.md +12 -0
- package/.claude/commands/mindforge/tokens.md +8 -0
- package/.claude/commands/mindforge/update.md +42 -0
- package/.claude/commands/mindforge/verify-phase.md +62 -0
- package/.claude/commands/mindforge/workspace.md +29 -0
- package/.forge/org/CONVENTIONS.md +0 -0
- package/.forge/org/ORG.md +0 -0
- package/.forge/org/SECURITY.md +0 -0
- package/.forge/org/TOOLS.md +0 -0
- package/.forge/personas/analyst.md +0 -0
- package/.forge/personas/architect.md +0 -0
- package/.forge/personas/debug-specialist.md +0 -0
- package/.forge/personas/developer.md +26 -0
- package/.forge/personas/qa-engineer.md +0 -0
- package/.forge/personas/release-manager.md +0 -0
- package/.forge/personas/security-reviewer.md +33 -0
- package/.forge/personas/tech-writer.md +0 -0
- package/.forge/skills/api-design/SKILL.md +0 -0
- package/.forge/skills/code-quality/SKILL.md +0 -0
- package/.forge/skills/documentation/SKILL.md +0 -0
- package/.forge/skills/security-review/SKILL.md +23 -0
- package/.forge/skills/testing-standards/SKILL.md +27 -0
- package/.github/workflows/mindforge-ci.yml +224 -0
- package/.gitlab-ci-mindforge.yml +18 -0
- package/.mindforge/MINDFORGE-SCHEMA.json +165 -0
- package/.mindforge/audit/AUDIT-SCHEMA.md +451 -0
- package/.mindforge/ci/ci-config-schema.md +21 -0
- package/.mindforge/ci/ci-mode.md +179 -0
- package/.mindforge/ci/github-actions-adapter.md +224 -0
- package/.mindforge/ci/gitlab-ci-adapter.md +31 -0
- package/.mindforge/ci/jenkins-adapter.md +44 -0
- package/.mindforge/distribution/registry-client.md +166 -0
- package/.mindforge/distribution/registry-schema.md +96 -0
- package/.mindforge/distribution/skill-publisher.md +44 -0
- package/.mindforge/distribution/skill-validator.md +74 -0
- package/.mindforge/engine/compaction-protocol.md +182 -0
- package/.mindforge/engine/context-injector.md +128 -0
- package/.mindforge/engine/dependency-parser.md +113 -0
- package/.mindforge/engine/skills/conflict-resolver.md +69 -0
- package/.mindforge/engine/skills/loader.md +184 -0
- package/.mindforge/engine/skills/registry.md +98 -0
- package/.mindforge/engine/skills/versioning.md +75 -0
- package/.mindforge/engine/verification-pipeline.md +111 -0
- package/.mindforge/engine/wave-executor.md +235 -0
- package/.mindforge/governance/GOVERNANCE-CONFIG.md +17 -0
- package/.mindforge/governance/approval-workflow.md +37 -0
- package/.mindforge/governance/change-classifier.md +63 -0
- package/.mindforge/governance/compliance-gates.md +31 -0
- package/.mindforge/integrations/confluence.md +27 -0
- package/.mindforge/integrations/connection-manager.md +163 -0
- package/.mindforge/integrations/github.md +25 -0
- package/.mindforge/integrations/gitlab.md +13 -0
- package/.mindforge/integrations/jira.md +102 -0
- package/.mindforge/integrations/slack.md +41 -0
- package/.mindforge/intelligence/antipattern-detector.md +75 -0
- package/.mindforge/intelligence/difficulty-scorer.md +55 -0
- package/.mindforge/intelligence/health-engine.md +208 -0
- package/.mindforge/intelligence/skill-gap-analyser.md +40 -0
- package/.mindforge/intelligence/smart-compaction.md +71 -0
- package/.mindforge/metrics/METRICS-SCHEMA.md +42 -0
- package/.mindforge/metrics/quality-tracker.md +32 -0
- package/.mindforge/monorepo/cross-package-planner.md +114 -0
- package/.mindforge/monorepo/dependency-graph-builder.md +32 -0
- package/.mindforge/monorepo/workspace-detector.md +129 -0
- package/.mindforge/org/CONVENTIONS.md +62 -0
- package/.mindforge/org/ORG.md +51 -0
- package/.mindforge/org/SECURITY.md +50 -0
- package/.mindforge/org/TOOLS.md +53 -0
- package/.mindforge/org/integrations/INTEGRATIONS-CONFIG.md +58 -0
- package/.mindforge/org/skills/MANIFEST.md +38 -0
- package/.mindforge/personas/analyst.md +52 -0
- package/.mindforge/personas/architect.md +75 -0
- package/.mindforge/personas/debug-specialist.md +52 -0
- package/.mindforge/personas/developer.md +85 -0
- package/.mindforge/personas/overrides/README.md +85 -0
- package/.mindforge/personas/qa-engineer.md +61 -0
- package/.mindforge/personas/release-manager.md +76 -0
- package/.mindforge/personas/security-reviewer.md +91 -0
- package/.mindforge/personas/tech-writer.md +51 -0
- package/.mindforge/plugins/PLUGINS-MANIFEST.md +23 -0
- package/.mindforge/plugins/plugin-loader.md +93 -0
- package/.mindforge/plugins/plugin-registry.md +44 -0
- package/.mindforge/plugins/plugin-schema.md +68 -0
- package/.mindforge/pr-review/ai-reviewer.md +266 -0
- package/.mindforge/pr-review/finding-formatter.md +46 -0
- package/.mindforge/pr-review/review-prompt-templates.md +44 -0
- package/.mindforge/production/compatibility-layer.md +39 -0
- package/.mindforge/production/migration-engine.md +52 -0
- package/.mindforge/production/production-checklist.md +165 -0
- package/.mindforge/production/token-optimiser.md +68 -0
- package/.mindforge/skills/accessibility/SKILL.md +106 -0
- package/.mindforge/skills/api-design/SKILL.md +98 -0
- package/.mindforge/skills/code-quality/SKILL.md +88 -0
- package/.mindforge/skills/data-privacy/SKILL.md +126 -0
- package/.mindforge/skills/database-patterns/SKILL.md +192 -0
- package/.mindforge/skills/documentation/SKILL.md +91 -0
- package/.mindforge/skills/incident-response/SKILL.md +180 -0
- package/.mindforge/skills/performance/SKILL.md +120 -0
- package/.mindforge/skills/security-review/SKILL.md +83 -0
- package/.mindforge/skills/testing-standards/SKILL.md +97 -0
- package/.mindforge/team/TEAM-PROFILE.md +42 -0
- package/.mindforge/team/multi-handoff.md +23 -0
- package/.mindforge/team/profiles/README.md +13 -0
- package/.mindforge/team/session-merger.md +18 -0
- package/.planning/ARCHITECTURE.md +0 -0
- package/.planning/AUDIT.jsonl +0 -0
- package/.planning/HANDOFF.json +28 -0
- package/.planning/PROJECT.md +33 -0
- package/.planning/RELEASE-CHECKLIST.md +68 -0
- package/.planning/REQUIREMENTS.md +0 -0
- package/.planning/ROADMAP.md +0 -0
- package/.planning/STATE.md +31 -0
- package/.planning/approvals/.gitkeep +1 -0
- package/.planning/archive/.gitkeep +1 -0
- package/.planning/audit-archive/.gitkeep +1 -0
- package/.planning/decisions/.gitkeep +0 -0
- package/.planning/decisions/ADR-001-handoff-tracking.md +41 -0
- package/.planning/decisions/ADR-002-markdown-commands.md +46 -0
- package/.planning/decisions/ADR-003-skills-trigger-model.md +37 -0
- package/.planning/decisions/ADR-004-wave-parallelism-model.md +45 -0
- package/.planning/decisions/ADR-005-append-only-audit-log.md +51 -0
- package/.planning/decisions/ADR-006-tiered-skills-system.md +22 -0
- package/.planning/decisions/ADR-007-trigger-keyword-model.md +22 -0
- package/.planning/decisions/ADR-008-just-in-time-skill-loading.md +29 -0
- package/.planning/decisions/ADR-009-enterprise-integration-retry-policy.md +8 -0
- package/.planning/decisions/ADR-010-governance-tier-escalation.md +8 -0
- package/.planning/decisions/ADR-011-multi-developer-handoff-contract.md +8 -0
- package/.planning/decisions/ADR-012-intelligence-feedback-loops.md +19 -0
- package/.planning/decisions/ADR-013-mindforge-md-constitution.md +16 -0
- package/.planning/decisions/ADR-014-metrics-as-signals-not-evaluation.md +15 -0
- package/.planning/decisions/ADR-015-npm-based-skill-registry.md +26 -0
- package/.planning/decisions/ADR-016-ci-exit-code-0-on-timeout.md +27 -0
- package/.planning/decisions/ADR-017-sdk-localhost-only.md +28 -0
- package/.planning/decisions/ADR-018-installer-self-install-detection.md +15 -0
- package/.planning/decisions/ADR-019-self-update-scope-preservation.md +14 -0
- package/.planning/decisions/ADR-020-v1.0.0-stable-interface-contract.md +23 -0
- package/.planning/jira-sync.json +9 -0
- package/.planning/milestones/.gitkeep +1 -0
- package/.planning/phases/day1/REVIEW-DAY1.md +50 -0
- package/.planning/phases/day1/SECURITY-REVIEW-DAY1.md +15 -0
- package/.planning/phases/day2/REVIEW-DAY2.md +521 -0
- package/.planning/phases/day3/REVIEW-DAY3.md +234 -0
- package/.planning/slack-threads.json +6 -0
- package/CHANGELOG.md +175 -0
- package/LICENSE +21 -0
- package/MINDFORGE.md +76 -0
- package/README.md +182 -0
- package/RELEASENOTES.md +41 -0
- package/SECURITY.md +4 -0
- package/bin/install.js +120 -0
- package/bin/installer-core.js +292 -0
- package/bin/migrations/0.1.0-to-0.5.0.js +37 -0
- package/bin/migrations/0.5.0-to-0.6.0.js +17 -0
- package/bin/migrations/0.6.0-to-1.0.0.js +100 -0
- package/bin/migrations/migrate.js +151 -0
- package/bin/migrations/schema-versions.js +64 -0
- package/bin/updater/changelog-fetcher.js +62 -0
- package/bin/updater/self-update.js +169 -0
- package/bin/updater/version-comparator.js +68 -0
- package/bin/validate-config.js +92 -0
- package/bin/wizard/config-generator.js +112 -0
- package/bin/wizard/environment-detector.js +76 -0
- package/bin/wizard/setup-wizard.js +237 -0
- package/docs/Context/Master-Context.md +701 -0
- package/docs/architecture/README.md +35 -0
- package/docs/architecture/decision-records-index.md +26 -0
- package/docs/ci-cd-integration.md +30 -0
- package/docs/ci-quickstart.md +78 -0
- package/docs/commands-reference.md +11 -0
- package/docs/contributing/CONTRIBUTING.md +38 -0
- package/docs/contributing/plugin-authoring.md +50 -0
- package/docs/contributing/skill-authoring.md +41 -0
- package/docs/enterprise-setup.md +25 -0
- package/docs/faq.md +38 -0
- package/docs/getting-started.md +36 -0
- package/docs/governance-guide.md +23 -0
- package/docs/mindforge-md-reference.md +53 -0
- package/docs/monorepo-guide.md +26 -0
- package/docs/persona-customisation.md +56 -0
- package/docs/quick-verify.md +33 -0
- package/docs/reference/audit-events.md +53 -0
- package/docs/reference/commands.md +82 -0
- package/docs/reference/config-reference.md +64 -0
- package/docs/reference/sdk-api.md +48 -0
- package/docs/reference/skills-api.md +57 -0
- package/docs/release-checklist-guide.md +37 -0
- package/docs/requirements.md +29 -0
- package/docs/sdk-reference.md +27 -0
- package/docs/security/SECURITY.md +42 -0
- package/docs/security/penetration-test-results.md +31 -0
- package/docs/security/threat-model.md +142 -0
- package/docs/skills-authoring-guide.md +119 -0
- package/docs/skills-publishing-guide.md +21 -0
- package/docs/team-setup-guide.md +21 -0
- package/docs/troubleshooting.md +119 -0
- package/docs/tutorial.md +195 -0
- package/docs/upgrade.md +44 -0
- package/docs/user-guide.md +131 -0
- package/docs/usp-features.md +214 -0
- package/eslint.config.mjs +31 -0
- package/examples/starter-project/.planning/AUDIT.jsonl +1 -0
- package/examples/starter-project/.planning/HANDOFF.json +23 -0
- package/examples/starter-project/.planning/PROJECT.md +27 -0
- package/examples/starter-project/.planning/STATE.md +10 -0
- package/examples/starter-project/MINDFORGE.md +40 -0
- package/examples/starter-project/README.md +14 -0
- package/implementation-roadmap/day-1-imp/DAY1-HARDEN.md +823 -0
- package/implementation-roadmap/day-1-imp/DAY1-IMPLEMENT.md +2459 -0
- package/implementation-roadmap/day-1-imp/DAY1-REVIEW.md +288 -0
- package/implementation-roadmap/day-2-imp/DAY2-HARDEN.md +954 -0
- package/implementation-roadmap/day-2-imp/DAY2-IMPLEMENT.md +2347 -0
- package/implementation-roadmap/day-2-imp/DAY2-REVIEW.md +422 -0
- package/implementation-roadmap/day-3-imp/DAY3-HARDEN.md +870 -0
- package/implementation-roadmap/day-3-imp/DAY3-IMPLEMENT.md +2798 -0
- package/implementation-roadmap/day-3-imp/DAY3-REVIEW.md +484 -0
- package/implementation-roadmap/day-4-imp/DAY4-HARDEN.md +1087 -0
- package/implementation-roadmap/day-4-imp/DAY4-IMPLEMENT.md +2874 -0
- package/implementation-roadmap/day-4-imp/DAY4-REVIEW.md +386 -0
- package/implementation-roadmap/day-5-imp/DAY5-HARDEN.md +1078 -0
- package/implementation-roadmap/day-5-imp/DAY5-IMPLEMENT.md +3151 -0
- package/implementation-roadmap/day-5-imp/DAY5-REVIEW.md +345 -0
- package/implementation-roadmap/day-6-imp/DAY6-COMPLETE.md +3919 -0
- package/implementation-roadmap/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +4513 -0
- package/package.json +31 -0
- package/sdk/README.md +69 -0
- package/sdk/eslint.config.mjs +34 -0
- package/sdk/package-lock.json +1507 -0
- package/sdk/package.json +30 -0
- package/sdk/src/client.ts +133 -0
- package/sdk/src/commands.ts +63 -0
- package/sdk/src/events.ts +166 -0
- package/sdk/src/index.ts +22 -0
- package/sdk/src/types.ts +87 -0
- package/sdk/tsconfig.json +13 -0
- package/tests/audit.test.js +206 -0
- package/tests/ci-mode.test.js +162 -0
- package/tests/compaction.test.js +161 -0
- package/tests/distribution.test.js +205 -0
- package/tests/e2e.test.js +618 -0
- package/tests/governance.test.js +130 -0
- package/tests/install.test.js +209 -0
- package/tests/integrations.test.js +128 -0
- package/tests/intelligence.test.js +117 -0
- package/tests/metrics.test.js +96 -0
- package/tests/migration.test.js +309 -0
- package/tests/production.test.js +416 -0
- package/tests/sdk.test.js +200 -0
- package/tests/skills-platform.test.js +403 -0
- package/tests/wave-engine.test.js +338 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: accessibility
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
min_mindforge_version: 0.3.0
|
|
5
|
+
status: stable
|
|
6
|
+
triggers: accessibility, a11y, aria, ARIA, wcag, WCAG, screen reader, keyboard, focus, tab order, colour contrast, color contrast, alt text, semantic HTML, form label, button, interactive, disabled, skip link, heading hierarchy, landmark, live region, modal, dialog, tooltip, dropdown, combobox
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill — Accessibility Engineering
|
|
10
|
+
|
|
11
|
+
## When this skill activates
|
|
12
|
+
Any task involving UI components, forms, interactive elements, or user-facing HTML.
|
|
13
|
+
Load this skill for ALL frontend work — accessibility is not optional.
|
|
14
|
+
|
|
15
|
+
## Mandatory standard
|
|
16
|
+
WCAG 2.2 Level AA is the minimum. This is the legal requirement in most jurisdictions.
|
|
17
|
+
Level AAA elements (where achievable without design compromise) are recommended.
|
|
18
|
+
|
|
19
|
+
## Mandatory actions when this skill is active
|
|
20
|
+
|
|
21
|
+
### Before writing any UI component
|
|
22
|
+
1. Identify the semantic HTML element that best represents the component.
|
|
23
|
+
Use native HTML before ARIA. A `<button>` is always better than a `<div role="button">`.
|
|
24
|
+
2. Map all interactive states: default, hover, focus, active, disabled, error, loading.
|
|
25
|
+
3. Confirm colour contrast meets WCAG AA:
|
|
26
|
+
- Normal text: contrast ratio ≥ 4.5:1
|
|
27
|
+
- Large text (≥ 18pt or ≥ 14pt bold): contrast ratio ≥ 3:1
|
|
28
|
+
- UI components and graphics: contrast ratio ≥ 3:1
|
|
29
|
+
|
|
30
|
+
### HTML semantics checklist (apply to every component)
|
|
31
|
+
|
|
32
|
+
**Structure:**
|
|
33
|
+
- [ ] One `<h1>` per page. Heading hierarchy is sequential (h1 → h2 → h3, never skip levels)
|
|
34
|
+
- [ ] Landmark roles present: `<main>`, `<nav>`, `<header>`, `<footer>`, `<aside>`
|
|
35
|
+
- [ ] Skip navigation link as the first focusable element on every page
|
|
36
|
+
- [ ] Focus order follows DOM order (do not rely on visual layout to imply order)
|
|
37
|
+
|
|
38
|
+
**Forms:**
|
|
39
|
+
- [ ] Every input has a visible `<label>` (not just placeholder text)
|
|
40
|
+
- [ ] Label is programmatically associated: `<label for="id">` or `aria-labelledby`
|
|
41
|
+
- [ ] Required fields marked: `required` attribute + visual indicator + aria description
|
|
42
|
+
- [ ] Error messages: `role="alert"` or `aria-live="polite"`, associated with field via `aria-describedby`
|
|
43
|
+
- [ ] Validation errors describe the problem AND the fix, not just "Invalid input"
|
|
44
|
+
|
|
45
|
+
**Interactive components:**
|
|
46
|
+
- [ ] All interactive elements reachable by Tab key
|
|
47
|
+
- [ ] Focus visible: never `outline: none` without a custom visible focus style
|
|
48
|
+
- [ ] Keyboard shortcuts documented and not conflicting with browser/OS shortcuts
|
|
49
|
+
- [ ] Custom widgets implement the correct ARIA pattern (see ARIA Authoring Practices Guide)
|
|
50
|
+
- [ ] Required ARIA props present when using roles (examples below)
|
|
51
|
+
|
|
52
|
+
**Images and media:**
|
|
53
|
+
- [ ] Decorative images: `alt=""` (empty string, not omitted)
|
|
54
|
+
- [ ] Informative images: `alt` describes the information conveyed
|
|
55
|
+
- [ ] Complex images (charts, diagrams): `aria-describedby` pointing to a full text description
|
|
56
|
+
- [ ] Videos: captions required. Audio descriptions for visual-only information.
|
|
57
|
+
|
|
58
|
+
**Dynamic content:**
|
|
59
|
+
- [ ] Content that updates dynamically: `aria-live="polite"` (non-critical) or `aria-live="assertive"` (critical)
|
|
60
|
+
- [ ] Modals/dialogs: focus moves to modal on open, returns to trigger on close, `aria-modal="true"`
|
|
61
|
+
- [ ] Loading states: `aria-busy="true"` on the container being updated
|
|
62
|
+
- [ ] Reduced motion respected: `prefers-reduced-motion` disables non-essential animation
|
|
63
|
+
|
|
64
|
+
### ARIA usage rules
|
|
65
|
+
- Use ARIA only when no native HTML element conveys the role
|
|
66
|
+
- ARIA roles override native semantics — applying a role to `<button>` changes it
|
|
67
|
+
- Required ARIA properties: never use a role without its required properties
|
|
68
|
+
(e.g., `role="checkbox"` requires `aria-checked`)
|
|
69
|
+
- Never use `aria-hidden="true"` on focusable elements
|
|
70
|
+
|
|
71
|
+
### ARIA required properties examples
|
|
72
|
+
- `role="checkbox"` → `aria-checked`
|
|
73
|
+
- `role="switch"` → `aria-checked`
|
|
74
|
+
- `role="textbox"` (non-input element) → `aria-multiline` (if multiline)
|
|
75
|
+
- `role="combobox"` → `aria-expanded`, `aria-controls`, `aria-haspopup`
|
|
76
|
+
- `role="dialog"` → `aria-modal`, `aria-labelledby` (and `aria-describedby` when needed)
|
|
77
|
+
|
|
78
|
+
### Testing protocol
|
|
79
|
+
```bash
|
|
80
|
+
# Automated testing (catches ~30-40% of issues)
|
|
81
|
+
npx axe-cli https://localhost:3000
|
|
82
|
+
|
|
83
|
+
# Keyboard testing (manual — must be done for every interactive component)
|
|
84
|
+
# 1. Tab through every interactive element — order must be logical
|
|
85
|
+
# 2. Activate every control with Enter/Space — must work
|
|
86
|
+
# 3. Navigate dropdowns/menus with arrow keys
|
|
87
|
+
# 4. Escape dismisses modals and dropdowns
|
|
88
|
+
|
|
89
|
+
# Screen reader testing (minimum: test with NVDA + Chrome on Windows OR
|
|
90
|
+
# VoiceOver + Safari on macOS)
|
|
91
|
+
# Key checks:
|
|
92
|
+
# - Every interactive element announced with role, name, and state
|
|
93
|
+
# - Dynamic updates announced appropriately
|
|
94
|
+
# - Images described correctly
|
|
95
|
+
|
|
96
|
+
# Contrast checking
|
|
97
|
+
# Install: axe DevTools browser extension or Colour Contrast Analyser
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Self-check before task completion
|
|
101
|
+
- [ ] Ran `axe-cli` — zero violations
|
|
102
|
+
- [ ] Keyboard navigation tested manually
|
|
103
|
+
- [ ] All interactive elements have accessible names
|
|
104
|
+
- [ ] Colour contrast meets 4.5:1 for text
|
|
105
|
+
- [ ] Focus management correct for modals and dynamic content
|
|
106
|
+
- [ ] No `aria-hidden` on focusable elements
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
min_mindforge_version: 0.1.0
|
|
5
|
+
status: stable
|
|
6
|
+
triggers: API, endpoint, REST, GraphQL, route, controller, handler, request, response, HTTP, POST, GET, PUT, PATCH, DELETE, contract, versioning, OpenAPI
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill — API Design
|
|
10
|
+
|
|
11
|
+
## When this skill activates
|
|
12
|
+
Any task involving creating or modifying API endpoints, request/response schemas,
|
|
13
|
+
or API contracts.
|
|
14
|
+
|
|
15
|
+
## Mandatory actions when this skill is active
|
|
16
|
+
|
|
17
|
+
### Before writing any code
|
|
18
|
+
1. Define the endpoint contract: method, path, auth requirement.
|
|
19
|
+
2. Define request and response schemas (including error shape).
|
|
20
|
+
|
|
21
|
+
### During implementation
|
|
22
|
+
- Validate input at the boundary.
|
|
23
|
+
- Use consistent status codes.
|
|
24
|
+
- Add security headers to responses.
|
|
25
|
+
|
|
26
|
+
### After implementation
|
|
27
|
+
- Document the endpoint in ARCHITECTURE.md.
|
|
28
|
+
- Add or update tests for the new contract.
|
|
29
|
+
|
|
30
|
+
## REST API standards
|
|
31
|
+
|
|
32
|
+
### URL conventions
|
|
33
|
+
- Lowercase, hyphen-separated: `/user-profiles` not `/userProfiles`
|
|
34
|
+
- Nouns for resources: `/orders` not `/getOrders`
|
|
35
|
+
- Hierarchy shows relationships: `/users/{id}/orders`
|
|
36
|
+
- Version in path: `/v1/users`
|
|
37
|
+
|
|
38
|
+
### HTTP method semantics
|
|
39
|
+
- GET: read only, idempotent, no body
|
|
40
|
+
- POST: create, non-idempotent, returns 201 + Location header
|
|
41
|
+
- PUT: full replace, idempotent
|
|
42
|
+
- PATCH: partial update, idempotent
|
|
43
|
+
- DELETE: remove, idempotent, returns 204
|
|
44
|
+
|
|
45
|
+
### Status codes (use precisely)
|
|
46
|
+
- 200 OK: successful GET, PUT, PATCH
|
|
47
|
+
- 201 Created: successful POST (include Location header)
|
|
48
|
+
- 204 No Content: successful DELETE
|
|
49
|
+
- 400 Bad Request: client validation error (include error details in body)
|
|
50
|
+
- 401 Unauthorized: missing or invalid authentication
|
|
51
|
+
- 403 Forbidden: authenticated but not authorised
|
|
52
|
+
- 404 Not Found: resource does not exist
|
|
53
|
+
- 409 Conflict: state conflict (duplicate, version mismatch)
|
|
54
|
+
- 422 Unprocessable Entity: semantic validation error
|
|
55
|
+
- 429 Too Many Requests: rate limit exceeded (include Retry-After header)
|
|
56
|
+
- 500 Internal Server Error: unexpected server error (never expose internals)
|
|
57
|
+
|
|
58
|
+
### Error response format (always consistent)
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"error": {
|
|
62
|
+
"code": "VALIDATION_ERROR",
|
|
63
|
+
"message": "Human-readable description",
|
|
64
|
+
"details": [
|
|
65
|
+
{ "field": "email", "issue": "must be a valid email address" }
|
|
66
|
+
],
|
|
67
|
+
"requestId": "req_abc123"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Request validation
|
|
73
|
+
- Validate at the route handler boundary, not deep in business logic
|
|
74
|
+
- Return all validation errors at once (not one at a time)
|
|
75
|
+
- Validate: type, format, length, range, required fields
|
|
76
|
+
|
|
77
|
+
### Security headers (add to every response)
|
|
78
|
+
```
|
|
79
|
+
X-Content-Type-Options: nosniff
|
|
80
|
+
X-Frame-Options: DENY
|
|
81
|
+
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
|
82
|
+
Content-Security-Policy: default-src 'self'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Output
|
|
86
|
+
New endpoints must be documented in ARCHITECTURE.md under the API section
|
|
87
|
+
with: method, path, auth requirement, request schema, response schema, errors.
|
|
88
|
+
|
|
89
|
+
## Self-check before task completion
|
|
90
|
+
|
|
91
|
+
Before marking a task done when this skill was active:
|
|
92
|
+
|
|
93
|
+
- [ ] Did I read the full SKILL.md before starting? (Not just the triggers)
|
|
94
|
+
- [ ] Did I activate the corresponding persona file?
|
|
95
|
+
- [ ] Did I apply every mandatory action in this skill, not just the ones
|
|
96
|
+
I remembered off the top of my head?
|
|
97
|
+
- [ ] If this skill produced an output file (review, security report, etc.),
|
|
98
|
+
has that file been written to the correct path?
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-quality
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
min_mindforge_version: 0.1.0
|
|
5
|
+
status: stable
|
|
6
|
+
triggers: refactor, code review, review, quality, tech debt, complexity, clean up, cleanup, lint, linting, code smell, duplication, naming, readability
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill — Code Quality
|
|
10
|
+
|
|
11
|
+
## When this skill activates
|
|
12
|
+
Any code review, refactoring task, or implementation where maintaining
|
|
13
|
+
quality standards is the primary goal.
|
|
14
|
+
|
|
15
|
+
## Mandatory actions when this skill is active
|
|
16
|
+
|
|
17
|
+
### Before writing any code
|
|
18
|
+
1. Read CONVENTIONS.md and apply all rules.
|
|
19
|
+
2. Identify complexity risks (hot paths, long functions, nested logic).
|
|
20
|
+
3. Decide up front where tests will be added or updated.
|
|
21
|
+
|
|
22
|
+
### During implementation or review
|
|
23
|
+
- Enforce function length and complexity limits.
|
|
24
|
+
- Remove unused code and dead imports.
|
|
25
|
+
- Replace magic numbers with named constants.
|
|
26
|
+
|
|
27
|
+
### After implementation or review
|
|
28
|
+
- Run linters and type checks for the project.
|
|
29
|
+
- Record findings or fixes in SUMMARY.md or the review report.
|
|
30
|
+
|
|
31
|
+
## Quality dimensions to evaluate
|
|
32
|
+
|
|
33
|
+
### Readability
|
|
34
|
+
- Can a new engineer understand this function in under 2 minutes?
|
|
35
|
+
- Are names precise and unambiguous? (Not `data`, `info`, `temp`, `flag`)
|
|
36
|
+
- Is every non-obvious decision explained with a comment?
|
|
37
|
+
- Are there magic numbers? (Replace with named constants)
|
|
38
|
+
|
|
39
|
+
### Complexity limits
|
|
40
|
+
- Functions: ≤ 40 lines. If longer, extract sub-functions.
|
|
41
|
+
- Cyclomatic complexity: ≤ 10 per function.
|
|
42
|
+
- Nesting depth: ≤ 3 levels. Extract to separate function if deeper.
|
|
43
|
+
- Parameters: ≤ 4 per function. If more, use an options object.
|
|
44
|
+
|
|
45
|
+
### Duplication
|
|
46
|
+
- DRY (Don't Repeat Yourself): extract any logic appearing 3+ times.
|
|
47
|
+
- Exception: duplication in tests is acceptable for clarity.
|
|
48
|
+
|
|
49
|
+
### Error handling
|
|
50
|
+
- Every async operation must have explicit error handling.
|
|
51
|
+
- No empty catch blocks (`catch(e) {}`).
|
|
52
|
+
- No swallowed errors (`catch(e) { return null }`).
|
|
53
|
+
- Errors must be logged with enough context to diagnose.
|
|
54
|
+
|
|
55
|
+
### Dependencies
|
|
56
|
+
- Before adding any new dependency: check bundle size, CVEs, last commit date,
|
|
57
|
+
weekly downloads, and licence compatibility.
|
|
58
|
+
- Prefer native platform APIs over dependencies for simple tasks.
|
|
59
|
+
|
|
60
|
+
## Metrics to check before marking a task done
|
|
61
|
+
Run these and fix any failures:
|
|
62
|
+
```bash
|
|
63
|
+
# TypeScript projects
|
|
64
|
+
npx tsc --noEmit
|
|
65
|
+
npx eslint . --ext .ts,.tsx
|
|
66
|
+
|
|
67
|
+
# Python projects
|
|
68
|
+
ruff check .
|
|
69
|
+
mypy .
|
|
70
|
+
|
|
71
|
+
# All projects
|
|
72
|
+
[project test command]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Output
|
|
76
|
+
If performing a code review: write findings to `.planning/phases/phase-N/CODE-REVIEW-N.md`
|
|
77
|
+
with file, line, severity (blocking / suggestion), and recommended fix.
|
|
78
|
+
|
|
79
|
+
## Self-check before task completion
|
|
80
|
+
|
|
81
|
+
Before marking a task done when this skill was active:
|
|
82
|
+
|
|
83
|
+
- [ ] Did I read the full SKILL.md before starting? (Not just the triggers)
|
|
84
|
+
- [ ] Did I activate the corresponding persona file?
|
|
85
|
+
- [ ] Did I apply every mandatory action in this skill, not just the ones
|
|
86
|
+
I remembered off the top of my head?
|
|
87
|
+
- [ ] If this skill produced an output file (review, security report, etc.),
|
|
88
|
+
has that file been written to the correct path?
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-privacy
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
min_mindforge_version: 0.3.0
|
|
5
|
+
status: stable
|
|
6
|
+
triggers: GDPR, CCPA, privacy, PII, personal data, personal information, consent, data retention, right to erasure, right to access, data portability, data subject, anonymise, anonymize, pseudonymise, pseudonymize, data minimisation, data minimization, lawful basis, cookie, tracking, analytics, marketing, third party, data transfer, cross-border
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill — Data Privacy Engineering
|
|
10
|
+
|
|
11
|
+
## When this skill activates
|
|
12
|
+
Any task touching personal data collection, storage, processing, or transfer.
|
|
13
|
+
Also activates for consent management, analytics, cookie handling, and any
|
|
14
|
+
feature where user data flows to third parties.
|
|
15
|
+
These rules are language-agnostic — apply them regardless of framework or stack.
|
|
16
|
+
|
|
17
|
+
## Regulatory coverage
|
|
18
|
+
This skill covers: GDPR (EU/UK), CCPA/CPRA (California), PIPEDA (Canada),
|
|
19
|
+
PDPA (Thailand/Singapore variants), LGPD (Brazil). Requirements often overlap —
|
|
20
|
+
implementing GDPR correctly satisfies most other frameworks.
|
|
21
|
+
|
|
22
|
+
## Mandatory actions when this skill is active
|
|
23
|
+
|
|
24
|
+
### Data audit — before touching any data feature
|
|
25
|
+
Answer these questions before writing code:
|
|
26
|
+
1. **What personal data is collected?** (Name, email, IP, device ID, location, behaviour)
|
|
27
|
+
2. **What is the lawful basis for processing?** (Consent / Contract / Legitimate interest / Legal obligation)
|
|
28
|
+
3. **How long is it retained?** (Must have a defined retention period — not "indefinitely")
|
|
29
|
+
4. **Who does it flow to?** (Internal systems only / third-party processors / international transfer)
|
|
30
|
+
5. **Can users access, export, and delete their data?**
|
|
31
|
+
|
|
32
|
+
If you cannot answer all 5: stop. Write the answers in ARCHITECTURE.md under
|
|
33
|
+
"Data Privacy" before implementing anything.
|
|
34
|
+
|
|
35
|
+
### PII handling standards
|
|
36
|
+
|
|
37
|
+
**Collection:**
|
|
38
|
+
- Collect the minimum data required for the stated purpose (data minimisation)
|
|
39
|
+
- Obtain consent before collecting non-essential data (analytics, marketing)
|
|
40
|
+
- Consent must be: specific, informed, freely given, unambiguous, and withdrawable
|
|
41
|
+
- Withdrawing consent must be as easy as giving it (no dark patterns, no extra steps)
|
|
42
|
+
- Never pre-tick consent checkboxes. Never bundle consent for different purposes.
|
|
43
|
+
|
|
44
|
+
**Storage:**
|
|
45
|
+
- PII fields in the database must be identified (document in ARCHITECTURE.md)
|
|
46
|
+
- Encrypt sensitive PII at rest: financial data, health data, government IDs
|
|
47
|
+
- Pseudonymisation: where possible, store a user ID reference rather than PII inline
|
|
48
|
+
- Never store PII in: logs, AUDIT.jsonl, git commits, error messages, URL parameters
|
|
49
|
+
|
|
50
|
+
**Transfer:**
|
|
51
|
+
- Third-party processors: must have a Data Processing Agreement (DPA)
|
|
52
|
+
- International transfer (out of EU): requires Standard Contractual Clauses or adequacy decision
|
|
53
|
+
- Document all third-party data flows in ARCHITECTURE.md
|
|
54
|
+
|
|
55
|
+
**Retention and deletion:**
|
|
56
|
+
- Define retention period for every PII field in the data model
|
|
57
|
+
- Implement automated deletion or anonymisation when retention period expires
|
|
58
|
+
- Implement "right to erasure": a complete user delete must remove or anonymise ALL their PII
|
|
59
|
+
- Implement "right to access": export of all user data in a portable format (JSON/CSV)
|
|
60
|
+
- Test deletion: verify that deleted user data does not appear in any API response
|
|
61
|
+
|
|
62
|
+
**Retention examples (defaults, adjust to policy/legal requirements):**
|
|
63
|
+
- Authentication logs: 30–90 days
|
|
64
|
+
- Security/audit logs: 90–365 days
|
|
65
|
+
- Billing records: 6–7 years (jurisdiction dependent)
|
|
66
|
+
- Analytics events: 12–24 months
|
|
67
|
+
Always confirm with legal/compliance for your jurisdiction.
|
|
68
|
+
|
|
69
|
+
**Erasure vs anonymisation:**
|
|
70
|
+
- Erasure: delete or irreversibly remove identifiers from all systems
|
|
71
|
+
- Anonymisation: permanently remove identifying attributes so data cannot be re-linked
|
|
72
|
+
If anonymisation is used, document the method and verify re-identification risk.
|
|
73
|
+
|
|
74
|
+
### Cookie and tracking standards
|
|
75
|
+
```javascript
|
|
76
|
+
// Required: granular consent per category
|
|
77
|
+
const consentCategories = {
|
|
78
|
+
necessary: true, // Always true — no consent needed
|
|
79
|
+
functional: false, // Requires consent
|
|
80
|
+
analytics: false, // Requires consent
|
|
81
|
+
marketing: false, // Requires consent — highest bar
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Required: record consent with timestamp and version
|
|
85
|
+
await recordConsent({
|
|
86
|
+
userId: user.id,
|
|
87
|
+
categories: consentCategories,
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
policyVersion: '2026-01',
|
|
90
|
+
ipHash: hash(userIp), // Store hash not raw IP for GDPR compliance
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Required: honour opt-out immediately
|
|
94
|
+
// If analytics: false — stop sending analytics events NOW, not on next page load
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Code patterns that are FORBIDDEN under data privacy
|
|
98
|
+
```
|
|
99
|
+
// ❌ NEVER: Log PII
|
|
100
|
+
console.log(`User ${user.email} logged in`) // email in logs = GDPR violation
|
|
101
|
+
logger.info({ user }) // entire user object = PII in logs
|
|
102
|
+
|
|
103
|
+
// ✅ ALWAYS: Log identifiers, never PII
|
|
104
|
+
logger.info({ userId: user.id, event: 'login' })
|
|
105
|
+
|
|
106
|
+
// ❌ NEVER: PII in error messages
|
|
107
|
+
throw new Error(`Could not find user ${user.email}`) // exposed in stack traces
|
|
108
|
+
|
|
109
|
+
// ✅ ALWAYS: identifiers in errors
|
|
110
|
+
throw new Error(`Could not find user [id:${user.id}]`)
|
|
111
|
+
|
|
112
|
+
// ❌ NEVER: PII in URL parameters
|
|
113
|
+
GET /api/users?email=john@example.com // logged by web servers, CDNs, browsers
|
|
114
|
+
|
|
115
|
+
// ✅ ALWAYS: POST body or path parameter by ID
|
|
116
|
+
GET /api/users/{id}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Privacy review checklist
|
|
120
|
+
Before marking any data-related task done:
|
|
121
|
+
- [ ] Lawful basis identified for every data point collected
|
|
122
|
+
- [ ] PII never appears in logs, error messages, or URL parameters
|
|
123
|
+
- [ ] Retention period defined for every new PII field
|
|
124
|
+
- [ ] Third-party data flows documented in ARCHITECTURE.md
|
|
125
|
+
- [ ] User delete removes or anonymises ALL PII ✅ / not yet implemented ⚠️
|
|
126
|
+
- [ ] Consent UI does not use dark patterns (pre-ticked, bundled, misleading)
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database-patterns
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
min_mindforge_version: 0.3.0
|
|
5
|
+
status: stable
|
|
6
|
+
triggers: database, DB, SQL, query, migration, schema, index, indexing, N+1, transaction, ACID, foreign key, join, aggregate, pagination, cursor, connection pool, ORM, Prisma, SQLAlchemy, Drizzle, Sequelize, PostgreSQL, MySQL, SQLite, MongoDB, Redis, Elasticsearch
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill — Database Patterns
|
|
10
|
+
|
|
11
|
+
## When this skill activates
|
|
12
|
+
Any task involving database schema design, query writing, migrations, or
|
|
13
|
+
ORM configuration.
|
|
14
|
+
|
|
15
|
+
## Mandatory actions when this skill is active
|
|
16
|
+
|
|
17
|
+
### Schema design standards
|
|
18
|
+
|
|
19
|
+
**Naming conventions (PostgreSQL default):**
|
|
20
|
+
```sql
|
|
21
|
+
-- Tables: snake_case, plural
|
|
22
|
+
CREATE TABLE user_profiles (...);
|
|
23
|
+
CREATE TABLE order_items (...);
|
|
24
|
+
|
|
25
|
+
-- Columns: snake_case
|
|
26
|
+
user_id, created_at, updated_at, deleted_at
|
|
27
|
+
|
|
28
|
+
-- Primary keys: always id (UUID preferred over auto-increment)
|
|
29
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
30
|
+
|
|
31
|
+
-- Foreign keys: {referenced_table_singular}_id
|
|
32
|
+
user_id UUID REFERENCES users(id) ON DELETE CASCADE
|
|
33
|
+
order_id UUID REFERENCES orders(id) ON DELETE SET NULL
|
|
34
|
+
|
|
35
|
+
-- Indexes: idx_{table}_{column(s)}
|
|
36
|
+
CREATE INDEX idx_users_email ON users(email);
|
|
37
|
+
CREATE INDEX idx_orders_user_id_created_at ON orders(user_id, created_at DESC);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Standard columns every table should have:**
|
|
41
|
+
```sql
|
|
42
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
43
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
44
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
45
|
+
-- For soft delete (preferred over hard delete):
|
|
46
|
+
deleted_at TIMESTAMPTZ -- NULL = active, timestamp = deleted
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**UUID strategy:**
|
|
50
|
+
- Prefer UUIDv7 or ULID for time-ordered inserts (better index locality)
|
|
51
|
+
- Use random UUIDv4 for high-entropy IDs when ordering is not important
|
|
52
|
+
- Document the choice in ARCHITECTURE.md and keep it consistent across tables
|
|
53
|
+
|
|
54
|
+
**Soft delete implementation:**
|
|
55
|
+
Use soft delete (setting `deleted_at`) instead of hard delete for:
|
|
56
|
+
- User records (GDPR right to erasure exception: anonymise, don't delete)
|
|
57
|
+
- Financial records (audit requirements)
|
|
58
|
+
- Any record that might be referenced by other records
|
|
59
|
+
|
|
60
|
+
For hard delete: cascade must be configured. Document the cascade in ARCHITECTURE.md.
|
|
61
|
+
|
|
62
|
+
### Query standards
|
|
63
|
+
|
|
64
|
+
**N+1 query detection and prevention:**
|
|
65
|
+
```typescript
|
|
66
|
+
// ❌ N+1 pattern: 1 query for users + N queries for their orders
|
|
67
|
+
const users = await db.users.findMany()
|
|
68
|
+
for (const user of users) {
|
|
69
|
+
user.orders = await db.orders.findMany({ where: { userId: user.id } })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ✅ Single query with JOIN or include
|
|
73
|
+
const users = await db.users.findMany({
|
|
74
|
+
include: { orders: true } // Prisma generates a single JOIN query
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// ✅ Or batch load with WHERE IN
|
|
78
|
+
const userIds = users.map(u => u.id)
|
|
79
|
+
const orders = await db.orders.findMany({ where: { userId: { in: userIds } } })
|
|
80
|
+
const ordersByUser = groupBy(orders, 'userId')
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Framework-agnostic SQL example (N+1):**
|
|
84
|
+
```sql
|
|
85
|
+
-- ❌ N+1 pattern (application loops)
|
|
86
|
+
-- SELECT * FROM users LIMIT 50;
|
|
87
|
+
-- then for each user:
|
|
88
|
+
-- SELECT * FROM orders WHERE user_id = ?;
|
|
89
|
+
|
|
90
|
+
-- ✅ Single query with JOIN
|
|
91
|
+
SELECT u.*, o.*
|
|
92
|
+
FROM users u
|
|
93
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
94
|
+
WHERE u.id IN (:user_ids);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Pagination patterns:**
|
|
98
|
+
```typescript
|
|
99
|
+
// ❌ OFFSET pagination (slow on large datasets — scans all previous rows)
|
|
100
|
+
SELECT * FROM posts ORDER BY created_at DESC LIMIT 20 OFFSET 10000;
|
|
101
|
+
|
|
102
|
+
// ✅ Compound cursor — handles duplicate timestamps correctly
|
|
103
|
+
// Application layer: encode (created_at, id) as the cursor
|
|
104
|
+
SELECT * FROM posts
|
|
105
|
+
WHERE (created_at, id) < (:cursor_time::timestamptz, :cursor_id::uuid)
|
|
106
|
+
ORDER BY created_at DESC, id DESC
|
|
107
|
+
LIMIT 20;
|
|
108
|
+
|
|
109
|
+
// Cursor encoding (application layer):
|
|
110
|
+
// encode: btoa(JSON.stringify({ t: row.created_at, id: row.id }))
|
|
111
|
+
// decode: JSON.parse(atob(cursor))
|
|
112
|
+
// Return:
|
|
113
|
+
{
|
|
114
|
+
"data": [...],
|
|
115
|
+
"nextCursor": "[base64 of {t, id} pair]",
|
|
116
|
+
"hasMore": true
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Why compound cursors matter
|
|
121
|
+
Single-field cursors (created_at only) produce incorrect pagination when
|
|
122
|
+
multiple records share the same timestamp — common in batch imports and
|
|
123
|
+
high-write systems. Always use at least (timestamp, id) as a compound cursor.
|
|
124
|
+
|
|
125
|
+
For simple cases where records are created sequentially and timestamps are
|
|
126
|
+
guaranteed unique (e.g., a single-writer queue): a single-field cursor is acceptable.
|
|
127
|
+
Document this assumption in the code.
|
|
128
|
+
|
|
129
|
+
**Transaction usage:**
|
|
130
|
+
```typescript
|
|
131
|
+
// Use transactions whenever multiple writes must succeed or fail together
|
|
132
|
+
await db.$transaction(async (tx) => {
|
|
133
|
+
const order = await tx.orders.create({ data: orderData })
|
|
134
|
+
await tx.orderItems.createMany({ data: items.map(i => ({...i, orderId: order.id})) })
|
|
135
|
+
await tx.inventory.updateMany({ /* deduct stock */ })
|
|
136
|
+
// All three succeed or all three roll back
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
For financial operations or ledger updates, use `SERIALIZABLE` isolation or
|
|
140
|
+
explicit row-level locks to prevent lost updates and double-spend conditions.
|
|
141
|
+
|
|
142
|
+
### Index strategy
|
|
143
|
+
|
|
144
|
+
**Always index:**
|
|
145
|
+
- All foreign key columns (ORM does not always do this automatically)
|
|
146
|
+
- Columns used in WHERE clauses on large tables
|
|
147
|
+
- Columns used in ORDER BY on large tables
|
|
148
|
+
- Columns used in JOIN conditions
|
|
149
|
+
|
|
150
|
+
**Composite indexes:**
|
|
151
|
+
- Order columns from most selective (highest cardinality) to least
|
|
152
|
+
- A composite index on (a, b) is used for queries filtering on a alone,
|
|
153
|
+
or on both a and b. Not for b alone.
|
|
154
|
+
- Example: index on (user_id, created_at DESC) for "get user's recent items"
|
|
155
|
+
|
|
156
|
+
**Never index:**
|
|
157
|
+
- Boolean columns on large tables (index selectivity too low to help)
|
|
158
|
+
- Columns that change very frequently (index maintenance overhead)
|
|
159
|
+
- Tables with fewer than 10,000 rows (full scan is faster)
|
|
160
|
+
|
|
161
|
+
### Migration standards
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Every schema change must have a migration file
|
|
165
|
+
# Naming: [timestamp]_[descriptive-name].sql or per ORM convention
|
|
166
|
+
|
|
167
|
+
# Migration must be:
|
|
168
|
+
# 1. Idempotent: safe to run multiple times
|
|
169
|
+
# 2. Reversible: has both UP and DOWN migration
|
|
170
|
+
# 3. Non-blocking: avoid full table locks in production migrations
|
|
171
|
+
|
|
172
|
+
# Non-blocking pattern for adding a column (PostgreSQL):
|
|
173
|
+
# Step 1: Add column with default as NULL (instant)
|
|
174
|
+
ALTER TABLE users ADD COLUMN phone_verified BOOLEAN;
|
|
175
|
+
|
|
176
|
+
# Step 2: Backfill in batches (separate deployment)
|
|
177
|
+
UPDATE users SET phone_verified = false
|
|
178
|
+
WHERE id IN (SELECT id FROM users WHERE phone_verified IS NULL LIMIT 1000);
|
|
179
|
+
|
|
180
|
+
# Step 3: Add NOT NULL constraint + default (after backfill completes)
|
|
181
|
+
ALTER TABLE users ALTER COLUMN phone_verified SET NOT NULL;
|
|
182
|
+
ALTER TABLE users ALTER COLUMN phone_verified SET DEFAULT false;
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Query performance checklist
|
|
186
|
+
Before committing any query-writing task:
|
|
187
|
+
- [ ] Ran EXPLAIN ANALYZE on all non-trivial queries
|
|
188
|
+
- [ ] All WHERE/JOIN/ORDER BY columns have indexes
|
|
189
|
+
- [ ] No N+1 queries in list-fetching code
|
|
190
|
+
- [ ] Large queries paginated (cursor-based for > 1K rows)
|
|
191
|
+
- [ ] Transactions used for multi-write operations
|
|
192
|
+
- [ ] Connection pooling configured (not creating connections per request)
|