forgedev 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CLAUDE.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +246 -0
  4. package/bin/devforge.js +4 -0
  5. package/package.json +33 -0
  6. package/src/claude-configurator.js +260 -0
  7. package/src/cli.js +119 -0
  8. package/src/composer.js +214 -0
  9. package/src/doctor-checks.js +743 -0
  10. package/src/doctor-prompts.js +295 -0
  11. package/src/doctor.js +281 -0
  12. package/src/guided.js +315 -0
  13. package/src/index.js +148 -0
  14. package/src/init-mode.js +134 -0
  15. package/src/prompts.js +155 -0
  16. package/src/recommender.js +186 -0
  17. package/src/scanner.js +368 -0
  18. package/src/uat-generator.js +189 -0
  19. package/src/utils.js +57 -0
  20. package/templates/auth/jwt-custom/backend/app/api/auth.py.template +45 -0
  21. package/templates/auth/jwt-custom/backend/app/api/deps.py.template +16 -0
  22. package/templates/auth/jwt-custom/backend/app/core/security.py.template +34 -0
  23. package/templates/auth/nextauth/src/app/api/auth/[...nextauth]/route.ts.template +3 -0
  24. package/templates/auth/nextauth/src/lib/auth.ts.template +30 -0
  25. package/templates/auth/nextauth/src/middleware.ts.template +14 -0
  26. package/templates/backend/fastapi/backend/Dockerfile.template +12 -0
  27. package/templates/backend/fastapi/backend/app/__init__.py +0 -0
  28. package/templates/backend/fastapi/backend/app/api/__init__.py +0 -0
  29. package/templates/backend/fastapi/backend/app/api/health.py.template +32 -0
  30. package/templates/backend/fastapi/backend/app/core/__init__.py +0 -0
  31. package/templates/backend/fastapi/backend/app/core/config.py.template +25 -0
  32. package/templates/backend/fastapi/backend/app/core/errors.py +37 -0
  33. package/templates/backend/fastapi/backend/app/core/retry.py +32 -0
  34. package/templates/backend/fastapi/backend/app/main.py.template +58 -0
  35. package/templates/backend/fastapi/backend/app/models/__init__.py +0 -0
  36. package/templates/backend/fastapi/backend/app/schemas/__init__.py +0 -0
  37. package/templates/backend/fastapi/backend/pyproject.toml.template +19 -0
  38. package/templates/backend/fastapi/backend/requirements.txt.template +14 -0
  39. package/templates/base/.gitignore.template +29 -0
  40. package/templates/base/README.md.template +25 -0
  41. package/templates/claude-code/agents/code-quality-reviewer.md +41 -0
  42. package/templates/claude-code/agents/production-readiness.md +55 -0
  43. package/templates/claude-code/agents/security-reviewer.md +41 -0
  44. package/templates/claude-code/agents/spec-validator.md +34 -0
  45. package/templates/claude-code/agents/uat-validator.md +37 -0
  46. package/templates/claude-code/claude-md/base.md +33 -0
  47. package/templates/claude-code/claude-md/fastapi.md +12 -0
  48. package/templates/claude-code/claude-md/fullstack.md +12 -0
  49. package/templates/claude-code/claude-md/nextjs.md +11 -0
  50. package/templates/claude-code/commands/audit-security.md +11 -0
  51. package/templates/claude-code/commands/audit-spec.md +9 -0
  52. package/templates/claude-code/commands/audit-wiring.md +17 -0
  53. package/templates/claude-code/commands/done.md +19 -0
  54. package/templates/claude-code/commands/generate-prd.md +45 -0
  55. package/templates/claude-code/commands/generate-uat.md +35 -0
  56. package/templates/claude-code/commands/help.md +26 -0
  57. package/templates/claude-code/commands/next.md +20 -0
  58. package/templates/claude-code/commands/optimize-claude-md.md +31 -0
  59. package/templates/claude-code/commands/pre-pr.md +19 -0
  60. package/templates/claude-code/commands/run-uat.md +21 -0
  61. package/templates/claude-code/commands/status.md +24 -0
  62. package/templates/claude-code/commands/verify-all.md +11 -0
  63. package/templates/claude-code/hooks/polyglot.json +36 -0
  64. package/templates/claude-code/hooks/python.json +36 -0
  65. package/templates/claude-code/hooks/scripts/autofix-polyglot.sh +16 -0
  66. package/templates/claude-code/hooks/scripts/autofix-python.sh +14 -0
  67. package/templates/claude-code/hooks/scripts/autofix-typescript.sh +14 -0
  68. package/templates/claude-code/hooks/scripts/guard-protected-files.sh +21 -0
  69. package/templates/claude-code/hooks/typescript.json +36 -0
  70. package/templates/claude-code/skills/ai-prompts/SKILL.md +43 -0
  71. package/templates/claude-code/skills/fastapi/SKILL.md +38 -0
  72. package/templates/claude-code/skills/nextjs/SKILL.md +39 -0
  73. package/templates/claude-code/skills/playwright/SKILL.md +37 -0
  74. package/templates/claude-code/skills/security-api/SKILL.md +47 -0
  75. package/templates/claude-code/skills/security-web/SKILL.md +41 -0
  76. package/templates/database/prisma-postgres/.env.example +1 -0
  77. package/templates/database/prisma-postgres/prisma/schema.prisma.template +18 -0
  78. package/templates/database/sqlalchemy-postgres/.env.example +1 -0
  79. package/templates/database/sqlalchemy-postgres/backend/alembic/env.py.template +40 -0
  80. package/templates/database/sqlalchemy-postgres/backend/alembic/versions/.gitkeep +0 -0
  81. package/templates/database/sqlalchemy-postgres/backend/alembic.ini.template +36 -0
  82. package/templates/database/sqlalchemy-postgres/backend/app/db/__init__.py +0 -0
  83. package/templates/database/sqlalchemy-postgres/backend/app/db/base.py +5 -0
  84. package/templates/database/sqlalchemy-postgres/backend/app/db/session.py.template +48 -0
  85. package/templates/frontend/nextjs/next.config.ts.template +7 -0
  86. package/templates/frontend/nextjs/package.json.template +41 -0
  87. package/templates/frontend/nextjs/postcss.config.mjs +7 -0
  88. package/templates/frontend/nextjs/src/app/api/health/route.ts.template +10 -0
  89. package/templates/frontend/nextjs/src/app/globals.css +1 -0
  90. package/templates/frontend/nextjs/src/app/layout.tsx.template +22 -0
  91. package/templates/frontend/nextjs/src/app/page.tsx.template +10 -0
  92. package/templates/frontend/nextjs/src/lib/db.ts.template +40 -0
  93. package/templates/frontend/nextjs/src/lib/errors.ts +28 -0
  94. package/templates/frontend/nextjs/src/lib/utils.ts +6 -0
  95. package/templates/frontend/nextjs/tsconfig.json +23 -0
  96. package/templates/infra/docker-compose/docker-compose.yml.template +19 -0
  97. package/templates/testing/playwright/e2e/example.spec.ts.template +15 -0
  98. package/templates/testing/playwright/playwright.config.ts.template +22 -0
  99. package/templates/testing/vitest/src/__tests__/example.test.ts.template +12 -0
