@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,692 @@
|
|
|
1
|
+
# Modular Monolith — Architecture Expertise Module
|
|
2
|
+
|
|
3
|
+
> A modular monolith is a single deployable unit with strictly enforced module boundaries, combining the operational simplicity of a monolith with the structural independence of microservices. It is often the ideal architecture for teams of 10-100+ developers who need module ownership without the distributed systems overhead.
|
|
4
|
+
|
|
5
|
+
> **Category:** Pattern
|
|
6
|
+
> **Complexity:** Moderate
|
|
7
|
+
> **Applies when:** Teams of 10-100+ developers needing module autonomy without distributed systems complexity
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What This Is (and What It Isn't)
|
|
12
|
+
|
|
13
|
+
A modular monolith is a **single deployable executable** whose internal structure is divided into discrete, domain-aligned modules with **enforced boundaries** — enforced at compile time, via static analysis tooling, or via runtime verification, not merely by convention or team discipline.
|
|
14
|
+
|
|
15
|
+
The critical distinction from every adjacent concept:
|
|
16
|
+
|
|
17
|
+
| Architecture | Deployment units | Boundary enforcement | Network calls between components |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| Regular monolith | 1 | None (by convention at best) | No |
|
|
20
|
+
| Modular monolith | 1 | Yes — tooling or compiler | No |
|
|
21
|
+
| Distributed monolith | Many | None (implicit tight coupling) | Yes |
|
|
22
|
+
| Microservices | Many (1 per service) | Process boundary (natural) | Yes |
|
|
23
|
+
|
|
24
|
+
**What it is not:**
|
|
25
|
+
|
|
26
|
+
- A "well-organized monolith" with nicely named folders but nothing preventing `import orders.internal.OrderRepository` from `billing/` — that is just a regular monolith with aspirations.
|
|
27
|
+
- A microservices system in disguise. All modules run in the same process, communicate via in-process calls or in-process event buses, and share a single deployment lifecycle.
|
|
28
|
+
- A transitional state that must be "fixed" by moving to microservices. Many organizations deliberately stay here permanently.
|
|
29
|
+
|
|
30
|
+
**The canonical real-world example: Shopify.** As of 2024, Shopify operates one of the largest Ruby on Rails codebases on the planet — over 2.8 million lines of Ruby, 500,000+ commits, hundreds of active engineers — as a single deployable application. Modules are enforced via **Packwerk** (Shopify's open-source static analysis gem) and Rails Engines. Engineers can own a bounded context (Orders, Billing, Checkout, Inventory) without stepping on each other, deploy dozens of times per day, and avoid the overhead of a distributed system.
|
|
31
|
+
|
|
32
|
+
The insight behind Shopify's approach: their pre-modular monolith suffered not from being a monolith, but from lacking enforced boundaries. Any code could call anything. The solution was not to split the process — it was to enforce the module contracts while keeping deployment simple.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## When to Use It
|
|
37
|
+
|
|
38
|
+
### Team size: 10–100+ developers working on the same codebase
|
|
39
|
+
|
|
40
|
+
When a second or third team joins a codebase, informal boundaries collapse. The modular monolith creates formal contracts between teams without requiring separate infrastructure. Each team owns a module (or a cluster of modules), publishes a public API surface, and other teams cannot reach through the module boundary.
|
|
41
|
+
|
|
42
|
+
### You understand your domain reasonably well
|
|
43
|
+
|
|
44
|
+
Modules need stable-enough boundaries to be worth enforcing. If you are in week 2 of a startup and still discovering what your domain even is, enforcing premature module boundaries is counterproductive overhead. Once you have 6-12 months of production use and domain clarity, modularization pays off.
|
|
45
|
+
|
|
46
|
+
### Operational complexity of microservices is not worth the tradeoff
|
|
47
|
+
|
|
48
|
+
Every microservice you add introduces: a deployment pipeline, a container, a network call, a timeout, a retry budget, distributed tracing overhead, schema versioning across service boundaries, and on-call burden. For most product teams, this operational tax is not offset by the benefits until the team and scale are large enough to justify it. The modular monolith defers that cost indefinitely — or forever.
|
|
49
|
+
|
|
50
|
+
### You want the *benefits* of microservices without the *cost*
|
|
51
|
+
|
|
52
|
+
- Independent team ownership of code → yes, via module contracts
|
|
53
|
+
- Ability to migrate a module to a service later → yes, the interfaces are already defined
|
|
54
|
+
- Clean domain separation → yes, enforced not assumed
|
|
55
|
+
- Independent scaling of each module → no, this is the main thing you give up
|
|
56
|
+
- Independent deployment of each module → no, this is the other thing you give up
|
|
57
|
+
|
|
58
|
+
### Real examples with numbers
|
|
59
|
+
|
|
60
|
+
**Shopify:** 2,000+ engineers, single Rails application, 40+ production deployments per day, 30TB of data processed per minute at peak. Modules enforced via Packwerk. Rails Engines used as isolation mechanism. Publicly documented as intentional architectural choice.
|
|
61
|
+
|
|
62
|
+
**Stack Overflow:** Serves 6,000+ requests/second, 2 billion page views/month, 34 million daily searches, pages rendered in ~12ms average. Runs on 9 web servers and a single SQL Server — a monolith. By obsessing over performance, scalability came nearly free. Their team explicitly avoided "SOA tax."
|
|
63
|
+
|
|
64
|
+
**Industry trend (2024-2025):** A 2025 CNCF survey found approximately 42% of organizations that adopted microservices have consolidated at least some services back into larger deployable units, citing debugging complexity, operational overhead, and network latency. A 2025 Gartner study found 60% of teams report regret about microservices for small-to-medium applications. Amazon Prime Video's 2023 public post-mortem described saving ~90% infrastructure cost by consolidating a microservices pipeline back to a monolith.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## When NOT to Use It
|
|
69
|
+
|
|
70
|
+
This section is as important as the previous one.
|
|
71
|
+
|
|
72
|
+
### When a simple monolith suffices (fewer than ~10 developers, single team)
|
|
73
|
+
|
|
74
|
+
If everyone on the team knows the whole codebase, enforced module boundaries are pure overhead. You gain nothing from Packwerk or ArchUnit rules if the entire engineering team fits in a single standup. A clean, well-factored monolith without formal enforcement is the correct choice. Premature modularization adds complexity that slows you down and pays no dividend.
|
|
75
|
+
|
|
76
|
+
**The failure pattern:** A 4-developer startup spends 2 weeks setting up ArchUnit rules, per-module DbContexts, and a published-API layer between Orders and Billing that will never have more than one developer touching them. They have introduced microservices-level design ceremony with none of the benefits.
|
|
77
|
+
|
|
78
|
+
### When you need independent deployment of components
|
|
79
|
+
|
|
80
|
+
If regulatory requirements, customer SLAs, or team autonomy demand that the Payments module must be deployable independently — on its own schedule, with its own rollback — a modular monolith cannot deliver this. Every deployment releases the entire application. If a billing team needs to deploy hotfixes 10x per day while a core-product team deploys once per week, shared deployment is a real constraint.
|
|
81
|
+
|
|
82
|
+
### When genuinely different scaling requirements exist per module
|
|
83
|
+
|
|
84
|
+
A modular monolith scales horizontally as a unit. If your VideoTranscoding module needs 200 CPU cores while your UserAuth module needs 2, you cannot scale them independently. You either over-provision the entire application or extract the resource-intensive module. This is a legitimate reason to extract a module to a service even from a well-designed modular monolith.
|
|
85
|
+
|
|
86
|
+
### When polyglot technology requirements are non-negotiable
|
|
87
|
+
|
|
88
|
+
If your ML inference module must be Python/PyTorch, your real-time gaming module must be C++, and your web API must be Go, they cannot coexist in a single deployable unit. Language-level polyglot requirements are a hard constraint that microservices solve and modular monoliths do not.
|
|
89
|
+
|
|
90
|
+
### When the team is already distributed across independent services
|
|
91
|
+
|
|
92
|
+
If you already have 12 separate services maintained by 12 separate teams with mature CI/CD pipelines, proposing to re-consolidate into a modular monolith is likely not worth the migration cost. The modular monolith is most valuable as a deliberate starting point or a deliberate consolidation from an unnecessarily distributed system — not as a re-centralization for its own sake.
|
|
93
|
+
|
|
94
|
+
### When boundary enforcement overhead outweighs benefit
|
|
95
|
+
|
|
96
|
+
The discipline to maintain module boundaries is real. Public API surfaces must be designed and kept stable. Cross-cutting concerns (logging, auth, feature flags) require shared kernel modules. Onboarding engineers need to understand module ownership rules. When the codebase is genuinely small and simple, this ceremony costs more than it saves.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## How It Works
|
|
101
|
+
|
|
102
|
+
### Module anatomy
|
|
103
|
+
|
|
104
|
+
Each module has three zones:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
src/modules/orders/
|
|
108
|
+
api/ # Public contract — the only thing other modules may reference
|
|
109
|
+
OrderService.java # Public interface
|
|
110
|
+
OrderCreatedEvent.java # Published domain event
|
|
111
|
+
dto/
|
|
112
|
+
CreateOrderRequest.java
|
|
113
|
+
OrderSummary.java
|
|
114
|
+
internal/ # Private — invisible to other modules
|
|
115
|
+
domain/
|
|
116
|
+
Order.java
|
|
117
|
+
OrderRepository.java # Interface defined here
|
|
118
|
+
application/
|
|
119
|
+
CreateOrderUseCase.java
|
|
120
|
+
infrastructure/
|
|
121
|
+
JpaOrderRepository.java # Implementation of domain interface
|
|
122
|
+
events/ # Events this module publishes (consumed by other modules)
|
|
123
|
+
OrderFulfilled.java
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The rule: **nothing outside `api/` may be referenced from outside the module.** This is the contract. The enforcement mechanism (ArchUnit, Packwerk, Java module system, Python `__all__`, etc.) is what makes it real rather than aspirational.
|
|
127
|
+
|
|
128
|
+
### Inter-module communication options
|
|
129
|
+
|
|
130
|
+
**Option 1: In-process method calls via interfaces (synchronous)**
|
|
131
|
+
|
|
132
|
+
Module A calls Module B's public API interface directly. B's implementation is injected (dependency injection). This is the fastest option — no serialization, no network, just a function call. Appropriate when A genuinely needs a synchronous answer from B before continuing.
|
|
133
|
+
|
|
134
|
+
```java
|
|
135
|
+
// In orders module — depends only on the billing API interface
|
|
136
|
+
public class CreateOrderUseCase {
|
|
137
|
+
private final BillingService billingService; // interface from billing/api/
|
|
138
|
+
|
|
139
|
+
public Order createOrder(CreateOrderRequest req) {
|
|
140
|
+
PaymentResult result = billingService.authorizePayment(req.paymentDetails());
|
|
141
|
+
// ...
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Option 2: In-process event bus (asynchronous, decoupled)**
|
|
147
|
+
|
|
148
|
+
Module A publishes a domain event. Module B subscribes. Neither knows about the other. This is the preferred integration style for reducing coupling — A does not need to know that B exists.
|
|
149
|
+
|
|
150
|
+
```java
|
|
151
|
+
// orders module publishes
|
|
152
|
+
eventBus.publish(new OrderCreatedEvent(orderId, customerId, total));
|
|
153
|
+
|
|
154
|
+
// notifications module subscribes — in the same process, no network
|
|
155
|
+
@EventHandler
|
|
156
|
+
public void on(OrderCreatedEvent event) {
|
|
157
|
+
emailService.sendConfirmation(event.customerId());
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Spring Modulith, Guava EventBus, MediatR (.NET), and NestJS EventEmitter all provide in-process event buses suitable for this pattern.
|
|
162
|
+
|
|
163
|
+
**Option 3: Async messaging (preparing for future service extraction)**
|
|
164
|
+
|
|
165
|
+
Some teams use an in-process message broker abstraction (backed by a real broker like Kafka or RabbitMQ even in the same process) to make a future service extraction easier. This is a deliberate choice to pay higher latency now in exchange for easier future decomposition. Only worth it if extraction is actually planned.
|
|
166
|
+
|
|
167
|
+
### Data ownership
|
|
168
|
+
|
|
169
|
+
Each module **owns its own tables**. No other module may query those tables directly.
|
|
170
|
+
|
|
171
|
+
Enforcement mechanisms:
|
|
172
|
+
- Database schemas per module (`orders.*`, `billing.*`, `inventory.*`) with database-level role permissions — the `orders` DB role cannot `SELECT` from `billing.*`.
|
|
173
|
+
- ORM DbContexts per module (Entity Framework, JPA) — each context maps only to its module's schema.
|
|
174
|
+
- Convention + static analysis — no cross-schema JOIN is allowed; violations flagged in CI.
|
|
175
|
+
|
|
176
|
+
The key rule: **no foreign key constraints between modules at the database level.** If Orders needs to know a Customer's email, it either calls the Customers module's API to fetch it at runtime, or it maintains a denormalized copy of the data it needs (an "anti-corruption layer" table). Cross-module transactions do not exist. Consistency between modules is eventual, achieved via events.
|
|
177
|
+
|
|
178
|
+
### Dependency rules
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
Module A's internal code
|
|
182
|
+
may reference: A's own internal code + A's own api/ code
|
|
183
|
+
may reference: B's api/ code (never B's internal/)
|
|
184
|
+
may reference: shared kernel (logging, auth, utilities)
|
|
185
|
+
may NOT reference: B's internal/ code
|
|
186
|
+
may NOT reference: B's database tables directly
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Cyclic dependencies between modules are prohibited. If Orders depends on Billing and Billing depends on Orders, something is wrong with the domain model. The fix is either: introduce a third module that both depend on, or make one dependency go via events rather than direct calls.
|
|
190
|
+
|
|
191
|
+
### Build enforcement
|
|
192
|
+
|
|
193
|
+
Enforcement mechanisms by language:
|
|
194
|
+
|
|
195
|
+
**Java:** ArchUnit (test-based) or Spring Modulith's `ApplicationModules.verify()`. Rules expressed as code, run in CI.
|
|
196
|
+
|
|
197
|
+
**Ruby (Shopify approach):** Packwerk — static analysis gem that detects constant references across package boundaries. Runs in CI. Packwerk distinguishes "dependency violations" (referencing a package you haven't declared a dependency on) from "privacy violations" (referencing a private constant from an external package).
|
|
198
|
+
|
|
199
|
+
**Python:** Package-level `__all__` declarations restricting exports + import-linter (third-party tool) that enforces contract rules across packages.
|
|
200
|
+
|
|
201
|
+
**TypeScript/NestJS:** Nx workspace boundary rules (enforced via ESLint plugin), or manual barrel exports with no internal re-exports. NestJS module system naturally encapsulates providers — only explicitly exported providers are accessible to importing modules.
|
|
202
|
+
|
|
203
|
+
**.NET:** Assembly-per-module (compile-time enforcement via project references) or NDepend rules. NetArchTest for test-based assertions.
|
|
204
|
+
|
|
205
|
+
**Go:** Go packages as natural unit of encapsulation. Unexported (lowercase) identifiers are package-private. Module boundary = explicit package API of exported identifiers only.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Trade-Offs Matrix
|
|
210
|
+
|
|
211
|
+
| You Get | You Pay |
|
|
212
|
+
|---------|---------|
|
|
213
|
+
| Single deployment — one artifact, one rollback, one pipeline | All modules deploy together — one bad module can block all others |
|
|
214
|
+
| No network calls between modules — microsecond latency vs milliseconds | Independent scaling per module is not possible |
|
|
215
|
+
| Full ACID transactions within a module | Cross-module transactions require eventual consistency via events |
|
|
216
|
+
| Standard debugger, single log stream, simple distributed tracing | Shared process means a memory leak in one module affects all |
|
|
217
|
+
| Team ownership via module contracts | Boundary enforcement discipline must be maintained actively |
|
|
218
|
+
| Clean migration path to microservices (interfaces already exist) | Public API design for modules is harder than just importing internals |
|
|
219
|
+
| Monorepo collaboration — shared tooling, easy cross-module refactoring | Shared deployment pipeline can create team coordination overhead |
|
|
220
|
+
| Simpler local development (single `docker-compose up`) | Larger codebase to clone, index, and navigate than individual services |
|
|
221
|
+
| In-process events are synchronous-reliable (no broker failures) | In-process events can't be replayed or dead-lettered without extra infrastructure |
|
|
222
|
+
| Lower infrastructure cost than equivalent microservices | Module dependencies still need governance to avoid becoming a big ball of mud |
|
|
223
|
+
| Easier onboarding — one app to understand, run, and test | Shared database server is still a single point of failure / contention |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Evolution Path
|
|
228
|
+
|
|
229
|
+
### Stage 1: Regular monolith (no enforced boundaries)
|
|
230
|
+
|
|
231
|
+
This is where most codebases start. Appropriate until the team or codebase grows enough that informal coordination breaks down.
|
|
232
|
+
|
|
233
|
+
**Signals to move to Stage 2:**
|
|
234
|
+
- Two or more teams work in the same codebase and step on each other
|
|
235
|
+
- A change in one area unexpectedly breaks another area
|
|
236
|
+
- Build and test times grow because everything is coupled
|
|
237
|
+
- Difficult to assign clear ownership to any area of code
|
|
238
|
+
|
|
239
|
+
### Stage 2: Identify module candidates
|
|
240
|
+
|
|
241
|
+
Before enforcing anything, map the domain. Use domain-driven design techniques:
|
|
242
|
+
- **By team:** Who owns what? Align module boundaries with team ownership.
|
|
243
|
+
- **By domain:** What are the bounded contexts? (Orders, Billing, Inventory, Notifications, Identity)
|
|
244
|
+
- **By data:** What data naturally clusters together? Which tables are joined most heavily?
|
|
245
|
+
- **By change rate:** What changes together should live together; what changes independently should be separated.
|
|
246
|
+
|
|
247
|
+
Produce a draft module map. Validate it: if a proposed module requires 40% of its lines to call into another proposed module, the boundary is wrong.
|
|
248
|
+
|
|
249
|
+
### Stage 3: Extract interfaces
|
|
250
|
+
|
|
251
|
+
Without changing the call graph, wrap the internal implementations behind interfaces that will become the public API. This is a refactoring pass — behavior does not change, but the "shape" of the module's public surface becomes explicit.
|
|
252
|
+
|
|
253
|
+
### Stage 4: Enforce dependencies
|
|
254
|
+
|
|
255
|
+
Install the enforcement tooling. Run it in audit mode first (report violations, don't fail the build). Address existing violations incrementally. Once the violation count reaches zero, switch to enforcement mode (fail CI on new violations).
|
|
256
|
+
|
|
257
|
+
### Stage 5: Enforce data ownership
|
|
258
|
+
|
|
259
|
+
Introduce per-module schemas or ORM contexts. Identify and eliminate cross-module database queries. For each cross-module JOIN, decide: does Module A call Module B's API, or does Module A maintain its own projection of the data it needs?
|
|
260
|
+
|
|
261
|
+
### Stage 6: Test module isolation
|
|
262
|
+
|
|
263
|
+
Write integration tests that instantiate a single module in isolation, with other modules replaced by test doubles. If you can't do this, you haven't achieved module independence.
|
|
264
|
+
|
|
265
|
+
### Stage 7 (optional): Extract a module to a service
|
|
266
|
+
|
|
267
|
+
If a specific module develops needs that a modular monolith can't satisfy (independent deployment, independent scaling, polyglot implementation), extract it using the strangler fig pattern:
|
|
268
|
+
|
|
269
|
+
1. Introduce a network-capable adapter behind the module's existing interface.
|
|
270
|
+
2. Deploy the module as a separate service.
|
|
271
|
+
3. Swap the in-process adapter for the network adapter — call sites do not change.
|
|
272
|
+
4. Remove the module code from the monolith.
|
|
273
|
+
|
|
274
|
+
The key advantage of starting as a modular monolith: the interfaces are already clean. The extraction is a mechanical wrapping operation, not a major refactor.
|
|
275
|
+
|
|
276
|
+
**Evolution signals that suggest selective extraction:**
|
|
277
|
+
- A specific module's build time dominates the overall build
|
|
278
|
+
- A specific module requires dramatically different scaling characteristics
|
|
279
|
+
- A specific module's release cadence is blocked by other modules
|
|
280
|
+
- A specific module team wants to use a different technology stack
|
|
281
|
+
- A specific module serves external consumers who need a stable versioned API
|
|
282
|
+
|
|
283
|
+
**Not a signal for extraction:** "Microservices are the industry standard." Architecture decisions must be driven by actual constraints, not trend-following.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Failure Modes
|
|
288
|
+
|
|
289
|
+
### Failure Mode 1: Boundary violations via direct cross-module database queries
|
|
290
|
+
|
|
291
|
+
**What it looks like:** The Orders service needs customer name for an invoice, and an engineer writes `SELECT c.name FROM customers.users c JOIN orders.orders o ON o.customer_id = c.id`. Fast, easy, and immediately violates module data ownership.
|
|
292
|
+
|
|
293
|
+
**Why it compounds:** Once one cross-schema join exists, the next is trivially justified. Within months, the database is a shared global state connecting all modules, and refactoring any table requires touching all modules.
|
|
294
|
+
|
|
295
|
+
**Fix:** Schema-level permissions enforced at the database. The `orders` DB role literally cannot `SELECT` from `billing.*`. Violations become errors, not reviews.
|
|
296
|
+
|
|
297
|
+
### Failure Mode 2: "Module" that is just a folder with no enforcement
|
|
298
|
+
|
|
299
|
+
**What it looks like:** The team creates `src/orders/`, `src/billing/`, etc., with a README saying "please don't reach into other modules' internals." No tooling. Within one sprint, `billing/` is importing from `orders/internal/` because it was "faster."
|
|
300
|
+
|
|
301
|
+
**Why it happens:** Enforcement tooling is seen as overhead to defer. Convention without enforcement is not modularity.
|
|
302
|
+
|
|
303
|
+
**Fix:** Install enforcement tooling on day one of modularization. A boundary that cannot be mechanically detected is not a boundary.
|
|
304
|
+
|
|
305
|
+
### Failure Mode 3: Shared mutable state via global objects or static fields
|
|
306
|
+
|
|
307
|
+
**What it looks like:** A `GlobalConfig` singleton holds state that multiple modules read and write. A `RequestContext` thread-local is populated by the HTTP layer and read inside domain logic in three different modules.
|
|
308
|
+
|
|
309
|
+
**Why it matters:** Shared mutable state creates coupling that does not show up in dependency graphs and is invisible to Packwerk or ArchUnit. Module A's behavior depends on Module B having set the right value in the global.
|
|
310
|
+
|
|
311
|
+
**Fix:** Explicit data passing. Shared state must live in a "shared kernel" module that is read-only for all consumers, or must be passed explicitly as parameters.
|
|
312
|
+
|
|
313
|
+
### Failure Mode 4: The big module
|
|
314
|
+
|
|
315
|
+
**What it looks like:** `core/` or `platform/` contains 60% of the codebase. Every other module depends on it. It is "shared utilities," but it has grown to include domain logic, persistence, and cross-cutting concerns.
|
|
316
|
+
|
|
317
|
+
**Why it happens:** It starts as genuinely shared utilities. Over time, convenience wins: "this is almost domain logic, but let's put it in core because it's used by both Orders and Billing."
|
|
318
|
+
|
|
319
|
+
**Fix:** Shared kernel modules must be governed. Any domain logic in the shared kernel is a red flag. The shared kernel should contain: logging, auth primitives, event bus abstractions, common value objects. It should not contain: domain entities, business rules, or orchestration logic.
|
|
320
|
+
|
|
321
|
+
### Failure Mode 5: Coupling through synchronous call chains
|
|
322
|
+
|
|
323
|
+
**What it looks like:** ModuleA calls ModuleB calls ModuleC calls ModuleD — a synchronous chain 4 modules deep. Module A's latency now includes B's latency, C's latency, and D's latency. A failure anywhere in the chain propagates upward.
|
|
324
|
+
|
|
325
|
+
**Why it matters:** Even in-process, deep synchronous call chains create temporal coupling and make the system fragile.
|
|
326
|
+
|
|
327
|
+
**Fix:** Evaluate each inter-module call. If Module A does not need an immediate synchronous response from Module B, use an event. Reserve synchronous calls for queries that genuinely require a real-time answer.
|
|
328
|
+
|
|
329
|
+
### Failure Mode 6: Cyclic dependencies
|
|
330
|
+
|
|
331
|
+
**What it looks like:** Orders depends on Billing (to check payment status), Billing depends on Orders (to get order total). The dependency graph has a cycle.
|
|
332
|
+
|
|
333
|
+
**Why it matters:** Cyclic dependencies prevent independent testing of either module and are usually a sign of incorrect boundary placement.
|
|
334
|
+
|
|
335
|
+
**Fix:** One of the dependencies usually points in the wrong direction. Either: introduce a shared event that breaks the synchronous cycle, introduce a third module that holds the shared concept, or reconsider where the boundary is drawn.
|
|
336
|
+
|
|
337
|
+
### Failure Mode 7: Ignoring the strangler fig — big bang module extraction
|
|
338
|
+
|
|
339
|
+
**What it looks like:** After 2 years of a modular monolith, the team decides to extract 5 modules to microservices simultaneously in a 3-month "migration sprint."
|
|
340
|
+
|
|
341
|
+
**Why it fails:** Even with clean interfaces, simultaneous extraction of multiple modules changes deployment topology, data management, distributed consistency, and monitoring all at once.
|
|
342
|
+
|
|
343
|
+
**Fix:** Extract one module at a time. Validate each extraction in production before starting the next.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Technology Landscape
|
|
348
|
+
|
|
349
|
+
### Java / Spring
|
|
350
|
+
|
|
351
|
+
**Spring Modulith** (GA since 2023) is the first-class framework for modular monoliths on the JVM. It builds on Spring Boot and uses ArchUnit under the hood for boundary verification.
|
|
352
|
+
|
|
353
|
+
Key capabilities:
|
|
354
|
+
- `ApplicationModules.of(Application.class).verify()` — detects boundary violations, cycles, and illegal internal access as a test
|
|
355
|
+
- `@ApplicationModule(allowedDependencies = {"billing", "identity"})` — explicit allowlist per module
|
|
356
|
+
- Integration test slices that bootstrap a single module with test doubles for others
|
|
357
|
+
- Event publication log for transactional outbox pattern (in-process events stored durably)
|
|
358
|
+
- Runtime verification mode (Spring Modulith 2.0+): `spring.modulith.runtime.verification-enabled=true`
|
|
359
|
+
- Generates documentation (C4 diagrams, module dependency graphs) from the structure
|
|
360
|
+
|
|
361
|
+
**ArchUnit** (standalone, framework-agnostic):
|
|
362
|
+
```java
|
|
363
|
+
@Test
|
|
364
|
+
void orders_module_should_not_access_billing_internals() {
|
|
365
|
+
noClasses()
|
|
366
|
+
.that().resideInAPackage("..orders..")
|
|
367
|
+
.should().accessClassesThat()
|
|
368
|
+
.resideInAPackage("..billing.internal..")
|
|
369
|
+
.check(importedClasses);
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Ruby / Rails
|
|
374
|
+
|
|
375
|
+
**Packwerk** (Shopify, open source): Static analysis gem. Packages defined by `package.yml` files. Violation types: dependency (accessing a package not declared as dependency) and privacy (accessing a private constant). Designed with zero false positives — accepts some false negatives.
|
|
376
|
+
|
|
377
|
+
**Rails Engines**: Shopify's other mechanism — each domain becomes a Rails Engine (a mini Rails app), with its own routes, controllers, models, and migrations. Provides harder isolation than Packwerk alone.
|
|
378
|
+
|
|
379
|
+
**Babbel** documented using Packwerk to modularize their Rails monolith, citing significant reduction in unintended cross-domain coupling.
|
|
380
|
+
|
|
381
|
+
### .NET
|
|
382
|
+
|
|
383
|
+
**Assembly-per-module**: The strongest boundary — if module B's assembly is not referenced by module A's project file, it cannot be accessed. Compile-time enforcement.
|
|
384
|
+
|
|
385
|
+
**NetArchTest**: Test-based assertion library, similar to ArchUnit for Java.
|
|
386
|
+
|
|
387
|
+
**NDepend**: Commercial static analysis with architectural rule enforcement.
|
|
388
|
+
|
|
389
|
+
**ABP Framework**: Provides an official modular application framework for ASP.NET Core with per-module configurations, database contexts, and dependency injection isolation.
|
|
390
|
+
|
|
391
|
+
**Entity Framework Core with multiple DbContexts**: Each module registers its own `DbContext` scoped to its schema:
|
|
392
|
+
```csharp
|
|
393
|
+
// Orders module
|
|
394
|
+
modelBuilder.HasDefaultSchema("orders");
|
|
395
|
+
|
|
396
|
+
// Billing module
|
|
397
|
+
modelBuilder.HasDefaultSchema("billing");
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Database-level enforcement: create a DB role per module with GRANT on its own schema only.
|
|
401
|
+
|
|
402
|
+
### TypeScript / NestJS
|
|
403
|
+
|
|
404
|
+
NestJS's native module system is designed for this:
|
|
405
|
+
```typescript
|
|
406
|
+
@Module({
|
|
407
|
+
imports: [TypeOrmModule.forFeature([Order])],
|
|
408
|
+
providers: [OrderService, OrderRepository],
|
|
409
|
+
exports: [OrderService], // Only this is visible to other modules
|
|
410
|
+
})
|
|
411
|
+
export class OrdersModule {}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
`exports` defines the public API. `providers` not in `exports` are private to the module.
|
|
415
|
+
|
|
416
|
+
**Nx** (monorepo tool): `@nx/enforce-module-boundaries` ESLint rule enforces which projects/libraries can import from which. Tags like `scope:orders` and `scope:billing` can be used to model module boundaries across the monorepo.
|
|
417
|
+
|
|
418
|
+
### Python
|
|
419
|
+
|
|
420
|
+
`__all__` in `__init__.py` restricts what is exported from a package. `import-linter` (third-party) defines contracts between packages and fails the build on violations.
|
|
421
|
+
|
|
422
|
+
### Go
|
|
423
|
+
|
|
424
|
+
Go's package visibility rules are language-level enforcement: unexported identifiers (lowercase) are package-private. Module boundary = the public exported API of a Go package. No additional tooling required for basic enforcement. For larger Go codebases, `golang.org/x/tools/go/analysis` framework enables custom static analysis rules.
|
|
425
|
+
|
|
426
|
+
### Monorepo tooling
|
|
427
|
+
|
|
428
|
+
**Nx**: Module boundary enforcement via ESLint, dependency graph visualization, affected test computation.
|
|
429
|
+
|
|
430
|
+
**Turborepo**: Build cache and task orchestration, not boundary enforcement — but works well alongside ArchUnit/Packwerk.
|
|
431
|
+
|
|
432
|
+
**Bazel**: Explicit `BUILD` files declare dependencies between packages. Any undeclared dependency fails the build. The strictest enforcement available.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Decision Tree
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
How many developers share the codebase?
|
|
440
|
+
│
|
|
441
|
+
├── Fewer than ~10, single team
|
|
442
|
+
│ └── Regular monolith. No module enforcement needed.
|
|
443
|
+
│ Revisit when team grows or second team joins.
|
|
444
|
+
│
|
|
445
|
+
├── 10-50 developers, 2-5 teams, shared codebase
|
|
446
|
+
│ ├── Do you know your domain well enough to draw boundaries?
|
|
447
|
+
│ │ ├── Yes → Modular monolith. Start with Packwerk/ArchUnit.
|
|
448
|
+
│ │ └── No → Regular monolith now, plan modularization at 6-12 months.
|
|
449
|
+
│ │
|
|
450
|
+
│ ├── Do any modules need independent deployment?
|
|
451
|
+
│ │ ├── No → Modular monolith.
|
|
452
|
+
│ │ └── Yes → Modular monolith + extract only those modules to services.
|
|
453
|
+
│ │
|
|
454
|
+
│ └── Do any modules need dramatically different scaling?
|
|
455
|
+
│ ├── No → Modular monolith.
|
|
456
|
+
│ └── Yes → Modular monolith + extract the resource-intensive module.
|
|
457
|
+
│
|
|
458
|
+
└── 50+ developers, multiple autonomous teams
|
|
459
|
+
├── Are teams blocked by each other's deployments?
|
|
460
|
+
│ ├── No → Modular monolith. Simpler than it looks at this scale
|
|
461
|
+
│ │ (see: Shopify, 2000+ engineers).
|
|
462
|
+
│ └── Yes → Modular monolith as foundation; selectively extract
|
|
463
|
+
│ modules that block independent deployment.
|
|
464
|
+
│
|
|
465
|
+
└── Is there a strong polyglot technology requirement?
|
|
466
|
+
├── No → Modular monolith.
|
|
467
|
+
└── Yes → Selective microservices for the polyglot modules;
|
|
468
|
+
modular monolith for the rest.
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**The default position:** Start with a modular monolith. Extract to microservices only when you have a specific, concrete constraint that the modular monolith cannot satisfy. "We might need to scale it someday" is not a constraint. "Module X's peak load is 10,000x higher than Module Y's, and we've measured this" is a constraint.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Implementation Sketch
|
|
476
|
+
|
|
477
|
+
### Folder structure
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
src/
|
|
481
|
+
modules/
|
|
482
|
+
orders/
|
|
483
|
+
api/
|
|
484
|
+
OrderService.java # Interface (public)
|
|
485
|
+
CreateOrderRequest.java # DTO (public)
|
|
486
|
+
OrderSummary.java # DTO (public)
|
|
487
|
+
OrderCreatedEvent.java # Domain event (public)
|
|
488
|
+
internal/
|
|
489
|
+
domain/
|
|
490
|
+
Order.java # Entity (private)
|
|
491
|
+
OrderItem.java # Value object (private)
|
|
492
|
+
OrderRepository.java # Repository interface (private)
|
|
493
|
+
application/
|
|
494
|
+
CreateOrderUseCase.java # Use case (private)
|
|
495
|
+
GetOrderUseCase.java
|
|
496
|
+
infrastructure/
|
|
497
|
+
JpaOrderRepository.java # JPA implementation (private)
|
|
498
|
+
billing/
|
|
499
|
+
api/
|
|
500
|
+
BillingService.java
|
|
501
|
+
AuthorizePaymentRequest.java
|
|
502
|
+
PaymentResult.java
|
|
503
|
+
internal/
|
|
504
|
+
...
|
|
505
|
+
inventory/
|
|
506
|
+
api/
|
|
507
|
+
InventoryService.java
|
|
508
|
+
StockReservedEvent.java
|
|
509
|
+
internal/
|
|
510
|
+
...
|
|
511
|
+
shared-kernel/ # Read-only shared utilities
|
|
512
|
+
events/
|
|
513
|
+
DomainEventPublisher.java
|
|
514
|
+
auth/
|
|
515
|
+
CurrentUser.java
|
|
516
|
+
money/
|
|
517
|
+
Money.java
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Cross-module communication example
|
|
521
|
+
|
|
522
|
+
```java
|
|
523
|
+
// orders/api/OrderService.java — public interface
|
|
524
|
+
public interface OrderService {
|
|
525
|
+
OrderSummary createOrder(CreateOrderRequest request);
|
|
526
|
+
OrderSummary getOrder(OrderId orderId);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// orders/internal/application/CreateOrderUseCase.java — private impl
|
|
530
|
+
@Service
|
|
531
|
+
class CreateOrderUseCase {
|
|
532
|
+
private final OrderRepository orderRepository;
|
|
533
|
+
private final BillingService billingService; // billing module's API
|
|
534
|
+
private final DomainEventPublisher eventPublisher; // shared kernel
|
|
535
|
+
|
|
536
|
+
OrderSummary execute(CreateOrderRequest req) {
|
|
537
|
+
PaymentResult payment = billingService.authorizePayment(
|
|
538
|
+
new AuthorizePaymentRequest(req.customerId(), req.total())
|
|
539
|
+
);
|
|
540
|
+
if (!payment.authorized()) {
|
|
541
|
+
throw new PaymentDeclinedException(payment.reason());
|
|
542
|
+
}
|
|
543
|
+
Order order = Order.create(req.customerId(), req.items());
|
|
544
|
+
orderRepository.save(order);
|
|
545
|
+
eventPublisher.publish(new OrderCreatedEvent(order.id(), order.customerId()));
|
|
546
|
+
return OrderSummary.from(order);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Database schema ownership
|
|
552
|
+
|
|
553
|
+
```sql
|
|
554
|
+
-- Each module owns its schema
|
|
555
|
+
CREATE SCHEMA orders;
|
|
556
|
+
CREATE SCHEMA billing;
|
|
557
|
+
CREATE SCHEMA inventory;
|
|
558
|
+
|
|
559
|
+
-- Module-specific DB roles (no cross-schema access)
|
|
560
|
+
CREATE ROLE orders_app;
|
|
561
|
+
GRANT USAGE ON SCHEMA orders TO orders_app;
|
|
562
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA orders TO orders_app;
|
|
563
|
+
-- orders_app has NO privileges on billing.* or inventory.*
|
|
564
|
+
|
|
565
|
+
-- Cross-module data: billing needs to store order_id as a reference,
|
|
566
|
+
-- but no FK constraint to orders.orders exists at the DB level.
|
|
567
|
+
-- Consistency is maintained via domain events, not FK cascades.
|
|
568
|
+
CREATE TABLE billing.payments (
|
|
569
|
+
id UUID PRIMARY KEY,
|
|
570
|
+
order_id UUID NOT NULL, -- logical reference, no FK constraint
|
|
571
|
+
amount NUMERIC NOT NULL,
|
|
572
|
+
status VARCHAR(50) NOT NULL
|
|
573
|
+
);
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### ArchUnit boundary enforcement (Java)
|
|
577
|
+
|
|
578
|
+
```java
|
|
579
|
+
@AnalyzeClasses(packages = "com.example")
|
|
580
|
+
class ModuleBoundaryTest {
|
|
581
|
+
|
|
582
|
+
@ArchTest
|
|
583
|
+
static final ArchRule orders_internal_is_private =
|
|
584
|
+
noClasses()
|
|
585
|
+
.that().resideOutsideOfPackage("com.example.modules.orders..")
|
|
586
|
+
.should().accessClassesThat()
|
|
587
|
+
.resideInAPackage("com.example.modules.orders.internal..");
|
|
588
|
+
|
|
589
|
+
@ArchTest
|
|
590
|
+
static final ArchRule no_cyclic_dependencies =
|
|
591
|
+
slices().matching("com.example.modules.(*)..").should().beFreeOfCycles();
|
|
592
|
+
|
|
593
|
+
@ArchTest
|
|
594
|
+
static final ArchRule modules_only_depend_on_api =
|
|
595
|
+
classes()
|
|
596
|
+
.that().resideInAPackage("com.example.modules.billing..")
|
|
597
|
+
.should().onlyDependOnClassesThat()
|
|
598
|
+
.resideInAnyPackage(
|
|
599
|
+
"com.example.modules.billing..",
|
|
600
|
+
"com.example.modules.orders.api..", // only the API
|
|
601
|
+
"com.example.sharedkernel..",
|
|
602
|
+
"java..",
|
|
603
|
+
"javax..",
|
|
604
|
+
"org.springframework.."
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
### Spring Modulith equivalent
|
|
610
|
+
|
|
611
|
+
```java
|
|
612
|
+
// Single test verifies all module boundaries
|
|
613
|
+
@Test
|
|
614
|
+
void verifyModuleStructure() {
|
|
615
|
+
ApplicationModules modules = ApplicationModules.of(Application.class);
|
|
616
|
+
modules.verify(); // Throws if any boundary is violated
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Module-scoped integration test
|
|
620
|
+
@ApplicationModuleTest // Only boots the orders module
|
|
621
|
+
class OrderServiceIntegrationTest {
|
|
622
|
+
@MockBean BillingService billingService; // Other modules are mocked
|
|
623
|
+
@Autowired OrderService orderService;
|
|
624
|
+
|
|
625
|
+
@Test
|
|
626
|
+
void createOrder_chargesPayment() {
|
|
627
|
+
given(billingService.authorizePayment(any())).willReturn(PaymentResult.approved());
|
|
628
|
+
OrderSummary result = orderService.createOrder(validRequest());
|
|
629
|
+
assertThat(result.status()).isEqualTo(CONFIRMED);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Packwerk (Ruby) — package definition
|
|
635
|
+
|
|
636
|
+
```yaml
|
|
637
|
+
# src/modules/orders/package.yml
|
|
638
|
+
enforce_dependencies: true
|
|
639
|
+
enforce_privacy: true
|
|
640
|
+
public_path: app/public # Only files here are accessible from outside
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
```ruby
|
|
644
|
+
# Violation detected by `bin/packwerk check`:
|
|
645
|
+
# orders/app/services/order_creator.rb:12:5
|
|
646
|
+
# Dependency violation: ::Billing::Internal::PaymentProcessor
|
|
647
|
+
# is private to 'billing' and cannot be referenced from 'orders'
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
### NestJS module boundary (TypeScript)
|
|
651
|
+
|
|
652
|
+
```typescript
|
|
653
|
+
// orders/orders.module.ts
|
|
654
|
+
@Module({
|
|
655
|
+
imports: [
|
|
656
|
+
TypeOrmModule.forFeature([OrderEntity]),
|
|
657
|
+
BillingModule, // depends on billing's public exports
|
|
658
|
+
],
|
|
659
|
+
providers: [
|
|
660
|
+
CreateOrderUseCase, // private
|
|
661
|
+
GetOrderUseCase, // private
|
|
662
|
+
OrderRepository, // private
|
|
663
|
+
OrderServiceImpl, // private implementation
|
|
664
|
+
],
|
|
665
|
+
exports: [
|
|
666
|
+
OrderServiceImpl, // exposed as OrderService to other modules
|
|
667
|
+
],
|
|
668
|
+
})
|
|
669
|
+
export class OrdersModule {}
|
|
670
|
+
|
|
671
|
+
// billing/billing.module.ts — BillingService is exported, internals are not
|
|
672
|
+
@Module({
|
|
673
|
+
providers: [BillingServiceImpl, PaymentGatewayAdapter],
|
|
674
|
+
exports: [BillingServiceImpl],
|
|
675
|
+
})
|
|
676
|
+
export class BillingModule {}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
---
|
|
680
|
+
|
|
681
|
+
## Cross-References
|
|
682
|
+
|
|
683
|
+
- **monolith:** The starting point. A modular monolith is a monolith with enforced structure. See `architecture/patterns/monolith.md`.
|
|
684
|
+
- **microservices:** The alternative for teams needing independent deployment or scaling per component. A modular monolith's clean interfaces make selective extraction to microservices tractable. See `architecture/patterns/microservices.md`.
|
|
685
|
+
- **domain-driven-design:** Module boundaries should align with DDD bounded contexts. Aggregates define transactional boundaries within a module. See `architecture/foundations/domain-driven-design.md`.
|
|
686
|
+
- **hexagonal-clean-architecture:** Each module can itself be internally structured as hexagonal/clean architecture (domain, application, infrastructure layers). The two patterns are orthogonal and complementary. See `architecture/patterns/hexagonal-clean-architecture.md`.
|
|
687
|
+
- **monolith-to-microservices:** The strangler fig extraction pattern is the recommended path when a modular monolith module needs to become an independent service. See `architecture/patterns/monolith-to-microservices.md`.
|
|
688
|
+
- **coupling-and-cohesion:** The theoretical foundation for why module boundaries matter. See `architecture/foundations/coupling-and-cohesion.md`.
|
|
689
|
+
|
|
690
|
+
---
|
|
691
|
+
|
|
692
|
+
*Researched: 2026-03-08 | Sources: [Shopify Engineering — Under Deconstruction](https://shopify.engineering/shopify-monolith) | [Shopify — Deconstructing the Monolith](https://shopify.engineering/deconstructing-monolith-designing-software-maximizes-developer-productivity) | [Shopify — Enforcing Modularity with Packwerk](https://shopify.engineering/enforcing-modularity-rails-apps-packwerk) | [Kamil Grzybek — Modular Monolith: A Primer](https://www.kamilgrzybek.com/blog/posts/modular-monolith-primer) | [Kamil Grzybek — Modular Monolith: Architecture Enforcement](https://www.kamilgrzybek.com/blog/posts/modular-monolith-architecture-enforcement) | [Kamil Grzybek — Modular Monolith: Integration Styles](https://www.kamilgrzybek.com/blog/posts/modular-monolith-integration-styles) | [Spring Modulith Reference Docs](https://docs.spring.io/spring-modulith/reference/fundamentals.html) | [Chris Richardson — Modular Monolith Patterns for Fast Flow](https://microservices.io/post/architecture/2024/09/09/modular-monolith-patterns-for-fast-flow.html) | [Milan Jovanovic — Modular Monolith Data Isolation](https://www.milanjovanovic.tech/blog/modular-monolith-data-isolation) | [ArXiv 2401.11867 — Modular Monolith: Is This the Trend?](https://arxiv.org/abs/2401.11867) | [MDPI — Modular Monolith in Cloud Environments: Systematic Literature Review](https://www.mdpi.com/1999-5903/17/11/496) | [Thoughtworks — When Modular Monolith is the Better Way](https://www.thoughtworks.com/en-us/insights/blog/microservices/modular-monolith-better-way-build-software) | [Stack Overflow Architecture — InfoQ](https://www.infoq.com/news/2015/06/scaling-stack-overflow/) | [GitHub — kgrzybek/modular-monolith-with-ddd](https://github.com/kgrzybek/modular-monolith-with-ddd) | [JetBrains — Migrating to Modular Monolith using Spring Modulith](https://blog.jetbrains.com/idea/2026/02/migrating-to-modular-monolith-using-spring-modulith-and-intellij-idea/) | [ABP.IO — Modular Monolith Architecture with .NET](https://abp.io/architecture/modular-monolith)*
|