@ryuenn3123/agentic-senior-core 2.5.22 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-context/prompts/init-project.md +5 -5
- package/.agent-context/prompts/refactor.md +2 -1
- package/.agent-context/prompts/review-code.md +3 -2
- package/.agent-context/review-checklists/pr-checklist.md +8 -1
- package/.agent-context/rules/architecture.md +11 -0
- package/.agent-context/rules/frontend-architecture.md +2 -2
- package/.agent-context/state/architecture-map.md +1 -1
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.agents/workflows/init-project.md +3 -3
- package/.agents/workflows/refactor.md +1 -1
- package/.agents/workflows/review-code.md +4 -5
- package/.cursorrules +27 -71
- package/.gemini/instructions.md +6 -7
- package/.github/copilot-instructions.md +5 -6
- package/.windsurfrules +27 -71
- package/AGENTS.md +7 -9
- package/CONTRIBUTING.md +18 -31
- package/README.md +21 -4
- package/bin/agentic-senior-core.js +0 -6
- package/lib/cli/commands/init.mjs +113 -650
- package/lib/cli/commands/launch.mjs +1 -23
- package/lib/cli/commands/rollback.mjs +1 -1
- package/lib/cli/commands/upgrade.mjs +1 -23
- package/lib/cli/compiler.mjs +77 -72
- package/lib/cli/constants.mjs +84 -26
- package/lib/cli/init-architecture-flow.mjs +231 -0
- package/lib/cli/init-detection-flow.mjs +123 -0
- package/lib/cli/init-options.mjs +344 -0
- package/lib/cli/init-selection.mjs +100 -0
- package/lib/cli/preflight.mjs +1 -1
- package/lib/cli/profile-packs.mjs +15 -1
- package/lib/cli/project-scaffolder.mjs +18 -154
- package/lib/cli/utils.mjs +16 -12
- package/mcp.json +19 -19
- package/package.json +5 -2
- package/scripts/context-triggered-audit.mjs +18 -18
- package/scripts/documentation-boundary-audit.mjs +92 -5
- package/scripts/forbidden-content-check.mjs +1 -1
- package/scripts/frontend-usability-audit.mjs +21 -28
- package/scripts/governance-weekly-report.mjs +29 -15
- package/scripts/llm-judge.mjs +2 -5
- package/scripts/mcp-server.mjs +389 -5
- package/scripts/release-gate.mjs +121 -145
- package/scripts/sync-thin-adapters.mjs +161 -0
- package/scripts/v3-purge-audit.mjs +231 -0
- package/scripts/validate-evidence-bundle.mjs +1 -1
- package/scripts/validate.mjs +224 -272
- package/.agent-context/blueprints/api-nextjs.md +0 -184
- package/.agent-context/blueprints/aspnet-api.md +0 -247
- package/.agent-context/blueprints/ci-github-actions.md +0 -226
- package/.agent-context/blueprints/ci-gitlab.md +0 -200
- package/.agent-context/blueprints/fastapi-service.md +0 -210
- package/.agent-context/blueprints/go-service.md +0 -217
- package/.agent-context/blueprints/graphql-grpc-api.md +0 -51
- package/.agent-context/blueprints/infrastructure-as-code.md +0 -62
- package/.agent-context/blueprints/kubernetes-manifests.md +0 -76
- package/.agent-context/blueprints/laravel-api.md +0 -233
- package/.agent-context/blueprints/mobile-app.md +0 -91
- package/.agent-context/blueprints/nestjs-logic.md +0 -247
- package/.agent-context/blueprints/observability.md +0 -227
- package/.agent-context/blueprints/spring-boot-api.md +0 -218
- package/.agent-context/profiles/platform.md +0 -13
- package/.agent-context/profiles/regulated.md +0 -13
- package/.agent-context/profiles/startup.md +0 -13
- package/.agent-context/review-checklists/frontend-excellence-rubric.md +0 -73
- package/.agent-context/review-checklists/frontend-skill-parity.md +0 -29
- package/.agent-context/review-checklists/frontend-usability.md +0 -35
- package/.agent-context/review-checklists/marketplace-acceptance.md +0 -60
- package/.agent-context/review-checklists/performance-audit.md +0 -71
- package/.agent-context/review-checklists/release-operations.md +0 -33
- package/.agent-context/review-checklists/security-audit.md +0 -119
- package/.agent-context/skills/README.md +0 -63
- package/.agent-context/skills/backend/README.md +0 -68
- package/.agent-context/skills/backend/architecture.md +0 -361
- package/.agent-context/skills/backend/compatibility-manifest.json +0 -8
- package/.agent-context/skills/backend/data-access.md +0 -231
- package/.agent-context/skills/backend/errors.md +0 -138
- package/.agent-context/skills/backend/validation.md +0 -117
- package/.agent-context/skills/backend.md +0 -29
- package/.agent-context/skills/cli/.evidence/compatibility-manifest.json +0 -5
- package/.agent-context/skills/cli/.evidence/sbom-excerpt.json +0 -10
- package/.agent-context/skills/cli/.evidence/test-report.json +0 -8
- package/.agent-context/skills/cli/CHANGELOG.md +0 -6
- package/.agent-context/skills/cli/README.md +0 -56
- package/.agent-context/skills/cli/compatibility-manifest.json +0 -8
- package/.agent-context/skills/cli/init.md +0 -38
- package/.agent-context/skills/cli/output.md +0 -36
- package/.agent-context/skills/cli/package.json +0 -5
- package/.agent-context/skills/cli/safety-telemetry.md +0 -39
- package/.agent-context/skills/cli/tests/.gitkeep +0 -1
- package/.agent-context/skills/cli/upgrade.md +0 -38
- package/.agent-context/skills/cli.md +0 -32
- package/.agent-context/skills/distribution/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/distribution/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/distribution/.evidence/test-report.json +0 -8
- package/.agent-context/skills/distribution/CHANGELOG.md +0 -7
- package/.agent-context/skills/distribution/README.md +0 -27
- package/.agent-context/skills/distribution/compatibility-manifest.json +0 -8
- package/.agent-context/skills/distribution/compatibility.md +0 -32
- package/.agent-context/skills/distribution/package.json +0 -5
- package/.agent-context/skills/distribution/provenance-attestation.md +0 -47
- package/.agent-context/skills/distribution/publish.md +0 -37
- package/.agent-context/skills/distribution/rollback.md +0 -32
- package/.agent-context/skills/distribution/tests/.gitkeep +0 -1
- package/.agent-context/skills/distribution.md +0 -32
- package/.agent-context/skills/frontend/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/frontend/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/frontend/.evidence/test-report.json +0 -8
- package/.agent-context/skills/frontend/CHANGELOG.md +0 -7
- package/.agent-context/skills/frontend/README.md +0 -50
- package/.agent-context/skills/frontend/accessibility.md +0 -107
- package/.agent-context/skills/frontend/compatibility-manifest.json +0 -8
- package/.agent-context/skills/frontend/conversion-clarity.md +0 -51
- package/.agent-context/skills/frontend/motion.md +0 -67
- package/.agent-context/skills/frontend/package.json +0 -5
- package/.agent-context/skills/frontend/performance.md +0 -63
- package/.agent-context/skills/frontend/responsive-delivery.md +0 -41
- package/.agent-context/skills/frontend/tests/.gitkeep +0 -1
- package/.agent-context/skills/frontend/ui-architecture.md +0 -128
- package/.agent-context/skills/frontend.md +0 -40
- package/.agent-context/skills/fullstack/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/fullstack/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/fullstack/.evidence/test-report.json +0 -8
- package/.agent-context/skills/fullstack/CHANGELOG.md +0 -7
- package/.agent-context/skills/fullstack/README.md +0 -27
- package/.agent-context/skills/fullstack/compatibility-manifest.json +0 -8
- package/.agent-context/skills/fullstack/contracts.md +0 -53
- package/.agent-context/skills/fullstack/end-to-end.md +0 -42
- package/.agent-context/skills/fullstack/feature-slicing.md +0 -65
- package/.agent-context/skills/fullstack/package.json +0 -5
- package/.agent-context/skills/fullstack/release-coordination.md +0 -51
- package/.agent-context/skills/fullstack/tests/.gitkeep +0 -1
- package/.agent-context/skills/fullstack.md +0 -30
- package/.agent-context/skills/index.json +0 -107
- package/.agent-context/skills/review-quality/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/review-quality/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/review-quality/.evidence/test-report.json +0 -8
- package/.agent-context/skills/review-quality/CHANGELOG.md +0 -7
- package/.agent-context/skills/review-quality/README.md +0 -27
- package/.agent-context/skills/review-quality/benchmark.md +0 -30
- package/.agent-context/skills/review-quality/compatibility-manifest.json +0 -8
- package/.agent-context/skills/review-quality/package.json +0 -5
- package/.agent-context/skills/review-quality/planning.md +0 -38
- package/.agent-context/skills/review-quality/release-decision.md +0 -49
- package/.agent-context/skills/review-quality/security.md +0 -34
- package/.agent-context/skills/review-quality/tests/.gitkeep +0 -1
- package/.agent-context/skills/review-quality.md +0 -34
- package/.agent-context/stacks/csharp.md +0 -149
- package/.agent-context/stacks/flutter.md +0 -16
- package/.agent-context/stacks/go.md +0 -181
- package/.agent-context/stacks/java.md +0 -135
- package/.agent-context/stacks/php.md +0 -192
- package/.agent-context/stacks/python.md +0 -153
- package/.agent-context/stacks/react-native.md +0 -16
- package/.agent-context/stacks/ruby.md +0 -80
- package/.agent-context/stacks/rust.md +0 -86
- package/.agent-context/stacks/typescript.md +0 -317
- package/.agent-context/state/skill-platform.json +0 -38
- package/lib/cli/skill-selector.mjs +0 -232
- package/lib/cli/templates/api-contract.md.id.tmpl +0 -143
- package/lib/cli/templates/api-contract.md.tmpl +0 -143
- package/lib/cli/templates/architecture-decision-record.md.id.tmpl +0 -106
- package/lib/cli/templates/architecture-decision-record.md.tmpl +0 -145
- package/lib/cli/templates/database-schema.md.id.tmpl +0 -74
- package/lib/cli/templates/database-schema.md.tmpl +0 -74
- package/lib/cli/templates/flow-overview.md.id.tmpl +0 -118
- package/lib/cli/templates/flow-overview.md.tmpl +0 -131
- package/lib/cli/templates/project-brief.md.id.tmpl +0 -55
- package/lib/cli/templates/project-brief.md.tmpl +0 -79
- package/scripts/init-project.ps1 +0 -105
- package/scripts/init-project.sh +0 -131
- package/scripts/skill-tier-policy.mjs +0 -76
- package/scripts/trust-scorer.mjs +0 -119
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
# Blueprint: NestJS Module (Clean Architecture)
|
|
2
|
-
|
|
3
|
-
> This blueprint defines how to scaffold a NestJS application or module.
|
|
4
|
-
> Every module follows strict layering. No shortcuts.
|
|
5
|
-
|
|
6
|
-
## Tech Stack
|
|
7
|
-
- **Runtime:** Node.js 20+ / Bun
|
|
8
|
-
- **Framework:** NestJS 10+
|
|
9
|
-
- **Validation:** Zod + nestjs-zod (or class-validator)
|
|
10
|
-
- **ORM:** Prisma (or Drizzle)
|
|
11
|
-
- **Documentation:** @nestjs/swagger (OpenAPI auto-generated)
|
|
12
|
-
- **Testing:** Vitest (or Jest)
|
|
13
|
-
- **Logger:** nestjs-pino
|
|
14
|
-
|
|
15
|
-
## Project Structure
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
project-name/
|
|
19
|
-
├── src/
|
|
20
|
-
│ ├── main.ts # Bootstrap + Swagger setup
|
|
21
|
-
│ ├── app.module.ts # Root module
|
|
22
|
-
│ │
|
|
23
|
-
│ ├── modules/ # Feature modules
|
|
24
|
-
│ │ ├── user/
|
|
25
|
-
│ │ │ ├── user.module.ts # Module registration
|
|
26
|
-
│ │ │ ├── user.controller.ts # Transport layer (HTTP)
|
|
27
|
-
│ │ │ ├── user.service.ts # Application layer (business logic)
|
|
28
|
-
│ │ │ ├── user.repository.ts # Infrastructure layer (data access)
|
|
29
|
-
│ │ │ ├── dto/
|
|
30
|
-
│ │ │ │ ├── create-user.dto.ts # Input validation schemas
|
|
31
|
-
│ │ │ │ ├── update-user.dto.ts
|
|
32
|
-
│ │ │ │ └── user-response.dto.ts # Output serialization
|
|
33
|
-
│ │ │ ├── entities/
|
|
34
|
-
│ │ │ │ └── user.entity.ts # Domain entity
|
|
35
|
-
│ │ │ ├── guards/
|
|
36
|
-
│ │ │ │ └── user-owner.guard.ts # Authorization guard
|
|
37
|
-
│ │ │ └── __tests__/
|
|
38
|
-
│ │ │ ├── user.controller.spec.ts
|
|
39
|
-
│ │ │ └── user.service.spec.ts
|
|
40
|
-
│ │ │
|
|
41
|
-
│ │ ├── auth/
|
|
42
|
-
│ │ │ ├── auth.module.ts
|
|
43
|
-
│ │ │ ├── auth.controller.ts
|
|
44
|
-
│ │ │ ├── auth.service.ts
|
|
45
|
-
│ │ │ ├── strategies/
|
|
46
|
-
│ │ │ │ ├── jwt.strategy.ts
|
|
47
|
-
│ │ │ │ └── local.strategy.ts
|
|
48
|
-
│ │ │ └── guards/
|
|
49
|
-
│ │ │ └── jwt-auth.guard.ts
|
|
50
|
-
│ │ │
|
|
51
|
-
│ │ └── health/
|
|
52
|
-
│ │ ├── health.module.ts
|
|
53
|
-
│ │ └── health.controller.ts
|
|
54
|
-
│ │
|
|
55
|
-
│ ├── shared/ # Cross-cutting concerns
|
|
56
|
-
│ │ ├── config/
|
|
57
|
-
│ │ │ ├── app.config.ts # Zod-validated config
|
|
58
|
-
│ │ │ └── database.config.ts
|
|
59
|
-
│ │ ├── errors/
|
|
60
|
-
│ │ │ ├── app-error.ts # Base error class
|
|
61
|
-
│ │ │ └── http-exception.filter.ts # Global exception filter
|
|
62
|
-
│ │ ├── interceptors/
|
|
63
|
-
│ │ │ ├── logging.interceptor.ts # Request logging
|
|
64
|
-
│ │ │ └── transform.interceptor.ts # Response transformation
|
|
65
|
-
│ │ ├── pipes/
|
|
66
|
-
│ │ │ └── zod-validation.pipe.ts # Zod validation pipe
|
|
67
|
-
│ │ ├── decorators/
|
|
68
|
-
│ │ │ └── current-user.decorator.ts
|
|
69
|
-
│ │ └── lib/
|
|
70
|
-
│ │ ├── prisma.service.ts # Prisma client lifecycle
|
|
71
|
-
│ │ └── logger.module.ts # Pino logger module
|
|
72
|
-
│ │
|
|
73
|
-
│ └── common/
|
|
74
|
-
│ └── types/
|
|
75
|
-
│ └── api-response.ts # Standardized API response type
|
|
76
|
-
│
|
|
77
|
-
├── prisma/
|
|
78
|
-
│ ├── schema.prisma
|
|
79
|
-
│ └── migrations/
|
|
80
|
-
│
|
|
81
|
-
├── test/ # E2E tests
|
|
82
|
-
│ └── app.e2e-spec.ts
|
|
83
|
-
│
|
|
84
|
-
├── .env.example
|
|
85
|
-
├── nest-cli.json
|
|
86
|
-
├── tsconfig.json # Strict mode!
|
|
87
|
-
├── tsconfig.build.json
|
|
88
|
-
├── vitest.config.ts
|
|
89
|
-
└── package.json
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Module Pattern (The Law)
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
// src/modules/user/user.module.ts
|
|
96
|
-
import { Module } from '@nestjs/common';
|
|
97
|
-
import { UserController } from './user.controller';
|
|
98
|
-
import { UserService } from './user.service';
|
|
99
|
-
import { UserRepository } from './user.repository';
|
|
100
|
-
|
|
101
|
-
@Module({
|
|
102
|
-
controllers: [UserController],
|
|
103
|
-
providers: [UserService, UserRepository],
|
|
104
|
-
exports: [UserService], // Only export the service — never the repository
|
|
105
|
-
})
|
|
106
|
-
export class UserModule {}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Controller Pattern (Transport ONLY)
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// src/modules/user/user.controller.ts
|
|
113
|
-
import { Controller, Get, Post, Body, Param, Query, UseGuards } from '@nestjs/common';
|
|
114
|
-
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
|
|
115
|
-
import { UserService } from './user.service';
|
|
116
|
-
import { CreateUserDto } from './dto/create-user.dto';
|
|
117
|
-
import { UserResponseDto } from './dto/user-response.dto';
|
|
118
|
-
import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard';
|
|
119
|
-
|
|
120
|
-
@ApiTags('Users')
|
|
121
|
-
@Controller('users')
|
|
122
|
-
export class UserController {
|
|
123
|
-
constructor(private readonly userService: UserService) {}
|
|
124
|
-
|
|
125
|
-
@ApiOperation({ summary: 'Create a new user' })
|
|
126
|
-
@ApiResponse({ status: 201, type: UserResponseDto })
|
|
127
|
-
@ApiResponse({ status: 400, description: 'Validation error' })
|
|
128
|
-
@ApiResponse({ status: 409, description: 'Email already exists' })
|
|
129
|
-
@Post()
|
|
130
|
-
async create(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
|
|
131
|
-
// Controller does: validate input (via pipe) → call service → return response
|
|
132
|
-
// Controller does NOT: query database, check business rules, format data
|
|
133
|
-
return this.userService.create(dto);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
@ApiBearerAuth()
|
|
137
|
-
@UseGuards(JwtAuthGuard)
|
|
138
|
-
@ApiOperation({ summary: 'List users with pagination' })
|
|
139
|
-
@Get()
|
|
140
|
-
async findAll(
|
|
141
|
-
@Query('page') page: number = 1,
|
|
142
|
-
@Query('limit') limit: number = 20,
|
|
143
|
-
): Promise<UserResponseDto[]> {
|
|
144
|
-
return this.userService.findAll({ page, limit });
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Service Pattern (Business Logic)
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
// src/modules/user/user.service.ts
|
|
153
|
-
import { Injectable, ConflictException } from '@nestjs/common';
|
|
154
|
-
import { UserRepository } from './user.repository';
|
|
155
|
-
import { CreateUserDto } from './dto/create-user.dto';
|
|
156
|
-
import { hash } from 'bcrypt';
|
|
157
|
-
|
|
158
|
-
@Injectable()
|
|
159
|
-
export class UserService {
|
|
160
|
-
constructor(private readonly userRepository: UserRepository) {}
|
|
161
|
-
|
|
162
|
-
async create(dto: CreateUserDto): Promise<UserResponseDto> {
|
|
163
|
-
// Business rule: email must be unique
|
|
164
|
-
const existingUser = await this.userRepository.findByEmail(dto.email);
|
|
165
|
-
if (existingUser) {
|
|
166
|
-
throw new ConflictException('Email already registered');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Business rule: hash password before storage
|
|
170
|
-
const hashedPassword = await hash(dto.password, 12);
|
|
171
|
-
|
|
172
|
-
return this.userRepository.create({
|
|
173
|
-
...dto,
|
|
174
|
-
password: hashedPassword,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Repository Pattern (Data Access Only)
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
// src/modules/user/user.repository.ts
|
|
184
|
-
import { Injectable } from '@nestjs/common';
|
|
185
|
-
import { PrismaService } from '@/shared/lib/prisma.service';
|
|
186
|
-
import { User } from '@prisma/client';
|
|
187
|
-
|
|
188
|
-
@Injectable()
|
|
189
|
-
export class UserRepository {
|
|
190
|
-
constructor(private readonly prisma: PrismaService) {}
|
|
191
|
-
|
|
192
|
-
async findByEmail(email: string): Promise<User | null> {
|
|
193
|
-
return this.prisma.user.findUnique({ where: { email } });
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async create(data: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<User> {
|
|
197
|
-
return this.prisma.user.create({ data });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async findAll(params: { skip: number; take: number }): Promise<User[]> {
|
|
201
|
-
return this.prisma.user.findMany({
|
|
202
|
-
skip: params.skip,
|
|
203
|
-
take: params.take,
|
|
204
|
-
select: { id: true, email: true, name: true, createdAt: true },
|
|
205
|
-
// NEVER select password
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
## Swagger Setup (Mandatory)
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
// src/main.ts
|
|
215
|
-
import { NestFactory } from '@nestjs/core';
|
|
216
|
-
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
|
217
|
-
import { AppModule } from './app.module';
|
|
218
|
-
|
|
219
|
-
async function bootstrap() {
|
|
220
|
-
const app = await NestFactory.create(AppModule);
|
|
221
|
-
|
|
222
|
-
// Swagger — auto-generates API documentation
|
|
223
|
-
const config = new DocumentBuilder()
|
|
224
|
-
.setTitle('API Documentation')
|
|
225
|
-
.setVersion('1.0')
|
|
226
|
-
.addBearerAuth()
|
|
227
|
-
.build();
|
|
228
|
-
|
|
229
|
-
const document = SwaggerModule.createDocument(app, config);
|
|
230
|
-
SwaggerModule.setup('docs', app, document);
|
|
231
|
-
|
|
232
|
-
await app.listen(3000);
|
|
233
|
-
}
|
|
234
|
-
bootstrap();
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Scaffolding Checklist
|
|
238
|
-
|
|
239
|
-
- [ ] Every module follows Controller → Service → Repository layering
|
|
240
|
-
- [ ] DTOs use Zod or class-validator for ALL input validation
|
|
241
|
-
- [ ] Swagger decorators on every controller method
|
|
242
|
-
- [ ] Global exception filter catches and formats all errors
|
|
243
|
-
- [ ] Repository NEVER exposes raw Prisma client outside its module
|
|
244
|
-
- [ ] Service is exported, Repository is NOT (module encapsulation)
|
|
245
|
-
- [ ] Tests exist for service logic (unit) and controller routes (integration)
|
|
246
|
-
- [ ] Environment variables validated with Zod at startup
|
|
247
|
-
- [ ] Health check endpoint exists at `/health`
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
# Blueprint: Observability Stack (OpenTelemetry)
|
|
2
|
-
|
|
3
|
-
> If you can't see it, you can't fix it.
|
|
4
|
-
> Observability is not optional — it's infrastructure.
|
|
5
|
-
|
|
6
|
-
## Tech Stack
|
|
7
|
-
|
|
8
|
-
| Pillar | Standard | Why |
|
|
9
|
-
|--------|----------|-----|
|
|
10
|
-
| **Tracing** | OpenTelemetry SDK | Vendor-neutral, W3C Trace Context |
|
|
11
|
-
| **Metrics** | OpenTelemetry SDK | OTLP export, histogram/counter/gauge |
|
|
12
|
-
| **Logging** | Structured JSON + OTel correlation | traceId in every log line |
|
|
13
|
-
| **Collector** | OpenTelemetry Collector | Pipeline: receive → process → export |
|
|
14
|
-
| **Backend** | Jaeger / Tempo (traces), Prometheus / Mimir (metrics), Loki (logs) | Or cloud: Datadog, Grafana Cloud, New Relic |
|
|
15
|
-
| **Dashboards** | Grafana | Universal visualization |
|
|
16
|
-
|
|
17
|
-
## The Three Pillars
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
┌──────────────────────────────────────────────────────────┐
|
|
21
|
-
│ Your Application │
|
|
22
|
-
│ │
|
|
23
|
-
│ Traces: "What path did this request take?" │
|
|
24
|
-
│ Metrics: "How is the system performing overall?" │
|
|
25
|
-
│ Logs: "What exactly happened at this moment?" │
|
|
26
|
-
│ │
|
|
27
|
-
│ ── All connected by traceId / spanId ── │
|
|
28
|
-
└────────────────────┬─────────────────────────────────────┘
|
|
29
|
-
│ OTLP (gRPC/HTTP)
|
|
30
|
-
┌─────────▼──────────┐
|
|
31
|
-
│ OTel Collector │
|
|
32
|
-
│ (receive/process/ │
|
|
33
|
-
│ export) │
|
|
34
|
-
└────┬────┬────┬─────┘
|
|
35
|
-
│ │ │
|
|
36
|
-
┌─────▼┐ ┌─▼──┐ ┌▼────┐
|
|
37
|
-
│Jaeger│ │Prom│ │Loki │
|
|
38
|
-
│Tempo │ │ │ │ │
|
|
39
|
-
└──────┘ └────┘ └─────┘
|
|
40
|
-
│
|
|
41
|
-
┌──────▼──────┐
|
|
42
|
-
│ Grafana │
|
|
43
|
-
│ (Dashboards) │
|
|
44
|
-
└─────────────┘
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Instrumentation Standards
|
|
48
|
-
|
|
49
|
-
### Auto-Instrumentation First
|
|
50
|
-
|
|
51
|
-
Start with auto-instrumentation for common libraries (HTTP servers, DB clients, message brokers). Add manual instrumentation for business-critical paths.
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
// Node.js: Initialize OpenTelemetry EARLY (before other imports)
|
|
55
|
-
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
56
|
-
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
57
|
-
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
|
|
58
|
-
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
59
|
-
|
|
60
|
-
const sdk = new NodeSDK({
|
|
61
|
-
traceExporter: new OTLPTraceExporter({
|
|
62
|
-
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
63
|
-
}),
|
|
64
|
-
metricReader: new PeriodicExportingMetricReader({
|
|
65
|
-
exporter: new OTLPMetricExporter(),
|
|
66
|
-
}),
|
|
67
|
-
instrumentations: [getNodeAutoInstrumentations()],
|
|
68
|
-
serviceName: process.env.OTEL_SERVICE_NAME,
|
|
69
|
-
serviceVersion: process.env.APP_VERSION,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
sdk.start();
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Manual Spans for Business Logic
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { trace } from '@opentelemetry/api';
|
|
79
|
-
|
|
80
|
-
const tracer = trace.getTracer('order-service');
|
|
81
|
-
|
|
82
|
-
async function processOrder(order: Order): Promise<void> {
|
|
83
|
-
return tracer.startActiveSpan('processOrder', async (span) => {
|
|
84
|
-
try {
|
|
85
|
-
span.setAttribute('order.id', order.id);
|
|
86
|
-
span.setAttribute('order.total', order.total);
|
|
87
|
-
span.setAttribute('order.item_count', order.items.length);
|
|
88
|
-
|
|
89
|
-
await validateInventory(order);
|
|
90
|
-
await processPayment(order);
|
|
91
|
-
await updateInventory(order);
|
|
92
|
-
|
|
93
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
94
|
-
} catch (error) {
|
|
95
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
96
|
-
span.recordException(error);
|
|
97
|
-
throw error;
|
|
98
|
-
} finally {
|
|
99
|
-
span.end();
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Metric Instruments
|
|
106
|
-
|
|
107
|
-
| Type | When | Example |
|
|
108
|
-
|------|------|---------|
|
|
109
|
-
| **Counter** | Monotonically increasing count | `http.requests.total` |
|
|
110
|
-
| **Histogram** | Distribution of values | `http.request.duration` |
|
|
111
|
-
| **Gauge** | Current snapshot value | `system.memory.usage` |
|
|
112
|
-
| **UpDownCounter** | Value that can go up and down | `queue.depth` |
|
|
113
|
-
|
|
114
|
-
### Structured Logging
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
// REQUIRED: Include traceId and spanId in every log
|
|
118
|
-
logger.info('Order processed', {
|
|
119
|
-
traceId: span.spanContext().traceId,
|
|
120
|
-
spanId: span.spanContext().spanId,
|
|
121
|
-
orderId: order.id,
|
|
122
|
-
userId: order.userId,
|
|
123
|
-
durationMs: Date.now() - startTime,
|
|
124
|
-
itemCount: order.items.length,
|
|
125
|
-
});
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Naming Conventions (Semantic Conventions)
|
|
129
|
-
|
|
130
|
-
Follow OpenTelemetry semantic conventions:
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
Metrics: {namespace}.{component}.{metric}
|
|
134
|
-
http.server.request.duration
|
|
135
|
-
db.client.operation.duration
|
|
136
|
-
messaging.publish.duration
|
|
137
|
-
|
|
138
|
-
Spans: {operation} {target}
|
|
139
|
-
GET /api/users
|
|
140
|
-
SELECT users
|
|
141
|
-
PUBLISH order.created
|
|
142
|
-
|
|
143
|
-
Attributes: {namespace}.{attribute}
|
|
144
|
-
http.request.method
|
|
145
|
-
db.system
|
|
146
|
-
service.name
|
|
147
|
-
service.version
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Alerting Strategy
|
|
151
|
-
|
|
152
|
-
### Golden Signals (Monitor These)
|
|
153
|
-
|
|
154
|
-
| Signal | Metric | Alert When |
|
|
155
|
-
|--------|--------|------------|
|
|
156
|
-
| **Latency** | `http.server.request.duration` p99 | > 500ms for 5 min |
|
|
157
|
-
| **Traffic** | `http.server.request.total` rate | Sudden drop > 50% |
|
|
158
|
-
| **Errors** | `http.server.request.error_ratio` | > 1% for 5 min |
|
|
159
|
-
| **Saturation** | CPU, memory, connection pool | > 80% for 10 min |
|
|
160
|
-
|
|
161
|
-
### Alert Rules
|
|
162
|
-
|
|
163
|
-
1. **Page** (wake someone up): Service is DOWN, error rate > 5%, data loss risk
|
|
164
|
-
2. **Alert** (respond this shift): Latency degradation, resource saturation > 80%
|
|
165
|
-
3. **Inform** (check next business day): Slow queries, disk space trending
|
|
166
|
-
|
|
167
|
-
## Collector Configuration
|
|
168
|
-
|
|
169
|
-
```yaml
|
|
170
|
-
# otel-collector-config.yaml
|
|
171
|
-
receivers:
|
|
172
|
-
otlp:
|
|
173
|
-
protocols:
|
|
174
|
-
grpc:
|
|
175
|
-
endpoint: 0.0.0.0:4317
|
|
176
|
-
http:
|
|
177
|
-
endpoint: 0.0.0.0:4318
|
|
178
|
-
|
|
179
|
-
processors:
|
|
180
|
-
batch:
|
|
181
|
-
timeout: 5s
|
|
182
|
-
send_batch_size: 1024
|
|
183
|
-
memory_limiter:
|
|
184
|
-
limit_mib: 512
|
|
185
|
-
spike_limit_mib: 128
|
|
186
|
-
attributes:
|
|
187
|
-
actions:
|
|
188
|
-
- key: environment
|
|
189
|
-
value: ${ENVIRONMENT}
|
|
190
|
-
action: upsert
|
|
191
|
-
|
|
192
|
-
exporters:
|
|
193
|
-
otlphttp/traces:
|
|
194
|
-
endpoint: http://jaeger:4318
|
|
195
|
-
prometheus:
|
|
196
|
-
endpoint: 0.0.0.0:8889
|
|
197
|
-
loki:
|
|
198
|
-
endpoint: http://loki:3100/loki/api/v1/push
|
|
199
|
-
|
|
200
|
-
service:
|
|
201
|
-
pipelines:
|
|
202
|
-
traces:
|
|
203
|
-
receivers: [otlp]
|
|
204
|
-
processors: [memory_limiter, batch]
|
|
205
|
-
exporters: [otlphttp/traces]
|
|
206
|
-
metrics:
|
|
207
|
-
receivers: [otlp]
|
|
208
|
-
processors: [memory_limiter, batch]
|
|
209
|
-
exporters: [prometheus]
|
|
210
|
-
logs:
|
|
211
|
-
receivers: [otlp]
|
|
212
|
-
processors: [memory_limiter, batch, attributes]
|
|
213
|
-
exporters: [loki]
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Scaffolding Checklist
|
|
217
|
-
|
|
218
|
-
- [ ] Install OpenTelemetry SDK for your language
|
|
219
|
-
- [ ] Configure auto-instrumentation for HTTP, DB, messaging
|
|
220
|
-
- [ ] Set `OTEL_SERVICE_NAME` and `OTEL_EXPORTER_OTLP_ENDPOINT` env vars
|
|
221
|
-
- [ ] Add manual spans to business-critical paths
|
|
222
|
-
- [ ] Ensure structured logs include `traceId` and `spanId`
|
|
223
|
-
- [ ] Deploy OpenTelemetry Collector with batch + memory limiter
|
|
224
|
-
- [ ] Configure exporters for traces, metrics, and logs
|
|
225
|
-
- [ ] Set up Grafana dashboards for golden signals
|
|
226
|
-
- [ ] Define alert rules for latency, errors, saturation
|
|
227
|
-
- [ ] Enable W3C Trace Context propagation across services
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
# Blueprint: Spring Boot API
|
|
2
|
-
|
|
3
|
-
> Java backend API service using Spring Boot 4.x, Java 25+, Spring Data JPA, and Flyway.
|
|
4
|
-
|
|
5
|
-
## Tech Stack
|
|
6
|
-
|
|
7
|
-
| Layer | Technology |
|
|
8
|
-
|-------|-----------|
|
|
9
|
-
| Framework | Spring Boot 4.x (Spring Framework 7) |
|
|
10
|
-
| Language | Java 25+ (LTS) |
|
|
11
|
-
| Validation | Jakarta Bean Validation |
|
|
12
|
-
| ORM | Spring Data JPA (Hibernate) |
|
|
13
|
-
| Migration | Flyway |
|
|
14
|
-
| Testing | JUnit 5 + Mockito + Testcontainers |
|
|
15
|
-
| DTO mapping | MapStruct |
|
|
16
|
-
| Logging | SLF4J + Logback (JSON) |
|
|
17
|
-
| API docs | springdoc-openapi (Swagger/Scalar) |
|
|
18
|
-
| Build | Gradle (Kotlin DSL) |
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Project Structure
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
project-name/
|
|
26
|
-
├── src/main/java/com/example/project/
|
|
27
|
-
│ ├── Application.java
|
|
28
|
-
│ │
|
|
29
|
-
│ ├── modules/
|
|
30
|
-
│ │ └── user/
|
|
31
|
-
│ │ ├── UserController.java
|
|
32
|
-
│ │ ├── UserService.java
|
|
33
|
-
│ │ ├── UserRepository.java
|
|
34
|
-
│ │ ├── UserMapper.java # MapStruct
|
|
35
|
-
│ │ ├── dto/
|
|
36
|
-
│ │ │ ├── CreateUserRequest.java # record + validation
|
|
37
|
-
│ │ │ └── UserResponse.java # record
|
|
38
|
-
│ │ ├── entity/
|
|
39
|
-
│ │ │ └── UserEntity.java # JPA entity
|
|
40
|
-
│ │ └── exception/
|
|
41
|
-
│ │ └── UserNotFoundException.java
|
|
42
|
-
│ │
|
|
43
|
-
│ └── shared/
|
|
44
|
-
│ ├── config/
|
|
45
|
-
│ │ ├── SecurityConfig.java
|
|
46
|
-
│ │ └── OpenApiConfig.java
|
|
47
|
-
│ ├── exception/
|
|
48
|
-
│ │ ├── AppException.java
|
|
49
|
-
│ │ ├── ErrorCode.java # Enum
|
|
50
|
-
│ │ ├── ErrorResponse.java # record
|
|
51
|
-
│ │ └── GlobalExceptionHandler.java # @ControllerAdvice
|
|
52
|
-
│ └── util/
|
|
53
|
-
│ └── LogContext.java
|
|
54
|
-
│
|
|
55
|
-
├── src/main/resources/
|
|
56
|
-
│ ├── application.yml
|
|
57
|
-
│ ├── application-dev.yml
|
|
58
|
-
│ └── db/migration/
|
|
59
|
-
│ └── V1__create_users_table.sql
|
|
60
|
-
│
|
|
61
|
-
├── src/test/java/com/example/project/
|
|
62
|
-
│ └── modules/user/
|
|
63
|
-
│ ├── UserServiceTest.java # Unit
|
|
64
|
-
│ └── UserControllerIT.java # Integration
|
|
65
|
-
│
|
|
66
|
-
├── build.gradle.kts
|
|
67
|
-
├── settings.gradle.kts
|
|
68
|
-
├── Dockerfile
|
|
69
|
-
└── .env.example
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## File Patterns
|
|
75
|
-
|
|
76
|
-
### Controller — Thin Transport
|
|
77
|
-
```java
|
|
78
|
-
@RestController
|
|
79
|
-
@RequestMapping("/api/v1/users")
|
|
80
|
-
@Tag(name = "Users")
|
|
81
|
-
public class UserController {
|
|
82
|
-
private final UserService userService;
|
|
83
|
-
|
|
84
|
-
public UserController(UserService userService) {
|
|
85
|
-
this.userService = userService;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@PostMapping
|
|
89
|
-
@ResponseStatus(HttpStatus.CREATED)
|
|
90
|
-
@Operation(summary = "Create a user account")
|
|
91
|
-
@ApiResponse(responseCode = "201", description = "User created")
|
|
92
|
-
@ApiResponse(responseCode = "400", description = "Validation error")
|
|
93
|
-
@ApiResponse(responseCode = "409", description = "Email already exists")
|
|
94
|
-
public UserResponse create(@Valid @RequestBody CreateUserRequest request) {
|
|
95
|
-
return userService.create(request);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
@GetMapping
|
|
99
|
-
@Operation(summary = "List users with pagination")
|
|
100
|
-
public Page<UserResponse> list(Pageable pageable) {
|
|
101
|
-
return userService.list(pageable);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### DTOs — Records with Validation
|
|
107
|
-
```java
|
|
108
|
-
public record CreateUserRequest(
|
|
109
|
-
@NotBlank @Size(max = 100)
|
|
110
|
-
@Schema(description = "Display name", example = "Jane Doe")
|
|
111
|
-
String name,
|
|
112
|
-
|
|
113
|
-
@NotBlank @Email
|
|
114
|
-
@Schema(description = "Unique email address", example = "jane@example.com")
|
|
115
|
-
String email,
|
|
116
|
-
|
|
117
|
-
@NotBlank @Size(min = 8)
|
|
118
|
-
String password
|
|
119
|
-
) {}
|
|
120
|
-
|
|
121
|
-
public record UserResponse(
|
|
122
|
-
UUID id,
|
|
123
|
-
String name,
|
|
124
|
-
String email,
|
|
125
|
-
Instant createdAt
|
|
126
|
-
) {}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Service — Business Logic
|
|
130
|
-
```java
|
|
131
|
-
@Service
|
|
132
|
-
@Transactional
|
|
133
|
-
public class UserService {
|
|
134
|
-
private static final Logger log = LoggerFactory.getLogger(UserService.class);
|
|
135
|
-
|
|
136
|
-
private final UserRepository userRepository;
|
|
137
|
-
private final UserMapper userMapper;
|
|
138
|
-
private final PasswordEncoder passwordEncoder;
|
|
139
|
-
|
|
140
|
-
public UserService(UserRepository userRepository, UserMapper userMapper,
|
|
141
|
-
PasswordEncoder passwordEncoder) {
|
|
142
|
-
this.userRepository = userRepository;
|
|
143
|
-
this.userMapper = userMapper;
|
|
144
|
-
this.passwordEncoder = passwordEncoder;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
public UserResponse create(CreateUserRequest request) {
|
|
148
|
-
if (userRepository.existsByEmail(request.email())) {
|
|
149
|
-
throw new AppException(ErrorCode.USER_ALREADY_EXISTS,
|
|
150
|
-
"Email already registered: " + request.email());
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
UserEntity entity = userMapper.toEntity(request);
|
|
154
|
-
entity.setPassword(passwordEncoder.encode(request.password()));
|
|
155
|
-
|
|
156
|
-
UserEntity saved = userRepository.save(entity);
|
|
157
|
-
log.info("User created: id={}, email={}", saved.getId(), saved.getEmail());
|
|
158
|
-
|
|
159
|
-
return userMapper.toResponse(saved);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
@Transactional(readOnly = true)
|
|
163
|
-
public Page<UserResponse> list(Pageable pageable) {
|
|
164
|
-
return userRepository.findAll(pageable).map(userMapper::toResponse);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Global Error Handler
|
|
170
|
-
```java
|
|
171
|
-
@ControllerAdvice
|
|
172
|
-
public class GlobalExceptionHandler {
|
|
173
|
-
|
|
174
|
-
@ExceptionHandler(AppException.class)
|
|
175
|
-
public ResponseEntity<ErrorResponse> handleAppException(AppException ex) {
|
|
176
|
-
return ResponseEntity
|
|
177
|
-
.status(ex.getHttpStatus())
|
|
178
|
-
.body(new ErrorResponse(ex.getCode().name(), ex.getMessage()));
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
182
|
-
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
|
|
183
|
-
var details = ex.getFieldErrors().stream()
|
|
184
|
-
.map(e -> new ErrorResponse.FieldError(e.getField(), e.getDefaultMessage()))
|
|
185
|
-
.toList();
|
|
186
|
-
return ResponseEntity.badRequest()
|
|
187
|
-
.body(new ErrorResponse("VALIDATION_ERROR", "Invalid input", details));
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
public record ErrorResponse(
|
|
192
|
-
String code,
|
|
193
|
-
String message,
|
|
194
|
-
List<FieldError> details
|
|
195
|
-
) {
|
|
196
|
-
public ErrorResponse(String code, String message) {
|
|
197
|
-
this(code, message, List.of());
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
public record FieldError(String field, String message) {}
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
---
|
|
205
|
-
|
|
206
|
-
## Scaffolding Checklist
|
|
207
|
-
|
|
208
|
-
- [ ] Initialize with Spring Initializr (Web, JPA, Validation, Security, Flyway)
|
|
209
|
-
- [ ] Set up modular structure under `modules/`
|
|
210
|
-
- [ ] Configure `application.yml` with profiles (dev, staging, prod)
|
|
211
|
-
- [ ] Create `GlobalExceptionHandler` with `@ControllerAdvice`
|
|
212
|
-
- [ ] Create `AppException` + `ErrorCode` enum
|
|
213
|
-
- [ ] Set up Flyway with initial migration
|
|
214
|
-
- [ ] Configure springdoc-openapi for API docs
|
|
215
|
-
- [ ] Create first module following the pattern
|
|
216
|
-
- [ ] Set up MapStruct for DTO mapping
|
|
217
|
-
- [ ] Create unit + integration tests
|
|
218
|
-
- [ ] Run `./gradlew test` — zero failures
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Team Profile Pack: Platform
|
|
2
|
-
|
|
3
|
-
slug: platform
|
|
4
|
-
displayName: Platform Team
|
|
5
|
-
description: Reliability-oriented defaults for shared platform modules across teams.
|
|
6
|
-
defaultProfile: balanced
|
|
7
|
-
defaultStack: go.md
|
|
8
|
-
defaultBlueprint: go-service.md
|
|
9
|
-
ciGuardrails: true
|
|
10
|
-
lockCi: false
|
|
11
|
-
blockingSeverities: critical, high
|
|
12
|
-
owner: platform-foundation
|
|
13
|
-
lastUpdated: 2026-03-19
|