groundwork-method 0.0.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +781 -0
- package/LICENSE +21 -0
- package/README.md +44 -29
- package/bin/groundwork.js +1654 -0
- package/dist/src/generators/add-capability/generator.d.ts +8 -0
- package/dist/src/generators/add-capability/generator.js +60 -0
- package/dist/src/generators/add-capability/generator.js.map +1 -0
- package/dist/src/generators/cli-app/generator.d.ts +9 -0
- package/dist/src/generators/cli-app/generator.js +140 -0
- package/dist/src/generators/cli-app/generator.js.map +1 -0
- package/dist/src/generators/docs-site/generator.d.ts +5 -0
- package/dist/src/generators/docs-site/generator.js +441 -0
- package/dist/src/generators/docs-site/generator.js.map +1 -0
- package/dist/src/generators/electron-app/generator.d.ts +6 -0
- package/dist/src/generators/electron-app/generator.js +261 -0
- package/dist/src/generators/electron-app/generator.js.map +1 -0
- package/dist/src/generators/flutter-app/generator.d.ts +6 -0
- package/dist/src/generators/flutter-app/generator.js +314 -0
- package/dist/src/generators/flutter-app/generator.js.map +1 -0
- package/dist/src/generators/go-microservice/generator.d.ts +8 -0
- package/dist/src/generators/go-microservice/generator.js +232 -0
- package/dist/src/generators/go-microservice/generator.js.map +1 -0
- package/dist/src/generators/nextjs-app/generator.d.ts +8 -0
- package/dist/src/generators/nextjs-app/generator.js +294 -0
- package/dist/src/generators/nextjs-app/generator.js.map +1 -0
- package/dist/src/generators/python-microservice/generator.d.ts +13 -0
- package/dist/src/generators/python-microservice/generator.js +265 -0
- package/dist/src/generators/python-microservice/generator.js.map +1 -0
- package/dist/src/generators/shared/brand-tokens.d.ts +89 -0
- package/dist/src/generators/shared/brand-tokens.js +308 -0
- package/dist/src/generators/shared/brand-tokens.js.map +1 -0
- package/dist/src/generators/shared/capabilities.d.ts +101 -0
- package/dist/src/generators/shared/capabilities.js +279 -0
- package/dist/src/generators/shared/capabilities.js.map +1 -0
- package/dist/src/generators/shared/provenance.d.ts +2 -0
- package/dist/src/generators/shared/provenance.js +85 -0
- package/dist/src/generators/shared/provenance.js.map +1 -0
- package/dist/src/generators/shared/scaffold-helpers.d.ts +72 -0
- package/dist/src/generators/shared/scaffold-helpers.js +309 -0
- package/dist/src/generators/shared/scaffold-helpers.js.map +1 -0
- package/dist/src/generators/system-test-runner/generator.d.ts +23 -0
- package/dist/src/generators/system-test-runner/generator.js +125 -0
- package/dist/src/generators/system-test-runner/generator.js.map +1 -0
- package/dist/src/generators/workspace-dev-cli/generator.d.ts +7 -0
- package/dist/src/generators/workspace-dev-cli/generator.js +138 -0
- package/dist/src/generators/workspace-dev-cli/generator.js.map +1 -0
- package/generators.json +57 -0
- package/lib/repo-map/grammars/tree-sitter-c.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-cpp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-csharp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-dart.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-go.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-java.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-javascript.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-kotlin.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-lua.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-php.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-python.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-ruby.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-rust.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-scala.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-swift.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-tsx.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-typescript.wasm +0 -0
- package/lib/repo-map/index.js +386 -0
- package/lib/repo-map/languages.js +514 -0
- package/lib/repo-map/pagerank.js +59 -0
- package/migrations/README.md +60 -0
- package/migrations/_template/cli-migration.js +27 -0
- package/migrations/gw-bet-prose-redesign.js +105 -0
- package/migrations/gw-drop-test-manifest.js +37 -0
- package/migrations/gw-register-serena-mcp.js +42 -0
- package/migrations/gw-relocate-hidden-skills.js +40 -0
- package/migrations/gw-seed-config-toml.js +24 -0
- package/migrations/index.json +40 -0
- package/package.json +70 -6
- package/src/AGENTS.md +36 -0
- package/src/config/config.toml +30 -0
- package/src/config/groundwork-state.json +5 -0
- package/src/docs/llms.txt +72 -0
- package/src/docs/principles/ai-native/agent-native-systems.md +90 -0
- package/src/docs/principles/ai-native/agentic-systems.md +78 -0
- package/src/docs/principles/ai-native/ai-engineering.md +100 -0
- package/src/docs/principles/ai-native/ai-native-product.md +76 -0
- package/src/docs/principles/delivery/cost-engineering.md +89 -0
- package/src/docs/principles/delivery/day-2-operational-baseline.md +57 -0
- package/src/docs/principles/delivery/devex.md +88 -0
- package/src/docs/principles/delivery/platform.md +101 -0
- package/src/docs/principles/delivery/progressive-delivery.md +92 -0
- package/src/docs/principles/design/ai-native-design.md +73 -0
- package/src/docs/principles/design/design-foundations.md +80 -0
- package/src/docs/principles/design/design-systems-and-tokens.md +72 -0
- package/src/docs/principles/design/interaction-and-motion.md +69 -0
- package/src/docs/principles/design/layout-and-space.md +72 -0
- package/src/docs/principles/design/usability-and-ux.md +68 -0
- package/src/docs/principles/design/visual-design.md +84 -0
- package/src/docs/principles/foundations/code-craft.md +86 -0
- package/src/docs/principles/foundations/continuous-discovery.md +75 -0
- package/src/docs/principles/foundations/documentation.md +102 -0
- package/src/docs/principles/foundations/prioritization-and-appetite.md +78 -0
- package/src/docs/principles/foundations/product-engineering.md +90 -0
- package/src/docs/principles/foundations/product-risks.md +89 -0
- package/src/docs/principles/foundations/requirements-and-specs.md +80 -0
- package/src/docs/principles/foundations/success-metrics.md +66 -0
- package/src/docs/principles/foundations/testing.md +82 -0
- package/src/docs/principles/index.md +23 -0
- package/src/docs/principles/quality/accessibility.md +88 -0
- package/src/docs/principles/quality/observability.md +84 -0
- package/src/docs/principles/quality/performance.md +84 -0
- package/src/docs/principles/quality/privacy.md +92 -0
- package/src/docs/principles/quality/reliability.md +89 -0
- package/src/docs/principles/quality/security.md +78 -0
- package/src/docs/principles/stack/postgres.md +100 -0
- package/src/docs/principles/system-design/api-design.md +86 -0
- package/src/docs/principles/system-design/architecture-decisions.md +81 -0
- package/src/docs/principles/system-design/code-structure.md +104 -0
- package/src/docs/principles/system-design/data-engineering.md +87 -0
- package/src/docs/principles/system-design/durable-execution.md +89 -0
- package/src/docs/principles/system-design/evolutionary-architecture.md +81 -0
- package/src/docs/principles/system-design/identity-and-access.md +76 -0
- package/src/docs/principles/system-design/integration-patterns.md +84 -0
- package/src/docs/principles/system-design/real-time.md +83 -0
- package/src/docs/principles/system-design/surface-architecture.md +74 -0
- package/src/docs/ways-of-working/documentation.md +69 -0
- package/src/docs/ways-of-working/how-we-work.md +76 -0
- package/src/docs/ways-of-working/units-of-work.md +40 -0
- package/src/engineer-skills/groundwork-electron-engineer/SKILL.md +118 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +107 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
- package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +14 -0
- package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +108 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +135 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
- package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +15 -0
- package/src/engineer-skills/groundwork-go-engineer/SKILL.md +171 -0
- package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
- package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
- package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
- package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
- package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
- package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
- package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
- package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
- package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
- package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
- package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
- package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
- package/src/engineer-skills/groundwork-go-engineer/references/testing.md +139 -0
- package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +11 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +107 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +433 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +278 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +9 -0
- package/src/engineer-skills/groundwork-python-engineer/SKILL.md +196 -0
- package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
- package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
- package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
- package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
- package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
- package/src/engineer-skills/groundwork-python-engineer/references/testing.md +177 -0
- package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +13 -0
- package/src/generators/add-capability/generator.ts +70 -0
- package/src/generators/add-capability/schema.json +30 -0
- package/src/generators/capabilities/llm/capability.json +28 -0
- package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
- package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
- package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
- package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
- package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
- package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
- package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
- package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
- package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
- package/src/generators/cli-app/files/README.md.template +76 -0
- package/src/generators/cli-app/files/build.mjs.template +15 -0
- package/src/generators/cli-app/files/package.json.template +21 -0
- package/src/generators/cli-app/files/src/cli.ts.template +67 -0
- package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
- package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
- package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
- package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
- package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
- package/src/generators/cli-app/files/src/registry.ts.template +31 -0
- package/src/generators/cli-app/files/tsconfig.json.template +16 -0
- package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
- package/src/generators/cli-app/generator.ts +138 -0
- package/src/generators/cli-app/schema.json +24 -0
- package/src/generators/docs-site/files/.gitignore.ejs +40 -0
- package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
- package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
- package/src/generators/docs-site/files/app/docs.css +43 -0
- package/src/generators/docs-site/files/app/layout.tsx +24 -0
- package/src/generators/docs-site/files/app/page.tsx +135 -0
- package/src/generators/docs-site/files/app/source.ts +8 -0
- package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
- package/src/generators/docs-site/files/next.config.mjs +10 -0
- package/src/generators/docs-site/files/package.json +32 -0
- package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
- package/src/generators/docs-site/files/postcss.config.mjs +6 -0
- package/src/generators/docs-site/files/source.config.ts +77 -0
- package/src/generators/docs-site/files/tailwind.config.js +10 -0
- package/src/generators/docs-site/files/tsconfig.json +27 -0
- package/src/generators/docs-site/generator.ts +476 -0
- package/src/generators/docs-site/schema.json +17 -0
- package/src/generators/electron-app/docs/principles/stack/electron/index.md +47 -0
- package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
- package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
- package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
- package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
- package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/electron-app/files/.gitignore.template +20 -0
- package/src/generators/electron-app/files/README.md.template +125 -0
- package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
- package/src/generators/electron-app/files/eslint.config.mjs +92 -0
- package/src/generators/electron-app/files/forge.config.ts.template +44 -0
- package/src/generators/electron-app/files/package.json.template +54 -0
- package/src/generators/electron-app/files/playwright.config.ts +18 -0
- package/src/generators/electron-app/files/project.json.template +65 -0
- package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
- package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
- package/src/generators/electron-app/files/src/main/index.ts +157 -0
- package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
- package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
- package/src/generators/electron-app/files/src/main/policy.ts +73 -0
- package/src/generators/electron-app/files/src/preload/index.ts +23 -0
- package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
- package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
- package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
- package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
- package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
- package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
- package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
- package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +68 -0
- package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
- package/src/generators/electron-app/files/tsconfig.json +7 -0
- package/src/generators/electron-app/files/tsconfig.node.json +27 -0
- package/src/generators/electron-app/files/tsconfig.web.json +22 -0
- package/src/generators/electron-app/files/vitest.config.ts +32 -0
- package/src/generators/electron-app/files/vitest.setup.ts +1 -0
- package/src/generators/electron-app/generator.ts +288 -0
- package/src/generators/electron-app/schema.json +23 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +74 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
- package/src/generators/flutter-app/files/.gitignore.template +30 -0
- package/src/generators/flutter-app/files/README.md.template +100 -0
- package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
- package/src/generators/flutter-app/files/integration_test/app_test.dart.template +30 -0
- package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
- package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
- package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
- package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
- package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
- package/src/generators/flutter-app/files/lib/main.dart +11 -0
- package/src/generators/flutter-app/files/lib/router.dart +23 -0
- package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
- package/src/generators/flutter-app/files/project.json.template +51 -0
- package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
- package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
- package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
- package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
- package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
- package/src/generators/flutter-app/generator.ts +362 -0
- package/src/generators/flutter-app/schema.json +23 -0
- package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
- package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
- package/src/generators/go-microservice/docs/principles/stack/go/testing.md +152 -0
- package/src/generators/go-microservice/files/.air.toml.template +38 -0
- package/src/generators/go-microservice/files/.env.template +4 -0
- package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
- package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
- package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
- package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
- package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
- package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
- package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
- package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
- package/src/generators/go-microservice/files/go.mod.template +39 -0
- package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
- package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
- package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
- package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
- package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
- package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
- package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
- package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
- package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
- package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
- package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
- package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
- package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
- package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
- package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
- package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
- package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
- package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
- package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
- package/src/generators/go-microservice/generator.ts +240 -0
- package/src/generators/go-microservice/schema.json +63 -0
- package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
- package/src/generators/nextjs-app/files/.env.example.template +24 -0
- package/src/generators/nextjs-app/files/.gitignore.template +5 -0
- package/src/generators/nextjs-app/files/Dockerfile +53 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
- package/src/generators/nextjs-app/files/app/error.tsx +39 -0
- package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
- package/src/generators/nextjs-app/files/app/globals.css +105 -0
- package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
- package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
- package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
- package/src/generators/nextjs-app/files/app/page.tsx +20 -0
- package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
- package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
- package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
- package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
- package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
- package/src/generators/nextjs-app/files/components.json +21 -0
- package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
- package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
- package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
- package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
- package/src/generators/nextjs-app/files/lib/config.ts +21 -0
- package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
- package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
- package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
- package/src/generators/nextjs-app/files/next.config.mjs +9 -0
- package/src/generators/nextjs-app/files/package.json +70 -0
- package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
- package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
- package/src/generators/nextjs-app/files/proxy.ts +31 -0
- package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
- package/src/generators/nextjs-app/files/tsconfig.json +42 -0
- package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
- package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
- package/src/generators/nextjs-app/generator.ts +307 -0
- package/src/generators/nextjs-app/schema.json +44 -0
- package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
- package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
- package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
- package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
- package/src/generators/python-microservice/docs/principles/stack/python/testing.md +281 -0
- package/src/generators/python-microservice/files/.env.example.template +30 -0
- package/src/generators/python-microservice/files/Dockerfile.template +36 -0
- package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
- package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
- package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
- package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
- package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
- package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
- package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
- package/src/generators/python-microservice/generator.ts +286 -0
- package/src/generators/python-microservice/schema.json +86 -0
- package/src/generators/shared/brand-tokens.ts +301 -0
- package/src/generators/shared/capabilities.ts +349 -0
- package/src/generators/shared/provenance.ts +61 -0
- package/src/generators/shared/scaffold-helpers.ts +309 -0
- package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
- package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
- package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
- package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
- package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
- package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
- package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
- package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +227 -0
- package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
- package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
- package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
- package/src/generators/system-test-runner/generator.ts +142 -0
- package/src/generators/system-test-runner/schema.json +24 -0
- package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
- package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
- package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
- package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
- package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
- package/src/generators/workspace-dev-cli/files/dev.template +16 -0
- package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
- package/src/generators/workspace-dev-cli/generator.ts +136 -0
- package/src/generators/workspace-dev-cli/schema.json +22 -0
- package/src/hidden-skills/code-intelligence.md +129 -0
- package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
- package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
- package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
- package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
- package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
- package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
- package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
- package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
- package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
- package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
- package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
- package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
- package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
- package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
- package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
- package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
- package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
- package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
- package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
- package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
- package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
- package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
- package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +191 -0
- package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
- package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +126 -0
- package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +35 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +35 -0
- package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
- package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +198 -0
- package/src/hidden-skills/groundwork-bet/workflows/02-design.md +168 -0
- package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +246 -0
- package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +193 -0
- package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +199 -0
- package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
- package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
- package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
- package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
- package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
- package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
- package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
- package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
- package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
- package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
- package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
- package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
- package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
- package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
- package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
- package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
- package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
- package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
- package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
- package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
- package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
- package/src/hidden-skills/groundwork-persona/instructions.md +54 -0
- package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
- package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
- package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
- package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
- package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
- package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
- package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
- package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
- package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
- package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
- package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
- package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
- package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
- package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
- package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
- package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
- package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
- package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +46 -0
- package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
- package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
- package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
- package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
- package/src/hidden-skills/groundwork-review/instructions.md +181 -0
- package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
- package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
- package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
- package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
- package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
- package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
- package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
- package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
- package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
- package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
- package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
- package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
- package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
- package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
- package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
- package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
- package/src/hidden-skills/groundwork-update/instructions.md +200 -0
- package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
- package/src/hidden-skills/maturity-model.md +125 -0
- package/src/hidden-skills/operating-contract.md +400 -0
- package/src/hidden-skills/repo-map-schema.md +90 -0
- package/src/hidden-skills/templates/adr.md +57 -0
- package/src/hidden-skills/templates/capability-ports.md +71 -0
- package/src/hidden-skills/templates/discovery-notes.md +33 -0
- package/src/hidden-skills/templates/domain-entity.md +80 -0
- package/src/hidden-skills/templates/gap-ledger.md +21 -0
- package/src/hidden-skills/templates/handoff.md +37 -0
- package/src/hidden-skills/templates/maturity.md +39 -0
- package/src/hidden-skills/templates/surfaces.md +207 -0
- package/src/skills/groundwork-check/SKILL.md +56 -0
- package/src/skills/groundwork-check/instructions.md +70 -0
- package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
- package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module <%= name %>
|
|
2
|
+
|
|
3
|
+
go 1.22.0
|
|
4
|
+
|
|
5
|
+
require (
|
|
6
|
+
github.com/danielgtaylor/huma/v2 v2.34.1
|
|
7
|
+
github.com/go-chi/chi/v5 v5.2.2
|
|
8
|
+
github.com/go-chi/cors v1.2.2
|
|
9
|
+
github.com/rs/zerolog v1.34.0
|
|
10
|
+
github.com/joho/godotenv v1.5.1
|
|
11
|
+
go.opentelemetry.io/otel v1.24.0
|
|
12
|
+
go.opentelemetry.io/otel/trace v1.24.0
|
|
13
|
+
go.opentelemetry.io/otel/sdk v1.24.0
|
|
14
|
+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0
|
|
15
|
+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0
|
|
16
|
+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0
|
|
17
|
+
go.opentelemetry.io/otel/metric v1.24.0
|
|
18
|
+
go.opentelemetry.io/otel/sdk/metric v1.24.0
|
|
19
|
+
github.com/stripe/pg-schema-diff v1.0.5
|
|
20
|
+
github.com/lib/pq v1.10.9
|
|
21
|
+
<% if (auth === 'clerk') { %>
|
|
22
|
+
github.com/clerk/clerk-sdk-go/v2 v2.5.1
|
|
23
|
+
github.com/svix/svix-webhooks v1.90.0
|
|
24
|
+
<% } %>
|
|
25
|
+
<% if (websockets) { %>
|
|
26
|
+
github.com/gorilla/websocket v1.5.3
|
|
27
|
+
<% } %>
|
|
28
|
+
<% if (messaging === 'kafka') { %>
|
|
29
|
+
github.com/confluentinc/confluent-kafka-go/v2 v2.14.1
|
|
30
|
+
<% } else if (messaging === 'gcp-pubsub') { %>
|
|
31
|
+
cloud.google.com/go/pubsub v1.37.0
|
|
32
|
+
<% } %>
|
|
33
|
+
github.com/sony/gobreaker v1.0.0
|
|
34
|
+
github.com/cenkalti/backoff/v4 v4.3.0
|
|
35
|
+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
|
|
36
|
+
github.com/stretchr/testify v1.9.0
|
|
37
|
+
github.com/testcontainers/testcontainers-go v0.29.1
|
|
38
|
+
github.com/testcontainers/testcontainers-go/modules/postgres v0.29.1
|
|
39
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
package config
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"log"
|
|
5
|
+
|
|
6
|
+
"github.com/caarlos0/env/v11"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
type Config struct {
|
|
10
|
+
Server ServerConfig
|
|
11
|
+
Database DatabaseConfig
|
|
12
|
+
Redis RedisConfig
|
|
13
|
+
Telemetry TelemetryConfig
|
|
14
|
+
<% if (auth === 'clerk') { %>
|
|
15
|
+
Auth AuthConfig
|
|
16
|
+
<% } %>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
<% if (auth === 'clerk') { %>
|
|
20
|
+
type AuthConfig struct {
|
|
21
|
+
// No default: a missing secret leaves this empty so the webhook handler
|
|
22
|
+
// fails loud ("not configured") rather than masquerading as a configured
|
|
23
|
+
// service with a stub secret that silently rejects every signature.
|
|
24
|
+
ClerkWebhookSecret string `env:"CLERK_WEBHOOK_SIGNING_SECRET"`
|
|
25
|
+
}
|
|
26
|
+
<% } %>
|
|
27
|
+
|
|
28
|
+
type ServerConfig struct {
|
|
29
|
+
Port int `env:"PORT" envDefault:"8080"`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type DatabaseConfig struct {
|
|
33
|
+
URI string `env:"DATABASE_URL" envDefault:"postgres://postgres:postgres@localhost:5432/<%= name %>?sslmode=disable"`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type RedisConfig struct {
|
|
37
|
+
URI string `env:"REDIS_URL"` // Optional: If set, enables Valkey/Redis for backplane and rate limiting
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type TelemetryConfig struct {
|
|
41
|
+
// Per the OTLP spec this carries a scheme (e.g. http://otel-host:4317).
|
|
42
|
+
// InitProvider parses it with WithEndpointURL, which is scheme-aware.
|
|
43
|
+
CollectorURL string `env:"OTEL_EXPORTER_OTLP_ENDPOINT" envDefault:"http://localhost:4317"`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func Load() *Config {
|
|
47
|
+
var cfg Config
|
|
48
|
+
if err := env.Parse(&cfg); err != nil {
|
|
49
|
+
log.Fatalf("failed to load configuration: %v", err)
|
|
50
|
+
}
|
|
51
|
+
return &cfg
|
|
52
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
package config
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"go.opentelemetry.io/otel"
|
|
8
|
+
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
|
|
9
|
+
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
|
10
|
+
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
|
11
|
+
"go.opentelemetry.io/otel/propagation"
|
|
12
|
+
"go.opentelemetry.io/otel/sdk/resource"
|
|
13
|
+
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
|
14
|
+
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
15
|
+
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// InitProvider initializes an OpenTelemetry trace provider connected to an OTLP endpoint.
|
|
19
|
+
func InitProvider(ctx context.Context, serviceName, collectorURL string) (func(context.Context) error, error) {
|
|
20
|
+
if collectorURL == "" {
|
|
21
|
+
// Use default standard OTEL environment variables if no URL is provided
|
|
22
|
+
collectorURL = "http://localhost:4317"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
res, err := resource.Merge(
|
|
26
|
+
resource.Default(),
|
|
27
|
+
resource.NewWithAttributes(
|
|
28
|
+
"", // Use empty schemaURL to inherit from resource.Default()
|
|
29
|
+
semconv.ServiceName(serviceName),
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
if err != nil {
|
|
33
|
+
return nil, fmt.Errorf("merge otel resources: %w", err)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// WithEndpointURL is scheme-aware and accepts the full OTLP endpoint URL
|
|
37
|
+
// (e.g. http://otel-host:4317). WithEndpoint, by contrast, wants a bare
|
|
38
|
+
// host:port and silently mis-dials when handed an http:// value.
|
|
39
|
+
client := otlptracegrpc.NewClient(
|
|
40
|
+
otlptracegrpc.WithEndpointURL(collectorURL),
|
|
41
|
+
otlptracegrpc.WithInsecure(),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
exporter, err := otlptrace.New(ctx, client)
|
|
45
|
+
if err != nil {
|
|
46
|
+
return nil, fmt.Errorf("create otel exporter: %w", err)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
tp := sdktrace.NewTracerProvider(
|
|
50
|
+
sdktrace.WithBatcher(exporter),
|
|
51
|
+
sdktrace.WithResource(res),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
otel.SetTracerProvider(tp)
|
|
55
|
+
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
|
|
56
|
+
propagation.TraceContext{},
|
|
57
|
+
propagation.Baggage{},
|
|
58
|
+
))
|
|
59
|
+
|
|
60
|
+
// --- Metrics ---
|
|
61
|
+
// The otelhttp middleware records baseline HTTP server metrics (request
|
|
62
|
+
// count, latency histogram, active in-flight requests) automatically once a
|
|
63
|
+
// global MeterProvider is registered. Export them over OTLP gRPC on a
|
|
64
|
+
// periodic reader to the same collector as traces.
|
|
65
|
+
metricExporter, err := otlpmetricgrpc.New(ctx,
|
|
66
|
+
otlpmetricgrpc.WithEndpointURL(collectorURL),
|
|
67
|
+
otlpmetricgrpc.WithInsecure(),
|
|
68
|
+
)
|
|
69
|
+
if err != nil {
|
|
70
|
+
return nil, fmt.Errorf("create otel metric exporter: %w", err)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
mp := sdkmetric.NewMeterProvider(
|
|
74
|
+
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter)),
|
|
75
|
+
sdkmetric.WithResource(res),
|
|
76
|
+
)
|
|
77
|
+
otel.SetMeterProvider(mp)
|
|
78
|
+
|
|
79
|
+
// Combined shutdown: flush and close both providers. The returned signature
|
|
80
|
+
// is unchanged, so main.go's `defer otelShutdown(ctx)` call is untouched.
|
|
81
|
+
shutdown := func(ctx context.Context) error {
|
|
82
|
+
var firstErr error
|
|
83
|
+
if err := tp.Shutdown(ctx); err != nil {
|
|
84
|
+
firstErr = err
|
|
85
|
+
}
|
|
86
|
+
if err := mp.Shutdown(ctx); err != nil && firstErr == nil {
|
|
87
|
+
firstErr = err
|
|
88
|
+
}
|
|
89
|
+
return firstErr
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return shutdown, nil
|
|
93
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package domain
|
|
2
|
+
|
|
3
|
+
import "errors"
|
|
4
|
+
|
|
5
|
+
// Standard Sentinel Errors
|
|
6
|
+
// These errors should be used across the core domain to represent
|
|
7
|
+
// business logic failures, allowing entrypoints (like HTTP routers)
|
|
8
|
+
// to map them to the appropriate status codes.
|
|
9
|
+
|
|
10
|
+
var (
|
|
11
|
+
ErrNotFound = errors.New("resource not found")
|
|
12
|
+
ErrConflict = errors.New("resource already exists")
|
|
13
|
+
ErrUnauthorized = errors.New("unauthorized action")
|
|
14
|
+
ErrInvalidPayload = errors.New("invalid payload provided")
|
|
15
|
+
ErrInternal = errors.New("internal server error")
|
|
16
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package domain
|
|
2
|
+
|
|
3
|
+
import "time"
|
|
4
|
+
|
|
5
|
+
// Entity represents a basic domain model.
|
|
6
|
+
// Replace this with your actual business entities.
|
|
7
|
+
type Entity struct {
|
|
8
|
+
ID string `json:"id"`
|
|
9
|
+
Name string `json:"name"`
|
|
10
|
+
CreatedAt time.Time `json:"created_at"`
|
|
11
|
+
UpdatedAt time.Time `json:"updated_at"`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// OutboxEvent represents a serialized event to be published
|
|
15
|
+
// via the Transactional Outbox pattern.
|
|
16
|
+
type OutboxEvent struct {
|
|
17
|
+
ID string `json:"id"`
|
|
18
|
+
EventType string `json:"event_type"`
|
|
19
|
+
Payload []byte `json:"payload"`
|
|
20
|
+
CreatedAt int64 `json:"created_at"`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Event represents a generic domain event used for synchronous
|
|
24
|
+
// broadcasting to connected clients (e.g., via WebSocket hub).
|
|
25
|
+
type Event struct {
|
|
26
|
+
Type string `json:"type"`
|
|
27
|
+
Payload any `json:"payload"`
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package core
|
|
2
|
+
|
|
3
|
+
// PageRequest models a standard cursor-based pagination request.
|
|
4
|
+
type PageRequest struct {
|
|
5
|
+
Cursor string `json:"cursor" query:"cursor" description:"Opaque cursor for the next page of results"`
|
|
6
|
+
Limit int `json:"limit" query:"limit" description:"Maximum number of items to return" default:"50"`
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// PageResponse is a generic container for paginated collections, ensuring all API
|
|
10
|
+
// lists return the same shape.
|
|
11
|
+
type PageResponse[T any] struct {
|
|
12
|
+
Items []T `json:"items" description:"The collection of items"`
|
|
13
|
+
NextCursor string `json:"nextCursor,omitempty" description:"Opaque cursor to retrieve the next page, omitted if there are no more pages"`
|
|
14
|
+
PrevCursor string `json:"prevCursor,omitempty" description:"Opaque cursor to retrieve the previous page"`
|
|
15
|
+
HasMore bool `json:"hasMore" description:"True if there are more items beyond the next cursor"`
|
|
16
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
package service
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"<%= name %>/internal/core/domain"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// AppService orchestrates business use-cases, coordinating between
|
|
11
|
+
// domain entities, database transactions, and message publishing.
|
|
12
|
+
//
|
|
13
|
+
// The interfaces it depends on (TransactionManager, Repository, EventHub,
|
|
14
|
+
// OutboxRepository) are declared in this package — the consumer owns the
|
|
15
|
+
// interface it needs, and adapters in internal/postgres, internal/kafka, etc.
|
|
16
|
+
// satisfy them implicitly. The dependency arrow points inward (edge -> core),
|
|
17
|
+
// enforced by depguard.
|
|
18
|
+
type AppService struct {
|
|
19
|
+
txManager TransactionManager
|
|
20
|
+
repo Repository[domain.Entity]
|
|
21
|
+
eventHub EventHub
|
|
22
|
+
<% if (messaging !== 'none') { %>
|
|
23
|
+
outbox OutboxRepository
|
|
24
|
+
<% } %>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// NewAppService creates a new instance of the application service.
|
|
28
|
+
func NewAppService(
|
|
29
|
+
txManager TransactionManager,
|
|
30
|
+
repo Repository[domain.Entity],
|
|
31
|
+
eventHub EventHub,
|
|
32
|
+
<% if (messaging !== 'none') { %>
|
|
33
|
+
outbox OutboxRepository,
|
|
34
|
+
<% } %>
|
|
35
|
+
) *AppService {
|
|
36
|
+
return &AppService{
|
|
37
|
+
txManager: txManager,
|
|
38
|
+
repo: repo,
|
|
39
|
+
eventHub: eventHub,
|
|
40
|
+
<% if (messaging !== 'none') { %>
|
|
41
|
+
outbox: outbox,
|
|
42
|
+
<% } %>
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ExecuteUseCase demonstrates a standard transactional use-case.
|
|
47
|
+
func (s *AppService) ExecuteUseCase(ctx context.Context, entity *domain.Entity) error {
|
|
48
|
+
// Begin transaction
|
|
49
|
+
tx, err := s.txManager.Begin(ctx)
|
|
50
|
+
if err != nil {
|
|
51
|
+
return fmt.Errorf("begin transaction: %w", err)
|
|
52
|
+
}
|
|
53
|
+
defer tx.Rollback(ctx)
|
|
54
|
+
|
|
55
|
+
// Perform business logic (e.g., save to DB)
|
|
56
|
+
if err := s.repo.Create(ctx, entity); err != nil {
|
|
57
|
+
return fmt.Errorf("create entity: %w", err)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
<% if (messaging !== 'none') { %>
|
|
61
|
+
// Insert domain event into the outbox within the same transaction
|
|
62
|
+
if err := s.outbox.InsertEvent(ctx, tx, "EntityCreated", []byte(`{"id":"`+entity.ID+`"}`)); err != nil {
|
|
63
|
+
return fmt.Errorf("insert outbox event: %w", err)
|
|
64
|
+
}
|
|
65
|
+
<% } %>
|
|
66
|
+
|
|
67
|
+
// Commit transaction
|
|
68
|
+
if err := tx.Commit(ctx); err != nil {
|
|
69
|
+
return fmt.Errorf("commit transaction: %w", err)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Broadcast the domain event synchronously to live clients
|
|
73
|
+
s.eventHub.Broadcast(domain.Event{
|
|
74
|
+
Type: "entity.created",
|
|
75
|
+
Payload: entity,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return nil
|
|
79
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<% if (messaging !== 'none') { %>package service
|
|
2
|
+
|
|
3
|
+
import "context"
|
|
4
|
+
|
|
5
|
+
// MessageQueue defines operations for publishing domain messages
|
|
6
|
+
// to an asynchronous message bus or queue.
|
|
7
|
+
type MessageQueue interface {
|
|
8
|
+
Publish(ctx context.Context, topic string, key, data []byte) error
|
|
9
|
+
}
|
|
10
|
+
<% } %>
|
package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<% if (messaging !== 'none') { %>package service
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
// OutboxEvent represents a serialized domain event stored in the outbox table.
|
|
8
|
+
type OutboxEvent struct {
|
|
9
|
+
ID string
|
|
10
|
+
EventType string
|
|
11
|
+
Payload []byte
|
|
12
|
+
CreatedAt int64
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// OutboxRepository manages transactional outbox events.
|
|
16
|
+
// Events are inserted in the same DB transaction as domain mutations,
|
|
17
|
+
// then published asynchronously by a background relay.
|
|
18
|
+
type OutboxRepository interface {
|
|
19
|
+
// InsertEvent inserts an outbox event. The implementation is responsible
|
|
20
|
+
// for managing its own transactional context when needed.
|
|
21
|
+
InsertEvent(ctx context.Context, tx Transaction, eventType string, payload []byte) error
|
|
22
|
+
|
|
23
|
+
// PollUnpublished returns up to `limit` unpublished events, oldest first.
|
|
24
|
+
// The implementation must ensure row-level locking within a transaction
|
|
25
|
+
// to prevent duplicate processing by concurrent relay instances.
|
|
26
|
+
PollUnpublished(ctx context.Context, limit int) ([]OutboxEvent, error)
|
|
27
|
+
|
|
28
|
+
// MarkPublished marks an outbox event as published.
|
|
29
|
+
MarkPublished(ctx context.Context, id string) error
|
|
30
|
+
}
|
|
31
|
+
<% } %>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package service
|
|
2
|
+
|
|
3
|
+
import "context"
|
|
4
|
+
|
|
5
|
+
// Repository defines a standard generic interface for data access.
|
|
6
|
+
type Repository[T any] interface {
|
|
7
|
+
GetByID(ctx context.Context, id string) (*T, error)
|
|
8
|
+
Create(ctx context.Context, entity *T) error
|
|
9
|
+
Update(ctx context.Context, entity *T) error
|
|
10
|
+
Delete(ctx context.Context, id string) error
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Transaction represents an active database transaction.
|
|
14
|
+
type Transaction interface {
|
|
15
|
+
Commit(ctx context.Context) error
|
|
16
|
+
Rollback(ctx context.Context) error
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// TransactionManager defines an interface for managing database transactions.
|
|
20
|
+
// This is typically injected into application services to wrap domain use-cases.
|
|
21
|
+
type TransactionManager interface {
|
|
22
|
+
Begin(ctx context.Context) (Transaction, error)
|
|
23
|
+
}
|
package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package service
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
|
|
6
|
+
"<%= name %>/internal/core/domain"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// UserRepository defines the interface for user data access
|
|
10
|
+
type UserRepository interface {
|
|
11
|
+
GetByClerkID(ctx context.Context, clerkID string) (*domain.User, error)
|
|
12
|
+
Save(ctx context.Context, user *domain.User) error
|
|
13
|
+
Update(ctx context.Context, user *domain.User) error
|
|
14
|
+
DeleteByClerkID(ctx context.Context, clerkID string) error
|
|
15
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package service
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"<%= name %>/internal/core/domain"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
type UserService struct {
|
|
11
|
+
repo UserRepository
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func NewUserService(repo UserRepository) *UserService {
|
|
15
|
+
return &UserService{
|
|
16
|
+
repo: repo,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func (s *UserService) GetByClerkID(ctx context.Context, clerkID string) (*domain.User, error) {
|
|
21
|
+
return s.repo.GetByClerkID(ctx, clerkID)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func (s *UserService) Save(ctx context.Context, user *domain.User) error {
|
|
25
|
+
if err := s.repo.Save(ctx, user); err != nil {
|
|
26
|
+
return fmt.Errorf("failed to save user: %w", err)
|
|
27
|
+
}
|
|
28
|
+
return nil
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func (s *UserService) Update(ctx context.Context, user *domain.User) error {
|
|
32
|
+
if err := s.repo.Update(ctx, user); err != nil {
|
|
33
|
+
return fmt.Errorf("failed to update user: %w", err)
|
|
34
|
+
}
|
|
35
|
+
return nil
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func (s *UserService) DeleteByClerkID(ctx context.Context, clerkID string) error {
|
|
39
|
+
if err := s.repo.DeleteByClerkID(ctx, clerkID); err != nil {
|
|
40
|
+
return fmt.Errorf("failed to delete user by clerk id: %w", err)
|
|
41
|
+
}
|
|
42
|
+
return nil
|
|
43
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
package api
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"errors"
|
|
6
|
+
"net/http"
|
|
7
|
+
"time"
|
|
8
|
+
|
|
9
|
+
"github.com/danielgtaylor/huma/v2"
|
|
10
|
+
|
|
11
|
+
"<%= name %>/internal/core/domain"
|
|
12
|
+
"<%= name %>/internal/core/service"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
type CreateEntityRequest struct {
|
|
16
|
+
Body struct {
|
|
17
|
+
Name string `json:"name" doc:"Name of the entity"`
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type CreateEntityResponse struct {
|
|
22
|
+
Body struct {
|
|
23
|
+
ID string `json:"id"`
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type ListEntitiesRequest struct {
|
|
28
|
+
Limit int `query:"limit" default:"20" minimum:"1" maximum:"100" doc:"Number of items to return"`
|
|
29
|
+
Cursor string `query:"cursor" required:"false" doc:"Cursor for pagination"`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type ListEntitiesResponse struct {
|
|
33
|
+
Body struct {
|
|
34
|
+
Data []*domain.Entity `json:"data"`
|
|
35
|
+
Pagination paginationEnvelope `json:"pagination"`
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// RegisterAppHandler demonstrates how to register endpoints mapped to use-cases in AppService.
|
|
40
|
+
func RegisterAppHandler(api huma.API, appSvc *service.AppService) {
|
|
41
|
+
huma.Register(api, huma.Operation{
|
|
42
|
+
OperationID: "create-entity",
|
|
43
|
+
Method: http.MethodPost,
|
|
44
|
+
Path: "/api/v1/entities",
|
|
45
|
+
Summary: "Create a new entity",
|
|
46
|
+
Description: "Creates a new domain entity and returns its ID.",
|
|
47
|
+
Tags: []string{"Entities"},
|
|
48
|
+
}, func(ctx context.Context, input *CreateEntityRequest) (*CreateEntityResponse, error) {
|
|
49
|
+
|
|
50
|
+
entity := &domain.Entity{
|
|
51
|
+
ID: "gen-id-123", // STUB: use uuid.New()
|
|
52
|
+
Name: input.Body.Name,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if err := appSvc.ExecuteUseCase(ctx, entity); err != nil {
|
|
56
|
+
if errors.Is(err, domain.ErrConflict) {
|
|
57
|
+
return nil, huma.Error409Conflict("Entity already exists", err)
|
|
58
|
+
}
|
|
59
|
+
return nil, huma.Error500InternalServerError("Internal server error", err)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
resp := &CreateEntityResponse{}
|
|
63
|
+
resp.Body.ID = entity.ID
|
|
64
|
+
return resp, nil
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
huma.Register(api, huma.Operation{
|
|
68
|
+
OperationID: "list-entities",
|
|
69
|
+
Method: http.MethodGet,
|
|
70
|
+
Path: "/api/v1/entities",
|
|
71
|
+
Summary: "List entities",
|
|
72
|
+
Description: "Returns a paginated list of entities.",
|
|
73
|
+
Tags: []string{"Entities"},
|
|
74
|
+
}, func(ctx context.Context, input *ListEntitiesRequest) (*ListEntitiesResponse, error) {
|
|
75
|
+
|
|
76
|
+
// 1. Decode Cursor
|
|
77
|
+
var afterID string
|
|
78
|
+
var afterCreatedAt time.Time
|
|
79
|
+
if payload := decodeCursor(input.Cursor); payload != nil {
|
|
80
|
+
afterID = payload.ID
|
|
81
|
+
afterCreatedAt = payload.CreatedAt
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_ = afterID
|
|
85
|
+
_ = afterCreatedAt
|
|
86
|
+
|
|
87
|
+
// STUB: Use afterID, afterCreatedAt and input.Limit to fetch items.
|
|
88
|
+
// Example: items, err := appSvc.ListEntities(ctx, afterID, afterCreatedAt, input.Limit+1)
|
|
89
|
+
|
|
90
|
+
// For demonstration, we create a mock list
|
|
91
|
+
now := time.Now()
|
|
92
|
+
items := []*domain.Entity{
|
|
93
|
+
{ID: "ent-1", Name: "First", CreatedAt: now.Add(-1 * time.Hour)},
|
|
94
|
+
{ID: "ent-2", Name: "Second", CreatedAt: now.Add(-2 * time.Hour)},
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 2. Build Pagination
|
|
98
|
+
data, pagination := buildPagination(items, input.Limit,
|
|
99
|
+
func(e *domain.Entity) string { return e.ID },
|
|
100
|
+
func(e *domain.Entity) time.Time { return e.CreatedAt },
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
resp := &ListEntitiesResponse{}
|
|
104
|
+
resp.Body.Data = data
|
|
105
|
+
resp.Body.Pagination = pagination
|
|
106
|
+
return resp, nil
|
|
107
|
+
})
|
|
108
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<% if (auth === 'clerk') { %>package api
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"net/http"
|
|
5
|
+
"net/http/httptest"
|
|
6
|
+
"testing"
|
|
7
|
+
|
|
8
|
+
"github.com/stretchr/testify/require"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
func protectedHandler() http.Handler {
|
|
12
|
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
13
|
+
w.WriteHeader(http.StatusOK)
|
|
14
|
+
_, _ = w.Write([]byte("protected"))
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// NOTE on status codes: Clerk's clerkhttp.RequireHeaderAuthorization (v2) responds
|
|
19
|
+
// with HTTP 403 Forbidden — NOT 401 — when the Authorization header is missing or
|
|
20
|
+
// carries an unverifiable token (it short-circuits before reaching the wrapped
|
|
21
|
+
// handler that would otherwise emit 401). No Clerk secret key is required for these
|
|
22
|
+
// paths: a missing token never decodes a JWT, and a malformed token fails
|
|
23
|
+
// jwt.Decode locally before any key/JWKS lookup, so both surface 403 offline.
|
|
24
|
+
|
|
25
|
+
func TestAuthMiddleware_BypassesHealthAndWebhooks(t *testing.T) {
|
|
26
|
+
h := AuthMiddleware()(protectedHandler())
|
|
27
|
+
|
|
28
|
+
for _, path := range []string{"/health", "/webhooks/clerk"} {
|
|
29
|
+
rr := httptest.NewRecorder()
|
|
30
|
+
h.ServeHTTP(rr, httptest.NewRequest(http.MethodGet, path, nil))
|
|
31
|
+
require.Equal(t, http.StatusOK, rr.Code, "auth must bypass %s", path)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func TestAuthMiddleware_RejectsMissingToken(t *testing.T) {
|
|
36
|
+
// No Authorization header on a protected route -> Clerk's RequireHeaderAuthorization
|
|
37
|
+
// rejects with 403 before reaching the inner handler.
|
|
38
|
+
h := AuthMiddleware()(protectedHandler())
|
|
39
|
+
rr := httptest.NewRecorder()
|
|
40
|
+
h.ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/api/v1/entities", nil))
|
|
41
|
+
require.Equal(t, http.StatusForbidden, rr.Code)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func TestAuthMiddleware_RejectsBadToken(t *testing.T) {
|
|
45
|
+
h := AuthMiddleware()(protectedHandler())
|
|
46
|
+
rr := httptest.NewRecorder()
|
|
47
|
+
req := httptest.NewRequest(http.MethodGet, "/api/v1/entities", nil)
|
|
48
|
+
req.Header.Set("Authorization", "Bearer not-a-real-jwt")
|
|
49
|
+
h.ServeHTTP(rr, req)
|
|
50
|
+
require.Equal(t, http.StatusForbidden, rr.Code, "an unverifiable token must not pass")
|
|
51
|
+
}
|
|
52
|
+
<% } %>
|