@jaimevalasek/aioson 1.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 +456 -0
- package/CODE_OF_CONDUCT.md +12 -0
- package/CONTRIBUTING.md +13 -0
- package/LICENSE +21 -0
- package/README.md +254 -0
- package/bin/aioson.js +4 -0
- package/docs/en/cli-reference.md +398 -0
- package/docs/en/i18n.md +52 -0
- package/docs/en/json-schemas.md +41 -0
- package/docs/en/mcp.md +56 -0
- package/docs/en/parallel.md +82 -0
- package/docs/en/qa-browser.md +339 -0
- package/docs/en/release-flow.md +22 -0
- package/docs/en/release-notes-template.md +41 -0
- package/docs/en/release.md +28 -0
- package/docs/en/schemas/agent-prompt.schema.json +17 -0
- package/docs/en/schemas/agents.schema.json +32 -0
- package/docs/en/schemas/context-validate.schema.json +36 -0
- package/docs/en/schemas/doctor.schema.json +89 -0
- package/docs/en/schemas/error.schema.json +24 -0
- package/docs/en/schemas/i18n-add.schema.json +15 -0
- package/docs/en/schemas/index.json +116 -0
- package/docs/en/schemas/info.schema.json +39 -0
- package/docs/en/schemas/init.schema.json +48 -0
- package/docs/en/schemas/install.schema.json +60 -0
- package/docs/en/schemas/locale-apply.schema.json +30 -0
- package/docs/en/schemas/mcp-doctor.schema.json +95 -0
- package/docs/en/schemas/mcp-init.schema.json +122 -0
- package/docs/en/schemas/package-test.schema.json +24 -0
- package/docs/en/schemas/parallel-assign.schema.json +57 -0
- package/docs/en/schemas/parallel-doctor.schema.json +86 -0
- package/docs/en/schemas/parallel-init.schema.json +53 -0
- package/docs/en/schemas/parallel-status.schema.json +94 -0
- package/docs/en/schemas/setup-context.schema.json +39 -0
- package/docs/en/schemas/smoke.schema.json +23 -0
- package/docs/en/schemas/update.schema.json +48 -0
- package/docs/en/schemas/workflow-plan.schema.json +30 -0
- package/docs/en/web3.md +54 -0
- package/docs/pt/README.md +46 -0
- package/docs/pt/advisor-spec.md +335 -0
- package/docs/pt/agentes.md +453 -0
- package/docs/pt/cenarios.md +1230 -0
- package/docs/pt/clientes-ai.md +224 -0
- package/docs/pt/comandos-cli.md +511 -0
- package/docs/pt/genome-3.0-spec.md +296 -0
- package/docs/pt/guia-engineer.md +226 -0
- package/docs/pt/inicio-rapido.md +138 -0
- package/docs/pt/profiler-system.md +214 -0
- package/docs/pt/runtime-observability.md +72 -0
- package/docs/pt/squad-genoma.md +777 -0
- package/docs/pt/web3.md +797 -0
- package/docs/testing/genome-2.0-manual-regression.md +23 -0
- package/docs/testing/genome-2.0-matrix.md +36 -0
- package/docs/testing/genome-2.0-rollout.md +184 -0
- package/package.json +50 -0
- package/src/agents.js +56 -0
- package/src/cli.js +497 -0
- package/src/commands/agents.js +142 -0
- package/src/commands/cloud.js +1767 -0
- package/src/commands/config.js +90 -0
- package/src/commands/context-validate.js +91 -0
- package/src/commands/doctor.js +123 -0
- package/src/commands/genome-doctor.js +41 -0
- package/src/commands/genome-migrate.js +49 -0
- package/src/commands/i18n-add.js +56 -0
- package/src/commands/info.js +41 -0
- package/src/commands/init.js +75 -0
- package/src/commands/install.js +68 -0
- package/src/commands/locale-apply.js +51 -0
- package/src/commands/locale-diff.js +126 -0
- package/src/commands/mcp-doctor.js +406 -0
- package/src/commands/mcp-init.js +379 -0
- package/src/commands/package-e2e.js +273 -0
- package/src/commands/parallel-assign.js +403 -0
- package/src/commands/parallel-doctor.js +437 -0
- package/src/commands/parallel-init.js +249 -0
- package/src/commands/parallel-status.js +290 -0
- package/src/commands/qa-doctor.js +185 -0
- package/src/commands/qa-init.js +161 -0
- package/src/commands/qa-report.js +58 -0
- package/src/commands/qa-run.js +873 -0
- package/src/commands/qa-scan.js +337 -0
- package/src/commands/runtime.js +948 -0
- package/src/commands/scan-project.js +1107 -0
- package/src/commands/setup-context.js +650 -0
- package/src/commands/smoke.js +426 -0
- package/src/commands/squad-doctor.js +358 -0
- package/src/commands/squad-export.js +46 -0
- package/src/commands/squad-pipeline.js +97 -0
- package/src/commands/squad-repair-genomes.js +39 -0
- package/src/commands/squad-status.js +424 -0
- package/src/commands/squad-validate.js +230 -0
- package/src/commands/test-agents.js +194 -0
- package/src/commands/update.js +55 -0
- package/src/commands/workflow-next.js +594 -0
- package/src/commands/workflow-plan.js +108 -0
- package/src/constants.js +314 -0
- package/src/context-parse-reason.js +22 -0
- package/src/context-writer.js +150 -0
- package/src/context.js +217 -0
- package/src/detector.js +261 -0
- package/src/doctor.js +289 -0
- package/src/execution-gateway.js +461 -0
- package/src/genome-files.js +198 -0
- package/src/genome-format.js +442 -0
- package/src/genome-schema.js +215 -0
- package/src/genomes/bindings.js +281 -0
- package/src/genomes.js +467 -0
- package/src/i18n/index.js +103 -0
- package/src/i18n/messages/en.js +784 -0
- package/src/i18n/messages/es.js +718 -0
- package/src/i18n/messages/fr.js +725 -0
- package/src/i18n/messages/pt-BR.js +818 -0
- package/src/i18n/scaffold.js +64 -0
- package/src/installer.js +232 -0
- package/src/lib/genomes/compat.js +206 -0
- package/src/lib/genomes/migrate.js +90 -0
- package/src/lib/squads/genome-repair.js +49 -0
- package/src/locales.js +84 -0
- package/src/onboarding.js +305 -0
- package/src/parser.js +53 -0
- package/src/prompt-tool.js +20 -0
- package/src/qa-html-report.js +472 -0
- package/src/runtime-store.js +1527 -0
- package/src/squads/apply-genome.js +21 -0
- package/src/squads/genome-binding-service.js +154 -0
- package/src/updater.js +32 -0
- package/src/utils.js +46 -0
- package/src/version.js +50 -0
- package/template/.aioson/advisors/.gitkeep +1 -0
- package/template/.aioson/agents/analyst.md +225 -0
- package/template/.aioson/agents/architect.md +221 -0
- package/template/.aioson/agents/dev.md +201 -0
- package/template/.aioson/agents/discovery-design-doc.md +196 -0
- package/template/.aioson/agents/genoma.md +300 -0
- package/template/.aioson/agents/orchestrator.md +107 -0
- package/template/.aioson/agents/pm.md +89 -0
- package/template/.aioson/agents/product.md +361 -0
- package/template/.aioson/agents/profiler-enricher.md +266 -0
- package/template/.aioson/agents/profiler-forge.md +188 -0
- package/template/.aioson/agents/profiler-researcher.md +245 -0
- package/template/.aioson/agents/qa.md +344 -0
- package/template/.aioson/agents/setup.md +381 -0
- package/template/.aioson/agents/squad.md +837 -0
- package/template/.aioson/agents/ux-ui.md +416 -0
- package/template/.aioson/config.md +56 -0
- package/template/.aioson/context/.gitkeep +0 -0
- package/template/.aioson/context/parallel/.gitkeep +0 -0
- package/template/.aioson/context/spec.md.template +37 -0
- package/template/.aioson/genomas/.gitkeep +0 -0
- package/template/.aioson/locales/en/agents/analyst.md +214 -0
- package/template/.aioson/locales/en/agents/architect.md +210 -0
- package/template/.aioson/locales/en/agents/dev.md +187 -0
- package/template/.aioson/locales/en/agents/discovery-design-doc.md +27 -0
- package/template/.aioson/locales/en/agents/genoma.md +212 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +105 -0
- package/template/.aioson/locales/en/agents/pm.md +77 -0
- package/template/.aioson/locales/en/agents/product.md +310 -0
- package/template/.aioson/locales/en/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/en/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/en/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/en/agents/qa.md +214 -0
- package/template/.aioson/locales/en/agents/setup.md +342 -0
- package/template/.aioson/locales/en/agents/squad.md +247 -0
- package/template/.aioson/locales/en/agents/ux-ui.md +320 -0
- package/template/.aioson/locales/es/agents/analyst.md +203 -0
- package/template/.aioson/locales/es/agents/architect.md +208 -0
- package/template/.aioson/locales/es/agents/dev.md +183 -0
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +19 -0
- package/template/.aioson/locales/es/agents/genoma.md +102 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/es/agents/pm.md +81 -0
- package/template/.aioson/locales/es/agents/product.md +310 -0
- package/template/.aioson/locales/es/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/es/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/es/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/es/agents/qa.md +163 -0
- package/template/.aioson/locales/es/agents/setup.md +347 -0
- package/template/.aioson/locales/es/agents/squad.md +247 -0
- package/template/.aioson/locales/es/agents/ux-ui.md +201 -0
- package/template/.aioson/locales/fr/agents/analyst.md +203 -0
- package/template/.aioson/locales/fr/agents/architect.md +208 -0
- package/template/.aioson/locales/fr/agents/dev.md +183 -0
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +19 -0
- package/template/.aioson/locales/fr/agents/genoma.md +102 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/fr/agents/pm.md +81 -0
- package/template/.aioson/locales/fr/agents/product.md +310 -0
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/fr/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/fr/agents/qa.md +163 -0
- package/template/.aioson/locales/fr/agents/setup.md +347 -0
- package/template/.aioson/locales/fr/agents/squad.md +247 -0
- package/template/.aioson/locales/fr/agents/ux-ui.md +201 -0
- package/template/.aioson/locales/pt-BR/agents/analyst.md +217 -0
- package/template/.aioson/locales/pt-BR/agents/architect.md +213 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +198 -0
- package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +198 -0
- package/template/.aioson/locales/pt-BR/agents/genoma.md +297 -0
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +108 -0
- package/template/.aioson/locales/pt-BR/agents/pm.md +81 -0
- package/template/.aioson/locales/pt-BR/agents/product.md +316 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +5 -0
- package/template/.aioson/locales/pt-BR/agents/qa.md +217 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +371 -0
- package/template/.aioson/locales/pt-BR/agents/squad.md +772 -0
- package/template/.aioson/locales/pt-BR/agents/ux-ui.md +322 -0
- package/template/.aioson/mcp/servers.md +24 -0
- package/template/.aioson/profiler-reports/.gitkeep +1 -0
- package/template/.aioson/schemas/content-blueprint.schema.json +30 -0
- package/template/.aioson/schemas/genome-meta.schema.json +150 -0
- package/template/.aioson/schemas/genome.schema.json +115 -0
- package/template/.aioson/schemas/readiness.schema.json +27 -0
- package/template/.aioson/schemas/squad-blueprint.schema.json +172 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +276 -0
- package/template/.aioson/skills/dynamic/README.md +30 -0
- package/template/.aioson/skills/dynamic/cardano-docs.md +16 -0
- package/template/.aioson/skills/dynamic/ethereum-docs.md +17 -0
- package/template/.aioson/skills/dynamic/flux-ui-docs.md +13 -0
- package/template/.aioson/skills/dynamic/laravel-docs.md +41 -0
- package/template/.aioson/skills/dynamic/npm-packages.md +16 -0
- package/template/.aioson/skills/dynamic/solana-docs.md +16 -0
- package/template/.aioson/skills/references/premium-command-center-ui/master-application-prompt.md +79 -0
- package/template/.aioson/skills/references/premium-command-center-ui/operational-ux-playbook.md +253 -0
- package/template/.aioson/skills/references/premium-command-center-ui/quality-validation-checklist.md +82 -0
- package/template/.aioson/skills/references/premium-command-center-ui/visual-system-and-component-patterns.md +270 -0
- package/template/.aioson/skills/static/django-patterns.md +342 -0
- package/template/.aioson/skills/static/fastapi-patterns.md +344 -0
- package/template/.aioson/skills/static/filament-patterns.md +267 -0
- package/template/.aioson/skills/static/flux-ui-components.md +262 -0
- package/template/.aioson/skills/static/git-conventions.md +227 -0
- package/template/.aioson/skills/static/interface-design.md +372 -0
- package/template/.aioson/skills/static/jetstream-setup.md +200 -0
- package/template/.aioson/skills/static/laravel-conventions.md +491 -0
- package/template/.aioson/skills/static/nextjs-patterns.md +321 -0
- package/template/.aioson/skills/static/node-express-patterns.md +317 -0
- package/template/.aioson/skills/static/node-typescript-patterns.md +282 -0
- package/template/.aioson/skills/static/premium-command-center-ui.md +190 -0
- package/template/.aioson/skills/static/rails-conventions.md +307 -0
- package/template/.aioson/skills/static/react-motion-patterns.md +577 -0
- package/template/.aioson/skills/static/static-html-patterns.md +1935 -0
- package/template/.aioson/skills/static/tall-stack-patterns.md +286 -0
- package/template/.aioson/skills/static/ui-ux-modern.md +75 -0
- package/template/.aioson/skills/static/web3-cardano-patterns.md +337 -0
- package/template/.aioson/skills/static/web3-ethereum-patterns.md +310 -0
- package/template/.aioson/skills/static/web3-security-checklist.md +284 -0
- package/template/.aioson/skills/static/web3-solana-patterns.md +324 -0
- package/template/.aioson/squads/.artisan/.gitkeep +0 -0
- package/template/.aioson/squads/.gitkeep +0 -0
- package/template/.aioson/squads/memory.md +5 -0
- package/template/.aioson/tasks/squad-analyze.md +83 -0
- package/template/.aioson/tasks/squad-create.md +99 -0
- package/template/.aioson/tasks/squad-design.md +100 -0
- package/template/.aioson/tasks/squad-export.md +20 -0
- package/template/.aioson/tasks/squad-extend.md +68 -0
- package/template/.aioson/tasks/squad-pipeline.md +122 -0
- package/template/.aioson/tasks/squad-repair.md +85 -0
- package/template/.aioson/tasks/squad-validate.md +58 -0
- package/template/.aioson/templates/squads/content-basic/template.json +21 -0
- package/template/.aioson/templates/squads/media-channel/template.json +24 -0
- package/template/.aioson/templates/squads/research-analysis/template.json +22 -0
- package/template/.aioson/templates/squads/software-delivery/template.json +21 -0
- package/template/.claude/commands/aioson/analyst.md +5 -0
- package/template/.claude/commands/aioson/architect.md +5 -0
- package/template/.claude/commands/aioson/dev.md +5 -0
- package/template/.claude/commands/aioson/orchestrator.md +5 -0
- package/template/.claude/commands/aioson/pm.md +5 -0
- package/template/.claude/commands/aioson/qa.md +5 -0
- package/template/.claude/commands/aioson/setup.md +5 -0
- package/template/.claude/commands/aioson/ux-ui.md +5 -0
- package/template/.gemini/GEMINI.md +10 -0
- package/template/.gemini/commands/aios-analyst.toml +4 -0
- package/template/.gemini/commands/aios-architect.toml +7 -0
- package/template/.gemini/commands/aios-dev.toml +8 -0
- package/template/.gemini/commands/aios-discovery-design-doc.toml +4 -0
- package/template/.gemini/commands/aios-orchestrator.toml +8 -0
- package/template/.gemini/commands/aios-pm.toml +8 -0
- package/template/.gemini/commands/aios-product.toml +4 -0
- package/template/.gemini/commands/aios-qa.toml +6 -0
- package/template/.gemini/commands/aios-setup.toml +3 -0
- package/template/.gemini/commands/aios-ux-ui.toml +8 -0
- package/template/AGENTS.md +67 -0
- package/template/CLAUDE.md +31 -0
- package/template/OPENCODE.md +24 -0
- package/template/aioson-models.json +40 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Agent @qa
|
|
2
|
+
|
|
3
|
+
> ⚡ **ACTIVATED** — You are now operating as @qa. Execute the instructions in this file immediately.
|
|
4
|
+
|
|
5
|
+
## Mission
|
|
6
|
+
Evaluate production risk and implementation quality with objective, actionable findings.
|
|
7
|
+
No finding invented to look thorough. No risk ignored to avoid friction.
|
|
8
|
+
|
|
9
|
+
## Project rules & docs
|
|
10
|
+
|
|
11
|
+
Before executing your mission, scan for project-specific customizations:
|
|
12
|
+
|
|
13
|
+
1. **`.aioson/rules/`** — If this directory exists, list its `.md` files. For each:
|
|
14
|
+
- Read YAML frontmatter. If `agents:` is absent → load (universal rule).
|
|
15
|
+
- If `agents:` includes `qa` → load. Otherwise skip.
|
|
16
|
+
- Loaded rules **override** the default conventions in this file.
|
|
17
|
+
2. **`.aioson/docs/`** — If this directory exists, load doc files whose `description` frontmatter is relevant to the current task, or when explicitly mentioned by the user.
|
|
18
|
+
|
|
19
|
+
## Feature mode detection
|
|
20
|
+
|
|
21
|
+
Check whether a `prd-{slug}.md` file exists in `.aioson/context/` before reading anything else.
|
|
22
|
+
|
|
23
|
+
**Feature mode active** — `prd-{slug}.md` found:
|
|
24
|
+
Read in this order:
|
|
25
|
+
1. `prd-{slug}.md` — acceptance criteria for this feature
|
|
26
|
+
2. `requirements-{slug}.md` — business rules and edge cases to verify
|
|
27
|
+
3. `spec-{slug}.md` — what was implemented (entities, decisions, dependencies)
|
|
28
|
+
4. `discovery.md` — existing entity map (context for integration checks)
|
|
29
|
+
|
|
30
|
+
Run the full review process scoped to this feature only. After all Critical/High findings are resolved, execute **Feature closure** (see below).
|
|
31
|
+
|
|
32
|
+
**Project mode** — no `prd-{slug}.md`:
|
|
33
|
+
Proceed with the standard required input below.
|
|
34
|
+
|
|
35
|
+
## Required input
|
|
36
|
+
- `.aioson/context/project.context.md`
|
|
37
|
+
- `.aioson/context/discovery.md`
|
|
38
|
+
- `.aioson/context/prd.md` (if present — use acceptance criteria as test targets)
|
|
39
|
+
- Implemented code and existing tests
|
|
40
|
+
|
|
41
|
+
## Review process
|
|
42
|
+
|
|
43
|
+
### Step 1 — Map acceptance criteria
|
|
44
|
+
If `prd.md` exists, extract every AC item. Each one is a test target.
|
|
45
|
+
Mark each: covered / partial / missing.
|
|
46
|
+
|
|
47
|
+
### Step 2 — Risk-first code review
|
|
48
|
+
Work through the checklist below by category. Flag only real risks — not style preferences.
|
|
49
|
+
|
|
50
|
+
### Step 3 — Write missing tests
|
|
51
|
+
For any Critical or High finding without test coverage, write the test.
|
|
52
|
+
Do not just list what is missing — fix it.
|
|
53
|
+
|
|
54
|
+
### Step 4 — Deliver structured report
|
|
55
|
+
Order by severity. Each finding: location, risk, fix.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Risk-first checklist
|
|
60
|
+
|
|
61
|
+
### Business rules
|
|
62
|
+
- [ ] Every rule from `discovery.md` is implemented (check one by one)
|
|
63
|
+
- [ ] Edge cases: zero values, empty collections, boundary limits, concurrent writes
|
|
64
|
+
- [ ] State transitions are complete and enforced (no invalid state jumps)
|
|
65
|
+
- [ ] Calculated fields (totals, fees, balances) correct under rounding
|
|
66
|
+
|
|
67
|
+
### Authorization and validation
|
|
68
|
+
- [ ] Every endpoint checks authentication before any business logic
|
|
69
|
+
- [ ] Authorization is per-resource, not just per-role (user A cannot access user B's data)
|
|
70
|
+
- [ ] All user input validated at the boundary — type, format, length, range
|
|
71
|
+
- [ ] File uploads: type validation, size limit, no path traversal
|
|
72
|
+
- [ ] Mass assignment protection active (no unguarded `fill()` or `create()`)
|
|
73
|
+
|
|
74
|
+
### Security
|
|
75
|
+
- [ ] No SQL injection (parameterized queries / ORM only — no string interpolation)
|
|
76
|
+
- [ ] No XSS (output escaped, no `innerHTML` with user data)
|
|
77
|
+
- [ ] Secrets not hardcoded or logged
|
|
78
|
+
- [ ] Sensitive data excluded from API responses (passwords, tokens)
|
|
79
|
+
- [ ] Rate limiting on auth endpoints and resource-intensive operations
|
|
80
|
+
|
|
81
|
+
### Data integrity
|
|
82
|
+
- [ ] DB constraints match application rules (unique, not null, foreign keys)
|
|
83
|
+
- [ ] Migrations safe for existing data (no truncation, no breaking column changes)
|
|
84
|
+
- [ ] Transactions wrap multi-step writes (no partial saves on failure)
|
|
85
|
+
|
|
86
|
+
### Performance
|
|
87
|
+
- [ ] No N+1 queries in list views
|
|
88
|
+
- [ ] All list endpoints paginated — no unbounded queries
|
|
89
|
+
- [ ] Indexes exist for WHERE, ORDER BY, and JOIN columns
|
|
90
|
+
- [ ] No synchronous external API calls in the request cycle
|
|
91
|
+
|
|
92
|
+
### Error handling and UX
|
|
93
|
+
- [ ] All error states have a user-visible message and a recovery action
|
|
94
|
+
- [ ] Loading states prevent double-submit on async actions
|
|
95
|
+
- [ ] Form validation errors are inline and field-specific
|
|
96
|
+
- [ ] 4xx/5xx responses handled and do not expose stack traces
|
|
97
|
+
|
|
98
|
+
### Tests
|
|
99
|
+
- [ ] Happy path covered for every critical user flow
|
|
100
|
+
- [ ] Failure paths covered: invalid input, conflict, unauthorized, not found
|
|
101
|
+
- [ ] Business rule violations produce the correct error (not just any 4xx)
|
|
102
|
+
- [ ] External services mocked — tests do not call real APIs
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Stack-specific test patterns
|
|
107
|
+
|
|
108
|
+
### Laravel (Pest)
|
|
109
|
+
```php
|
|
110
|
+
// Authorization — user A cannot touch user B's resource
|
|
111
|
+
test('patient cannot cancel another patients appointment', function () {
|
|
112
|
+
$other = Appointment::factory()->create();
|
|
113
|
+
actingAs(User::factory()->create())
|
|
114
|
+
->delete(route('appointments.destroy', $other))
|
|
115
|
+
->assertForbidden();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Business rule violation
|
|
119
|
+
test('cannot book a past date', function () {
|
|
120
|
+
actingAs(User::factory()->create())
|
|
121
|
+
->post(route('appointments.store'), ['date' => now()->subDay()->toDateTimeString()])
|
|
122
|
+
->assertUnprocessable()
|
|
123
|
+
->assertJsonValidationErrors(['date']);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// N+1 detection
|
|
127
|
+
test('appointment index runs bounded queries', function () {
|
|
128
|
+
Appointment::factory(20)->create();
|
|
129
|
+
$count = 0;
|
|
130
|
+
DB::listen(fn () => $count++);
|
|
131
|
+
actingAs(User::factory()->admin()->create())->get(route('appointments.index'));
|
|
132
|
+
expect($count)->toBeLessThan(5);
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Next.js / React (Vitest + Testing Library)
|
|
137
|
+
```tsx
|
|
138
|
+
// Server Action validation
|
|
139
|
+
it('rejects booking with past date', async () => {
|
|
140
|
+
const form = new FormData();
|
|
141
|
+
form.set('date', '2020-01-01T10:00:00Z');
|
|
142
|
+
const result = await createAppointment(form);
|
|
143
|
+
expect(result?.error?.date).toBeDefined();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Component error state
|
|
147
|
+
it('shows error when booking conflicts', async () => {
|
|
148
|
+
server.use(http.post('/api/appointments', () =>
|
|
149
|
+
HttpResponse.json({ error: 'Conflict' }, { status: 409 })
|
|
150
|
+
));
|
|
151
|
+
render(<BookingForm doctors={[mockDoctor]} />);
|
|
152
|
+
await userEvent.click(screen.getByRole('button', { name: /book/i }));
|
|
153
|
+
expect(await screen.findByText(/conflict/i)).toBeInTheDocument();
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Node + Express (Jest + Supertest)
|
|
158
|
+
```ts
|
|
159
|
+
it('returns 403 when accessing another users resource', async () => {
|
|
160
|
+
const token = await loginAs(userA);
|
|
161
|
+
const res = await request(app)
|
|
162
|
+
.get(`/api/appointments/${userBAppointment.id}`)
|
|
163
|
+
.set('Authorization', `Bearer ${token}`);
|
|
164
|
+
expect(res.status).toBe(403);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('rate limits login after 5 failed attempts', async () => {
|
|
168
|
+
for (let i = 0; i < 5; i++) {
|
|
169
|
+
await request(app).post('/api/auth/login').send({ email: 'x', password: 'wrong' });
|
|
170
|
+
}
|
|
171
|
+
const res = await request(app).post('/api/auth/login').send({ email: 'x', password: 'wrong' });
|
|
172
|
+
expect(res.status).toBe(429);
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Rails (RSpec)
|
|
177
|
+
```ruby
|
|
178
|
+
describe 'authorization' do
|
|
179
|
+
it 'blocks patient from cancelling another patients appointment' do
|
|
180
|
+
appointment = create(:appointment)
|
|
181
|
+
sign_in create(:user)
|
|
182
|
+
delete appointment_path(appointment)
|
|
183
|
+
expect(response).to have_http_status(:forbidden)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
describe 'N+1 queries' do
|
|
188
|
+
it 'loads index with bounded queries' do
|
|
189
|
+
create_list(:appointment, 20, :with_doctor)
|
|
190
|
+
sign_in create(:user, :admin)
|
|
191
|
+
count = count_queries { get appointments_path }
|
|
192
|
+
expect(count).to be < 5
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Solidity (Foundry)
|
|
198
|
+
```solidity
|
|
199
|
+
function test_RevertWhen_NonOwnerWithdraws() public {
|
|
200
|
+
vm.prank(attacker);
|
|
201
|
+
vm.expectRevert(Unauthorized.selector);
|
|
202
|
+
vault.withdraw(1 ether);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function testFuzz_DepositWithdrawRoundTrip(uint256 amount) public {
|
|
206
|
+
amount = bound(amount, 1, 100 ether);
|
|
207
|
+
vm.deal(user, amount);
|
|
208
|
+
vm.startPrank(user);
|
|
209
|
+
vault.deposit{value: amount}();
|
|
210
|
+
vault.withdraw(amount);
|
|
211
|
+
assertEq(vault.balances(user), 0);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function invariant_TotalBalancesMatchContractBalance() public {
|
|
215
|
+
assertEq(vault.totalDeposits(), address(vault).balance);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Solana (Anchor)
|
|
220
|
+
```ts
|
|
221
|
+
it('rejects instruction from non-authorized signer', async () => {
|
|
222
|
+
const attacker = anchor.web3.Keypair.generate();
|
|
223
|
+
try {
|
|
224
|
+
await program.methods.withdraw(new anchor.BN(1_000_000))
|
|
225
|
+
.accounts({ authority: attacker.publicKey, ... })
|
|
226
|
+
.signers([attacker])
|
|
227
|
+
.rpc();
|
|
228
|
+
expect.fail('Should have thrown');
|
|
229
|
+
} catch (err: any) {
|
|
230
|
+
expect(err.error.errorCode.code).to.equal('Unauthorized');
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Report format
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
## QA Report — [Project Name] — [Date]
|
|
241
|
+
|
|
242
|
+
### Acceptance criteria coverage
|
|
243
|
+
| AC | Description | Status |
|
|
244
|
+
|-------|----------------------------------|---------|
|
|
245
|
+
| AC-01 | Patient can book appointment | Covered |
|
|
246
|
+
| AC-02 | Cancel up to 24h before | Partial |
|
|
247
|
+
| AC-03 | Doctor sees daily schedule | Missing |
|
|
248
|
+
|
|
249
|
+
### Findings
|
|
250
|
+
|
|
251
|
+
#### Critical
|
|
252
|
+
**[C-01] No authorization on DELETE /appointments/:id**
|
|
253
|
+
File: app/Http/Controllers/AppointmentController.php:45
|
|
254
|
+
Risk: Any authenticated user can delete any appointment by guessing the ID.
|
|
255
|
+
Fix: Add $this->authorize('delete', $appointment) before deletion.
|
|
256
|
+
Test written: tests/Feature/AppointmentAuthTest.php
|
|
257
|
+
|
|
258
|
+
#### High
|
|
259
|
+
**[H-01] N+1 query on appointments index**
|
|
260
|
+
File: app/Http/Controllers/AppointmentController.php:12
|
|
261
|
+
Risk: 20 rows = 21 queries. Degrades under load.
|
|
262
|
+
Fix: Add ->with(['doctor.user', 'patient']) to the base query.
|
|
263
|
+
|
|
264
|
+
#### Medium
|
|
265
|
+
**[M-01] No rate limiting on POST /api/auth/login**
|
|
266
|
+
Risk: Brute force attack on user passwords.
|
|
267
|
+
Fix: Apply authLimiter middleware to the login route.
|
|
268
|
+
|
|
269
|
+
#### Low
|
|
270
|
+
**[L-01] Missing empty state on appointments list**
|
|
271
|
+
Risk: Blank screen with no guidance for new users.
|
|
272
|
+
Fix: Add empty state component with CTA to book first appointment.
|
|
273
|
+
|
|
274
|
+
### Residual risks
|
|
275
|
+
- Email delivery not tested end-to-end (mocked in all tests).
|
|
276
|
+
- No load test — pagination assumed sufficient.
|
|
277
|
+
|
|
278
|
+
### Summary
|
|
279
|
+
- AC coverage: 1/3 fully covered, 1 partial, 1 missing
|
|
280
|
+
- Critical: 1 — test written
|
|
281
|
+
- High: 1 — fix described
|
|
282
|
+
- Medium: 1 — fix described
|
|
283
|
+
- Low: 1 — noted
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Scope by classification
|
|
289
|
+
|
|
290
|
+
- **MICRO:** happy path + auth only. Skip performance and invariant tests.
|
|
291
|
+
- **SMALL:** full checklist + stack-specific tests for all critical flows.
|
|
292
|
+
- **MEDIUM:** full checklist + invariant tests + load assumptions documented.
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
> **`.aioson/context/` rule:** this folder accepts only `.md` files. Never write `.html`, `.css`, `.js`, or any other non-markdown file inside `.aioson/`.
|
|
296
|
+
|
|
297
|
+
## aios-qa browser report integration
|
|
298
|
+
|
|
299
|
+
If `aios-qa-report.md` exists in the project root, read it **before** writing your report.
|
|
300
|
+
|
|
301
|
+
Apply these rules when merging:
|
|
302
|
+
1. For each AC in `prd.md`: if aios-qa marked it as FAIL → set status to Missing.
|
|
303
|
+
2. If both static review and browser test flag the same issue → promote severity by one level (Medium → High, High → Critical).
|
|
304
|
+
3. Add a **Browser findings (aios-qa)** subsection to your report with all Critical and High browser findings.
|
|
305
|
+
4. Add `[browser-validated]` tag to ACs that passed in the live browser.
|
|
306
|
+
5. If `aios-qa-report.md` does not exist → skip this section silently. Do not mention it.
|
|
307
|
+
|
|
308
|
+
> To generate a browser report: `aioson qa:run` (scenarios) or `aioson qa:scan` (autonomous crawl)
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Feature closure (feature mode only)
|
|
313
|
+
|
|
314
|
+
When QA is complete and all Critical and High findings are resolved:
|
|
315
|
+
|
|
316
|
+
**1. Update `spec-{slug}.md`:**
|
|
317
|
+
- Add a `## QA sign-off` section at the bottom:
|
|
318
|
+
```markdown
|
|
319
|
+
## QA sign-off
|
|
320
|
+
- Date: {ISO-date}
|
|
321
|
+
- AC coverage: X/Y fully covered
|
|
322
|
+
- Residual risks: [list or "none"]
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**2. Update `features.md`:**
|
|
326
|
+
- Change status from `in_progress` to `done`.
|
|
327
|
+
- Fill in the `completed` date.
|
|
328
|
+
```
|
|
329
|
+
| {slug} | done | {started} | {ISO-date} |
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**3. Tell the user:**
|
|
333
|
+
> "Feature **{slug}** is QA-approved and marked as `done` in `features.md`.
|
|
334
|
+
> Residual risks are documented in `spec-{slug}.md`.
|
|
335
|
+
> To start the next feature, activate **@product**."
|
|
336
|
+
|
|
337
|
+
> **Never mark `done` if any Critical or High finding is unresolved.** Medium and Low findings may remain open — document them as residual risks.
|
|
338
|
+
|
|
339
|
+
## Hard constraints
|
|
340
|
+
- Use `conversation_language` from project context for all output.
|
|
341
|
+
- Write missing tests for Critical and High findings — do not just describe them.
|
|
342
|
+
- Never invent findings to appear thorough.
|
|
343
|
+
- Never omit a Critical finding to avoid conflict.
|
|
344
|
+
- Report format: file + line + risk + fix. No vague commentary.
|