Imported from ritikkatiyar/livic (
.agents/skills/backend-engineering/SKILL.md). Install upstream withnpx skills add ritikkatiyar/livic --skill backend-engineering. Copyright stays with the author.
Senior Backend Engineer - Production-Grade Spring Boot Standards
Before generating or modifying any code, STRICTLY follow the engineering standards defined below.
ARCHITECTURE STANDARD
- Architecture: Modular Monolith
- Pattern:
- Package-by-feature
- Layered architecture
- DDD-lite
Module structure: module/ ├── controller/ ├── service/ │ ├── interface/ │ └── impl/ ├── domain/ ├── repository/ ├── dto/ ├── mapper/
MODULE BOUNDARY RULES
- Bounded Contexts Only: Modules must be organized by Domain (Bounded Contexts), NOT by individual database tables (Entity Services).
- Approved modules, grouped under
com.livic.<layer>.<module>:platform- Shared foundations with no business rules, and nothing about buildings:common/config- Cross-cutting concerns.security- Current-user principal and JWT verification (depends only oncommon).auth- Identity & Access Management (Logins, Tokens, Memberships, Roles & Permissions).user- Core User Profile and Global Roles.notification- Multi-channel alert delivery (Email, Push, WhatsApp).storage- Pluggable media storage and CDN integration (Cloudinary, S3, R2, Local).payment- Payment gateway integrations (Razorpay, Stripe, PayPal), payment initiation, webhooks, and ledger transactions.subscription- Livic SaaS subscriptions, plan tiers, feature limits, and quota enforcement.
core- The building and its money, shared by every product line: 9.property- Properties, blocks (towers/wings), units, andunit_member(who belongs to a unit: owners, tenants, family). 10.finance- Charge configs, bills, bill lines, ledger, meter readings, worksheets. 11.community- Product-neutral resident features:announcement,issue,analytics.verticals- Only what is unique to one product line: 12.rental- Leases, unit bookings, deposits, roommate splits, andinventory(move-in/move-out asset tracking). 13.marketplace- Public listings, prospect OTP verification, tour requests and bookings, landlord visiting hours. 14. (planned)society- Ownership transfer, committee, visitors/gate, amenities, parking.
- Dependencies flow
verticals->core->platform, and modules must stay free of cycles (enforced byModuleBoundaryTest). Never the reverse:platformmust not referencecoreorverticals,coremust not referenceverticals, and one vertical must not reference another. - Core must never know about a vertical. This is what keeps residential, society and hostel additive rather than rewrites. Anything that needs to know "who is in this unit" reads
unit_memberincore.property, never leases inverticals.rental. - When a lower layer needs something from a higher one, declare an SPI in the lower layer and implement it in the higher one (e.g.
platform.subscription.spi.PropertyUsageProviderimplemented bycore.property), or publish a synchronous event. - No direct repository access across modules
- Modules communicate ONLY via facade or service interfaces (e.g.
com.livic.core.finance.facadeorcom.livic.core.finance.service.interfaces) - Controllers must remain thin
- Business logic only inside services
DATABASE STANDARDS
- Table naming:
- lowercase + "_tbl" Example: user_tbl, property_tbl
- Column naming:
- snake_case
- Primary keys:
- UUID only
- Foreign keys:
- *_id format
- Flyway:
- schema changes ONLY via migrations
- Never use ddl-auto=create/update
API STANDARDS
Standard response format: { "success": true, "data": {}, "error": null }
Rules:
- Domain-Prefixed Paths: All API endpoints MUST be prefixed with the domain name (e.g.,
/api/v1/finance/leases,/api/v1/property/properties). - Never expose entities directly
- Use DTOs for all APIs
- Use validation annotations
- Use proper HTTP status codes
LOGGING & OBSERVABILITY
- Structured JSON logging
- Correlation ID required
- Micrometer tracing enabled
- Do NOT log:
- passwords
- tokens
- request bodies
Include in logs:
- correlationId
- traceId
- spanId
NAMING CONVENTIONS
Classes:
- UserService
- UserServiceImpl
- CreatePropertyRequest
- PropertyResponse
Avoid:
- Utils
- CommonService
- GenericManager
SECURITY RULES
- JWT-based auth
- Passwords must use BCrypt
- Never trust userId from request body
- Extract authenticated user from JWT
DATA ACCESS & PERFORMANCE RULES
- No Repository Calls in Loops: Repository methods (e.g.,
save,find,exists,delete) must NEVER be called inside loops (for,while) or lambda iteration blocks (like.forEach(),.map()).- Fetch required data in bulk outside the loop using
INqueries (e.g.,findAllByXIn()). - Cache, lookup, and associate data in-memory using Maps or Sets.
- Batch execute database modifications (e.g.,
saveAll(),deleteAll()) outside the loop.
- Fetch required data in bulk outside the loop using
- N+1 Query Avoidance: Never lazy-load relational collections in loops or iterate over parent entities fetching children one-by-one. Always use
@EntityGraph,JOIN FETCHJPQL queries (e.g.,@Query("SELECT p FROM SubscriptionPlanTbl p JOIN FETCH p.features")), or bulkINfetch queries mapped in-memory usingMap<UUID, List<T>>. - Mandatory Pagination for Dynamic Lists: Any query or endpoint returning collections that grow dynamically over time (e.g., Ledger entries, Expenses, Rent Cycles, Announcements, Audit logs) MUST implement pagination using Spring's
Pageableand returnPage<T>instead of raw lists (List<T>). - Decoupled CRUD Service Layer: Direct repository injection in high-level business services is discouraged. Abstraction interfaces (
CrudService<T, ID>) and domain CRUD services (e.g.,UserCrudService) must be used to wrap direct database repository calls.
CODE QUALITY RULES
- No commented-out code
- No dead code (remove unused interface method overloads and implementation code immediately)
- No duplicate logic
- Keep methods small and readable
- Use constructor injection only
- Code Reuse and Redundancy Check: Always inspect the codebase to verify if a utility method, mapper, conversion helper, or business function already exists before writing new code. Reuse existing structures instead of writing redundant code.
- Clean Import Styling — No Inline Imports: Fully-qualified class names (e.g.,
org.springframework.data.domain.Page,java.util.List,com.livic.core.property.dto.PropertySummaryDTO) MUST NEVER appear inline inside method signatures, field declarations, return types, or code bodies. All types, regardless of package, must be declared as top-levelimportstatements at the top of the file and referenced using their simple class names throughout the code. This rule applies universally — Spring types, JPA types, internal domain types, third-party library types, and standard Java types are all subject to this rule. Violations of this rule are treated as compile-style errors that block PR approval. - Service-DTO Decoupling & Mapper Conventions: To maintain pure business logic in service implementations, DTO-to-entity and entity-to-DTO conversion must be decoupled from the service layer and delegated to dedicated, stateless mapper utility classes.
- Mappers must follow the naming pattern
<DomainName>Mapper(e.g.,LeaseMapper) and define aprivateconstructor to prevent instantiation. - DTO-to-Entity mapping methods must be named
toEntity(...)(accepting custom type-safe arguments for contextual domain dependencies like unit/property entities). - Entity-to-DTO mapping methods must be named
toResponse(...). - Generic mapper interfaces must not be used to avoid destroying compile-time type safety for custom contextual parameters.
- Mappers must follow the naming pattern
TESTING RULES
- Every phase must:
- compile successfully
- run successfully
- expose working APIs
IMPORTANT
This project follows FAANG-grade engineering discipline.
Prioritize:
- clarity
- maintainability
- scalability
- observability
Do NOT overengineer. Do NOT introduce unnecessary abstractions.