@wazir-dev/cli 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/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,1271 @@
|
|
|
1
|
+
# API Design Anti-Patterns
|
|
2
|
+
> A catalog of structural, semantic, and operational mistakes in HTTP API design that cause outages, security breaches, developer churn, and integration nightmares. Each entry is grounded in production incidents and post-mortems, not theoretical complaints.
|
|
3
|
+
> **Domain:** Backend
|
|
4
|
+
> **Anti-patterns covered:** 21
|
|
5
|
+
> **Highest severity:** Critical
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
1. [AP-01: Chatty API](#ap-01-chatty-api)
|
|
11
|
+
2. [AP-02: God Endpoint](#ap-02-god-endpoint)
|
|
12
|
+
3. [AP-03: Ignoring HTTP Semantics](#ap-03-ignoring-http-semantics)
|
|
13
|
+
4. [AP-04: Breaking Changes Without Versioning](#ap-04-breaking-changes-without-versioning)
|
|
14
|
+
5. [AP-05: Inconsistent Naming Conventions](#ap-05-inconsistent-naming-conventions)
|
|
15
|
+
6. [AP-06: Exposing Internal Implementation Details](#ap-06-exposing-internal-implementation-details)
|
|
16
|
+
7. [AP-07: Missing Pagination](#ap-07-missing-pagination)
|
|
17
|
+
8. [AP-08: Over-Fetching and Under-Fetching](#ap-08-over-fetching-and-under-fetching)
|
|
18
|
+
9. [AP-09: Misusing HTTP Status Codes](#ap-09-misusing-http-status-codes)
|
|
19
|
+
10. [AP-10: Ignoring Idempotency](#ap-10-ignoring-idempotency)
|
|
20
|
+
11. [AP-11: Missing Rate Limiting](#ap-11-missing-rate-limiting)
|
|
21
|
+
12. [AP-12: Authentication in Query Parameters](#ap-12-authentication-in-query-parameters)
|
|
22
|
+
13. [AP-13: Inconsistent Response Shapes](#ap-13-inconsistent-response-shapes)
|
|
23
|
+
14. [AP-14: Nested Resource Hell](#ap-14-nested-resource-hell)
|
|
24
|
+
15. [AP-15: Ignoring HATEOAS When It Matters](#ap-15-ignoring-hateoas-when-it-matters)
|
|
25
|
+
16. [AP-16: Stringly-Typed Everything](#ap-16-stringly-typed-everything)
|
|
26
|
+
17. [AP-17: Missing Request Validation](#ap-17-missing-request-validation)
|
|
27
|
+
18. [AP-18: Synchronous Long-Running Operations](#ap-18-synchronous-long-running-operations)
|
|
28
|
+
19. [AP-19: Leaking PII in URLs and Logs](#ap-19-leaking-pii-in-urls-and-logs)
|
|
29
|
+
20. [AP-20: Undocumented Error Responses](#ap-20-undocumented-error-responses)
|
|
30
|
+
21. [AP-21: Coupling Client to Server Implementation](#ap-21-coupling-client-to-server-implementation)
|
|
31
|
+
22. [Root Cause Analysis](#root-cause-analysis)
|
|
32
|
+
23. [Self-Check Questions](#self-check-questions)
|
|
33
|
+
24. [Code Smell Quick Reference](#code-smell-quick-reference)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### AP-01: Chatty API
|
|
38
|
+
|
|
39
|
+
**Also known as:** Death by a Thousand Requests, N+1 API, Micro-Endpoint Syndrome
|
|
40
|
+
**Frequency:** Very Common
|
|
41
|
+
**Severity:** High
|
|
42
|
+
**Detection difficulty:** Moderate
|
|
43
|
+
|
|
44
|
+
**What it looks like:**
|
|
45
|
+
|
|
46
|
+
A client needs to render a single page but must make 15+ sequential API calls because every piece of data lives behind its own endpoint.
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
GET /users/42 -> { name, email, avatarUrl }
|
|
50
|
+
GET /users/42/preferences -> { theme, locale }
|
|
51
|
+
GET /users/42/subscription -> { plan, expiresAt }
|
|
52
|
+
GET /users/42/notifications -> [ ... ]
|
|
53
|
+
GET /users/42/recent-activity -> [ ... ]
|
|
54
|
+
GET /users/42/team -> { teamId, role }
|
|
55
|
+
GET /teams/7/members -> [ ... ]
|
|
56
|
+
GET /teams/7/plan -> { ... }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This is the classic GraphQL N+1 problem applied to REST. Shopify engineering documented how their GraphQL layer suffered from this pattern: a single query for musicians and their albums would generate 1 query for n musicians plus n additional queries to fetch albums, totaling n+1 database round trips. At 25 items, that is 26 requests per render.
|
|
60
|
+
|
|
61
|
+
**Why developers do it:**
|
|
62
|
+
|
|
63
|
+
- Each microservice owns one resource, so each gets one endpoint.
|
|
64
|
+
- "Small endpoints are easier to test."
|
|
65
|
+
- Premature decomposition: the team splits resources before understanding access patterns.
|
|
66
|
+
|
|
67
|
+
**What goes wrong:**
|
|
68
|
+
|
|
69
|
+
- Latency compounds: 15 sequential requests at 50ms each = 750ms minimum, before any rendering.
|
|
70
|
+
- Mobile clients on high-latency networks suffer disproportionately.
|
|
71
|
+
- Backend load multiplies: one page view becomes 15 database queries.
|
|
72
|
+
- Frontend teams build complex orchestration layers that are fragile and hard to debug.
|
|
73
|
+
|
|
74
|
+
**The fix:**
|
|
75
|
+
|
|
76
|
+
- Provide composite endpoints for known access patterns: `GET /users/42/dashboard` returns everything the dashboard needs.
|
|
77
|
+
- Use field selection (`?fields=name,email,subscription`) to let clients control payload scope.
|
|
78
|
+
- Consider BFF (Backend for Frontend) services that aggregate calls server-side.
|
|
79
|
+
- If using GraphQL, implement DataLoaders to batch N+1 queries into a single batched database call.
|
|
80
|
+
|
|
81
|
+
**Detection rule:**
|
|
82
|
+
|
|
83
|
+
Flag any client workflow that makes more than 3 sequential API calls to render a single view. Monitor for endpoints consistently called together in a fixed sequence.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### AP-02: God Endpoint
|
|
88
|
+
|
|
89
|
+
**Also known as:** Kitchen Sink Endpoint, Do-Everything RPC, Swiss Army Endpoint
|
|
90
|
+
**Frequency:** Common
|
|
91
|
+
**Severity:** High
|
|
92
|
+
**Detection difficulty:** Easy
|
|
93
|
+
|
|
94
|
+
**What it looks like:**
|
|
95
|
+
|
|
96
|
+
A single endpoint that handles dozens of operations through query parameters or request body flags.
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
POST /api/execute
|
|
100
|
+
{
|
|
101
|
+
"action": "createUser",
|
|
102
|
+
"params": { "name": "Alice" }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
POST /api/execute
|
|
106
|
+
{
|
|
107
|
+
"action": "deleteOrder",
|
|
108
|
+
"params": { "orderId": 999 }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
POST /api/execute
|
|
112
|
+
{
|
|
113
|
+
"action": "generateReport",
|
|
114
|
+
"params": { "type": "monthly", "includeCharts": true }
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Or the parameter-flag variant:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
GET /api/data?type=user&id=42&includeOrders=true&includeComments=true&includeProfile=true
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Why developers do it:**
|
|
125
|
+
|
|
126
|
+
- "One endpoint is simpler than managing dozens of routes."
|
|
127
|
+
- RPC habits carried into REST contexts.
|
|
128
|
+
- Convenience during early prototyping that becomes permanent.
|
|
129
|
+
- Fear of URL proliferation.
|
|
130
|
+
|
|
131
|
+
**What goes wrong:**
|
|
132
|
+
|
|
133
|
+
- Authorization becomes a nightmare: you need per-action permission checks inside one handler.
|
|
134
|
+
- Caching is impossible: every request to the same URL does something different.
|
|
135
|
+
- Documentation is unmanageable: one endpoint with 47 possible `action` values.
|
|
136
|
+
- Monitoring and alerting lose granularity: error rate on `/api/execute` tells you nothing about which operation failed.
|
|
137
|
+
- Rate limiting per operation becomes impossible without inspecting request bodies.
|
|
138
|
+
|
|
139
|
+
**The fix:**
|
|
140
|
+
|
|
141
|
+
- Decompose into resource-oriented endpoints: `POST /users`, `DELETE /orders/999`, `POST /reports`.
|
|
142
|
+
- Use HTTP methods to express intent (GET for reads, POST for creates, etc.).
|
|
143
|
+
- If you genuinely need RPC semantics (rare), use a proper RPC framework (gRPC, JSON-RPC) with schema-driven contracts, not a freeform POST body.
|
|
144
|
+
|
|
145
|
+
**Detection rule:**
|
|
146
|
+
|
|
147
|
+
Flag any endpoint that accepts an `action`, `method`, `operation`, or `type` parameter that changes the fundamental behavior of the request. Flag single endpoints receiving more than 5 distinct payload schemas.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### AP-03: Ignoring HTTP Semantics
|
|
152
|
+
|
|
153
|
+
**Also known as:** POST-for-Everything, GET with Side Effects, Method Abuse
|
|
154
|
+
**Frequency:** Very Common
|
|
155
|
+
**Severity:** Critical
|
|
156
|
+
**Detection difficulty:** Moderate
|
|
157
|
+
|
|
158
|
+
**What it looks like:**
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
# Deleting via GET (crawlers and prefetch will trigger this)
|
|
162
|
+
GET /api/users/42/delete
|
|
163
|
+
|
|
164
|
+
# Creating via GET (browser link-checkers will create records)
|
|
165
|
+
GET /api/orders/create?product=widget&qty=5
|
|
166
|
+
|
|
167
|
+
# Reading via POST (breaks caching, bookmarking, and link sharing)
|
|
168
|
+
POST /api/search
|
|
169
|
+
{ "query": "shoes" }
|
|
170
|
+
|
|
171
|
+
# Modifying state with GET (web accelerators pre-fetch GET URLs)
|
|
172
|
+
GET /api/account/close?confirm=true
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The OWASP Web Security Testing Guide explicitly warns about HTTP verb tampering, where attackers manipulate HTTP methods to bypass security controls, such as using PUT or DELETE when only GET access is intended.
|
|
176
|
+
|
|
177
|
+
**Why developers do it:**
|
|
178
|
+
|
|
179
|
+
- Many developers learn web development via HTML forms, which only support GET and POST.
|
|
180
|
+
- "GET is simpler; I just put everything in the query string."
|
|
181
|
+
- Lack of understanding that GET requests can be pre-fetched, cached, replayed by proxies, and triggered by link checkers.
|
|
182
|
+
|
|
183
|
+
**What goes wrong:**
|
|
184
|
+
|
|
185
|
+
- Google Web Accelerator (2005) pre-fetched GET URLs, triggering `GET /delete` endpoints and deleting real user data across hundreds of applications. This was one of the earliest large-scale demonstrations of why GET must be safe and idempotent.
|
|
186
|
+
- Web crawlers and link-checkers trigger state-changing GETs, creating or deleting resources.
|
|
187
|
+
- CDNs and browser caches serve stale responses for POST-based reads.
|
|
188
|
+
- CSRF attacks exploit GET-based mutations trivially (embed an `<img src="/api/transfer?amount=10000">` in an email).
|
|
189
|
+
|
|
190
|
+
**The fix:**
|
|
191
|
+
|
|
192
|
+
- GET and HEAD: read-only, safe, cacheable. Never mutate state.
|
|
193
|
+
- POST: create resources, trigger actions. Not idempotent by default.
|
|
194
|
+
- PUT: full replacement of a resource. Idempotent.
|
|
195
|
+
- PATCH: partial update. Not necessarily idempotent.
|
|
196
|
+
- DELETE: remove a resource. Idempotent.
|
|
197
|
+
- Return `405 Method Not Allowed` for unsupported methods on each endpoint with an `Allow` header listing valid methods.
|
|
198
|
+
|
|
199
|
+
**Detection rule:**
|
|
200
|
+
|
|
201
|
+
Static analysis: flag any GET handler that calls write/delete/update operations on a database or external service. Runtime: flag GET endpoints where the database transaction log shows write operations.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### AP-04: Breaking Changes Without Versioning
|
|
206
|
+
|
|
207
|
+
**Also known as:** YOLO Deployment, Implicit Contract Violation, The Silent Break
|
|
208
|
+
**Frequency:** Common
|
|
209
|
+
**Severity:** Critical
|
|
210
|
+
**Detection difficulty:** Hard
|
|
211
|
+
|
|
212
|
+
**What it looks like:**
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
# Monday: API returns
|
|
216
|
+
{ "user_name": "alice", "email": "alice@example.com" }
|
|
217
|
+
|
|
218
|
+
# Wednesday: same endpoint, same URL
|
|
219
|
+
{ "username": "alice", "contactEmail": "alice@example.com", "name": { "first": "Alice", "last": "Smith" } }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
No version bump. No deprecation notice. No migration guide. Every consumer breaks.
|
|
223
|
+
|
|
224
|
+
In one documented production incident, a team added a required field to what they considered a backward-compatible update. The "minor" schema change broke an enterprise client's entire payment processing pipeline. In another case, a team kept `/v1` alive "just for a few months" — two years later it was still serving a frightening amount of production traffic.
|
|
225
|
+
|
|
226
|
+
**Why developers do it:**
|
|
227
|
+
|
|
228
|
+
- "We only have one consumer and we control it."
|
|
229
|
+
- Versioning infrastructure feels like overhead when the team is small.
|
|
230
|
+
- Misunderstanding what constitutes a breaking change (renaming fields, changing types, removing optional fields, altering enum values).
|
|
231
|
+
|
|
232
|
+
**What goes wrong:**
|
|
233
|
+
|
|
234
|
+
- Hyrum's Law: "With a sufficient number of users of an API, all observable behaviors of your system will be depended on by somebody." Consumers depend on field names, ordering, null behavior, and timing.
|
|
235
|
+
- Mobile apps cannot be force-updated — broken API responses crash apps in production for days.
|
|
236
|
+
- Partner integrations fail silently, corrupting data before anyone notices.
|
|
237
|
+
- Twitter's 2023 API changes broke hundreds of third-party apps with minimal warning. Bot accounts including accessibility tools like Alt Text Reader shut down. Elon Musk had to backtrack on the API paywall after widespread developer backlash.
|
|
238
|
+
|
|
239
|
+
**The fix:**
|
|
240
|
+
|
|
241
|
+
- Version from day one: URL-based (`/v1/users`) or header-based (`Accept: application/vnd.api.v2+json`).
|
|
242
|
+
- Additive-only changes within a version: new optional fields are fine, removing or renaming fields is a new version.
|
|
243
|
+
- Maintain a changelog and deprecation timeline. Communicate through multiple channels.
|
|
244
|
+
- Run contract tests (Pact, Specmatic) in CI that fail on breaking schema changes.
|
|
245
|
+
- Set sunset dates on old versions and enforce them with monitoring.
|
|
246
|
+
|
|
247
|
+
**Detection rule:**
|
|
248
|
+
|
|
249
|
+
CI/CD schema diff: compare OpenAPI/JSON Schema between current and previous release. Flag any removed field, renamed field, type change, or new required field as a breaking change requiring a version bump.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### AP-05: Inconsistent Naming Conventions
|
|
254
|
+
|
|
255
|
+
**Also known as:** Convention Roulette, Schizophrenic Schema, The Naming Jungle
|
|
256
|
+
**Frequency:** Very Common
|
|
257
|
+
**Severity:** Medium
|
|
258
|
+
**Detection difficulty:** Easy
|
|
259
|
+
|
|
260
|
+
**What it looks like:**
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"user_name": "alice",
|
|
265
|
+
"firstName": "Alice",
|
|
266
|
+
"last-name": "Smith",
|
|
267
|
+
"EmailAddress": "alice@example.com",
|
|
268
|
+
"created_at": "2024-01-01",
|
|
269
|
+
"updatedOn": "January 2, 2024",
|
|
270
|
+
"isActive": true,
|
|
271
|
+
"account_status": "ACTIVE"
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Mixing `snake_case`, `camelCase`, `kebab-case`, and `PascalCase` in the same response. Date formats vary between ISO 8601, Unix timestamps, and human-readable strings. Boolean concepts represented as both booleans and string enums.
|
|
276
|
+
|
|
277
|
+
**Why developers do it:**
|
|
278
|
+
|
|
279
|
+
- Multiple developers or teams contribute endpoints without shared style guides.
|
|
280
|
+
- Backend language conventions leak into API surface (Python uses snake_case, Java uses camelCase).
|
|
281
|
+
- Copy-pasting from different documentation sources.
|
|
282
|
+
- No automated linting.
|
|
283
|
+
|
|
284
|
+
**What goes wrong:**
|
|
285
|
+
|
|
286
|
+
- Developer experience degrades: consumers must check documentation for every field name because nothing is predictable.
|
|
287
|
+
- SDK generation produces inconsistent code.
|
|
288
|
+
- Integrations contain typos and casing bugs that pass code review but fail at runtime.
|
|
289
|
+
- One API review of 300+ API designs found inconsistent naming as one of the top 3 most frequent mistakes.
|
|
290
|
+
|
|
291
|
+
**The fix:**
|
|
292
|
+
|
|
293
|
+
- Pick one convention for the API surface (typically `camelCase` for JSON, `snake_case` for query parameters) and enforce it with a linter.
|
|
294
|
+
- Standardize date format (ISO 8601), pagination terminology (`limit`/`offset` or `cursor`/`pageSize`), and boolean naming (`isActive`, not `active_status`).
|
|
295
|
+
- Use OpenAPI/JSON Schema linting tools (Spectral, Redocly) in CI to catch violations before merge.
|
|
296
|
+
|
|
297
|
+
**Detection rule:**
|
|
298
|
+
|
|
299
|
+
Lint rule: scan all response schemas for mixed casing conventions within a single API. Flag any endpoint where field names use more than one casing style.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### AP-06: Exposing Internal Implementation Details
|
|
304
|
+
|
|
305
|
+
**Also known as:** Leaky Abstraction API, Database-as-API, Implementation Coupling
|
|
306
|
+
**Frequency:** Common
|
|
307
|
+
**Severity:** High
|
|
308
|
+
**Detection difficulty:** Moderate
|
|
309
|
+
|
|
310
|
+
**What it looks like:**
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
// Exposing database column names and internal IDs
|
|
314
|
+
{
|
|
315
|
+
"pk_user_id": 42,
|
|
316
|
+
"fk_org_id": 7,
|
|
317
|
+
"tbl_users_created_at": "2024-01-01",
|
|
318
|
+
"mysql_auto_increment_offset": 42
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Exposing internal service topology
|
|
322
|
+
{
|
|
323
|
+
"data": { ... },
|
|
324
|
+
"_debug": {
|
|
325
|
+
"served_by": "user-service-pod-3a7f",
|
|
326
|
+
"db_query_time_ms": 12,
|
|
327
|
+
"cache_hit": false,
|
|
328
|
+
"redis_node": "cache-east-2"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Stack traces in production error responses
|
|
333
|
+
{
|
|
334
|
+
"error": "NullPointerException at com.myapp.service.UserService.getProfile(UserService.java:142)"
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Why developers do it:**
|
|
339
|
+
|
|
340
|
+
- Direct database-to-JSON serialization without a DTO/mapping layer.
|
|
341
|
+
- Debug information left enabled in production.
|
|
342
|
+
- Error handlers that dump raw exception details.
|
|
343
|
+
- The API was originally "internal only" but scope expanded.
|
|
344
|
+
|
|
345
|
+
**What goes wrong:**
|
|
346
|
+
|
|
347
|
+
- Attackers gain reconnaissance: database technology, table structures, service topology, and code paths.
|
|
348
|
+
- Internal refactoring (renaming a column, moving to a different database) becomes a breaking API change.
|
|
349
|
+
- Leaky abstractions create implicit coupling — consumers depend on internals they should never have seen, and those dependencies are invisible in the codebase.
|
|
350
|
+
- The Experian API incident (2021) demonstrated this: their API exposed credit scores of tens of millions of Americans because the API design leaked internal data access patterns, authenticating users with only name and address — essentially public information.
|
|
351
|
+
|
|
352
|
+
**The fix:**
|
|
353
|
+
|
|
354
|
+
- Always map internal models to API-specific DTOs/response schemas.
|
|
355
|
+
- Strip debug headers and internal metadata in production (or gate behind an internal-only header).
|
|
356
|
+
- Use a generic error envelope that never includes stack traces, SQL queries, or internal paths.
|
|
357
|
+
- Treat the API schema as a public contract independent of internal implementation.
|
|
358
|
+
|
|
359
|
+
**Detection rule:**
|
|
360
|
+
|
|
361
|
+
Scan response schemas for field names containing `pk_`, `fk_`, `tbl_`, `_id` with database prefixes, `_internal`, `_debug`. Scan error responses for stack traces, file paths, or SQL fragments.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### AP-07: Missing Pagination
|
|
366
|
+
|
|
367
|
+
**Also known as:** The Unbounded Query, SELECT * FROM production, Memory Bomb
|
|
368
|
+
**Frequency:** Very Common
|
|
369
|
+
**Severity:** Critical
|
|
370
|
+
**Detection difficulty:** Easy
|
|
371
|
+
|
|
372
|
+
**What it looks like:**
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
GET /api/orders
|
|
376
|
+
-> Returns ALL 2.3 million orders in a single response
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
```
|
|
380
|
+
GET /api/logs?since=2020-01-01
|
|
381
|
+
-> 47GB JSON response, server OOMs, gateway times out after 30 seconds
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
The endpoint works perfectly with 50 test records during development. Then real data arrives.
|
|
385
|
+
|
|
386
|
+
**Why developers do it:**
|
|
387
|
+
|
|
388
|
+
- "We'll add pagination later" (they will not add pagination later).
|
|
389
|
+
- Test datasets are small, so the problem is invisible during development.
|
|
390
|
+
- Premature optimization aversion taken too far.
|
|
391
|
+
|
|
392
|
+
**What goes wrong:**
|
|
393
|
+
|
|
394
|
+
- Database queries without LIMIT scan entire tables, holding locks and blocking other queries.
|
|
395
|
+
- Application servers OOM trying to serialize millions of records.
|
|
396
|
+
- Network timeouts as response payloads exceed gateway limits (many API gateways cap at 10MB).
|
|
397
|
+
- A single client request can degrade service for all users — effectively a self-inflicted DDoS.
|
|
398
|
+
- In one documented incident, an Oracle API integration experienced persistent timeouts when fetching large record volumes because no pagination was implemented, requiring complete architectural rework.
|
|
399
|
+
|
|
400
|
+
**The fix:**
|
|
401
|
+
|
|
402
|
+
- Paginate from day one. Every list endpoint gets `limit` and `offset` (or cursor-based pagination).
|
|
403
|
+
- Set a maximum page size (e.g., 100) and a default (e.g., 20). Reject requests exceeding the max.
|
|
404
|
+
- Return pagination metadata: `{ "data": [...], "pagination": { "total": 23400, "limit": 20, "offset": 0, "next": "/api/orders?cursor=abc123" } }`.
|
|
405
|
+
- Prefer cursor-based pagination for datasets that change frequently — offset-based pagination skips or duplicates items when records are inserted between pages.
|
|
406
|
+
|
|
407
|
+
**Detection rule:**
|
|
408
|
+
|
|
409
|
+
Flag any list endpoint that lacks `limit`/`offset` or `cursor` parameters. Flag any database query in a list handler that has no `LIMIT` clause. Alert when response payloads exceed 1MB.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### AP-08: Over-Fetching and Under-Fetching
|
|
414
|
+
|
|
415
|
+
**Also known as:** Data Mismatch, One-Size-Fits-None Responses, Payload Bloat
|
|
416
|
+
**Frequency:** Very Common
|
|
417
|
+
**Severity:** Medium
|
|
418
|
+
**Detection difficulty:** Moderate
|
|
419
|
+
|
|
420
|
+
**What it looks like:**
|
|
421
|
+
|
|
422
|
+
Over-fetching: client needs a user's name and avatar, but the API returns the entire user object with 47 fields including address history, preferences, and audit trail.
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
GET /api/users/42
|
|
426
|
+
-> Returns 4KB response when client needs 200 bytes
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Under-fetching: client needs user + team + subscription but must call three endpoints because the user endpoint returns only user fields with no option to include related resources.
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
GET /api/users/42 -> { name, teamId }
|
|
433
|
+
GET /api/teams/7 -> { name, planId }
|
|
434
|
+
GET /api/plans/3 -> { name, price }
|
|
435
|
+
// Three round trips for one card component
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Why developers do it:**
|
|
439
|
+
|
|
440
|
+
- Over-fetching: serializing the entire ORM model is the path of least resistance.
|
|
441
|
+
- Under-fetching: rigid adherence to "one resource per endpoint" without considering access patterns.
|
|
442
|
+
- Lack of field selection or resource embedding mechanisms.
|
|
443
|
+
|
|
444
|
+
**What goes wrong:**
|
|
445
|
+
|
|
446
|
+
- Over-fetching wastes bandwidth, especially on mobile (data costs money in many markets).
|
|
447
|
+
- Under-fetching forces the chatty API pattern (AP-01), compounding latency.
|
|
448
|
+
- Both problems are why GraphQL gained traction — Facebook created it specifically to solve mobile over-fetching and under-fetching in their news feed.
|
|
449
|
+
- GraphQL itself can suffer from the same problems: unrestricted query depth causes server-side over-fetching from databases (the N+1 problem).
|
|
450
|
+
|
|
451
|
+
**The fix:**
|
|
452
|
+
|
|
453
|
+
- Support sparse fieldsets: `GET /users/42?fields=name,avatarUrl`.
|
|
454
|
+
- Support resource embedding: `GET /users/42?include=team,subscription`.
|
|
455
|
+
- For GraphQL: implement query complexity analysis and depth limiting. Use DataLoaders for batching.
|
|
456
|
+
- Define "thin" and "full" representations: list endpoints return summaries, detail endpoints return full objects.
|
|
457
|
+
|
|
458
|
+
**Detection rule:**
|
|
459
|
+
|
|
460
|
+
Compare response payload size against actual field usage in client code. Flag endpoints where clients consume less than 30% of returned fields. Flag views that require more than 3 API calls to render.
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
### AP-09: Misusing HTTP Status Codes
|
|
465
|
+
|
|
466
|
+
**Also known as:** 200-for-Everything, Status Code Ignorance, The Lying API
|
|
467
|
+
**Frequency:** Very Common
|
|
468
|
+
**Severity:** High
|
|
469
|
+
**Detection difficulty:** Easy
|
|
470
|
+
|
|
471
|
+
**What it looks like:**
|
|
472
|
+
|
|
473
|
+
```
|
|
474
|
+
POST /api/users
|
|
475
|
+
-> 200 OK
|
|
476
|
+
{
|
|
477
|
+
"success": false,
|
|
478
|
+
"error": "Email already exists"
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
```
|
|
483
|
+
DELETE /api/orders/999
|
|
484
|
+
-> 200 OK
|
|
485
|
+
{
|
|
486
|
+
"status": "error",
|
|
487
|
+
"message": "Order not found"
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
```
|
|
492
|
+
GET /api/health
|
|
493
|
+
-> 500 Internal Server Error
|
|
494
|
+
{
|
|
495
|
+
"healthy": true,
|
|
496
|
+
"message": "All systems operational"
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**Why developers do it:**
|
|
501
|
+
|
|
502
|
+
- Legacy systems and older frameworks defaulted to 200 for everything.
|
|
503
|
+
- "The HTTP request itself succeeded, the application error is in the body" — a misunderstanding of what HTTP status codes represent.
|
|
504
|
+
- Framework makes it easier to return 200 and stuff errors in the body.
|
|
505
|
+
- JSON-RPC and some SOAP conventions normalize this behavior.
|
|
506
|
+
|
|
507
|
+
**What goes wrong:**
|
|
508
|
+
|
|
509
|
+
- HTTP clients, SDKs, and libraries use status codes for control flow. A 200 with an error body bypasses all error handling.
|
|
510
|
+
- Reverse proxies (Cloudflare, Fastly, Nginx) cannot distinguish real successes from application errors. CDN caches "successful" error responses.
|
|
511
|
+
- Monitoring dashboards show 100% success rate while users cannot log in.
|
|
512
|
+
- Alerting systems never fire because 5xx rate stays at zero.
|
|
513
|
+
- Retry logic does not trigger on 200 responses, so transient failures are never retried.
|
|
514
|
+
- SLO dashboards become meaningless.
|
|
515
|
+
|
|
516
|
+
**The fix:**
|
|
517
|
+
|
|
518
|
+
- 200: success with body. 201: created. 204: success, no body.
|
|
519
|
+
- 400: client sent invalid data. 401: not authenticated. 403: not authorized. 404: not found. 409: conflict. 422: validation error. 429: rate limited.
|
|
520
|
+
- 500: server fault. 502: bad gateway. 503: temporarily unavailable. 504: gateway timeout.
|
|
521
|
+
- Adopt RFC 9457 (Problem Details for HTTP APIs) for structured error responses.
|
|
522
|
+
- Use at minimum: 200, 201, 204, 400, 401, 403, 404, 409, 429, 500, 503.
|
|
523
|
+
|
|
524
|
+
**Detection rule:**
|
|
525
|
+
|
|
526
|
+
Flag any response with status 200 that contains `"error"`, `"success": false`, `"status": "error"`, or `"fault"` in the body. Flag any 5xx response with `"healthy": true` or `"success": true`.
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
### AP-10: Ignoring Idempotency
|
|
531
|
+
|
|
532
|
+
**Also known as:** Double-Charge Problem, Retry Roulette, Non-Idempotent Mutations
|
|
533
|
+
**Frequency:** Common
|
|
534
|
+
**Severity:** Critical
|
|
535
|
+
**Detection difficulty:** Hard
|
|
536
|
+
|
|
537
|
+
**What it looks like:**
|
|
538
|
+
|
|
539
|
+
```
|
|
540
|
+
# Client sends payment request
|
|
541
|
+
POST /api/payments { amount: 100, userId: 42 }
|
|
542
|
+
-> Network timeout, no response received
|
|
543
|
+
|
|
544
|
+
# Client retries (did the first one go through?)
|
|
545
|
+
POST /api/payments { amount: 100, userId: 42 }
|
|
546
|
+
-> 201 Created (second charge processed)
|
|
547
|
+
|
|
548
|
+
# User charged $200 instead of $100
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
No idempotency key. No deduplication. The server treats every request as a new operation.
|
|
552
|
+
|
|
553
|
+
**Why developers do it:**
|
|
554
|
+
|
|
555
|
+
- Idempotency infrastructure adds complexity (storing keys, handling races, expiring old keys).
|
|
556
|
+
- "Our network is reliable" (it is not).
|
|
557
|
+
- Testing idempotency requires simulating partial failures, which is hard.
|
|
558
|
+
- Misunderstanding: developers think idempotency only matters for payment systems.
|
|
559
|
+
|
|
560
|
+
**What goes wrong:**
|
|
561
|
+
|
|
562
|
+
- Stripe documented this as a core design challenge as their user base grew: double payments became a significant issue. They built their entire idempotency key system to guarantee exactly-once processing for retried requests.
|
|
563
|
+
- In a WooCommerce-Stripe integration incident, idempotency keys were set for the `/charges` API but not for `/payment_intents`. A customer got charged 3 times for a single subscription renewal.
|
|
564
|
+
- Duplicate order creation, duplicate email sends, duplicate webhook deliveries — any non-idempotent POST is vulnerable.
|
|
565
|
+
- Retry storms during partial outages multiply the damage: if the server is slow, clients retry, creating more load, causing more timeouts, causing more retries.
|
|
566
|
+
|
|
567
|
+
**The fix:**
|
|
568
|
+
|
|
569
|
+
- Accept an `Idempotency-Key` header on all state-changing endpoints.
|
|
570
|
+
- Store the key with the response on first execution. Return the cached response on subsequent requests with the same key.
|
|
571
|
+
- Stripe's approach: cache both the status code and body for 24 hours, including 500 errors.
|
|
572
|
+
- For naturally idempotent operations (PUT replacing a full resource, DELETE), ensure the implementation is actually idempotent — `DELETE /orders/42` should return 204 whether the order exists or was already deleted.
|
|
573
|
+
- Use database constraints (unique indexes on business keys) as a safety net.
|
|
574
|
+
|
|
575
|
+
**Detection rule:**
|
|
576
|
+
|
|
577
|
+
Flag all POST endpoints that create resources or trigger side effects but do not accept or enforce an idempotency key. Flag POST handlers that lack deduplication logic.
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
### AP-11: Missing Rate Limiting
|
|
582
|
+
|
|
583
|
+
**Also known as:** Open Firehose, Unthrottled API, DDoS Welcome Mat
|
|
584
|
+
**Frequency:** Common
|
|
585
|
+
**Severity:** Critical
|
|
586
|
+
**Detection difficulty:** Easy
|
|
587
|
+
|
|
588
|
+
**What it looks like:**
|
|
589
|
+
|
|
590
|
+
```
|
|
591
|
+
# No rate limit headers, no throttling, no pushback
|
|
592
|
+
for i in $(seq 1 1000000); do
|
|
593
|
+
curl -s https://api.example.com/search?q=test &
|
|
594
|
+
done
|
|
595
|
+
# Server falls over at request 50,000
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
**Why developers do it:**
|
|
599
|
+
|
|
600
|
+
- "We'll add rate limiting when we need it" (you need it before you think you need it).
|
|
601
|
+
- Internal APIs feel safe from abuse (until a runaway integration script hits them).
|
|
602
|
+
- Confusion about where rate limiting should live (application vs. gateway vs. CDN).
|
|
603
|
+
|
|
604
|
+
**What goes wrong:**
|
|
605
|
+
|
|
606
|
+
- Cloudflare's September 2025 dashboard and API outage was triggered by a bug in their own dashboard that caused repeated, unnecessary calls to an internal Tenant Service API. The fix required installing a global rate limit on the service. Even Cloudflare's own internal APIs needed rate limiting.
|
|
607
|
+
- In a separate Cloudflare incident, a rate limit intended for one customer was misapplied to a wider set of customers across Europe, causing widespread outages during DDoS mitigation. Misconfigured rate limits can be as dangerous as missing ones.
|
|
608
|
+
- Without rate limiting, a single misconfigured client, a scraping bot, or a DDoS attack can exhaust database connections, CPU, and memory for all users.
|
|
609
|
+
- OWASP lists "Lack of Resources & Rate Limiting" as a top API security vulnerability.
|
|
610
|
+
|
|
611
|
+
**The fix:**
|
|
612
|
+
|
|
613
|
+
- Implement rate limiting at the API gateway level with per-client quotas.
|
|
614
|
+
- Return `429 Too Many Requests` with a `Retry-After` header.
|
|
615
|
+
- Include rate limit headers in every response: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`.
|
|
616
|
+
- Use token bucket or sliding window algorithms. Set different limits for different endpoints (search is more expensive than profile reads).
|
|
617
|
+
- Rate limit by authenticated user, not just by IP (to handle shared NATs and proxies).
|
|
618
|
+
|
|
619
|
+
**Detection rule:**
|
|
620
|
+
|
|
621
|
+
Flag any public-facing endpoint that does not have rate limiting configured at the gateway or application level. Flag endpoints missing `429` in their response code documentation.
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
### AP-12: Authentication in Query Parameters
|
|
626
|
+
|
|
627
|
+
**Also known as:** Token-in-URL, Secret in the Address Bar, The Log File Goldmine
|
|
628
|
+
**Frequency:** Common
|
|
629
|
+
**Severity:** Critical
|
|
630
|
+
**Detection difficulty:** Easy
|
|
631
|
+
|
|
632
|
+
**What it looks like:**
|
|
633
|
+
|
|
634
|
+
```
|
|
635
|
+
GET /api/users?api_key=REDACTED_STRIPE_KEY
|
|
636
|
+
GET /api/data?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
637
|
+
GET /api/admin/export?password=hunter2
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Why developers do it:**
|
|
641
|
+
|
|
642
|
+
- Simpler for quick integrations: "just append the key to the URL."
|
|
643
|
+
- Some legacy systems only support query parameters.
|
|
644
|
+
- Webhook callbacks sometimes pass verification tokens in URLs.
|
|
645
|
+
- Developers testing in browsers find it easier than setting headers.
|
|
646
|
+
|
|
647
|
+
**What goes wrong:**
|
|
648
|
+
|
|
649
|
+
- URLs are logged everywhere: web server access logs, proxy logs, CDN logs, browser history, analytics tools, referer headers.
|
|
650
|
+
- The OWASP vulnerability catalog explicitly lists "Information Exposure Through Query Strings in URL" — URLs are stored in browser history, passed in Referer headers to third-party resources, and visible in server logs accessible to operations staff.
|
|
651
|
+
- Shared URLs leak credentials: copying a URL to share with a colleague or paste into a bug report includes the token.
|
|
652
|
+
- HTTP Referer headers send the full URL (including query parameters) to third-party resources loaded on the page.
|
|
653
|
+
- SSL/TLS encrypts URL content in transit, but URLs are logged in plaintext at both endpoints and any intermediary that terminates TLS.
|
|
654
|
+
|
|
655
|
+
**The fix:**
|
|
656
|
+
|
|
657
|
+
- Use the `Authorization` header with Bearer tokens: `Authorization: Bearer <token>`.
|
|
658
|
+
- For API keys, use a custom header: `X-API-Key: <key>`.
|
|
659
|
+
- If query parameter tokens are unavoidable (e.g., webhook verification), use short-lived, single-use tokens that expire within minutes.
|
|
660
|
+
- Configure log scrubbing to redact known sensitive query parameters.
|
|
661
|
+
- Audit server, proxy, and CDN log configurations to ensure sensitive parameters are not recorded.
|
|
662
|
+
|
|
663
|
+
**Detection rule:**
|
|
664
|
+
|
|
665
|
+
Scan API endpoint definitions for query parameters named `key`, `token`, `api_key`, `secret`, `password`, `auth`, or `access_token`. Flag any endpoint that accepts authentication credentials outside of headers.
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
### AP-13: Inconsistent Response Shapes
|
|
670
|
+
|
|
671
|
+
**Also known as:** Shape Shifting API, Schema Roulette, The Parser's Nightmare
|
|
672
|
+
**Frequency:** Common
|
|
673
|
+
**Severity:** High
|
|
674
|
+
**Detection difficulty:** Moderate
|
|
675
|
+
|
|
676
|
+
**What it looks like:**
|
|
677
|
+
|
|
678
|
+
```json
|
|
679
|
+
// GET /api/users/42
|
|
680
|
+
{ "id": 42, "name": "Alice", "email": "alice@example.com" }
|
|
681
|
+
|
|
682
|
+
// GET /api/users (list endpoint)
|
|
683
|
+
{ "results": [{ "userId": 42, "fullName": "Alice", "emailAddress": "alice@example.com" }] }
|
|
684
|
+
|
|
685
|
+
// GET /api/users/42/orders
|
|
686
|
+
[{ "order_id": 1, "user": 42 }]
|
|
687
|
+
|
|
688
|
+
// POST /api/users (error)
|
|
689
|
+
{ "error": true, "msg": "Validation failed" }
|
|
690
|
+
|
|
691
|
+
// POST /api/orders (error)
|
|
692
|
+
{ "success": false, "errors": [{ "field": "quantity", "message": "Required" }] }
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
Same resource, five different field names. Error responses with different structures per endpoint.
|
|
696
|
+
|
|
697
|
+
**Why developers do it:**
|
|
698
|
+
|
|
699
|
+
- Different developers built different endpoints at different times.
|
|
700
|
+
- No shared response envelope or schema standard.
|
|
701
|
+
- Organic growth without API design review.
|
|
702
|
+
|
|
703
|
+
**What goes wrong:**
|
|
704
|
+
|
|
705
|
+
- Every consumer writes custom parsing logic per endpoint, multiplying integration effort.
|
|
706
|
+
- SDK code generation fails or produces inconsistent types.
|
|
707
|
+
- An API reviewer who analyzed 300+ API designs identified inconsistent response shapes as one of the most pervasive mistakes.
|
|
708
|
+
- Automated testing becomes fragile: assertion logic varies per endpoint.
|
|
709
|
+
- API consumers lose trust and over-defensively code against every possible shape variation.
|
|
710
|
+
|
|
711
|
+
**The fix:**
|
|
712
|
+
|
|
713
|
+
- Define a standard response envelope: `{ "data": T, "meta": {}, "errors": [] }`.
|
|
714
|
+
- Same resource, same field names, everywhere. A user's email is `email` whether returned from `/users/42`, a list endpoint, or embedded in an order.
|
|
715
|
+
- Adopt RFC 9457 for error responses: consistent `type`, `title`, `status`, `detail`, `instance` fields.
|
|
716
|
+
- Use OpenAPI `$ref` to share component schemas across endpoints.
|
|
717
|
+
|
|
718
|
+
**Detection rule:**
|
|
719
|
+
|
|
720
|
+
Compare response schemas across all endpoints that return the same resource type. Flag any field name or structure differences for the same logical entity. Flag endpoints with non-standard error response shapes.
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
### AP-14: Nested Resource Hell
|
|
725
|
+
|
|
726
|
+
**Also known as:** URL Inception, Deep Nesting, The Matryoshka Endpoint
|
|
727
|
+
**Frequency:** Common
|
|
728
|
+
**Severity:** Medium
|
|
729
|
+
**Detection difficulty:** Easy
|
|
730
|
+
|
|
731
|
+
**What it looks like:**
|
|
732
|
+
|
|
733
|
+
```
|
|
734
|
+
GET /organizations/5/departments/3/teams/12/members/42/tasks/99/comments/7/attachments/2
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Seven levels of nesting. Every intermediate ID must be known and valid. Changing organizational structure breaks every URL.
|
|
738
|
+
|
|
739
|
+
```
|
|
740
|
+
# What if a member moves to a different team?
|
|
741
|
+
# Old: /organizations/5/departments/3/teams/12/members/42
|
|
742
|
+
# New: /organizations/5/departments/3/teams/15/members/42
|
|
743
|
+
# Every bookmark, every cached URL, every integration breaks
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
**Why developers do it:**
|
|
747
|
+
|
|
748
|
+
- "The URL should reflect the data model hierarchy."
|
|
749
|
+
- Attempting to encode full context into the URL.
|
|
750
|
+
- ORMs that expose parent-child relationships encourage this pattern.
|
|
751
|
+
|
|
752
|
+
**What goes wrong:**
|
|
753
|
+
|
|
754
|
+
- URLs become brittle: any hierarchy change breaks all deep URLs.
|
|
755
|
+
- Clients must know every ancestor ID to reference a leaf resource, even when they only have the leaf ID.
|
|
756
|
+
- Authorization middleware must validate every intermediate segment, multiplying database lookups.
|
|
757
|
+
- Documentation becomes unwieldy with combinatorial explosion of path parameters.
|
|
758
|
+
- URL length limits (2048 characters in some browsers/proxies) become a real constraint.
|
|
759
|
+
|
|
760
|
+
**The fix:**
|
|
761
|
+
|
|
762
|
+
- Limit nesting to one level: `/teams/12/members` is fine. `/organizations/5/departments/3/teams/12/members` is not.
|
|
763
|
+
- Provide direct access via canonical URLs: `GET /members/42`, `GET /tasks/99`, `GET /comments/7`.
|
|
764
|
+
- Use query parameters for filtering by parent: `GET /members?teamId=12`.
|
|
765
|
+
- Resources should be addressable by their own ID without requiring ancestor context.
|
|
766
|
+
|
|
767
|
+
**Detection rule:**
|
|
768
|
+
|
|
769
|
+
Flag any endpoint with more than 2 levels of path parameter nesting. Count path segments that are dynamic (`:id` or `{id}`) — alert if more than 2 exist in a single URL pattern.
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
### AP-15: Ignoring HATEOAS When It Matters
|
|
774
|
+
|
|
775
|
+
**Also known as:** Hardcoded URL Syndrome, Missing Navigation, Undiscoverable API
|
|
776
|
+
**Frequency:** Occasional
|
|
777
|
+
**Severity:** Medium
|
|
778
|
+
**Detection difficulty:** Hard
|
|
779
|
+
|
|
780
|
+
**What it looks like:**
|
|
781
|
+
|
|
782
|
+
```json
|
|
783
|
+
// API returns bare data, no links
|
|
784
|
+
{
|
|
785
|
+
"orderId": 42,
|
|
786
|
+
"status": "pending",
|
|
787
|
+
"total": 99.99
|
|
788
|
+
}
|
|
789
|
+
// Client must hardcode: "if status == pending, I can cancel at /orders/42/cancel"
|
|
790
|
+
// Client must hardcode: "payment URL is /orders/42/payment"
|
|
791
|
+
// Client must hardcode: "invoice URL is /orders/42/invoice"
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
Every client independently maintains a mapping of resource states to available actions and their URLs.
|
|
795
|
+
|
|
796
|
+
**Why developers do it:**
|
|
797
|
+
|
|
798
|
+
- HATEOAS is perceived as over-engineering for most APIs.
|
|
799
|
+
- Most API documentation tools lack support for hypermedia links.
|
|
800
|
+
- "Our clients already know the URLs."
|
|
801
|
+
- OpenAPI generation struggles with HATEOAS — parts of the response (links) are not documented in the generated spec.
|
|
802
|
+
|
|
803
|
+
**What goes wrong:**
|
|
804
|
+
|
|
805
|
+
- Changing URL structures requires updating every client simultaneously.
|
|
806
|
+
- Clients implement business logic that belongs on the server (e.g., "can this order be cancelled?").
|
|
807
|
+
- State machine transitions are scattered across client codebases and fall out of sync.
|
|
808
|
+
- API evolution becomes harder: adding a new action requires client updates even if the client could discover it dynamically.
|
|
809
|
+
|
|
810
|
+
**The fix:**
|
|
811
|
+
|
|
812
|
+
- You do not need full HATEOAS for every API. Apply it selectively where it provides value:
|
|
813
|
+
- Workflow-driven resources (orders, applications, tickets) with state-dependent available actions.
|
|
814
|
+
- Paginated collections (always include `next`, `prev`, `first`, `last` links).
|
|
815
|
+
- Resource discovery (root endpoint listing available resources).
|
|
816
|
+
- Use a standard link format (HAL, JSON:API, or simple `_links` objects).
|
|
817
|
+
- At minimum, include pagination links and self-references.
|
|
818
|
+
|
|
819
|
+
```json
|
|
820
|
+
{
|
|
821
|
+
"orderId": 42,
|
|
822
|
+
"status": "pending",
|
|
823
|
+
"_links": {
|
|
824
|
+
"self": { "href": "/orders/42" },
|
|
825
|
+
"cancel": { "href": "/orders/42/cancel", "method": "POST" },
|
|
826
|
+
"payment": { "href": "/orders/42/payment", "method": "POST" }
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Detection rule:**
|
|
832
|
+
|
|
833
|
+
Flag workflow-driven resources that return status fields but no associated action links. Flag paginated endpoints that lack `next`/`prev` links in the response.
|
|
834
|
+
|
|
835
|
+
---
|
|
836
|
+
|
|
837
|
+
### AP-16: Stringly-Typed Everything
|
|
838
|
+
|
|
839
|
+
**Also known as:** String Soup, Primitive Obsession in APIs, Parse-It-Yourself Data
|
|
840
|
+
**Frequency:** Common
|
|
841
|
+
**Severity:** Medium
|
|
842
|
+
**Detection difficulty:** Moderate
|
|
843
|
+
|
|
844
|
+
**What it looks like:**
|
|
845
|
+
|
|
846
|
+
```json
|
|
847
|
+
{
|
|
848
|
+
"price": "99.99",
|
|
849
|
+
"quantity": "5",
|
|
850
|
+
"isActive": "true",
|
|
851
|
+
"createdAt": "Jan 5, 2024",
|
|
852
|
+
"tags": "electronics,sale,featured",
|
|
853
|
+
"metadata": "{\"color\": \"red\", \"size\": \"large\"}",
|
|
854
|
+
"coordinates": "40.7128,-74.0060",
|
|
855
|
+
"permissions": "read,write,admin"
|
|
856
|
+
}
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
Numbers as strings. Booleans as strings. Dates as unstructured strings. Arrays as comma-separated strings. JSON as escaped strings inside JSON. Every client must parse, validate, and handle malformed values.
|
|
860
|
+
|
|
861
|
+
**Why developers do it:**
|
|
862
|
+
|
|
863
|
+
- Serialization from databases or languages that treat everything as strings (some NoSQL stores, shell scripts, CSV imports).
|
|
864
|
+
- "Strings are flexible" — avoiding schema constraints during rapid prototyping.
|
|
865
|
+
- Legacy system integration where everything passes through text pipelines.
|
|
866
|
+
- Fear of type mismatches across different client languages.
|
|
867
|
+
|
|
868
|
+
**What goes wrong:**
|
|
869
|
+
|
|
870
|
+
- Every client independently implements parsing and validation, introducing subtle bugs (is "true" truthy? What about "True", "TRUE", "1", "yes"?).
|
|
871
|
+
- Numeric precision issues: `"99.99"` parsed as a float might become `99.98999999999999`.
|
|
872
|
+
- Date parsing ambiguity: is `"01/02/03"` January 2, 2003 or February 1, 2003 or February 3, 2001?
|
|
873
|
+
- JSON-in-JSON requires double-escaping and double-parsing, a common source of injection vulnerabilities.
|
|
874
|
+
- OpenAPI code generation produces string types instead of proper typed models, losing all type safety.
|
|
875
|
+
|
|
876
|
+
**The fix:**
|
|
877
|
+
|
|
878
|
+
- Use native JSON types: numbers for numbers, booleans for booleans, arrays for arrays, objects for objects.
|
|
879
|
+
- Use ISO 8601 for all dates and timestamps: `"2024-01-05T00:00:00Z"`.
|
|
880
|
+
- Use arrays for lists, not comma-separated strings.
|
|
881
|
+
- Use nested objects for structured data, not JSON-encoded strings.
|
|
882
|
+
- Define enums explicitly in your schema for constrained string values.
|
|
883
|
+
|
|
884
|
+
**Detection rule:**
|
|
885
|
+
|
|
886
|
+
Scan response schemas for string fields that contain patterns matching numbers (`^\d+\.?\d*$`), booleans (`^(true|false)$`), ISO dates, JSON objects, or comma-separated values. Flag for type promotion.
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
890
|
+
### AP-17: Missing Request Validation
|
|
891
|
+
|
|
892
|
+
**Also known as:** Trust-All-Input, The Permissive Endpoint, Garbage-In-Garbage-Out
|
|
893
|
+
**Frequency:** Very Common
|
|
894
|
+
**Severity:** Critical
|
|
895
|
+
**Detection difficulty:** Moderate
|
|
896
|
+
|
|
897
|
+
**What it looks like:**
|
|
898
|
+
|
|
899
|
+
```
|
|
900
|
+
POST /api/users
|
|
901
|
+
{
|
|
902
|
+
"name": "",
|
|
903
|
+
"email": "not-an-email",
|
|
904
|
+
"age": -5,
|
|
905
|
+
"role": "superadmin",
|
|
906
|
+
"bio": "<script>alert('xss')</script>" + "A".repeat(10_000_000)
|
|
907
|
+
}
|
|
908
|
+
-> 201 Created
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
The server accepts anything, stores it in the database, and lets downstream systems deal with the consequences.
|
|
912
|
+
|
|
913
|
+
**Why developers do it:**
|
|
914
|
+
|
|
915
|
+
- "The frontend validates; the backend doesn't need to."
|
|
916
|
+
- Validation code feels like boilerplate.
|
|
917
|
+
- "We trust our clients" (APIs have no trusted clients — even your own frontend can be bypassed with curl).
|
|
918
|
+
- Tight deadlines prioritize feature delivery over input validation.
|
|
919
|
+
|
|
920
|
+
**What goes wrong:**
|
|
921
|
+
|
|
922
|
+
- SQL injection, XSS, and command injection through unvalidated string fields.
|
|
923
|
+
- Denial of service through unbounded payload sizes (10MB bio field stored in the database).
|
|
924
|
+
- Privilege escalation through unvalidated enum fields (`"role": "superadmin"`).
|
|
925
|
+
- Data corruption: invalid emails prevent password reset, negative ages break age-gated features, empty names break display logic.
|
|
926
|
+
- The Peloton API vulnerability (2021) demonstrated how insufficient validation and access controls exposed personal data of approximately 3 million users. API requests were not validated for authentication, allowing anyone to pull private user data.
|
|
927
|
+
|
|
928
|
+
**The fix:**
|
|
929
|
+
|
|
930
|
+
- Validate every input field at the API boundary: type, format, length, range, enum membership.
|
|
931
|
+
- Use schema validation (JSON Schema, Joi, Zod, Pydantic) as middleware, not inline checks.
|
|
932
|
+
- Whitelist allowed fields to prevent mass assignment (reject unknown fields).
|
|
933
|
+
- Set `Content-Length` limits at the gateway (e.g., 1MB max request body).
|
|
934
|
+
- Never trust enum values from clients — validate against server-side allowed values.
|
|
935
|
+
- Sanitize but do not rely on sanitization alone; validate first, sanitize second.
|
|
936
|
+
|
|
937
|
+
**Detection rule:**
|
|
938
|
+
|
|
939
|
+
Flag POST/PUT/PATCH handlers that do not call a validation function or middleware before processing. Flag schemas without `maxLength`, `minimum`, `maximum`, or `enum` constraints on string and number fields.
|
|
940
|
+
|
|
941
|
+
---
|
|
942
|
+
|
|
943
|
+
### AP-18: Synchronous Long-Running Operations
|
|
944
|
+
|
|
945
|
+
**Also known as:** The Hanging Request, Timeout Roulette, Blocking API Call
|
|
946
|
+
**Frequency:** Common
|
|
947
|
+
**Severity:** High
|
|
948
|
+
**Detection difficulty:** Moderate
|
|
949
|
+
|
|
950
|
+
**What it looks like:**
|
|
951
|
+
|
|
952
|
+
```
|
|
953
|
+
POST /api/reports/generate
|
|
954
|
+
{ "type": "annual", "years": [2020, 2021, 2022, 2023, 2024] }
|
|
955
|
+
|
|
956
|
+
# Client waits... 30 seconds... 60 seconds... 120 seconds...
|
|
957
|
+
# Gateway returns 504 Gateway Timeout
|
|
958
|
+
# Client retries, creating a second report generation job
|
|
959
|
+
# Server is now running two expensive report jobs
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
```
|
|
963
|
+
POST /api/videos/transcode
|
|
964
|
+
{ "sourceUrl": "https://example.com/4k-video.mp4" }
|
|
965
|
+
# Connection held open for 45 minutes
|
|
966
|
+
# Any network hiccup kills the request with no recovery
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
**Why developers do it:**
|
|
970
|
+
|
|
971
|
+
- Synchronous request-response is the simplest mental model.
|
|
972
|
+
- "It usually completes in under 30 seconds" (until it does not).
|
|
973
|
+
- Adding async infrastructure (queues, status endpoints, webhooks) feels like over-engineering.
|
|
974
|
+
- The team does not have experience with asynchronous patterns.
|
|
975
|
+
|
|
976
|
+
**What goes wrong:**
|
|
977
|
+
|
|
978
|
+
- Gateway and proxy timeouts kill the request before completion (Nginx default: 60s, ALB default: 60s).
|
|
979
|
+
- Thread/connection pool exhaustion: long-running requests hold server resources, blocking other requests.
|
|
980
|
+
- Retries create duplicate work (see AP-10: Ignoring Idempotency).
|
|
981
|
+
- Mobile clients on unreliable networks lose the connection and have no way to retrieve the result.
|
|
982
|
+
- Microsoft's Azure Architecture Center documents the Asynchronous Request-Reply pattern specifically because synchronous long-running operations are a top cause of reliability issues.
|
|
983
|
+
|
|
984
|
+
**The fix:**
|
|
985
|
+
|
|
986
|
+
- Return `202 Accepted` immediately with a status URL.
|
|
987
|
+
- Provide a polling endpoint: `GET /api/reports/status/abc123` returning progress and eventual result.
|
|
988
|
+
- Support webhooks for completion notification: client provides a `callbackUrl` in the original request.
|
|
989
|
+
- Use exponential backoff in polling to avoid hammering the status endpoint.
|
|
990
|
+
- Include `Retry-After` header in 202 responses to guide polling frequency.
|
|
991
|
+
|
|
992
|
+
```
|
|
993
|
+
POST /api/reports/generate -> 202 Accepted
|
|
994
|
+
{
|
|
995
|
+
"statusUrl": "/api/reports/status/abc123",
|
|
996
|
+
"estimatedCompletionSeconds": 120
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
GET /api/reports/status/abc123 -> 200 OK
|
|
1000
|
+
{
|
|
1001
|
+
"status": "processing",
|
|
1002
|
+
"progress": 65,
|
|
1003
|
+
"estimatedRemainingSeconds": 42
|
|
1004
|
+
}
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
**Detection rule:**
|
|
1008
|
+
|
|
1009
|
+
Flag any endpoint with a p95 response time exceeding 10 seconds. Flag handlers that perform file I/O, external API calls, or database operations expected to exceed 5 seconds without returning 202.
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
### AP-19: Leaking PII in URLs and Logs
|
|
1014
|
+
|
|
1015
|
+
**Also known as:** The GDPR Time Bomb, PII in the Address Bar, Log File Liability
|
|
1016
|
+
**Frequency:** Common
|
|
1017
|
+
**Severity:** Critical
|
|
1018
|
+
**Detection difficulty:** Hard
|
|
1019
|
+
|
|
1020
|
+
**What it looks like:**
|
|
1021
|
+
|
|
1022
|
+
```
|
|
1023
|
+
GET /api/users?email=alice@example.com&ssn=123-45-6789
|
|
1024
|
+
GET /api/lookup?phone=+15551234567&dob=1990-01-15
|
|
1025
|
+
GET /api/verify?creditCard=4111111111111111&cvv=123
|
|
1026
|
+
|
|
1027
|
+
# These URLs end up in:
|
|
1028
|
+
# - Nginx access logs (retained for 90 days)
|
|
1029
|
+
# - CDN edge logs (retained by third party)
|
|
1030
|
+
# - Browser history on shared computers
|
|
1031
|
+
# - Referer headers sent to third-party analytics
|
|
1032
|
+
# - APM tools (Datadog, New Relic, Splunk)
|
|
1033
|
+
# - Error tracking (Sentry, Bugsnag)
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
**Why developers do it:**
|
|
1037
|
+
|
|
1038
|
+
- GET requests are the easiest way to fetch data, and parameters go in the URL.
|
|
1039
|
+
- Logging middleware records full URLs by default.
|
|
1040
|
+
- Developers do not think of URLs as a data storage and transmission vector.
|
|
1041
|
+
- "It's HTTPS so it's encrypted" (true in transit, but URLs are logged in plaintext at endpoints).
|
|
1042
|
+
|
|
1043
|
+
**What goes wrong:**
|
|
1044
|
+
|
|
1045
|
+
- Trend Micro research documented PII leaks from e-commerce APIs that passed customer information as URL query parameters, allowing unauthenticated users to look up other users' order status using predictable URLs.
|
|
1046
|
+
- The Experian API incident exposed credit scores by accepting name and address as API parameters — essentially public information used as authentication material, allowing anyone to look up credit scores for most Americans.
|
|
1047
|
+
- GDPR and CCPA violations: PII in log files makes those log files subject to data retention and deletion requirements. Log rotation is not the same as GDPR-compliant deletion.
|
|
1048
|
+
- Security audits flag log files containing PII, requiring expensive remediation (retroactive log scrubbing across distributed systems).
|
|
1049
|
+
|
|
1050
|
+
**The fix:**
|
|
1051
|
+
|
|
1052
|
+
- Never put PII in URLs or query parameters. Use POST with a request body for PII-based lookups.
|
|
1053
|
+
- Use opaque identifiers (UUIDs) in URLs instead of email addresses, phone numbers, or SSNs.
|
|
1054
|
+
- Configure log scrubbing at the infrastructure level: redact known PII patterns from access logs, APM traces, and error reports.
|
|
1055
|
+
- Audit Referer header exposure: set `Referrer-Policy: no-referrer` or `same-origin`.
|
|
1056
|
+
- Treat URLs as public data — design them accordingly.
|
|
1057
|
+
|
|
1058
|
+
**Detection rule:**
|
|
1059
|
+
|
|
1060
|
+
Scan endpoint definitions for query parameters matching PII patterns: `email`, `ssn`, `phone`, `dob`, `creditCard`, `address`, `name` with format constraints suggesting PII. Scan access logs for query strings containing email addresses, phone numbers, or SSN patterns.
|
|
1061
|
+
|
|
1062
|
+
---
|
|
1063
|
+
|
|
1064
|
+
### AP-20: Undocumented Error Responses
|
|
1065
|
+
|
|
1066
|
+
**Also known as:** Surprise Error Format, The Undocumented 500, Error Response Guessing Game
|
|
1067
|
+
**Frequency:** Very Common
|
|
1068
|
+
**Severity:** Medium
|
|
1069
|
+
**Detection difficulty:** Moderate
|
|
1070
|
+
|
|
1071
|
+
**What it looks like:**
|
|
1072
|
+
|
|
1073
|
+
API documentation shows only the happy path:
|
|
1074
|
+
|
|
1075
|
+
```
|
|
1076
|
+
POST /api/orders
|
|
1077
|
+
Response: 201 Created
|
|
1078
|
+
{ "orderId": 42, "status": "created" }
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
Undocumented reality:
|
|
1082
|
+
|
|
1083
|
+
```
|
|
1084
|
+
400: { "error": "Bad Request" } # What was bad?
|
|
1085
|
+
400: "Validation failed" # Plain text, not JSON
|
|
1086
|
+
400: { "errors": { "items": ["At least one required"] }} # Different shape
|
|
1087
|
+
401: <html><body>Login Required</body></html> # HTML from auth proxy
|
|
1088
|
+
403: { "code": "FORBIDDEN", "msg": "Insufficient scope" } # Yet another shape
|
|
1089
|
+
500: { "timestamp": "...", "path": "/api/orders", "message": "...", "trace": "..." } # Spring Boot default
|
|
1090
|
+
502: <html>Bad Gateway</html> # Nginx HTML, not JSON
|
|
1091
|
+
503: (empty body) # No body at all
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
**Why developers do it:**
|
|
1095
|
+
|
|
1096
|
+
- Error paths get less testing and documentation effort than happy paths.
|
|
1097
|
+
- Different middleware layers (auth proxy, API gateway, application framework, custom code) each produce errors in their own format.
|
|
1098
|
+
- "Errors are self-explanatory" — they are not.
|
|
1099
|
+
|
|
1100
|
+
**What goes wrong:**
|
|
1101
|
+
|
|
1102
|
+
- Client developers write error handling code against observed behavior, which changes without notice.
|
|
1103
|
+
- JSON parsing crashes when the response is HTML or plain text (the auth proxy returned HTML but the client expected JSON).
|
|
1104
|
+
- Error messages are too vague to be actionable: `"Bad Request"` does not tell the developer which field was wrong.
|
|
1105
|
+
- Support tickets increase because developers cannot self-serve through error messages.
|
|
1106
|
+
- One analysis found that URLs, examples, error shapes, and documentation slowly fall out of sync with the published API version, creating a growing gap between documented and actual behavior.
|
|
1107
|
+
|
|
1108
|
+
**The fix:**
|
|
1109
|
+
|
|
1110
|
+
- Document every error response for every endpoint in your OpenAPI spec.
|
|
1111
|
+
- Adopt RFC 9457 (Problem Details) as the standard error format across all layers.
|
|
1112
|
+
- Ensure all middleware layers (proxy, gateway, framework) produce errors in the same format — or configure a centralized error-formatting middleware.
|
|
1113
|
+
- Include machine-readable error codes (`"code": "VALIDATION_ERROR"`), human-readable messages, and field-level details.
|
|
1114
|
+
|
|
1115
|
+
```json
|
|
1116
|
+
{
|
|
1117
|
+
"type": "https://api.example.com/errors/validation",
|
|
1118
|
+
"title": "Validation Error",
|
|
1119
|
+
"status": 422,
|
|
1120
|
+
"detail": "Request body contains invalid fields",
|
|
1121
|
+
"errors": [
|
|
1122
|
+
{ "field": "email", "message": "Must be a valid email address" },
|
|
1123
|
+
{ "field": "quantity", "message": "Must be greater than 0" }
|
|
1124
|
+
]
|
|
1125
|
+
}
|
|
1126
|
+
```
|
|
1127
|
+
|
|
1128
|
+
**Detection rule:**
|
|
1129
|
+
|
|
1130
|
+
Compare documented error responses in OpenAPI spec against actual error responses observed in production logs. Flag any undocumented status code or error format. Flag endpoints where the error response `Content-Type` differs from the success response `Content-Type`.
|
|
1131
|
+
|
|
1132
|
+
---
|
|
1133
|
+
|
|
1134
|
+
### AP-21: Coupling Client to Server Implementation
|
|
1135
|
+
|
|
1136
|
+
**Also known as:** Leaky Contract, Implementation-Aware Client, Tight Coupling Across the Wire
|
|
1137
|
+
**Frequency:** Common
|
|
1138
|
+
**Severity:** High
|
|
1139
|
+
**Detection difficulty:** Very Hard
|
|
1140
|
+
|
|
1141
|
+
**What it looks like:**
|
|
1142
|
+
|
|
1143
|
+
```javascript
|
|
1144
|
+
// Client code that assumes server implementation details
|
|
1145
|
+
const user = await fetch('/api/users/42');
|
|
1146
|
+
// Client assumes database auto-increment IDs are sequential
|
|
1147
|
+
const nextUser = await fetch(`/api/users/${user.id + 1}`);
|
|
1148
|
+
|
|
1149
|
+
// Client assumes specific ORM behavior
|
|
1150
|
+
const orders = await fetch(`/api/users/42/orders?_expand=items&_embed=payments`);
|
|
1151
|
+
// These query parameters mirror json-server/ORM conventions, not API design
|
|
1152
|
+
|
|
1153
|
+
// Client parses internal error codes that map to server packages
|
|
1154
|
+
if (error.code === 'SEQUELIZE_UNIQUE_CONSTRAINT') { ... }
|
|
1155
|
+
if (error.source === 'redis-cache-miss') { ... }
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
WunderGraph's analysis of generated GraphQL APIs describes this as "tight coupling as a service" — when the API schema is auto-generated from the database schema, every database migration becomes a potential API breaking change.
|
|
1159
|
+
|
|
1160
|
+
**Why developers do it:**
|
|
1161
|
+
|
|
1162
|
+
- Auto-generating APIs from database schemas (PostgREST, Hasura, Prisma) exposes database structure directly.
|
|
1163
|
+
- Same team owns client and server, so they share implementation knowledge informally.
|
|
1164
|
+
- Convenience: "it works" is prioritized over "it's decoupled."
|
|
1165
|
+
- Lack of an explicit API design phase — the API is whatever the ORM produces.
|
|
1166
|
+
|
|
1167
|
+
**What goes wrong:**
|
|
1168
|
+
|
|
1169
|
+
- Database migration (renaming a column, changing a primary key strategy from auto-increment to UUID) breaks the API contract.
|
|
1170
|
+
- Switching ORMs, databases, or caching layers requires API changes.
|
|
1171
|
+
- Clients developed by external teams break when internal infrastructure changes.
|
|
1172
|
+
- The coupling is implicit — no import statement or type dependency makes it visible. As one analysis notes, "leaky abstractions create coupling that won't be made explicit in the codebase through dependencies such as imports or type usage."
|
|
1173
|
+
|
|
1174
|
+
**The fix:**
|
|
1175
|
+
|
|
1176
|
+
- Design the API contract first (API-first design), then implement the server to fulfill it.
|
|
1177
|
+
- Use DTOs/view models to decouple API responses from internal models.
|
|
1178
|
+
- Never expose database column names, ORM query parameters, or internal error codes in the API.
|
|
1179
|
+
- Use API description languages (OpenAPI, AsyncAPI) as the contract, and generate server stubs from the contract — not the reverse.
|
|
1180
|
+
- Test contract stability independently: schema diff tests in CI that prevent accidental coupling.
|
|
1181
|
+
|
|
1182
|
+
**Detection rule:**
|
|
1183
|
+
|
|
1184
|
+
Flag API field names that match database column naming patterns (`_id` suffixes, `fk_` prefixes, `created_at` matching ORM defaults). Flag error responses containing framework-specific error codes (e.g., `SEQUELIZE_`, `PRISMA_`, `HIBERNATE_`). Flag query parameters that mirror ORM filter syntax.
|
|
1185
|
+
|
|
1186
|
+
---
|
|
1187
|
+
|
|
1188
|
+
## Root Cause Analysis
|
|
1189
|
+
|
|
1190
|
+
| Root Cause | Anti-Patterns Triggered | Frequency |
|
|
1191
|
+
|---|---|---|
|
|
1192
|
+
| No API design phase (code-first) | AP-05, AP-06, AP-13, AP-14, AP-16, AP-21 | Very Common |
|
|
1193
|
+
| Small test datasets hiding scale issues | AP-07, AP-08, AP-18 | Very Common |
|
|
1194
|
+
| "We control all the clients" assumption | AP-04, AP-10, AP-13, AP-17, AP-20 | Common |
|
|
1195
|
+
| Backend language conventions leaking | AP-05, AP-06, AP-16, AP-21 | Common |
|
|
1196
|
+
| Security as afterthought | AP-11, AP-12, AP-17, AP-19 | Common |
|
|
1197
|
+
| Premature microservice decomposition | AP-01, AP-08, AP-14 | Common |
|
|
1198
|
+
| No schema validation in CI | AP-04, AP-05, AP-13, AP-16 | Common |
|
|
1199
|
+
| Convenience over correctness | AP-02, AP-03, AP-09, AP-12 | Very Common |
|
|
1200
|
+
| Framework defaults accepted uncritically | AP-06, AP-09, AP-19, AP-20 | Common |
|
|
1201
|
+
| Missing async infrastructure knowledge | AP-10, AP-18 | Occasional |
|
|
1202
|
+
| No cross-team API style guide | AP-05, AP-09, AP-13, AP-20 | Common |
|
|
1203
|
+
| Legacy system migration pressure | AP-02, AP-03, AP-09, AP-16 | Occasional |
|
|
1204
|
+
|
|
1205
|
+
---
|
|
1206
|
+
|
|
1207
|
+
## Self-Check Questions
|
|
1208
|
+
|
|
1209
|
+
Use these questions during API design review. A "yes" answer indicates a potential anti-pattern.
|
|
1210
|
+
|
|
1211
|
+
1. **Does a single page or screen require more than 3 sequential API calls to render?** (AP-01: Chatty API)
|
|
1212
|
+
|
|
1213
|
+
2. **Does any endpoint accept an `action` or `type` parameter that fundamentally changes what it does?** (AP-02: God Endpoint)
|
|
1214
|
+
|
|
1215
|
+
3. **Do any GET endpoints write to a database, send emails, or trigger side effects?** (AP-03: HTTP Semantics)
|
|
1216
|
+
|
|
1217
|
+
4. **Can you rename a database column without changing your API response schema?** (AP-06, AP-21: Leaky Abstraction / Coupling)
|
|
1218
|
+
|
|
1219
|
+
5. **What happens when your list endpoint is called against a table with 10 million rows and no query parameters?** (AP-07: Missing Pagination)
|
|
1220
|
+
|
|
1221
|
+
6. **If a POST request times out and the client retries, will the operation execute twice?** (AP-10: Idempotency)
|
|
1222
|
+
|
|
1223
|
+
7. **Are authentication tokens, API keys, or PII visible in your access logs?** (AP-12, AP-19: Auth in Query Params / PII Leak)
|
|
1224
|
+
|
|
1225
|
+
8. **Do all endpoints that return the same resource type use the same field names and response structure?** (AP-13: Inconsistent Response Shapes)
|
|
1226
|
+
|
|
1227
|
+
9. **Do any endpoints have more than 2 path parameters (dynamic segments)?** (AP-14: Nested Resource Hell)
|
|
1228
|
+
|
|
1229
|
+
10. **Are there fields in your API responses that are strings but always contain numbers, booleans, or dates?** (AP-16: Stringly-Typed)
|
|
1230
|
+
|
|
1231
|
+
11. **Can a client send `"role": "admin"` in a POST body and have it accepted?** (AP-17: Missing Validation)
|
|
1232
|
+
|
|
1233
|
+
12. **Do any endpoints regularly take more than 10 seconds to respond?** (AP-18: Synchronous Long-Running)
|
|
1234
|
+
|
|
1235
|
+
13. **Does your OpenAPI spec document every error status code and response shape for every endpoint?** (AP-20: Undocumented Errors)
|
|
1236
|
+
|
|
1237
|
+
14. **If you switched from PostgreSQL to MongoDB, how many API response fields would change?** (AP-21: Client-Server Coupling)
|
|
1238
|
+
|
|
1239
|
+
15. **Do all error responses across your API follow the same structure, including those from proxies and gateways?** (AP-09, AP-13, AP-20: Status Codes / Shapes / Errors)
|
|
1240
|
+
|
|
1241
|
+
---
|
|
1242
|
+
|
|
1243
|
+
## Code Smell Quick Reference
|
|
1244
|
+
|
|
1245
|
+
| Code Smell | Likely Anti-Pattern | Severity | Detection Method |
|
|
1246
|
+
|---|---|---|---|
|
|
1247
|
+
| Client makes >5 API calls per page render | AP-01: Chatty API | High | Client-side request tracing |
|
|
1248
|
+
| Single endpoint with `action` parameter | AP-02: God Endpoint | High | Route definition scan |
|
|
1249
|
+
| GET handler with DB write call | AP-03: HTTP Semantics | Critical | Static analysis of handlers |
|
|
1250
|
+
| Removed or renamed field in API diff | AP-04: Breaking Changes | Critical | Schema diff in CI |
|
|
1251
|
+
| Mixed camelCase/snake_case in same response | AP-05: Naming Conventions | Medium | OpenAPI schema lint |
|
|
1252
|
+
| `pk_`, `fk_`, `tbl_` prefixes in field names | AP-06: Leaky Abstraction | High | Schema field name scan |
|
|
1253
|
+
| List endpoint without `limit` parameter | AP-07: Missing Pagination | Critical | Route parameter audit |
|
|
1254
|
+
| Response >1MB for a list endpoint | AP-07/AP-08: Pagination/Fetching | High | Response size monitoring |
|
|
1255
|
+
| Status 200 body contains `"error"` | AP-09: Status Code Misuse | High | Response body pattern scan |
|
|
1256
|
+
| POST handler without idempotency key support | AP-10: No Idempotency | Critical | Handler code review |
|
|
1257
|
+
| No `429` status in endpoint documentation | AP-11: Missing Rate Limit | Critical | OpenAPI spec audit |
|
|
1258
|
+
| `api_key` or `token` in query string | AP-12: Auth in URL | Critical | Route parameter scan |
|
|
1259
|
+
| Same resource, different field names per endpoint | AP-13: Inconsistent Shapes | High | Cross-endpoint schema comparison |
|
|
1260
|
+
| URL with >2 dynamic path segments | AP-14: Deep Nesting | Medium | Route pattern analysis |
|
|
1261
|
+
| Status field returned without `_links` | AP-15: Missing HATEOAS | Medium | Response schema audit |
|
|
1262
|
+
| String field matching `^\d+$` or `^(true\|false)$` | AP-16: Stringly-Typed | Medium | Response payload sampling |
|
|
1263
|
+
| Handler with no validation middleware | AP-17: No Validation | Critical | Middleware chain inspection |
|
|
1264
|
+
| p95 latency >10s on any endpoint | AP-18: Sync Long-Running | High | APM latency percentiles |
|
|
1265
|
+
| PII patterns in access log URLs | AP-19: PII in URLs | Critical | Log pattern scanning |
|
|
1266
|
+
| Error `Content-Type` differs from success | AP-20: Undocumented Errors | Medium | Response header monitoring |
|
|
1267
|
+
| Field names match ORM/DB column conventions | AP-21: Client-Server Coupling | High | Schema naming analysis |
|
|
1268
|
+
|
|
1269
|
+
---
|
|
1270
|
+
|
|
1271
|
+
*Researched: 2026-03-08 | Sources: Stripe Engineering Blog (idempotency design), Shopify Engineering (GraphQL N+1 batching), Cloudflare Post-Mortems (September 2025 API outage, rate limiting incident), Krebs on Security (Experian API leak 2021), TechCrunch (Peloton API vulnerability 2021), OWASP (query string information exposure, HTTP verb tampering, API security top 10), Engadget/Yahoo Finance (Twitter API breaking changes 2023), Microsoft Azure Architecture Center (async request-reply pattern), RFC 9457 (Problem Details for HTTP APIs), WunderGraph (tight coupling in generated APIs), InfoQ (REST anti-patterns), Specmatic (API design anti-patterns detection), Salt Security (Experian and Peloton incident analysis), Tyk (200-for-everything anti-pattern)*
|