specgen-spring-jpa-restapi — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited specgen-spring-jpa-restapi (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill generates a comprehensive specification document (Markdown) that serves as a blueprint for building a Spring Boot 3 REST API application. The spec is intended to be followed by a developer or a coding agent to produce a fully functional project scaffold.
The specification does NOT generate code. It produces a detailed, opinionated technical document describing every layer of the application — from Maven configuration to controller endpoints to security filter chains — so that implementation becomes a mechanical exercise.
These are the fixed versions the spec targets. Do not deviate unless the user explicitly requests different versions.
| Component | Version |
|---|---|
| Java JDK | 21 |
| Spring Boot | 3.5.7 |
| Maven | 4.0.0 |
Include in the version table only when the corresponding integration is selected.
| Component | Version | When Selected |
|---|---|---|
| MongoDB | 8.0.19 | Database = MongoDB |
| PostgreSQL | 17.x | Database = PostgreSQL |
| MySQL | 8.4.x | Database = MySQL |
| Keycloak | 26.5.3 | Auth = Keycloak |
| RabbitMQ | 4.x | Messaging = yes OR Remote Partitioning = yes |
The spec must include these in the Maven configuration section (always):
springdoc-openapi-starter-webmvc-ui) for API documentationIf Database = MongoDB:
spring-boot-starter-data-mongodb)spring-modulith-starter-mongodb)If Database = PostgreSQL or MySQL:
spring-boot-starter-data-jpa)org.postgresql:postgresql) or MySQL driver (com.mysql:mysql-connector-j)org.flywaydb:flyway-core) for schema migrationspring-modulith-starter-jpa)If Auth = Keycloak:
spring-boot-starter-security)spring-boot-starter-oauth2-resource-server)If Auth = Spring Security (JWT):
spring-boot-starter-security)io.jsonwebtoken:jjwt-api, jjwt-impl, jjwt-jackson for JWT token generation/validationIf Scheduling = yes:
spring-boot-starter-quartz)io.fluidsonic.mirror:fluidsonic-mirror-quartz (MongoDB job store for Quartz)If Scheduling = yes AND Spring Batch = yes:
spring-boot-starter-batch)If Scheduling = yes AND Spring Batch = yes AND Remote Partitioning = yes:
spring-batch-integration)spring-integration-amqp)spring-boot-starter-amqp)If Messaging = yes:
spring-boot-starter-amqp)(shared with Remote Partitioning — if both are selected, include the dependency once)
If Reporting = yes:
net.sf.jasperreports:jasperreports:7.0.3) — report engine with JRDesign API for programmatic layoutnet.sf.jasperreports:jasperreports-fonts:7.0.3)com.github.librepdf:openpdf:2.0.4) — PDF export engine for JasperReports 7.xorg.apache.poi:poi-ooxml:5.4.1) — XLSX export supportGenerate the spec when the user provides an application name and version that corresponds to one of the custom applications defined in CLAUDE.md. The skill reads all required inputs from the project's context files — no interactive Q&A is needed for the core inputs.
The user invokes this skill by specifying the target application and version, for example:
/specgen-spring-jpa-restapi hc_adapter v1.0.0/specgen-spring-jpa-restapi hc_adapter v1.0.0 module:Job Demand/specgen-spring-jpa-restapi "HC Adapter" v1.0.0The skill then locates the matching context folder and reads all input files automatically.
Before starting any work, resolve the application folder first (see Input Resolution below), then check CHANGELOG.md in the application folder (<app_folder>/CHANGELOG.md):
<app_folder>/CHANGELOG.md does not exist, skip this check (first-ever execution for this application).<app_folder>/CHANGELOG.md exists, scan all ## vX.Y.Z headings and determine the highest version using semantic versioning comparison."Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected." Do NOT proceed with any work.This skill uses standardized input resolution. Provide:
| Argument | Required | Example | Description |
|---|---|---|---|
<application> | Yes | hc_adapter | Application name to locate the context folder |
<version> | Yes | v1.0.0 | Version to scope processing |
module:<name> | No | module:Job Demand | Limit generation to a single module |
The application name is matched against root-level application folders:
<number>_ prefix from folder names (e.g., 1_hc_adapter -> hc_adapter)| File | Resolved Path |
|---|---|
| PRD.md | <app_folder>/context/PRD.md |
| Module Models | <app_folder>/context/model/ |
| Output (specification) | <app_folder>/context/specification/ |
/specgen-spring-jpa-restapi hc_adapter v1.0.0 (all modules)/specgen-spring-jpa-restapi hc_adapter v1.0.0 module:Job Demand (one module)/specgen-spring-jpa-restapi "HC Adapter" v1.0.0When a version is provided, only include user stories, NFRs, and constraints from versions <= the provided version. For example, if v1.0.3 is specified:
[v1.0.0], [v1.0.1], [v1.0.2], [v1.0.3][v1.0.4] or laterWhen module:<name> is provided:
SPEC.md for that specific moduleSPECIFICATION.md (root) gets a partial update — only that module's entry in the TOCis added or updated; all other TOC entries are preserved as-is
The specification is driven by five input sources that are read from the project's context files. The skill does NOT ask the user for database, authentication, scheduling, or messaging choices — it determines these automatically from the context.
From CLAUDE.md (already loaded in context), locate the target application under the Custom Applications section. Extract:
optional components (see Determining Optional Components)
The application name is used to derive:
hc-adapter)com.bestinet.urp (project-level constant)com.bestinet.urp.<artifactid_no_hyphens> (e.g., com.bestinet.urp.hcadapter)Read <app_folder>/context/PRD.md. This file contains all user stories organized by module. Extract:
# System Module heading (e.g., User, Notification,Activities, Audit Trail). These become system-level modules in the spec.
# Business Module heading (e.g., LocationInformation, Corridor, Employer). These become business-level modules.
### User Story section contains tagged items like[USHC00108] As a user, I want to.... These define the functional requirements for each module's service interface and API endpoints.
The user stories directly inform:
Important: Items with strikethrough (~~text~~) are deprecated — do NOT include them as active requirements. Instead, list them in the "Removed / Replaced" subsection of the traceability table (see spec-template.md) so that developers can see what was removed and which version removed it. If a deprecated item has a replacement (e.g., USHC00015 replaced by USHC00222), note the replacement ID.
### User Story, ### Non Functional Requirement,and ### Constraint section contains one or more version blocks formatted as [v1.0.x]. Items listed under each version tag belong to that version. The skill must track the version tag for each item (user story, NFR, constraint) and carry it through to the generated specification's traceability section. When a version block explicitly lists "Removed ... from previous version", record those removals in a "Removed / Replaced" subsection with the version that removed them and the replacement ID (if any).
Within the same PRD.md, each module has a ### Non Functional Requirement section with tagged items like [NFRHC0120]. These inform:
NFRs should be mapped to specific technical decisions in the spec — for example, an NFR stating "staging database" confirms adapter pattern, while "sent asynchronously" confirms event-driven processing.
Within the same PRD.md, each module has a ### Constraint section with tagged items like [CONSHC042]. These define hard boundaries that the spec must enforce:
Constraints are embedded directly into the relevant module blueprint — they inform service interface contracts, validation rules, and API endpoint configurations.
Read <app_folder>/context/model/MODEL.md first as the index, then read the individual module model files in each module subfolder.
MODEL.md provides:
Per-module files (e.g., model/job-demand/model.md):
Per-module schema (e.g., model/job-demand/schemas.json):
Per-module diagram (e.g., model/job-demand/entity-model.mermaid):
The module model directly maps to:
which versions each module participates in (e.g., "1.0.0, 1.0.1, 1.0.3"). Per-module model.md files may also include version annotations on fields and indexes. The skill must carry these version tags into the generated specification.
Before determining optional components, check PRD.md for the following extended sections and extract their content for use throughout specification generation:
If PRD.md contains an # Architecture Principle section, read it and extract architectural patterns as a structured context object. These patterns serve as primary signals for optional component determination and specification content:
| Pattern to Extract | How It Influences the Specification |
|---|---|
| Framework mention (e.g., "Spring Boot") | Validates technology stack choice |
| "Stateless" | Confirms stateless REST API — no HTTP session, JWT validation only; include in Security section |
| "Event-driven" | Enhances event publishing/subscribing sections with event catalog and explicit listener patterns |
| "Message driven" / "message queue" | Validates RabbitMQ integration; include message flow per module |
| "Document based database" / "MongoDB" | Primary signal for Database = MongoDB |
| "At-least-once delivery" | Add Idempotency section with idempotency key header pattern and deduplication |
| "Container based deployment" | Confirms ${ENV_VAR} syntax for configuration |
| "API gateway" | Adjust base URL configuration for gateway routing |
| "Scale out" / "horizontally scalable" | Note horizontal scaling considerations in deployment section |
If the section is absent, proceed with existing CLAUDE.md-only detection.
If PRD.md contains a # High Level Process Flow section:
If the section is absent, derive messaging patterns from NFRs only (existing behavior).
Instead of asking the user, the skill determines optional components by analyzing the dependencies listed in CLAUDE.md, the # Architecture Principle section in PRD.md (if present), and cross-referencing with PRD.md NFRs and constraints.
First check PRD.md `# Architecture Principle`: If it explicitly mentions a database type (e.g., "document based database", "MongoDB", "relational database", "MySQL"), use that as the primary signal.
Fallback to CLAUDE.md: Examine the "Depends on" list in CLAUDE.md for the target application:
| Dependency Pattern | Database Selection |
|---|---|
| References "Hub Database" (MongoDB) | Database = MongoDB |
| References "HC Database" or "SC Database" (MySQL) | Database = MySQL |
| No database dependency listed | Database = none |
Also check CLAUDE.md's database section for the exact database name, host, and credentials to use in the spec's application configuration. Read ENVIRONMENT.md (in the project root) for host, port, and credentials.
| Dependency Pattern | Auth Selection |
|---|---|
| References "Hub Single Sign On" (Keycloak) | Auth = Keycloak (Resource Server) |
| PRD.md constraint says "does not manage any user, permissions and roles" | Auth = none |
| PRD.md NFRs reference "JWT token" or "Bearer token" | Auth = Keycloak (Resource Server) |
| No SSO/Keycloak dependency but has user management stories | Auth = JWT (self-issued) |
If Auth = Keycloak (Resource Server), also extract from CLAUDE.md:
http://localhost:8180/realms/<realm>| Dependency Pattern | Messaging Selection |
|---|---|
| References "Hub to HC Adapter Message Queue" or "Hub to SC Adapter Message Queue" (RabbitMQ) | Messaging = yes |
| No message queue dependency listed | Messaging = no |
If Messaging = yes, also extract the RabbitMQ version from the corresponding message queue section in CLAUDE.md.
Scheduling is determined from PRD.md content:
| Content Pattern | Scheduling Selection |
|---|---|
| NFRs mention "automatically deleted after X days", "scheduled", "periodic", "batch processing" | Scheduling = yes |
| User stories describe recurring jobs, cleanup tasks, or time-triggered operations | Scheduling = yes |
| No scheduling-related requirements found | Scheduling = no |
If Scheduling = yes, further determine:
or processing large volumes of data with reader/processor/writer patterns
scaling", or "partitioned batch jobs"
Reporting is determined from PRD.md content:
| Content Pattern | Reporting Selection |
|---|---|
| NFRs mention "report", "Report interface", "generate report", "report generation" | Reporting = yes |
| User stories describe generating/downloading PDF, Excel, or CSV reports | Reporting = yes |
| A "Report" module exists in PRD.md with NFRs defining a Report interface | Reporting = yes |
| No reporting-related requirements found | Reporting = no |
If Reporting = yes, the spec includes:
ReportDefinition interface with buildDesign() method for modules to implementReportDesignHelper utility class with static builders for common layout patternsReportService orchestrating compile → fill → export via JRBeanCollectionDataSourceAfter analyzing all inputs, produce a determination summary before generating the spec. Present it to the user for confirmation:
Optional Component Determination:
- Database: MySQL (from CLAUDE.md -> depends on HC Database)
- Authentication: Keycloak Resource Server (from CLAUDE.md -> depends on Hub Single Sign On)
- Scheduling: no
- Messaging: yes (from CLAUDE.md -> depends on Hub to HC Adapter Message Queue)
- Reporting: yes (from PRD.md → Report module with Report interface NFR)If the user disagrees with any determination, allow them to override before proceeding.
After determination, these values are needed. Most are derived automatically:
Auto-derived from context files:
com.bestinet.urpcom.bestinet.urp.<artifactid>Auto-derived from CLAUDE.md (Port Allocation table):
Port Allocation table in the Custom Applications section of CLAUDE.md. Do NOT hardcode a default — the port MUST match the allocated port for this application.Optional (use sensible defaults if not found in context):
/api/v1INFO for application, WARN for frameworksOnce inputs are gathered from context files and optional components are determined, generate the specification as a multi-file output split by module. Read the spec template at references/spec-template.md for the exact structure and content of each section. The template is the authoritative guide — follow it closely.
The specification is split into two categories:
and application-level sections that apply across all modules.
a self-contained specification file covering that module's complete blueprint.
This split enables a coding agent to:
SPECIFICATION.md<module>/SPEC.mdImportant: The generated spec must use real module data from the context files, not generic placeholders. Specifically:
(e.g., jobDemand, candidateRegistration, employer — not module1, module2)
files (e.g., model/job-demand/model.md), not placeholder fieldOne/fieldTwo
a story says "search job demands by country", the service needs searchByCountry())
"view details of a job demand", there must be a GET /api/v1/job-demands/{id} endpoint)
must include its version tag (e.g., USHC00228 [v1.0.3]).
subsection listing any deprecated items from previous versions.
<app_folder>/context/specification/
├── SPECIFICATION.md <- TOC + shared/application-level specs
├── job-demand/
│ └── SPEC.md <- Module blueprint for Job Demand
├── candidate-registration/
│ └── SPEC.md <- Module blueprint for Candidate Registration
├── ... <- One folder per module from PRD.mdSPECIFICATION.md (Root)The root file contains the TOC and all shared/application-level sections. These are the sections that a coding agent implements first before any module work:
#### 1. Project Overview Project metadata, application description, technology stack summary, the complete list of API consumers/roles, and the Module Index — a table listing every module with a link to its <module>/SPEC.md file.
#### 2. Maven Configuration Complete pom.xml structure with all dependencies (core + selected conditional), plugin configurations (MapStruct annotation processor, Spring Boot Maven plugin), and property management.
#### 3. Application Configuration (conditional content varies) A single application.yml (no profile-specific files like application-dev.yml or application-prod.yml) covering database connection (MongoDB URI or JDBC datasource depending on selection), auth settings (Keycloak Resource Server JWT validation if selected, or self-issued JWT if selected), scheduling config (if selected), and logging configuration. All environment-sensitive values (ports, hostnames, credentials, URIs) MUST use Spring's `${ENV_VAR:default}` syntax to allow externalization via environment variables while keeping sensible defaults for local development. Do NOT use Spring profiles or profile-specific YAML files — environment differences are handled entirely through environment variables (e.g., via .env file locally or system environment variables in deployment).
#### 3a. Application-Specific Configuration (app: namespace)
All application-owned configuration — any config specific to THIS application, as opposed to the Spring/Java ecosystem — MUST live under the top-level app: key in application.yml. NEVER place application-specific keys under Spring framework namespaces (spring.*, server.*, management.*, logging.*, springdoc.*) — those are reserved for framework configuration.
Grouping rule. Organise the app: tree by module:
shared security settings, shared messaging infrastructure, shared object-storage settings) sit directly under app.* with no module prefix.
app.<module-kebab-case>.*, one blockper module that needs runtime config. A module with a single config value still gets its own block — do not flatten.
notification:, batch-job:, audit-trail:). They MUST be nested under app:.
Naming rule. YAML keys use kebab-case (from-address, retry-limit, max-retry). Spring Boot's relaxed binding maps them to camelCase Java fields automatically. Do NOT use camelCase or snake_case in YAML.
Binding rule. For every app.* subtree (cross-cutting OR per-module), bind once via @ConfigurationProperties on a record in the corresponding module's config subpackage — or, for cross-cutting values, in the application-level config subpackage. Do NOT inject individual values via @Value("${app....}") scattered across beans. Bind once at the module boundary and inject the typed record.
Environment-override rule. Every app.* leaf value MUST use Spring's ${ENV_VAR:default} syntax so it can be overridden per environment without editing YAML. Every referenced ${ENV_VAR} MUST appear in the .env file generated in section 3b.
Example structure:
app:
# Cross-cutting (no module prefix)
version: ${APP_VERSION:1.0.0}
cors:
allowed-origins: ${APP_CORS_ALLOWED_ORIGINS:http://localhost:3000}
security:
public-paths:
- /actuator/health
- /api/v1/info
# Per-module blocks — one per module with runtime config
notification:
email:
from-address: ${NOTIFICATION_FROM_ADDRESS:[email protected]}
retry-limit: ${NOTIFICATION_RETRY_LIMIT:3}
cleanup:
retention-days: ${NOTIFICATION_RETENTION_DAYS:30}
batch-job:
cleanup:
retention-days: ${BATCH_JOB_RETENTION_DAYS:90}
audit-trail:
cleanup:
retention-days: ${AUDIT_TRAIL_RETENTION_DAYS:365}*Example cross-cutting record (`app.`):**
@ConfigurationProperties(prefix = "app")
public record AppProperties(String version, Cors cors, Security security) {
public record Cors(List<String> allowedOrigins) {}
public record Security(List<String> publicPaths) {}
}*Example per-module record (`app.<module>.`):**
@ConfigurationProperties(prefix = "app.notification")
public record NotificationProperties(
Email email,
Cleanup cleanup
) {
public record Email(String fromAddress, int retryLimit) {}
public record Cleanup(int retentionDays) {}
}Enable binding at the application root with @ConfigurationPropertiesScan on the main application class, or register each record individually via @EnableConfigurationProperties on a @Configuration class in the owning module.
Mandatory cross-cutting values:
| Key | Purpose | Binding |
|---|---|---|
app.version | Current application version; must match pom.xml <version> | AppProperties.version() |
Additional cross-cutting keys may be added as the application grows, but app.version is always present.
`app.version` specifics. The .env file must include APP_VERSION={version} with the actual version value. The pom.xml <version> element MUST also be set to the same version value (e.g., 1.0.3). When multiple versions were provided during skill invocation, use the highest one. The REST API MUST expose the application version in:
GET /api/v1/info or Spring Actuator/actuator/info) returning {"version": "1.0.3", ...}. Inject AppProperties into the controller and read the version via appProperties.version().
include a version field (e.g., {"version": "1.0.3", "data": {...}}).
#### 3b. .env File Generation from ENVIRONMENT.md Generate a .env file at the project root by reading ENVIRONMENT.md from the project root. The .env file maps ENVIRONMENT.md credential and platform values to the environment variable names referenced in application.yml. The spec must define the complete .env content with actual values from ENVIRONMENT.md.
Process:
ENVIRONMENT.md from the project rootENVIRONMENT.md (# Supporting 3rd Party Applicationsfor database hosts, ports, usernames, passwords, plus Keycloak/RabbitMQ); read toolchain paths (JDK, Maven) from DEVTOOL.md
${ENV_VAR} name used in application.yml.env file with KEY=value pairsExample `.env` output (derived from ENVIRONMENT.md):
# Database
DB_HOST=localhost
DB_PORT=3306
DB_NAME=hub_supp
DB_USERNAME=root
DB_PASSWORD=B3st1n3t@2025
# Authentication (Keycloak)
KEYCLOAK_HOST=http://localhost:8180
KEYCLOAK_REALM=urp
KEYCLOAK_CLIENT_ID=hub-middleware-api
# Messaging (RabbitMQ)
RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=guest
# Server
SERVER_PORT=<port from CLAUDE.md Port Allocation table>
# Platform
JAVA_HOME=C:\Users\rashidee.rashid.BESTINET\.jdks\azul-21.0.9
MAVEN_HOME=C:\Users\rashidee.rashid.BESTINET\apache-maven-3.9.12Rules:
application.ymlTODOdevelopment (e.g., localhost, default ports)
.env file is gitignored (already covered in .gitignore)#### 4. .gitignore Generate a .gitignore file at the project root that excludes all generated, downloaded, and environment-specific files from version control.
#### 5. Package Structure The complete directory tree rooted at the base package. The structure follows Domain-Driven Design with Spring Modulith conventions, adapted for REST API with controller subpackages (not page/fragment). Use actual module names. Read references/modulith-patterns.md for the detailed module layout and inter-module communication rules.
#### 6. Security Configuration (conditional — include only if Auth != none) If Auth = Keycloak (Resource Server): OAuth2 Resource Server setup with JWT validation. SecurityFilterChain with oauth2ResourceServer(jwt -> ...). Keycloak JWT decoder configuration. Role extraction from JWT claims (realm_access, resource_access). Stateless session policy. CORS configuration. Read references/security-patterns.md for the full security architecture.
If Auth = JWT (self-issued): Spring Security with custom JWT token provider. SecurityFilterChain with JwtAuthenticationFilter. JwtTokenProvider for token generation and validation. Stateless session policy. CORS configuration.
#### 7. REST API Conventions Standardized REST API patterns including:
/api/v1/... path prefix)ApiError record)Page serialization)Read references/restapi-patterns.md for the complete REST API patterns.
#### 8. Error Handling & Exceptions Global @RestControllerAdvice exception handler returning standardized JSON error responses. Base ApiException with status/code/message. ResourceNotFoundException, ValidationException, ConflictException hierarchy. Consistent ApiError envelope across all error responses.
#### 9. Pagination & Filtering Support Standardized pagination using Spring Data Pageable. Sorting support via query parameters. Dynamic filtering using Spring Data Specifications (JPA) or Query DSL (MongoDB). Default page size, maximum page size configuration.
#### 10. Data Access (conditional content varies) If Database = MongoDB: MongoDB repositories per module with Spring Data MongoRepository. DTO mapping via MapStruct. All list endpoints paginated. Use actual collection names.
If Database = PostgreSQL/MySQL: JPA repositories per module with Spring Data JpaRepository. JPA entities with @Entity/@Table annotations extending BaseEntity. BaseEntity uses @UuidGenerator(style = UuidGenerator.Style.TIME) with @Column(columnDefinition = "CHAR(36)") and private String id. Flyway migration scripts. DTO mapping via MapStruct. All list endpoints paginated. Use actual table names. MySQL UUID rule: All UUID primary keys and foreign keys use CHAR(36) in DDL.
If Database = none: In-memory data structures or stubs.
#### 11. API Documentation (SpringDoc OpenAPI) SpringDoc OpenAPI configuration for auto-generating Swagger UI. Controller annotations (@Tag, @Operation, @ApiResponse). Configuration in application.yml.
#### 12. Logging Strategy SLF4J with Logback configuration, correlation ID filter (X-Correlation-Id header), MDC context filter, per-module log levels.
#### 13. Scheduling and Batch Processing (conditional — include only if Scheduling = yes) Quartz scheduler configuration with job store matching the selected database. Read references/batch-patterns.md for the full scaffolding spec.
#### 14. Event-Driven Architecture Spring Modulith application events for inter-module communication. Read references/modulith-patterns.md for details.
#### 15. Messaging (RabbitMQ Pub/Sub) (conditional — include only if Messaging = yes) Standalone RabbitMQ publisher/consumer services for inter-system communication. Read references/messaging-patterns.md for the full messaging architecture.
#### 16. MapStruct Usage Per-module MapStruct mapper conventions and mapping flow patterns.
#### 17. Testing Strategy Overview of testing approach — unit tests (service layer with Mockito), integration tests (controller layer with @WebMvcTest and MockMvc), security test utilities (JWT mocking if Keycloak, or @WithMockUser if JWT), Spring Modulith module verification.
#### 18. Caching Strategy (optional — include if applicable) HTTP caching headers (Cache-Control, ETag). Application-level caching with Spring Cache and Caffeine. Cache eviction strategies.
#### 19. Idempotency (optional — include if applicable) Idempotency-Key header pattern for mutating operations. Duplicate detection and response replay.
#### 20. Reporting (JasperReports JRDesign API) (conditional — include only if Reporting = yes) JasperReports infrastructure with fully programmatic report layout via JRDesign API — no .jrxml XML templates. Report layouts are built entirely in Java code using JasperDesign, JRDesignBand, JRDesignStaticText, JRDesignTextField, and JRDesignField classes. Includes ReportDefinition interface with buildDesign() method for modules to implement, ReportDesignHelper utility with static builders for common patterns (A4 portrait/landscape, column headers, detail bands, page footers), ReportService orchestrating compile → fill → export via JRBeanCollectionDataSource, ReportRegistry for auto-discovering and persisting report definitions at startup, REST controller with report list, details, and generation endpoints (GET /api/v1/reports, POST /api/v1/reports/{id}/generate), multi-format export (PDF via OpenPDF, XLSX via Apache POI, CSV). Modules register reports by creating @Component classes implementing ReportDefinition — each report builds its layout programmatically and calls module services to produce DTOs (never repositories directly), preserving Spring Modulith module boundaries. Read references/reporting-patterns.md for the full reporting architecture.
<module>/SPEC.md (Per-Module)For EACH module from PRD.md and MODEL.md, create a folder named after the module (kebab-case, e.g., job-demand/) and generate a SPEC.md inside it.
Each module SPEC.md is a self-contained blueprint that a coding agent can pick up and implement independently (after the shared infrastructure is in place). It must include:
SPECIFICATION.mdmodel/<module>/model.md andmodel/<module>/schemas.json
@RestController)Separating REST API Layer from Messaging/Async Pipeline:
When a module has BOTH user-facing endpoints (user stories) AND async processing NFRs (e.g., RabbitMQ message consumption, message validation, ACK publishing, forwarding), the SPEC.md MUST clearly separate these into distinct sections:
update, delete), REST controllers, request/response DTOs. These are driven by user stories (USHCxxxxx).
@RabbitListener), messagevalidator, ACK publisher, forward publisher, queue configuration, domain events, processIncomingMessage() service method. These are driven by NFRs (NFRHCxxxx).
MQ listener placement (mandatory). Every@RabbitListenerclass generated for a module MUST be placed inside that module'sinternal/package ({{base}}.{{module}}.internal), package-private, alongside the controller. Shared messaging infrastructure (RabbitMQMessagingConfig,RabbitMQPublisher,MessageConverterConfig, cross-module event/command DTOs) lives inshared/messaging/, but that package must contain no@RabbitListenerclasses. Seereferences/messaging-patterns.md§ "Consumer Service (module-internal)" for the canonical pattern.
See references/spec-template.md for the exact template structure.
After all specification files are successfully generated, append an entry to CHANGELOG.md in the application folder (<app_folder>/CHANGELOG.md):
<app_folder>/CHANGELOG.md. If it does not exist, create it with: # Changelog
- This file tracks all skill executions by version for this application.
- The highest version recorded here is the current application version.
- Skills MUST NOT execute for a version lower than the highest version in this file.
---## {version} heading matching the current version.--- below the context header and before any existing ## vX.Y.Z section (newest-first ordering), with a new table header and the first row.| {YYYY-MM-DD} | {application_name} | specgen-spring-jpa-restapi | {module or "All"} | Generated Spring Boot REST API technical specification |The generated specification is a folder of files, not a single document:
<app_folder>/context/specification/
├── SPECIFICATION.md <- Root: TOC + shared/application-level specs
├── <module-1>/
│ └── SPEC.md <- Module blueprint (self-contained)
├── <module-2>/
│ └── SPEC.md
├── <module-N>/
│ └── SPEC.md<app_folder>/context/specification/SPECIFICATION.mdSPEC.md is self-contained with full code samplesSample code is mandatory. Every component described in any spec file must include a complete, self-explanatory code sample inside a fenced code block (Java, YAML, or JSON as appropriate). The sample code must be continuous (not fragments stitched with "// ..." gaps) and usable as a direct reference by a coding agent or developer.
These constraints are non-negotiable. Every code sample in the generated spec must follow them. If any constraint is violated, the spec is incorrect.
Do NOT use Lombok's `@Data` annotation — anywhere. Use @Getter and @Setter explicitly on every class that needs accessors. @Data generates equals(), hashCode(), and toString() which cause problems with persistent entities, lazy-loaded collections, and circular references. The spec must use @Getter @Setter consistently.
Do NOT use field injection. Every Spring-managed bean must use constructor injection. Use Lombok's @RequiredArgsConstructor with private final fields. Never use @Autowired on fields. This applies to services, controllers, configurations, filters, and any other Spring component.
Use Java records for DTOs. All request and response DTOs should be Java records (immutable, auto-generated equals/hashCode/toString). Records with Bean Validation annotations for request DTOs.
Use MapStruct for all object mapping. Define MapStruct mappers per module with @Mapper(componentModel = "spring"). Avoid handwritten mapping beyond simple passthroughs.
Never expose JPA entities or MongoDB documents directly in API responses. Always map to response DTOs via MapStruct.
All data listings must be paginated. Every endpoint that returns a list must accept Pageable parameters and return Page<T>. Never return unbounded lists.
Use real module data from context files. The spec must use actual field names, collection/table names, module names, and user stories from the context files.
REST API URI conventions:
/api/v1/job-demands, NOT /api/v1/job-demand)/api/v1/job-demands, NOT /api/v1/jobDemands){id} path variable for single resource access (e.g., /api/v1/job-demands/{id})/api/v1/employers/{id}/contacts)POST /api/v1/orders/{id}/cancel)Return correct HTTP status codes:
200 OK for successful retrieval and updates201 Created with Location header for resource creation204 No Content for successful deletion400 Bad Request for validation errors401 Unauthorized for missing/invalid credentials403 Forbidden for insufficient permissions404 Not Found for non-existent resources409 Conflict for state conflictsIf Auth = Keycloak (Resource Server):
in the Authorization: Bearer header. Stateless — no HTTP session.
The application only reads roles from JWT claims to enforce access control.
If Auth = JWT (self-issued):
JwtAuthenticationFilter extracts and validates tokens.If Scheduling = yes and Database = MongoDB:
If Scheduling = yes and Database = PostgreSQL/MySQL:
If Messaging = yes:
app.*) must not collide with batchpartition queues (batch.partition.*). Use distinct prefixes for each concern.
These principles should be woven into every section of the spec rather than listed separately.
@Valid)@RequiredArgsConstructor + private final)@Getter @Setter instead of @Data on all entity/document classesapplication.yml with environment variables for all environment-specific values (no profile-specific YAML files)@RestControllerAdviceauthentication and authorization (stateless). No user/role management — external IdP only.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.