@@ -0,0 +1,34 @@
1
+ from datetime import datetime, timedelta, timezone
2
+
3
+ from jose import JWTError, jwt
4
+ from passlib.context import CryptContext
5
+
6
+ from app.core.config import settings
7
+
8
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
9
+
10
+ SECRET_KEY = "change-me-in-production" # TODO: Move to settings/env
11
+ ALGORITHM = "HS256"
12
+ ACCESS_TOKEN_EXPIRE_MINUTES = 30
13
+
14
+
15
+ def verify_password(plain_password: str, hashed_password: str) -> bool:
16
+ return pwd_context.verify(plain_password, hashed_password)
17
+
18
+
19
+ def hash_password(password: str) -> str:
20
+ return pwd_context.hash(password)
21
+
22
+
23
+ def create_access_token(data: dict, expires_delta: timedelta | None = None) -> str:
24
+ to_encode = data.copy()
25
+ expire = datetime.now(timezone.utc) + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
26
+ to_encode.update({"exp": expire})
27
+ return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
28
+
29
+
30
+ def decode_access_token(token: str) -> dict | None:
31
+ try:
32
+ return jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
33
+ except JWTError:
34
+ return None
@@ -0,0 +1,3 @@
1
+ import { handlers } from '@/lib/auth';
2
+
3
+ export const { GET, POST } = handlers;
@@ -0,0 +1,30 @@
1
+ import NextAuth from 'next-auth';
2
+ import CredentialsProvider from 'next-auth/providers/credentials';
3
+
4
+ export const { handlers, signIn, signOut, auth } = NextAuth({
5
+ providers: [
6
+ CredentialsProvider({
7
+ name: 'Credentials',
8
+ credentials: {
9
+ email: { label: 'Email', type: 'email' },
10
+ password: { label: 'Password', type: 'password' },
11
+ },
12
+ async authorize(credentials) {
13
+ // TODO: Implement actual authentication logic
14
+ // Replace with database lookup and password verification
15
+ if (!credentials?.email || !credentials?.password) {
16
+ return null;
17
+ }
18
+ return {
19
+ id: '1',
20
+ email: credentials.email as string,
21
+ name: 'User',
22
+ };
23
+ },
24
+ }),
25
+ ],
26
+ session: { strategy: 'jwt' },
27
+ pages: {
28
+ signIn: '/login',
29
+ },
30
+ });
@@ -0,0 +1,14 @@
1
+ import { auth } from '@/lib/auth';
2
+
3
+ export default auth((req) => {
4
+ const isLoggedIn = !!req.auth;
5
+ const isOnProtectedRoute = req.nextUrl.pathname.startsWith('/dashboard');
6
+
7
+ if (isOnProtectedRoute && !isLoggedIn) {
8
+ return Response.redirect(new URL('/login', req.nextUrl));
9
+ }
10
+ });
11
+
12
+ export const config = {
13
+ matcher: ['/dashboard/:path*'],
14
+ };
@@ -0,0 +1,12 @@
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ EXPOSE 8000
11
+
12
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,32 @@
1
+ from fastapi import APIRouter
2
+ from sqlalchemy import text
3
+
4
+ from app.db.session import async_session
5
+
6
+ router = APIRouter()
7
+
8
+
9
+ @router.get("/health")
10
+ async def health_check():
11
+ return {
12
+ "status": "ok",
13
+ "service": "{{PROJECT_NAME}}",
14
+ }
15
+
16
+
17
+ @router.get("/healthz")
18
+ async def health_check_deep():
19
+ """Deep health check — verifies database connectivity."""
20
+ try:
21
+ async with async_session() as session:
22
+ await session.execute(text("SELECT 1"))
23
+ db_status = "connected"
24
+ except Exception:
25
+ db_status = "disconnected"
26
+
27
+ status = "ok" if db_status == "connected" else "degraded"
28
+ return {
29
+ "status": status,
30
+ "service": "{{PROJECT_NAME}}",
31
+ "checks": {"database": db_status},
32
+ }
@@ -0,0 +1,25 @@
1
+ from pydantic_settings import BaseSettings
2
+
3
+
4
+ class Settings(BaseSettings):
5
+ # Application
6
+ app_name: str = "{{PROJECT_NAME_PASCAL}}"
7
+ debug: bool = False
8
+
9
+ # Database
10
+ database_url: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}"
11
+
12
+ # CORS
13
+ cors_origins: list[str] = ["http://localhost:3000"]
14
+
15
+ # External service timeouts (seconds)
16
+ external_service_timeout: float = 30.0
17
+ ai_service_timeout: float = 60.0
18
+
19
+ # Rate limiting
20
+ rate_limit_per_minute: int = 60
21
+
22
+ model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
23
+
24
+
25
+ settings = Settings()
@@ -0,0 +1,37 @@
1
+ class AppError(Exception):
2
+ """Structured application error — never leaks stack traces to clients."""
3
+
4
+ def __init__(
5
+ self,
6
+ message: str,
7
+ status_code: int = 500,
8
+ code: str = "INTERNAL_ERROR",
9
+ ):
10
+ self.message = message
11
+ self.status_code = status_code
12
+ self.code = code
13
+ super().__init__(message)
14
+
15
+
16
+ class NotFoundError(AppError):
17
+ def __init__(self, resource: str, resource_id: str):
18
+ super().__init__(
19
+ message=f"{resource} not found: {resource_id}",
20
+ status_code=404,
21
+ code="NOT_FOUND",
22
+ )
23
+
24
+
25
+ class ValidationError(AppError):
26
+ def __init__(self, message: str):
27
+ super().__init__(message=message, status_code=422, code="VALIDATION_ERROR")
28
+
29
+
30
+ class AuthenticationError(AppError):
31
+ def __init__(self, message: str = "Authentication required"):
32
+ super().__init__(message=message, status_code=401, code="AUTHENTICATION_ERROR")
33
+
34
+
35
+ class AuthorizationError(AppError):
36
+ def __init__(self, message: str = "Insufficient permissions"):
37
+ super().__init__(message=message, status_code=403, code="AUTHORIZATION_ERROR")
@@ -0,0 +1,32 @@
1
+ import asyncio
2
+ import functools
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ def with_retry(max_retries: int = 3, base_delay: float = 1.0, max_delay: float = 30.0):
9
+ """Decorator for retrying async functions with exponential backoff."""
10
+
11
+ def decorator(func):
12
+ @functools.wraps(func)
13
+ async def wrapper(*args, **kwargs):
14
+ last_exception = None
15
+ for attempt in range(1, max_retries + 1):
16
+ try:
17
+ return await func(*args, **kwargs)
18
+ except Exception as e:
19
+ last_exception = e
20
+ if attempt == max_retries:
21
+ break
22
+ delay = min(base_delay * (2 ** (attempt - 1)), max_delay)
23
+ logger.warning(
24
+ f"{func.__name__} attempt {attempt}/{max_retries} failed: {e}. "
25
+ f"Retrying in {delay:.1f}s..."
26
+ )
27
+ await asyncio.sleep(delay)
28
+ raise last_exception
29
+
30
+ return wrapper
31
+
32
+ return decorator
@@ -0,0 +1,58 @@
1
+ from contextlib import asynccontextmanager
2
+ from fastapi import FastAPI, Request
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi.responses import JSONResponse
5
+
6
+ from app.api.health import router as health_router
7
+ from app.core.config import settings
8
+ from app.core.errors import AppError
9
+
10
+
11
+ @asynccontextmanager
12
+ async def lifespan(app: FastAPI):
13
+ # Startup: connect to database with retry
14
+ from app.db.session import engine, connect_with_retry
15
+
16
+ await connect_with_retry(engine)
17
+ yield
18
+ # Shutdown: close database connections gracefully
19
+ await engine.dispose()
20
+
21
+
22
+ app = FastAPI(
23
+ title="{{PROJECT_NAME_PASCAL}}",
24
+ version="0.1.0",
25
+ lifespan=lifespan,
26
+ )
27
+
28
+ # CORS
29
+ app.add_middleware(
30
+ CORSMiddleware,
31
+ allow_origins=settings.cors_origins,
32
+ allow_credentials=True,
33
+ allow_methods=["*"],
34
+ allow_headers=["*"],
35
+ )
36
+
37
+ # Routes
38
+ app.include_router(health_router, tags=["health"])
39
+
40
+
41
+ # Global exception handler — never leak stack traces
42
+ @app.exception_handler(AppError)
43
+ async def app_error_handler(request: Request, exc: AppError):
44
+ return JSONResponse(
45
+ status_code=exc.status_code,
46
+ content={"error": {"code": exc.code, "message": exc.message}},
47
+ )
48
+
49
+
50
+ @app.exception_handler(Exception)
51
+ async def global_exception_handler(request: Request, exc: Exception):
52
+ import logging
53
+
54
+ logging.exception("Unhandled exception")
55
+ return JSONResponse(
56
+ status_code=500,
57
+ content={"error": {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"}},
58
+ )
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "{{PROJECT_NAME}}"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.11"
5
+
6
+ [tool.ruff]
7
+ target-version = "py311"
8
+ line-length = 100
9
+
10
+ [tool.ruff.lint]
11
+ select = ["E", "F", "I", "N", "W", "UP", "B", "SIM"]
12
+
13
+ [tool.pytest.ini_options]
14
+ asyncio_mode = "auto"
15
+ testpaths = ["tests"]
16
+
17
+ [tool.pyright]
18
+ pythonVersion = "3.11"
19
+ typeCheckingMode = "basic"
@@ -0,0 +1,14 @@
1
+ fastapi>=0.115.0
2
+ uvicorn[standard]>=0.34.0
3
+ sqlalchemy[asyncio]>=2.0.38
4
+ asyncpg>=0.30.0
5
+ pydantic>=2.11.0
6
+ pydantic-settings>=2.8.0
7
+ alembic>=1.15.0
8
+ python-jose[cryptography]>=3.4.0
9
+ passlib[bcrypt]>=1.7.4
10
+ httpx>=0.28.0
11
+ pytest>=8.3.0
12
+ pytest-asyncio>=0.25.0
13
+ ruff>=0.11.0
14
+ pyright>=1.1.400
@@ -0,0 +1,29 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Environment
5
+ .env
6
+ .env.local
7
+ .env.*.local
8
+
9
+ # Build output
10
+ dist/
11
+ .next/
12
+ out/
13
+ build/
14
+
15
+ # IDE
16
+ .vscode/
17
+ .idea/
18
+ *.swp
19
+ *.swo
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # Testing
26
+ coverage/
27
+ test-results/
28
+ playwright-report/
29
+ {{EXTRA_IGNORES}}
@@ -0,0 +1,25 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ {{STACK_DESCRIPTION}}
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ {{SETUP_COMMANDS}}
9
+ ```
10
+
11
+ ## Available Scripts
12
+
13
+ {{AVAILABLE_SCRIPTS}}
14
+
15
+ ## Project Structure
16
+
17
+ See `CLAUDE.md` for the complete project map and development conventions.
18
+
19
+ ## Testing
20
+
21
+ See `docs/uat/` for acceptance testing templates and checklists.
22
+
23
+ ## License
24
+
25
+ MIT
@@ -0,0 +1,41 @@
1
+ ---
2
+ disallowedTools:
3
+ - Write
4
+ - Edit
5
+ - MultiEdit
6
+ ---
7
+
8
+ # Code Quality Reviewer
9
+
10
+ You are a code quality reviewer for {{PROJECT_NAME_PASCAL}}.
11
+ Stack: {{STACK_SUMMARY}}
12
+
13
+ ## Review all changed files for:
14
+
15
+ ### Code Quality
16
+ - [ ] Functions have single responsibility
17
+ - [ ] No unused imports or variables
18
+ - [ ] No hardcoded values that should be config/env
19
+ - [ ] Error cases handled with descriptive messages
20
+ - [ ] No console.log / print statements left in production code
21
+
22
+ ### Patterns & Conventions
23
+ - [ ] Follows project conventions from CLAUDE.md
24
+ - [ ] Uses existing utilities instead of reimplementing
25
+ - [ ] Consistent naming conventions
26
+ - [ ] Proper type annotations (TypeScript/Python type hints)
27
+
28
+ ### Performance
29
+ - [ ] No N+1 queries
30
+ - [ ] No unnecessary re-renders (React) or redundant DB calls
31
+ - [ ] Proper use of async/await
32
+ - [ ] No blocking operations in request handlers
33
+
34
+ ### Maintainability
35
+ - [ ] Code is self-documenting (clear names, simple logic)
36
+ - [ ] Complex logic has explanatory comments
37
+ - [ ] No dead code or commented-out blocks
38
+ - [ ] Functions are reasonably sized (< 50 lines)
39
+
40
+ ## Output
41
+ For each issue: **File** | **Line** | **Severity** (critical/warning/info) | **Issue** | **Fix**
@@ -0,0 +1,55 @@
1
+ ---
2
+ disallowedTools:
3
+ - Write
4
+ - Edit
5
+ - MultiEdit
6
+ ---
7
+
8
+ # Production Readiness Reviewer
9
+
10
+ You verify that {{PROJECT_NAME_PASCAL}} is ready for production deployment.
11
+ Stack: {{STACK_SUMMARY}}
12
+ Read-only. Never modify code.
13
+
14
+ ## Checklist
15
+
16
+ ### Health & Observability
17
+ - [ ] Health check endpoint exists and returns structured response
18
+ - [ ] Deep health check verifies database connectivity
19
+ - [ ] Structured logging configured (not console.log/print)
20
+ - [ ] Error tracking integration ready
21
+
22
+ ### Resilience
23
+ - [ ] Graceful shutdown handler registered
24
+ - [ ] Database connection retry with exponential backoff
25
+ - [ ] External service timeouts configured
26
+ - [ ] Rate limiting on public endpoints
27
+ - [ ] Circuit breaker for external dependencies (if applicable)
28
+
29
+ ### Security
30
+ - [ ] No hardcoded secrets in codebase
31
+ - [ ] `.env.example` documents all required environment variables
32
+ - [ ] CORS configured for production origins
33
+ - [ ] Security headers set
34
+ - [ ] Authentication on all protected routes
35
+
36
+ ### Data
37
+ - [ ] Database migrations are up to date
38
+ - [ ] No raw SQL (use ORM)
39
+ - [ ] Sensitive data encrypted at rest
40
+ - [ ] Backup strategy documented
41
+
42
+ ### Deployment
43
+ - [ ] Dockerfile exists and builds successfully
44
+ - [ ] CI/CD pipeline configured
45
+ - [ ] Environment-specific configuration (dev/staging/prod)
46
+ - [ ] Build produces no warnings
47
+
48
+ ### Testing
49
+ - [ ] Unit tests pass
50
+ - [ ] E2E tests pass
51
+ - [ ] Test coverage adequate for critical paths
52
+ - [ ] UAT scenarios documented
53
+
54
+ ## Output
55
+ For each item: **Category** | **Check** | **Status** (PASS/FAIL/N/A) | **Details**
@@ -0,0 +1,41 @@
1
+ ---
2
+ disallowedTools:
3
+ - Write
4
+ - Edit
5
+ - MultiEdit
6
+ ---
7
+
8
+ # Security Reviewer
9
+
10
+ You are a security reviewer for {{PROJECT_NAME_PASCAL}}.
11
+ Stack: {{STACK_SUMMARY}}
12
+ Read-only. Never modify code.
13
+
14
+ ## Review all changed files for:
15
+
16
+ ### Authentication & Authorization
17
+ - [ ] Protected routes check authentication
18
+ - [ ] Authorization checks before sensitive operations
19
+ - [ ] No hardcoded credentials or tokens
20
+ - [ ] Session/token expiration configured
21
+
22
+ ### Input Validation
23
+ - [ ] All user input validated before use
24
+ - [ ] SQL injection prevention (parameterized queries/ORM)
25
+ - [ ] XSS prevention (proper escaping/sanitization)
26
+ - [ ] File upload validation (type, size, extension)
27
+
28
+ ### Data Exposure
29
+ - [ ] No sensitive data in logs
30
+ - [ ] No secrets in error responses
31
+ - [ ] No stack traces exposed to clients
32
+ - [ ] API responses don't leak internal fields
33
+
34
+ ### Configuration
35
+ - [ ] Secrets in environment variables, not code
36
+ - [ ] CORS properly configured (not wildcard in production)
37
+ - [ ] Security headers set
38
+ - [ ] HTTPS enforced
39
+
40
+ ## Output
41
+ For each finding: **File** | **Line** | **Severity** (critical/high/medium/low) | **Vulnerability** | **Remediation**
@@ -0,0 +1,34 @@
1
+ ---
2
+ disallowedTools:
3
+ - Write
4
+ - Edit
5
+ - MultiEdit
6
+ ---
7
+
8
+ # Spec Validator
9
+
10
+ You validate that the implementation matches the specification.
11
+ Read-only. Never modify code.
12
+
13
+ ## Process
14
+ 1. Read the spec file provided as argument
15
+ 2. For each requirement in the spec:
16
+ a. Search the codebase for the implementation
17
+ b. Verify the implementation matches the requirement
18
+ c. Check for edge cases mentioned in the spec
19
+
20
+ ## Output: Traceability Matrix
21
+
22
+ | Spec Requirement | Status | Implementation File | Notes |
23
+ |---|---|---|---|
24
+ | [requirement] | IMPLEMENTED / MISSING / PARTIAL | [file:line] | [details] |
25
+
26
+ ## Summary
27
+ - Total requirements: X
28
+ - Implemented: X
29
+ - Partial: X
30
+ - Missing: X
31
+ - Coverage: X%
32
+
33
+ ## Gaps
34
+ List any requirements that are MISSING or PARTIAL with details on what's missing.
@@ -0,0 +1,37 @@
1
+ ---
2
+ disallowedTools:
3
+ - Write
4
+ - Edit
5
+ - MultiEdit
6
+ ---
7
+
8
+ # UAT Validator
9
+
10
+ You are a QA engineer validating UAT scenarios for {{PROJECT_NAME_PASCAL}}.
11
+ Read-only. Never modify code.
12
+
13
+ ## Process
14
+ 1. Read `docs/uat/UAT_TEMPLATE.md`
15
+ 2. For each UAT scenario:
16
+ a. Verify the feature exists in the codebase
17
+ b. Check if there's a corresponding automated test
18
+ c. If automated test exists, verify it covers the scenario's steps
19
+ d. Flag gaps: scenarios without tests, tests without scenarios
20
+
21
+ ## Output: Traceability Matrix
22
+
23
+ | UAT ID | Feature | Has Automated Test? | Test File | Coverage |
24
+ |---|---|---|---|---|
25
+ | UAT-001 | [feature] | YES/NO | [file:line] | FULL/PARTIAL/NONE |
26
+
27
+ ## Summary
28
+ - Total scenarios: X
29
+ - Automated: X
30
+ - Manual only: X
31
+ - Coverage: X%
32
+
33
+ ## Gaps
34
+ List scenarios that need automated tests, prioritized by UAT priority (P0 first).
35
+
36
+ ## Recommendations
37
+ Suggest specific test implementations for uncovered P0 scenarios.
@@ -0,0 +1,33 @@
1
+ # {{PROJECT_NAME_PASCAL}}
2
+
3
+ ## WHAT
4
+ - {{STACK_SUMMARY}}
5
+ {{DIR_MAP}}
6
+
7
+ ## HOW
8
+ - Lint: `{{LINT_COMMAND}}`
9
+ - Type check: `{{TYPE_CHECK_COMMAND}}`
10
+ - Test: `{{TEST_COMMAND}}`
11
+ - Build: `{{BUILD_COMMAND}}`
12
+ - Dev: `{{DEV_COMMAND}}`
13
+
14
+ ## RULES
15
+ - Never commit `.env` files or secrets
16
+ - Never modify migration files directly — generate new migrations instead
17
+ - All API responses use structured error format: `{ error: { code, message } }`
18
+ - Never leak stack traces to clients
19
+ - Health check endpoints must always be available
20
+ - Write tests for new features before marking them complete
21
+
22
+ {{STACK_SPECIFIC_RULES}}
23
+
24
+ ## Skills
25
+ Framework-specific knowledge is in `.claude/skills/` — reference these for deep patterns:
26
+ {{SKILLS_LIST}}
27
+
28
+ ## Completion Protocol
29
+ Before marking any task complete:
30
+ 1. Run lint: `{{LINT_COMMAND}}`
31
+ 2. Run type check: `{{TYPE_CHECK_COMMAND}}`
32
+ 3. Run tests: `{{TEST_COMMAND}}`
33
+ 4. Verify no `.env` files or secrets in changes
@@ -0,0 +1,12 @@
1
+ ## FastAPI Conventions
2
+ - Pydantic v2 for all request/response schemas (use model_config, not class Config)
3
+ - SQLAlchemy 2.0 async style — use `select()` not `query()`, `async with session` not `session.query`
4
+ - Dependency injection via `Depends()` for DB sessions, auth, etc.
5
+ - All endpoints return Pydantic models — never return raw dicts
6
+ - Use `@asynccontextmanager` lifespan for startup/shutdown
7
+ - Database session via `get_db()` dependency (backend/app/db/session.py)
8
+ - Error responses use `AppError` classes (backend/app/core/errors.py)
9
+ - Use `with_retry` decorator for external service calls
10
+ - Alembic for migrations: `alembic revision --autogenerate -m "description"`
11
+ - Environment config via Pydantic Settings (backend/app/core/config.py)
12
+ - Ruff for linting, pyright for type checking
@@ -0,0 +1,12 @@
1
+ ## Polyglot Full-Stack Conventions
2
+ - `frontend/` contains the Next.js application — follow Next.js conventions above
3
+ - `backend/` contains the FastAPI application — follow FastAPI conventions above
4
+ - Frontend and backend communicate via REST API only
5
+ - API base URL configured in frontend via `NEXT_PUBLIC_API_URL` environment variable
6
+ - Shared types: define API contracts in backend Pydantic schemas, mirror in frontend TypeScript types
7
+ - Never import between frontend and backend directories
8
+ - Docker Compose orchestrates both services + PostgreSQL
9
+ - Frontend runs on port 3000, backend on port 8000
10
+ - Database owned by backend — frontend never accesses DB directly
11
+ - Authentication: NextAuth on frontend, JWT validation on backend
12
+ - E2E tests in root `e2e/` directory test the full stack together
@@ -0,0 +1,11 @@
1
+ ## Next.js Conventions
2
+ - Use App Router (src/app/) — no pages/ directory
3
+ - Server Components by default; add 'use client' only when needed (event handlers, hooks, browser APIs)
4
+ - Use server actions for mutations, not API routes
5
+ - Colocate loading.tsx, error.tsx, not-found.tsx with page.tsx
6
+ - Use `@/` path alias for imports from src/
7
+ - Tailwind CSS for styling — use `cn()` from `@/lib/utils` for conditional classes
8
+ - Prisma client accessed via `@/lib/db` singleton (includes retry + graceful shutdown)
9
+ - Form validation with Zod schemas shared between client and server
10
+ - Images via `next/image`, links via `next/link`
11
+ - Environment variables: NEXT_PUBLIC_ prefix for client-side, plain for server-side