@polymorphism-tech/morph-spec 3.0.1 → 3.1.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/CLAUDE.md +52 -88
- package/LICENSE +72 -72
- package/README.md +198 -76
- package/bin/detect-agents.js +3 -1
- package/bin/morph-spec.js +10 -0
- package/bin/render-template.js +5 -4
- package/bin/semantic-detect-agents.js +2 -1
- package/bin/{task-manager.js → task-manager.cjs} +12 -1
- package/bin/validate-agents-skills.js +10 -4
- package/bin/validate-agents.js +4 -3
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +3 -3
- package/docs/templates.md +418 -418
- package/package.json +3 -3
- package/scripts/postinstall.js +132 -132
- package/scripts/reorganize-skills.cjs +1 -1
- package/scripts/validate-agents-structure.cjs +1 -1
- package/scripts/validate-skills.cjs +2 -2
- package/src/commands/analyze-blazor-concurrency.js +193 -193
- package/src/commands/create-story.js +5 -2
- package/src/commands/deploy.js +780 -780
- package/src/commands/detect-agents.js +4 -2
- package/src/commands/generate.js +149 -149
- package/src/commands/lint-fluent.js +352 -352
- package/src/commands/rollback-phase.js +185 -185
- package/src/commands/session-summary.js +291 -291
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/task.js +1 -1
- package/src/commands/troubleshoot.js +222 -222
- package/src/commands/validate-blazor-state.js +210 -210
- package/src/commands/validate-blazor.js +156 -156
- package/src/commands/validate-css.js +84 -84
- package/src/commands/validate-phase.js +221 -221
- package/src/lib/blazor-concurrency-analyzer.js +288 -288
- package/src/lib/blazor-state-validator.js +291 -291
- package/src/lib/blazor-validator.js +374 -374
- package/src/lib/context-generator.js +7 -4
- package/src/lib/css-validator.js +352 -352
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/hook-executor.js +2 -1
- package/src/lib/learning-system.js +520 -520
- package/src/lib/mockup-generator.js +366 -366
- package/src/lib/stack-resolver.js +148 -0
- package/src/lib/standards-context-injector.js +4 -3
- package/src/lib/team-orchestrator.js +2 -1
- package/src/lib/troubleshoot-grep.js +204 -194
- package/src/lib/troubleshoot-index.js +144 -144
- package/src/lib/ui-detector.js +350 -350
- package/src/lib/validation-runner.js +2 -1
- package/src/lib/validators/architecture-validator.js +387 -387
- package/src/lib/validators/package-validator.js +360 -360
- package/src/lib/validators/ui-contrast-validator.js +422 -422
- package/src/utils/file-copier.js +3 -1
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/{content → stacks/blazor-azure}/.azure/README.md +2 -2
- package/{content → stacks/blazor-azure}/.azure/pipelines/pipeline-variables.yml +1 -1
- package/{content → stacks/blazor-azure}/.azure/pipelines/prod-pipeline.yml +1 -1
- package/{content → stacks/blazor-azure}/.azure/pipelines/staging-pipeline.yml +1 -1
- package/{content → stacks/blazor-azure}/.claude/commands/morph-preflight.md +227 -227
- package/{content → stacks/blazor-azure}/.claude/commands/morph-troubleshoot.md +122 -122
- package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-setup.md +1 -1
- package/{content → stacks/blazor-azure}/.morph/docs/workflows/enforcement-pipeline.md +3 -3
- package/{content → stacks/blazor-azure}/.morph/hooks/README.md +12 -12
- package/{content → stacks/blazor-azure}/.morph/standards/agent-teams-workflow.md +2 -2
- package/{content → stacks/blazor-azure}/.morph/standards/migration-guide.md +2 -2
- package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy-checklist.md +426 -426
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +244 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +335 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +189 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +170 -0
- package/stacks/nextjs-supabase/.morph/config/agents.json +345 -0
- package/stacks/nextjs-supabase/.morph/config/config.template.json +92 -0
- package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +169 -0
- package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +247 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +697 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +85 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +86 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +498 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +121 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +138 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +162 -0
- package/stacks/nextjs-supabase/.morph/project.md +168 -0
- package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +191 -0
- package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +193 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +171 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +164 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +179 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +148 -0
- package/stacks/nextjs-supabase/.morph/templates/contracts.cs +173 -0
- package/stacks/nextjs-supabase/.morph/templates/contracts.ts +168 -0
- package/stacks/nextjs-supabase/.morph/templates/decisions.md +115 -0
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +38 -0
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +48 -0
- package/stacks/nextjs-supabase/.morph/templates/proposal.md +145 -0
- package/stacks/nextjs-supabase/.morph/templates/recap.md +134 -0
- package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +57 -0
- package/stacks/nextjs-supabase/.morph/templates/spec.md +231 -0
- package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +100 -0
- package/stacks/nextjs-supabase/.morph/templates/tasks.md +257 -0
- package/stacks/nextjs-supabase/CLAUDE.md +149 -0
- package/stacks/nextjs-supabase/README.md +112 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/azure-devops-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/branch-strategy.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/local-development.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/build-dotnet.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-app-service.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-container-app.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/infra-deploy.yml +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-apply.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-archive.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-deploy.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-infra.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-status.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/settings.local.json +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/code-review.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/morph-checklist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/simulation-checklist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/morph-replicate.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-clarify.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-design.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-uiux.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/resend-email.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-3-technologies/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-4-patterns/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/.morphversion +0 -0
- /package/{content → stacks/blazor-azure}/.morph/archive/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/config/agents.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/config/config.template.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/design-impl.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/fast-track.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/full-morph.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/standard.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/ui-refresh.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/contracts.ts +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/state-v3.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/features/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-agents.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-all.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-specs.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-tests.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/task-completed.js +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/teammate-idle.js +0 -0
- /package/{content → stacks/blazor-azure}/.morph/project.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/schemas/agent.schema.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/schemas/tasks.schema.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/specs/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-blazor-ui.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-production.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-workflows.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/architecture.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/azure.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/coding.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/dotnet10-migration.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/fluent-ui-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/passkeys-auth.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/vector-search-rag.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/state.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT-FEATURE.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/FluentDesignTheme.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/MudTheme.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/agent.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/clarify-questions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/component.razor +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Commands.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Entities.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Queries.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/design-system.css +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/.dockerignore.example +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/Dockerfile.example +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-insights.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-service.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/azure-pipelines-deploy.yml +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app-env.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.ps1 +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/key-vault.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/main.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.dev.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.prod.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.staging.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/sql-database.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/storage.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-client.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-webhook.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/azure-identity-config.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/clerk-config.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/job.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/migration.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/recap.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/repository.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/saas/subscription.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/saas/tenant.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/service.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/simulation.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/sprint-status.yaml +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/state.template.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/story.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/test.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-components.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-design-system.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-flows.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-mockups.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/test-infra/example.bicep +0 -0
- /package/{content → stacks/blazor-azure}/CLAUDE.md +0 -0
- /package/{content → stacks/blazor-azure}/README.md +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Multi-Tenant SaaS - Architectural Decision Records
|
|
2
|
+
|
|
3
|
+
## ADR-001: RLS-Based Tenant Isolation vs Schema-Per-Tenant
|
|
4
|
+
|
|
5
|
+
**Status**: Accepted
|
|
6
|
+
|
|
7
|
+
**Context**: Choose a multi-tenancy strategy for data isolation. The two main approaches are (a) shared database with Row Level Security filtering by tenant_id, and (b) separate PostgreSQL schema per tenant.
|
|
8
|
+
|
|
9
|
+
**Decision**: RLS-based tenant isolation with a single shared schema.
|
|
10
|
+
|
|
11
|
+
**Rationale**:
|
|
12
|
+
- Supabase natively supports RLS with built-in functions like `auth.uid()` and custom JWT claims
|
|
13
|
+
- Single schema simplifies migrations (one migration applies to all tenants)
|
|
14
|
+
- More cost-effective: one Supabase project serves all tenants
|
|
15
|
+
- Scales well to thousands of small-to-medium tenants
|
|
16
|
+
- Custom JWT claim `app_metadata.tenant_id` provides tenant context automatically
|
|
17
|
+
|
|
18
|
+
**Alternatives Considered**:
|
|
19
|
+
- Schema-per-tenant: Better isolation but Supabase does not natively manage multiple schemas per project. Migration management becomes complex. Operational overhead grows linearly with tenant count.
|
|
20
|
+
- Database-per-tenant: Maximum isolation but requires separate Supabase projects. Cost-prohibitive ($25/tenant/month on Pro).
|
|
21
|
+
|
|
22
|
+
**Consequences**:
|
|
23
|
+
- All queries must include tenant_id (enforced by RLS, not application code)
|
|
24
|
+
- Careful attention needed for admin/service-role queries that bypass RLS
|
|
25
|
+
- Bulk data export for a single tenant requires explicit filtering
|
|
26
|
+
- Index strategy must account for tenant_id prefix on all key queries
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ADR-002: Stripe for Subscription Billing
|
|
31
|
+
|
|
32
|
+
**Status**: Accepted
|
|
33
|
+
|
|
34
|
+
**Context**: Choose a billing provider for SaaS subscription management.
|
|
35
|
+
|
|
36
|
+
**Decision**: Stripe Billing with Checkout Sessions and Customer Portal.
|
|
37
|
+
|
|
38
|
+
**Rationale**:
|
|
39
|
+
- Industry standard for SaaS billing with mature subscription lifecycle management
|
|
40
|
+
- Stripe Checkout handles PCI compliance (no card data on our servers)
|
|
41
|
+
- Customer Portal lets users self-manage subscriptions, reducing support burden
|
|
42
|
+
- Webhook-driven architecture integrates cleanly with our event-based approach
|
|
43
|
+
- Extensive test mode for development without real charges
|
|
44
|
+
- Global reach with support for 135+ currencies
|
|
45
|
+
|
|
46
|
+
**Alternatives Considered**:
|
|
47
|
+
- Paddle: Simpler tax handling (Merchant of Record) but less customization and higher fees
|
|
48
|
+
- LemonSqueezy: Good for indie hackers but less mature API and limited webhook events
|
|
49
|
+
- Custom implementation: Too complex for MVP, PCI compliance burden
|
|
50
|
+
|
|
51
|
+
**Consequences**:
|
|
52
|
+
- Stripe fees: 2.9% + $0.30 per transaction
|
|
53
|
+
- Webhook handler must be idempotent (Stripe retries on failure)
|
|
54
|
+
- Subscription state must be synced between Stripe and our database
|
|
55
|
+
- Need to handle edge cases: failed payments, plan changes mid-cycle, proration
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## ADR-003: pgvector for AI-Powered Search
|
|
60
|
+
|
|
61
|
+
**Status**: Accepted
|
|
62
|
+
|
|
63
|
+
**Context**: Choose a vector storage and similarity search solution for semantic document search.
|
|
64
|
+
|
|
65
|
+
**Decision**: pgvector extension on Supabase PostgreSQL.
|
|
66
|
+
|
|
67
|
+
**Rationale**:
|
|
68
|
+
- Native PostgreSQL extension, no additional infrastructure needed
|
|
69
|
+
- Supabase Pro includes pgvector out of the box
|
|
70
|
+
- Keeps vectors co-located with tenant data (RLS applies to vector queries too)
|
|
71
|
+
- IVFFlat index provides good performance up to ~1M vectors per tenant
|
|
72
|
+
- Cosine similarity search with SQL-native syntax
|
|
73
|
+
- No vendor lock-in to proprietary vector databases
|
|
74
|
+
|
|
75
|
+
**Alternatives Considered**:
|
|
76
|
+
- Pinecone: Better performance at scale but adds another service, separate billing, and no native tenant isolation (would need namespace-per-tenant)
|
|
77
|
+
- Qdrant: Open source and performant but requires self-hosting another service
|
|
78
|
+
- Supabase Edge Functions + Pinecone: Adds latency and complexity for the AI path
|
|
79
|
+
|
|
80
|
+
**Consequences**:
|
|
81
|
+
- Embedding dimension fixed at 1536 (text-embedding-3-small). Changing models requires re-embedding all documents
|
|
82
|
+
- IVFFlat index requires periodic `REINDEX` as data grows significantly
|
|
83
|
+
- For >1M documents per tenant, consider HNSW index (higher memory, faster queries)
|
|
84
|
+
- OpenAI API call required for each search query (adds ~200ms latency)
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## ADR-004: Custom JWT Claims for Tenant Context
|
|
89
|
+
|
|
90
|
+
**Status**: Accepted
|
|
91
|
+
|
|
92
|
+
**Context**: Determine how to pass tenant context through the authentication flow so that RLS policies and API endpoints can identify the current tenant.
|
|
93
|
+
|
|
94
|
+
**Decision**: Store `tenant_id` in Supabase Auth `app_metadata`, which is included in the JWT automatically.
|
|
95
|
+
|
|
96
|
+
**Rationale**:
|
|
97
|
+
- Supabase Auth includes `app_metadata` in every JWT token by default
|
|
98
|
+
- No additional API calls needed to resolve tenant context
|
|
99
|
+
- RLS policies can read `request.jwt.claims -> 'app_metadata' -> 'tenant_id'`
|
|
100
|
+
- .NET API can extract tenant_id from JWT claims without database lookup
|
|
101
|
+
- Set via database trigger when user joins a tenant (no application code needed for claim updates)
|
|
102
|
+
|
|
103
|
+
**Alternatives Considered**:
|
|
104
|
+
- Header-based (`X-Tenant-ID`): Requires client to send header on every request, vulnerable to spoofing unless validated server-side
|
|
105
|
+
- Subdomain-based: Good UX but requires wildcard DNS, SSL, and URL parsing on every request. Supabase Auth redirect URLs become complex.
|
|
106
|
+
- Database lookup per request: Adds latency and database load to every authenticated request
|
|
107
|
+
|
|
108
|
+
**Implementation**:
|
|
109
|
+
- Trigger on `tenant_members` INSERT sets `raw_app_meta_data.tenant_id`
|
|
110
|
+
- User must re-authenticate (or refresh token) after joining a tenant to get updated claims
|
|
111
|
+
- Multi-tenant users: current implementation supports one active tenant per session. Switching tenants requires token refresh.
|
|
112
|
+
|
|
113
|
+
**Consequences**:
|
|
114
|
+
- Token refresh needed when user switches tenants
|
|
115
|
+
- app_metadata is read-only from client side (only service_role can modify)
|
|
116
|
+
- JWT size increases slightly (~50 bytes for tenant_id claim)
|
|
117
|
+
- Users without a tenant_id claim are redirected to onboarding
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Multi-Tenant SaaS - Specification
|
|
2
|
+
|
|
3
|
+
## 1. Overview
|
|
4
|
+
|
|
5
|
+
Multi-tenant SaaS platform with tenant isolation via PostgreSQL RLS, Stripe subscription billing, team management, and AI-powered semantic search using pgvector.
|
|
6
|
+
|
|
7
|
+
### 1.1 Objectives
|
|
8
|
+
|
|
9
|
+
- Tenant isolation at the database level via RLS with custom JWT claims
|
|
10
|
+
- Subscription billing with Stripe (free, starter, pro tiers)
|
|
11
|
+
- Team management with invite flows and role-based access
|
|
12
|
+
- AI-powered document search using OpenAI embeddings + pgvector
|
|
13
|
+
- Dashboard with tenant-scoped metrics and usage tracking
|
|
14
|
+
|
|
15
|
+
### 1.2 Personas
|
|
16
|
+
|
|
17
|
+
| Persona | Description |
|
|
18
|
+
|---------|-------------|
|
|
19
|
+
| **Tenant Owner** | Creates tenant, manages billing and team |
|
|
20
|
+
| **Tenant Admin** | Manages team members and settings |
|
|
21
|
+
| **Tenant Member** | Uses the platform (documents, search) |
|
|
22
|
+
| **Platform Admin** | Super admin with cross-tenant visibility |
|
|
23
|
+
|
|
24
|
+
## 2. Functional Requirements
|
|
25
|
+
|
|
26
|
+
### 2.1 Tenant Management
|
|
27
|
+
|
|
28
|
+
| ID | Requirement |
|
|
29
|
+
|----|-------------|
|
|
30
|
+
| TEN-001 | Create tenant during onboarding (name, slug) |
|
|
31
|
+
| TEN-002 | Tenant slug used for identification (unique) |
|
|
32
|
+
| TEN-003 | Tenant settings page (name, logo) |
|
|
33
|
+
| TEN-004 | Tenant status lifecycle: active, past_due, suspended |
|
|
34
|
+
| TEN-005 | tenant_id stored in Supabase Auth app_metadata for JWT claims |
|
|
35
|
+
|
|
36
|
+
### 2.2 Billing (Stripe)
|
|
37
|
+
|
|
38
|
+
| ID | Requirement |
|
|
39
|
+
|----|-------------|
|
|
40
|
+
| BILL-001 | Plans: Free, Starter ($29/mo), Pro ($79/mo) |
|
|
41
|
+
| BILL-002 | Stripe Checkout for subscription creation |
|
|
42
|
+
| BILL-003 | Stripe Customer Portal for plan management |
|
|
43
|
+
| BILL-004 | Webhook handling: subscription.created, updated, deleted |
|
|
44
|
+
| BILL-005 | Webhook handling: invoice.payment_failed |
|
|
45
|
+
| BILL-006 | Grace period of 7 days on payment failure before suspension |
|
|
46
|
+
|
|
47
|
+
### 2.3 Team Management
|
|
48
|
+
|
|
49
|
+
| ID | Requirement |
|
|
50
|
+
|----|-------------|
|
|
51
|
+
| TEAM-001 | Invite members by email |
|
|
52
|
+
| TEAM-002 | Roles: owner, admin, member |
|
|
53
|
+
| TEAM-003 | Owner can promote/demote members |
|
|
54
|
+
| TEAM-004 | Admin can invite and remove members |
|
|
55
|
+
| TEAM-005 | Member limits per plan (Free: 2, Starter: 5, Pro: 25) |
|
|
56
|
+
|
|
57
|
+
### 2.4 AI Search (pgvector)
|
|
58
|
+
|
|
59
|
+
| ID | Requirement |
|
|
60
|
+
|----|-------------|
|
|
61
|
+
| SEARCH-001 | Upload documents with automatic embedding generation |
|
|
62
|
+
| SEARCH-002 | Semantic search across tenant documents |
|
|
63
|
+
| SEARCH-003 | Configurable similarity threshold (default 0.7) |
|
|
64
|
+
| SEARCH-004 | Search results ranked by cosine similarity |
|
|
65
|
+
| SEARCH-005 | Search quota per plan (Free: 100/mo, Starter: 1K/mo, Pro: 10K/mo) |
|
|
66
|
+
|
|
67
|
+
### 2.5 Dashboard
|
|
68
|
+
|
|
69
|
+
| ID | Requirement |
|
|
70
|
+
|----|-------------|
|
|
71
|
+
| DASH-001 | Overview: total documents, team size, storage used, plan |
|
|
72
|
+
| DASH-002 | Search usage counter (monthly resets) |
|
|
73
|
+
| DASH-003 | Quick actions: invite member, upload document, search |
|
|
74
|
+
| DASH-004 | Billing status and upgrade prompt |
|
|
75
|
+
|
|
76
|
+
## 3. Non-Functional Requirements
|
|
77
|
+
|
|
78
|
+
### 3.1 Performance
|
|
79
|
+
|
|
80
|
+
| ID | Requirement |
|
|
81
|
+
|----|-------------|
|
|
82
|
+
| PERF-001 | API response < 200ms (P95) for CRUD endpoints |
|
|
83
|
+
| PERF-002 | Semantic search < 500ms (P95) for 100K documents |
|
|
84
|
+
| PERF-003 | pgvector IVFFlat index for sub-linear search time |
|
|
85
|
+
|
|
86
|
+
### 3.2 Security
|
|
87
|
+
|
|
88
|
+
| ID | Requirement |
|
|
89
|
+
|----|-------------|
|
|
90
|
+
| SEC-001 | RLS enforced on all tenant-scoped tables |
|
|
91
|
+
| SEC-002 | Stripe webhook signature validation |
|
|
92
|
+
| SEC-003 | Service role key never exposed to frontend |
|
|
93
|
+
| SEC-004 | Rate limiting per tenant (not per user) |
|
|
94
|
+
| SEC-005 | Audit log for team management actions |
|
|
95
|
+
|
|
96
|
+
### 3.3 Data Isolation
|
|
97
|
+
|
|
98
|
+
| ID | Requirement |
|
|
99
|
+
|----|-------------|
|
|
100
|
+
| ISO-001 | Single database with tenant_id column on all data tables |
|
|
101
|
+
| ISO-002 | RLS policies read tenant_id from JWT app_metadata |
|
|
102
|
+
| ISO-003 | No cross-tenant data leakage (validated by tests) |
|
|
103
|
+
|
|
104
|
+
## 4. Plans and Limits
|
|
105
|
+
|
|
106
|
+
| Feature | Free | Starter | Pro |
|
|
107
|
+
|---------|------|---------|-----|
|
|
108
|
+
| Team Members | 2 | 5 | 25 |
|
|
109
|
+
| Documents | 100 | 1,000 | 10,000 |
|
|
110
|
+
| Storage | 100MB | 1GB | 10GB |
|
|
111
|
+
| Searches/month | 100 | 1,000 | 10,000 |
|
|
112
|
+
| Support | Community | Email | Priority |
|
|
113
|
+
| Price/month | $0 | $29 | $79 |
|
|
114
|
+
|
|
115
|
+
## 5. Integrations
|
|
116
|
+
|
|
117
|
+
### 5.1 Stripe
|
|
118
|
+
|
|
119
|
+
- Customer management (one customer per tenant)
|
|
120
|
+
- Subscription lifecycle
|
|
121
|
+
- Checkout sessions and Customer Portal
|
|
122
|
+
- Webhook handling for payment events
|
|
123
|
+
|
|
124
|
+
### 5.2 OpenAI
|
|
125
|
+
|
|
126
|
+
- text-embedding-3-small for document embeddings (1536 dimensions)
|
|
127
|
+
- Called server-side only (API key never on frontend)
|
|
128
|
+
|
|
129
|
+
### 5.3 Supabase
|
|
130
|
+
|
|
131
|
+
- Auth with custom claims (tenant_id in app_metadata)
|
|
132
|
+
- PostgreSQL with RLS for tenant isolation
|
|
133
|
+
- pgvector extension for similarity search
|
|
134
|
+
- Storage for document files (per-tenant buckets)
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Multi-Tenant SaaS - Tasks
|
|
2
|
+
|
|
3
|
+
## Phase 1: Supabase Setup
|
|
4
|
+
|
|
5
|
+
| ID | Task | Dependencies | Estimate |
|
|
6
|
+
|----|------|--------------|----------|
|
|
7
|
+
| T001 | Create Supabase Pro project with pgvector extension enabled | - | S |
|
|
8
|
+
| T002 | Create tenants table and tenant_members table with RLS policies | T001 | M |
|
|
9
|
+
| T003 | Create auth.tenant_id() helper function for RLS | T001 | S |
|
|
10
|
+
| T004 | Create trigger to set app_metadata.tenant_id on tenant_members INSERT | T002 | M |
|
|
11
|
+
|
|
12
|
+
## Phase 2: Tenant Data Model
|
|
13
|
+
|
|
14
|
+
| ID | Task | Dependencies | Estimate |
|
|
15
|
+
|----|------|--------------|----------|
|
|
16
|
+
| T005 | Create documents table with tenant_id, embedding column (vector 1536), and RLS | T003 | M |
|
|
17
|
+
| T006 | Create IVFFlat index on documents.embedding for cosine similarity search | T005 | S |
|
|
18
|
+
| T007 | Create search_logs table for usage tracking (searches per month per tenant) | T003 | S |
|
|
19
|
+
| T008 | Create Supabase Storage bucket with per-tenant folder policies | T001 | S |
|
|
20
|
+
|
|
21
|
+
## Phase 3: .NET API Core
|
|
22
|
+
|
|
23
|
+
| ID | Task | Dependencies | Estimate |
|
|
24
|
+
|----|------|--------------|----------|
|
|
25
|
+
| T009 | Create .NET 10 Minimal API project with Dapper, Npgsql, Stripe.net | - | S |
|
|
26
|
+
| T010 | Configure JWT authentication with Supabase JWT secret and tenant_id claim extraction | T001, T009 | M |
|
|
27
|
+
| T011 | Create TenantMiddleware to extract and validate tenant_id from JWT claims | T010 | M |
|
|
28
|
+
| T012 | Configure CORS and health check endpoints | T009 | S |
|
|
29
|
+
|
|
30
|
+
## Phase 4: Stripe Billing Integration
|
|
31
|
+
|
|
32
|
+
| ID | Task | Dependencies | Estimate |
|
|
33
|
+
|----|------|--------------|----------|
|
|
34
|
+
| T013 | Create Stripe products and prices (Free, Starter $29, Pro $79) in Stripe Dashboard | - | S |
|
|
35
|
+
| T014 | Implement CreateCheckoutSession endpoint (creates Stripe customer + checkout) | T009, T013 | M |
|
|
36
|
+
| T015 | Implement Stripe Customer Portal endpoint for subscription management | T014 | S |
|
|
37
|
+
| T016 | Implement Stripe webhook handler (subscription.created/updated/deleted, invoice.payment_failed) | T009, T013 | L |
|
|
38
|
+
| T017 | Add plan enforcement middleware (check limits: members, documents, searches) | T016 | M |
|
|
39
|
+
|
|
40
|
+
## Phase 5: Team Management Endpoints
|
|
41
|
+
|
|
42
|
+
| ID | Task | Dependencies | Estimate |
|
|
43
|
+
|----|------|--------------|----------|
|
|
44
|
+
| T018 | Implement invite member endpoint (create tenant_member, trigger claim update) | T011 | M |
|
|
45
|
+
| T019 | Implement list members, update role, remove member endpoints | T011 | M |
|
|
46
|
+
| T020 | Add member count validation against plan limits | T017 | S |
|
|
47
|
+
|
|
48
|
+
## Phase 6: AI Search Endpoints
|
|
49
|
+
|
|
50
|
+
| ID | Task | Dependencies | Estimate |
|
|
51
|
+
|----|------|--------------|----------|
|
|
52
|
+
| T021 | Implement document upload endpoint with OpenAI embedding generation | T005, T011 | L |
|
|
53
|
+
| T022 | Implement semantic search endpoint with pgvector cosine similarity | T006, T011 | M |
|
|
54
|
+
| T023 | Implement search quota tracking and enforcement per plan | T007, T017 | M |
|
|
55
|
+
|
|
56
|
+
## Phase 7: Dashboard Endpoint
|
|
57
|
+
|
|
58
|
+
| ID | Task | Dependencies | Estimate |
|
|
59
|
+
|----|------|--------------|----------|
|
|
60
|
+
| T024 | Implement dashboard metrics endpoint (documents, members, storage, plan, searches) | T011 | M |
|
|
61
|
+
|
|
62
|
+
## Phase 8: Next.js Frontend Core
|
|
63
|
+
|
|
64
|
+
| ID | Task | Dependencies | Estimate |
|
|
65
|
+
|----|------|--------------|----------|
|
|
66
|
+
| T025 | Create Next.js 15 project with Tailwind CSS, @supabase/ssr | - | S |
|
|
67
|
+
| T026 | Implement Supabase client (browser) and server client with cookie handling | T025, T001 | M |
|
|
68
|
+
| T027 | Create login/signup pages with Supabase Auth | T026 | M |
|
|
69
|
+
| T028 | Create auth callback route and Next.js middleware for protected routes | T026 | M |
|
|
70
|
+
| T029 | Create onboarding page (create tenant for new users without tenant_id) | T026 | M |
|
|
71
|
+
|
|
72
|
+
## Phase 9: Next.js Dashboard Pages
|
|
73
|
+
|
|
74
|
+
| ID | Task | Dependencies | Estimate |
|
|
75
|
+
|----|------|--------------|----------|
|
|
76
|
+
| T030 | Create TenantProvider context component (reads tenant from session) | T028 | M |
|
|
77
|
+
| T031 | Create dashboard layout with sidebar navigation | T030 | M |
|
|
78
|
+
| T032 | Create dashboard overview page with metric cards | T024, T031 | M |
|
|
79
|
+
| T033 | Create documents page (list, upload, delete) | T021, T031 | M |
|
|
80
|
+
| T034 | Create search page with query input and ranked results | T022, T031 | M |
|
|
81
|
+
|
|
82
|
+
## Phase 10: Team and Billing Pages
|
|
83
|
+
|
|
84
|
+
| ID | Task | Dependencies | Estimate |
|
|
85
|
+
|----|------|--------------|----------|
|
|
86
|
+
| T035 | Create team management page (list members, invite, remove, change role) | T018, T031 | M |
|
|
87
|
+
| T036 | Create billing page (current plan, upgrade button, Stripe Portal link) | T014, T031 | M |
|
|
88
|
+
| T037 | Create settings page (tenant name, logo) | T031 | S |
|
|
89
|
+
|
|
90
|
+
## Phase 11: Docker and Deploy
|
|
91
|
+
|
|
92
|
+
| ID | Task | Dependencies | Estimate |
|
|
93
|
+
|----|------|--------------|----------|
|
|
94
|
+
| T038 | Create Dockerfile.api (multi-stage .NET build) | T024 | S |
|
|
95
|
+
| T039 | Create Dockerfile.web (Next.js standalone output) | T037 | S |
|
|
96
|
+
| T040 | Create docker-compose.yml for local development | T038, T039 | S |
|
|
97
|
+
| T041 | Configure EasyPanel services (API + Web) with env vars and health checks | T040 | M |
|
|
98
|
+
|
|
99
|
+
## Phase 12: Testing and Validation
|
|
100
|
+
|
|
101
|
+
| ID | Task | Dependencies | Estimate |
|
|
102
|
+
|----|------|--------------|----------|
|
|
103
|
+
| T042 | Write RLS isolation tests (verify no cross-tenant data leakage) | T005 | M |
|
|
104
|
+
| T043 | Write Stripe webhook handler tests (idempotency, signature validation) | T016 | M |
|
|
105
|
+
| T044 | Write search endpoint tests (embedding, similarity threshold, quota) | T022 | M |
|
|
106
|
+
|
|
107
|
+
## Checkpoints
|
|
108
|
+
|
|
109
|
+
| Checkpoint | After Tasks | Validation |
|
|
110
|
+
|------------|-------------|------------|
|
|
111
|
+
| CP1 | T004 | Supabase tenant setup complete, auth claims working |
|
|
112
|
+
| CP2 | T008 | Full data model with RLS, pgvector, and storage |
|
|
113
|
+
| CP3 | T012 | API skeleton with JWT auth and tenant middleware |
|
|
114
|
+
| CP4 | T017 | Stripe billing fully integrated with webhooks |
|
|
115
|
+
| CP5 | T020 | Team management working with plan limits |
|
|
116
|
+
| CP6 | T024 | All API endpoints complete (search, dashboard, team, billing) |
|
|
117
|
+
| CP7 | T029 | Auth flow complete (login, signup, onboarding, protected routes) |
|
|
118
|
+
| CP8 | T037 | All frontend pages complete |
|
|
119
|
+
| CP9 | T041 | Docker setup and EasyPanel deployment ready |
|
|
120
|
+
| CP10 | T044 | All tests passing, no cross-tenant leakage |
|
|
121
|
+
|
|
122
|
+
## Legend
|
|
123
|
+
|
|
124
|
+
- **S** = Small (< 1h)
|
|
125
|
+
- **M** = Medium (1-3h)
|
|
126
|
+
- **L** = Large (3-8h)
|
|
127
|
+
|
|
128
|
+
## Execution Order
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Supabase Setup (independent):
|
|
132
|
+
T001 -> T002 -> T003 -> T004 (CP1)
|
|
133
|
+
T005 -> T006 -> T007 -> T008 (CP2)
|
|
134
|
+
|
|
135
|
+
API Core (after T001):
|
|
136
|
+
T009 -> T010 -> T011 -> T012 (CP3)
|
|
137
|
+
|
|
138
|
+
Billing (after API core):
|
|
139
|
+
T013 -> T014 -> T015 -> T016 -> T017 (CP4)
|
|
140
|
+
|
|
141
|
+
Team + Search + Dashboard (after billing):
|
|
142
|
+
T018 -> T019 -> T020 (CP5)
|
|
143
|
+
T021 -> T022 -> T023
|
|
144
|
+
T024 (CP6)
|
|
145
|
+
|
|
146
|
+
Frontend (after T001):
|
|
147
|
+
T025 -> T026 -> T027 -> T028 -> T029 (CP7)
|
|
148
|
+
|
|
149
|
+
Frontend Pages (after API + auth):
|
|
150
|
+
T030 -> T031 -> T032 -> T033 -> T034
|
|
151
|
+
T035 -> T036 -> T037 (CP8)
|
|
152
|
+
|
|
153
|
+
Deploy:
|
|
154
|
+
T038 -> T039 -> T040 -> T041 (CP9)
|
|
155
|
+
|
|
156
|
+
Tests:
|
|
157
|
+
T042 -> T043 -> T044 (CP10)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Project Context - {PROJECT_NAME}
|
|
2
|
+
|
|
3
|
+
> Fill in project-specific information for MORPH agents.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
**Name:** {PROJECT_NAME}
|
|
8
|
+
**Description:** {Brief project description}
|
|
9
|
+
**Type:** Next.js + Supabase Application
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Technical Stack
|
|
14
|
+
|
|
15
|
+
| Layer | Technology | Version |
|
|
16
|
+
|-------|------------|---------|
|
|
17
|
+
| Frontend | Next.js (App Router) | 15.x |
|
|
18
|
+
| UI Library | shadcn/ui + Tailwind CSS | Latest |
|
|
19
|
+
| Backend | .NET Minimal API | 10.0 |
|
|
20
|
+
| Database | PostgreSQL (Supabase) | 15+ |
|
|
21
|
+
| Data Access | Npgsql + Dapper | Latest |
|
|
22
|
+
| Auth | Supabase Auth | Latest |
|
|
23
|
+
| Storage | Supabase Storage | Latest |
|
|
24
|
+
| Realtime | Supabase Realtime | Latest |
|
|
25
|
+
| Vector Search | pgvector (Supabase) | Latest |
|
|
26
|
+
| Hosting | EasyPanel on VPS | Latest |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
+-------------------------------------------------+
|
|
34
|
+
| Web (Next.js 15 App Router) |
|
|
35
|
+
+-------------------------------------------------+
|
|
36
|
+
| API (.NET 10 Minimal API) |
|
|
37
|
+
+-------------------------------------------------+
|
|
38
|
+
| Data Access (Npgsql + Dapper) |
|
|
39
|
+
+-------------------------------------------------+
|
|
40
|
+
| Supabase Cloud (DB, Auth, Storage) |
|
|
41
|
+
+-------------------------------------------------+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Project Structure
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
src/
|
|
48
|
+
api/
|
|
49
|
+
{Project}.Api/ # .NET 10 Minimal API
|
|
50
|
+
Endpoints/ # Minimal API endpoint groups
|
|
51
|
+
Services/ # Business logic
|
|
52
|
+
Repositories/ # Dapper queries
|
|
53
|
+
Models/ # Entities, DTOs (records)
|
|
54
|
+
web/
|
|
55
|
+
app/ # Next.js App Router pages
|
|
56
|
+
components/ # React components (shadcn/ui)
|
|
57
|
+
lib/ # Utilities, Supabase client
|
|
58
|
+
hooks/ # Custom React hooks
|
|
59
|
+
|
|
60
|
+
supabase/
|
|
61
|
+
migrations/ # SQL migrations
|
|
62
|
+
seeds/ # Seed data
|
|
63
|
+
policies/ # RLS policies
|
|
64
|
+
|
|
65
|
+
tests/
|
|
66
|
+
{Project}.Tests.Unit/ # .NET unit tests (xUnit)
|
|
67
|
+
{Project}.Tests.Integration/ # .NET integration tests
|
|
68
|
+
web/__tests__/ # Vitest + Testing Library
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Conventions
|
|
74
|
+
|
|
75
|
+
### Naming
|
|
76
|
+
|
|
77
|
+
- **C# Classes:** PascalCase (e.g., `ReportScheduleService`)
|
|
78
|
+
- **C# Interfaces:** I + PascalCase (e.g., `IReportScheduleService`)
|
|
79
|
+
- **C# Methods:** PascalCase, async with Async suffix (e.g., `GetByIdAsync`)
|
|
80
|
+
- **C# Variables:** camelCase (e.g., `reportSchedule`)
|
|
81
|
+
- **C# Private fields:** _camelCase (e.g., `_repository`)
|
|
82
|
+
- **TypeScript Functions/Variables:** camelCase (e.g., `getReportSchedule`)
|
|
83
|
+
- **TypeScript Components:** PascalCase (e.g., `ReportScheduleCard`)
|
|
84
|
+
- **TypeScript Types/Interfaces:** PascalCase (e.g., `ReportScheduleDto`)
|
|
85
|
+
- **SQL Tables:** snake_case (e.g., `report_schedules`)
|
|
86
|
+
- **SQL Columns:** snake_case (e.g., `created_at`)
|
|
87
|
+
|
|
88
|
+
### Code Style
|
|
89
|
+
|
|
90
|
+
- C#: Primary constructors (C# 14), records for DTOs, sealed classes by default
|
|
91
|
+
- TypeScript: Strict mode, prefer `const`, arrow functions for components
|
|
92
|
+
- SQL: Lowercase keywords, explicit column lists (never SELECT *)
|
|
93
|
+
|
|
94
|
+
### Documentation
|
|
95
|
+
|
|
96
|
+
- Code in English
|
|
97
|
+
- XML comments on public C# methods
|
|
98
|
+
- JSDoc on exported TypeScript functions
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Supabase Resources
|
|
103
|
+
|
|
104
|
+
| Resource | Purpose | Tier |
|
|
105
|
+
|----------|---------|------|
|
|
106
|
+
| PostgreSQL | Primary database | Pro / Free |
|
|
107
|
+
| Auth | Authentication (OAuth) | Included |
|
|
108
|
+
| Storage | File uploads | Included |
|
|
109
|
+
| Realtime | WebSocket subscriptions | Included |
|
|
110
|
+
| pgvector | Vector search (if needed) | Extension |
|
|
111
|
+
|
|
112
|
+
### Auth Configuration
|
|
113
|
+
|
|
114
|
+
- **Provider:** Supabase Auth
|
|
115
|
+
- **OAuth:** Google + GitHub
|
|
116
|
+
- **Session:** @supabase/ssr (server-side cookies)
|
|
117
|
+
- **JWT:** Validated in .NET API via Supabase JWT secret
|
|
118
|
+
|
|
119
|
+
### Cost Estimates
|
|
120
|
+
|
|
121
|
+
| Environment | Monthly Cost |
|
|
122
|
+
|-------------|-------------|
|
|
123
|
+
| Dev (Supabase Free + VPS) | ~$6 |
|
|
124
|
+
| Prod (Supabase Pro + VPS) | ~$31 |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## External Integrations
|
|
129
|
+
|
|
130
|
+
| Service | Purpose | Auth Method |
|
|
131
|
+
|---------|---------|-------------|
|
|
132
|
+
| Supabase | DB, Auth, Storage | Service Role Key |
|
|
133
|
+
| {Service} | {Purpose} | {Method} |
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Development Guidelines
|
|
138
|
+
|
|
139
|
+
### Git Flow
|
|
140
|
+
|
|
141
|
+
- **main** -- Production
|
|
142
|
+
- **develop** -- Development
|
|
143
|
+
- **feature/{name}** -- Features
|
|
144
|
+
|
|
145
|
+
### Commit Convention
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
{type}({scope}): {message}
|
|
149
|
+
|
|
150
|
+
Types: feat, fix, docs, style, refactor, test, chore
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### PR Requirements
|
|
154
|
+
|
|
155
|
+
- [ ] Tests passing
|
|
156
|
+
- [ ] Code review approved
|
|
157
|
+
- [ ] No conflicts
|
|
158
|
+
- [ ] Linked to work item
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Notes
|
|
163
|
+
|
|
164
|
+
{Add project-specific notes here}
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
*Generated by MORPH Framework*
|