My implementation of @PicPay using Java and Spring Framework to create a small representation of the PicPay API
Minimal, auditable clone of PicPay's P2P wallet β instant transfers with type-based rules, external authorization & notification, JWT stateless auth, JPA persistence.
Built against the official PicPay Backend Challenge Β· Interview-ready Β· Dockerized Β· Deep-documented
Quick Start Β· Architecture (Interactive) Β· Docs Hub Β· API Β· Business Rules Β· Security
- At a Glance
- Why this project?
- Quick Start β 5 min
- Tech Stack
- Architecture
- Project Structure
- API Reference
- Business Rules
- Security
- Data Model
- Configuration
- Testing
- Deployment
- Roadmap & Gaps
- Troubleshooting
- Contributing
- License
- Hosted Demo
| Dimension | Value |
|---|---|
| Language / Framework | Java 17 Β· Spring Boot 3.1.5 (Spring 6.0.13, Hibernate 6.2, Jakarta EE 10) |
| Persistence | PostgreSQL 16 (prod) / H2 (test) Β· Spring Data JPA Β· tb_users / tb_transactions |
| Auth | Spring Security 6 Β· java-jwt 4.4.0 HMAC256 Β· BCrypt Β· Stateless JWTAuthMiddleware (OncePerRequestFilter) Β· 2h expiry policy |
| API style | REST Β· MVC Β· Jackson Β· Jakarta Validation Β· springdoc-openapi 2.2.0 (Swagger UI) β remove springfox 3.0.0 duplicate |
| External | RestTemplate β HttpGateway β Authorization (GET /authorize) + Notification (POST /notify) via Mocky |
| Containers | docker-compose (api 8080 + postgres 5432 + pgAdmin 5050) Β· Paketo builder |
| Tests | JUnit 5 / Mockito / Spring Security Test β coverage ~15% β target 80% |
| Docs | README.md + 14 guides in docs/ + explorable docs/diagrams/architecture.html |
Party-mode deep audit by 6 specialists:
wilson-architectΒ·tiago-dev(java/spring) Β·carla-qaΒ·Atlas-DevOpsΒ·paige-tech-writerΒ·maria-analyst/joao-pm. All findings consolidated below & indocs/.
For Brazilians needing instant P2P value movement, who are COMMON individuals or MERCHANT shops, the PicPay Simplified is a wallet ledger API that enforces type-based invariants (merchants cannot send, balance checked, external authorization, notification), unlike generic CRUD, it encodes PicPay's core business rules as executable policies.
Out-of-scope by design (MVP): KYC, Pix, fees, limits, reversal, idempotency, multi-currency β see Roadmap.
Java 17+ Β· Maven 3.8+ Β· Docker & Docker Compose Β· Git
git clone <repo> picpay-payment && cd picpay-payment/payment
cp .env.example .env
# edit .env β set JWT_SECRET (min 32 chars), keep defaults for local
cp .env.test.example .env.test # H2 test DB
cat .env.env essentials
| Key | Example | Used by |
|---|---|---|
AUTHORIZATION_API_URL |
https://run.mocky.io/v3/9b89b419-a2f7-4885-aa86-5ddcea24d520 |
AuthorizationGatewayImpl |
NOTIFICATION_API_URL |
https://run.mocky.io/v3/54dc2cf1-β¦ |
NotificationGatewayImpl |
DATABASE_URL |
jdbc:postgresql://postgres:5432/picpay |
application.properties |
POSTGRES_USER/PASSWORD |
admin/admin |
postgres service |
JWT_SECRET |
gf928zRJbMrc6XkavpzEvuRsnOwok3f0 |
CryptographyConfig HMAC256 |
PGADMIN_DEFAULT_EMAIL/PASSWORD |
pgadmin4@pgadmin.org/admin |
pgAdmin |
docker compose up --build
# api β http://localhost:8080
# pgAdmin β http://localhost:5050 (login with PGADMIN_* from .env)
# postgres β localhost:5432
# Swagger UI β http://localhost:8080/swagger-ui/index.html (also /v3/api-docs)# set DATABASE_URL to host postgres, e.g. jdbc:postgresql://localhost:5432/picpay
./mvnw spring-boot:run
# or
mvn spring-boot:run# 1) Register (ADMIN only β bootstrap via direct DB or make first user ADMIN)
curl -s http://localhost:8080/swagger-ui/index.html | head
# 2) Login β token (2h)
curl -s -X POST http://localhost:8080/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","password":"secret123"}' | jq
# 3) Create transaction (needs EXECUTE_TRANSACTION)
TOKEN=... # from login response
curl -s -X POST http://localhost:8080/transactions \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"value":10.00,"senderId":"<UUID>","receiverId":"<UUID>"}' | jqSee docs/api.md for full curl catalog & RBAC matrix, and docs/configuration.md for profiles & env precedence.
| Dependency | Version | Purpose | Verdict |
|---|---|---|---|
spring-boot-starter-parent |
3.1.5 (Spring 6.0.13, Hibernate 6.2.9, Tomcat 10.1.15) | BOM | |
java.version |
17 | LTS | β OK, target 25 + virtual threads for Bradesco |
spring-boot-starter-web |
3.1.5 | MVC + Jackson | β |
spring-boot-starter-data-jpa |
3.1.5 | Spring Data JPA | β |
spring-boot-starter-security |
3.1.5 | FilterChain, BCrypt | β |
spring-boot-starter-validation |
3.1.5 | Jakarta Validation 3.0 | β |
postgresql |
42.5.4 (managed) | JDBC | β |
h2 |
test | In-memory tests | β |
lombok |
1.18.30 | Boilerplate | @EqualsAndHashCode(of=id) risk with mutable entities |
spring-boot-starter-test |
duplicated | JUnit5/Mockito/AssertJ | β declared twice β remove one |
com.auth0:java-jwt |
4.4.0 | HMAC256 JWT | β
works; latest 4.5.2 (4.4.0 = Mar 2023); native spring-security-oauth2-jose alternative |
io.springfox:* |
3.0.0 Γ2 | Swagger 2 | β Incompatible with Boot 3 (javax) β remove, keep springdoc |
org.springdoc:springdoc-openapi-starter-webmvc-ui |
2.2.0 | OpenAPI 3 / Swagger UI | β correct for Boot 3 |
spring-boot-devtools |
runtime optional | LiveReload | .:/picpay must not ship to prod |
RestTemplate |
β | HTTP gateway | RestClient (Spring 6.1+) + Resilience4j |
Details β docs/tech-stack.md
Style: Pseudo-hexagonal / layered hybrid. Intent: domain (pure) β application (use-cases/policies) β infra (adapters/config). Dependency leak: application.policy.auth.NotRequireAuthInWhiteListPolicyImpl imports infra.config.security.SecurityConfig.WHITE_LIST. Field injection dominates; no ports package (uses gateways/services as ports).
Quality scores (wilson-architect): Maintainability 6/10 Β· Testability 4/10 Β· Scalability ~100 TPS ceiling Β· Security 6/10. Path to Bradesco standards: Boot 4 + Java 25 + modular Flyway + @Transactional + WebClient + 80% coverage.
Host (docker-compose)
ββ api:8080 β Controllers β Services/UseCases β Policies β Gateways β JPA/Security
ββ postgres:5432 (tb_users, tb_transactions)
ββ pgadmin:5050
External: Authorization API (Mocky) & Notification API (Mocky) via HttpGateway
Interactive: docs/diagrams/architecture.html β C4 L1/L2/L3, auth & transaction sequences, ERD, lifecycle, deployment hotspots (light/dark, SVG export).
flowchart LR
A[COMMON / MERCHANT] -->|JWT Bearer| B(PicPay API<br/>Spring Boot 3.1.5)
B --> C[(PostgreSQL<br/>JPA)]
B -->|GET authorize| D[[Authorization Mocky]]
B -.->|POST notify| E[[Notification Mocky]]
style B fill:#0ea5e9,stroke:#0284c7,color:#fff
Deep dive β docs/architecture.md Β· ADRs β docs/decisions.md
payment/
ββ pom.xml # Boot 3.1.5, Java 17, deps
ββ docker-compose.yaml # api + postgres + pgadmin
ββ Dockerfile # maven:3.8-openjdk-17-slim β mvn spring-boot:run (dev)
ββ .env / .env.example / .env.test
ββ src/main/java/com/picpay/payment/
β ββ PaymentApplication.java # @SpringBootApplication
β ββ domain/ # pure: entitiesΒ·dtoΒ·repositoriesΒ·services(ports)Β·gatewaysΒ·policies(IF)
β β ββ entities/{user,transaction,auth} # User implements UserDetails; UserType COMMON/MERCHANT; Role/Permissions
β β ββ dto/{user,transaction,auth,notification,error}
β β ββ repositories/{UserRepository,TransactionRepository}
β β ββ services/{TransactionService,UserService,AuthorizationService,NotificationService, auth/*}
β β ββ gateways/{HttpGateway,AuthorizationGateway,NotificationGateway}
β β ββ policy/{transaction,auth/token,security}
β ββ application/ # orchestration: controllersΒ·services implΒ·usecasesΒ·policies impl
β β ββ controllers/{App,User,Transaction,auth/Authentication}Controller
β β ββ service/{Transaction,User,Authorization,Notification,auth/*}Impl
β β ββ usecase/{transaction,authorization,auth/*,user,notification}
β β ββ policy/{transaction,auth,security}
β ββ infra/ # adapters & config
β ββ config/{AppConfig,security/*,docs/SwaggerConfig}
β ββ gateway/{generic/HttpGatewayImpl, AuthorizationGatewayImpl, NotificationGatewayImpl}
β ββ middleware/{auth/jwt/JWTAuthMiddleware, error/ControllerExceptionHandler}
β ββ security/auditing/ApplicationAuditAware
ββ src/main/resources/application.properties # dev profile, JPA update, external URLs
ββ src/test/ ~13 files (data builders + 9 real tests)
ββ docs/ β hub + 14 guides + diagrams/architecture.html
ββ target/ (build output β ignored)
Base: http://localhost:8080 Β· Auth: Authorization: Bearer <JWT> (except whitelist) Β· Content: application/json
| Method | Path | Auth | RBAC | Body | Success | Notes |
|---|---|---|---|---|---|---|
GET |
/ |
no | permitAll |
β | 200 | Health/root (whitelisted) |
POST |
/auth/login |
no | permitAll |
LoginDTO {email,password} |
LoginResponseDTO {token} |
JWT 2h, BCrypt check |
POST |
/auth/register |
yes | CREATE_USER (ADMIN only) |
UserDTO |
User |
Encrypts password via policy |
POST |
/auth/logout |
yes | authenticated | β | 200 | SecurityContextHolder.clearContext() |
GET |
/users |
yes | hasAnyRole(USER,ADMIN) |
β | List<User> |
Paginated? No β returns all β |
POST |
/transactions |
yes | EXECUTE_TRANSACTION |
TransactionDTO {value,senderId,receiverId} |
Transaction |
5-step validate β atomic? see gaps |
GET |
/transactions |
yes | READ_TRANSACTION |
β | List<Transaction> |
|
GET |
/v3/api-docs/** etc |
no | permitAll |
β | OpenAPI JSON | Whitelisted Swagger |
DTOs
record UserDTO(@NotBlank String firstName, @NotBlank String lastName,
@NotBlank @Email String email, @NotBlank String document,
@NotNull BigDecimal balance, @NotBlank @Size(min=3) String password,
@NotNull UserType userType, @NotNull Role role) {}
record TransactionDTO(@NotNull BigDecimal value,
@NotNull UUID senderId, @NotNull UUID receiverId) {}
record LoginDTO(@Email String email, String password) {}RBAC matrix
| Permission | Role USER | Role ADMIN | Endpoint |
|---|---|---|---|
READ_USER |
β | β | GET /users (+ ROLE_USER/ADMIN) |
CREATE_USER |
β | β | POST /auth/register |
EXECUTE_TRANSACTION |
β | β | POST /transactions |
READ_TRANSACTION |
β | β | GET /transactions |
DELETE_USER etc |
β | β | (reserved) |
Whitelist (no JWT): /, /auth/login, /v3/api-docs/**, /api-docs.yaml, /swagger-resources/**, /swagger-ui/**, β¦
Curl catalog
# login
curl -X POST http://localhost:8080/auth/login -H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","password":"alice123"}'
# register (ADMIN token)
curl -X POST http://localhost:8080/auth/register \
-H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
-d '{"firstName":"Bob","lastName":"Buyer","email":"bob@example.com","document":"12345678901","balance":100.00,"password":"bob123","userType":"COMMON","role":"USER"}'
# transact (COMMON sender)
curl -X POST http://localhost:8080/transactions \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"value":25.50,"senderId":"<COMMON_UUID>","receiverId":"<MERCHANT_UUID>"}'
# list
curl http://localhost:8080/transactions -H "Authorization: Bearer $TOKEN"
curl http://localhost:8080/users -H "Authorization: Bearer $TOKEN"
curl http://localhost:8080/v3/api-docs -H "Accept: application/json" | jqSwagger UI: http://localhost:8080/swagger-ui/index.html β docs/api.md for screenshots & error table.
The API has an Authentication System that identifies the registered user based on a JWT Token and an Authorization System that defines which resources an authenticated user can access β a normal user cannot create other users, but an admin user can. User password is encrypted with BCrypt for better security.
Once authenticated, a normal user can transact an amount with others if they have enough balance; they will request an external simulated microservice to see if they can carry out the transaction. All Domain Rules are encapsulated in Policies implemented at the Application Layer. After the transaction is completed successfully, the API consults another external simulated microservice to send a notification to users informing them that everything went well.
All data passed through this microservice has validation and expected structure defined by DTOs and all documentation is done with Swagger.
In the testing environment, H2 is configured for Database instead of a dedicated PostgreSQL β H2 uses memory which is very fast, and since it is just a test, the database restarts on startup (faster, disposable, emulates real behavior).
Docker is used to set up the environment and run tests. The application image is published on GitHub with each commit to the Main Branch, automated by GitHub Actions.
Implementation enforces invariants as policies (Strategy):
| ID | Rule | Enforced by | Error | Tested? |
|---|---|---|---|---|
| R1 | Merchant users cannot send transfers; only receive | MerchantUserCantTransactPolicyImpl.execute(UserType) β checks == MERCHANT |
Exception("Merchant User is not authorized to transact") |
β MerchantUserCantTransactPolicyTest |
| R2 | Sender must have sufficient balance (balance >= value) |
CannotTransactWithoutSufficientBalancePolicyImpl.execute(User, amount) |
Exception("Balance is not enough") |
β (2 cases) |
| R3 | Transaction requires external authorization ({message: Autorizado}) |
AuthorizationService.isTransactionAuthorized() β IsAuthorizedUseCase β AuthorizationGateway.get() |
Exception("Transaction Not Authorized, try again later...") |
β mocked true-only |
| R4 | Notification fire-and-forget post-persist | SendNotificationOnTransactPolicyImpl.execute(Transaction) β NotificationGateway.post() |
swallowed (no rollback) | β assertDoesNotThrow only |
| R5 | Password encrypted before registration | EncryptPasswordBeforeRegisteringUserPolicyImpl β BCryptPasswordEncoder |
β | β |
| R6 | JWT expires in 2 hours | TokenMustExpiresInTwoHoursPolicyImpl |
β | β |
| R7 | Auth not required on whitelist | NotRequireAuthInWhiteListPolicyImpl + SecurityConfig.WHITE_LIST |
401 vs permitAll | β (leak) |
Flow (happy path): find sender β validate(R1+R2+R3) β find receiver β TransactionUseCase.execute() {sender.balance-=amount; receiver.balance+=amount} β save transaction + users β notify.
Gaps (no R): idempotency, reversal, limits/velocity, fees, audit, concurrent balance race (no
@Transactional/@Version). See docs/business-rules.md.
| Layer | Mechanism | File | Notes |
|---|---|---|---|
| AuthN | Spring Security DaoAuthenticationProvider + UserDetailsService (findByEmail) |
infra/config/AppConfig.java |
BCryptPasswordEncoder, AuthenticationManager |
| JWT | com.auth0:java-jwt 4.4.0 HMAC256, secret ${JWT_SECRET} β Algorithm bean @Lazy @Primary |
infra/config/security/CryptographyConfig.java, application/service/auth/token/JWTService.java |
2h expiry; GetTokenFromHeaderUseCase parses Authorization: Bearer |
| Filter | JWTAuthMiddleware extends OncePerRequestFilter β validate β SaveAuthContextUseCase β SecurityContextHolder |
infra/middleware/auth/jwt/JWTAuthMiddleware.java |
Skips whitelist via NotRequireAuthInWhiteListPolicy |
| AuthZ | SecurityConfig.securityFilterChain() β stateless, CSRF disabled, whitelist + method+path RBAC |
infra/config/security/SecurityConfig.java:WHITE_LIST |
hasAnyRole(USER,ADMIN), hasAuthority(EXECUTE_TRANSACTION β¦) |
| RBAC | Role.USER {READ_USER, EXECUTE_TRANSACTION, READ_TRANSACTION}; Role.ADMIN extends USER + {DELETE,CREATE,UPDATE}_USER; Permissions enum β SimpleGrantedAuthority + ROLE_* |
domain/entities/auth/Role.java, Permissions.java |
User.getAuthorities() returns both |
| Validation | Jakarta Validation on DTOs (@NotBlank @Email @Size @NotNull) + @Valid in controllers |
domain/dto/* |
No @Valid on some endpoints? audit |
| Error | ControllerExceptionHandler β ExceptionDTO |
infra/middleware/error/ControllerExceptionHandler.java |
Generic Exception β 4xx/5xx mapping incomplete |
Threats & fixes: Role stored as ORDINAL (reorder = privilege escalation) β fix @Enumerated(STRING); no rate-limit/brute-force; JWT secret from env not vault; HttpGateway has no timeout/circuit-breaker β see docs/security.md.
PostgreSQL Β· JPA/Hibernate 6 Β· ddl-auto=update (should be Flyway)
erDiagram
tb_users ||--o{ tb_transactions : "sender_id"
tb_users ||--o{ tb_transactions : "receiver_id"
tb_users {
uuid id PK "UUID random"
varchar firstName
varchar lastName
varchar email UK "UserDetails.username"
varchar password "BCrypt"
varchar document UK
numeric balance "β no precision/scale"
varchar userType "COMMON/MERCHANT STRING"
int role "β ORDINAL bug"
}
tb_transactions {
uuid id PK "AUTO (β users UUID)"
numeric amount
uuid sender_id FK
uuid receiver_id FK
timestamp createdAt "@CreatedDate"
}
User @Entity(tb_users) @Table(tb_users) id @GeneratedValue(UUID), document/email @Column(unique), userType @Enumerated(STRING), role @Enumerated (ordinal!), balance BigDecimal (no precision/scale). Transaction @Entity(tb_transactions) id AUTO, @ManyToOne sender/receiver, @CreatedDate LocalDateTime (no @Version, no idempotency).
Deep dive + migration plan β docs/data-model.md
| File | Profile | Key props |
|---|---|---|
src/main/resources/application.properties |
dev (hardcoded) |
app.security.token.secret=${JWT_SECRET}, app.external.api.authorization.url=${AUTHORIZATION_API_URL}, app.external.api.notification.url=${NOTIFICATION_API_URL}, spring.datasource.* (Postgres), hibernate.ddl-auto=update |
src/test/resources/application-test.properties |
test |
jdbc:h2:mem:picpay (overrides) |
.env |
host | real secrets (ignored) |
.env.test |
host | H2 creds |
Env precedence: Docker compose env_file: [.env,.env.test] (bug: test leaks into prod) β System env β application.properties. No application-dev/prod.yaml, no management.* actuator, no logback-spring.xml. See docs/configuration.md.
| Layer | Tests (9 real) | Coverage | Risk |
|---|---|---|---|
policy/transaction |
3 (balance, merchant, notify) | ~75% | low |
repositories |
2 (@DataJpaTest H2) |
~12% | high β only findAll()!=null etc |
service/* |
4 mocked @SpringBootTest |
~35% | medium β happy path only |
controllers / security / jwt / gateways |
0 | 0% | critical |
| Overall | ~12-18% est. | FAIL DoD 80% | REJECT |
Run: mvn test (H2) Β· No jacoco, no Testcontainers, no ArchUnit, no WireMock. PaymentApplicationTests.contextLoads() smoke only. Builders in src/test/java/data/* use non-deterministic random. See docs/testing.md for P0/P1 plan (@WebMvcTest + MockMvc + WireMock + Testcontainers + Jacoco gate).
docker compose up --build # api 8080 / postgres 5432 / pgadmin 5050
# production hardening (P0):
# - pin postgres:16-alpine (not :latest), remove version: header, fix env_file split,
# - add .dockerignore, healthcheck, multistage Dockerfile, actuator /health
# - ignore .docker/postgres, set JWT_SECRET via vault.github/workflows/docker-publish.yml builds GHCR image + cosign sign β not a CI gate. Missing: tests β build β scan β deploy, SBOM, Trivy. See docs/deployment.md for compose fixes & GitHub Actions sketch.
| Priority | Gap | Fix | Doc |
|---|---|---|---|
| P0 | No @Transactional on transact() β partial commit |
Add @Transactional + @Version optimistic lock |
architecture.md |
| P0 | springfox 3.0.0 classpath clash |
Remove, keep springdoc 2.2.0 |
tech-stack.md |
| P0 | Role ORDINAL privilege escalation |
@Enumerated(STRING) + Flyway V2 |
data-model.md |
| P0 | Coverage 15% < 80% gate | MockMvc + WireMock + Jacoco gate |
testing.md |
| P0 | Compose env_file leak + postgres:latest + .docker/postgres tracked |
Fix compose, .dockerignore, .gitignore |
deployment.md |
| P1 | ddl-auto=update in prod |
Flyway V1__init.sql |
data-model.md |
| P1 | No idempotency / double-spend race | idempotencyKey + DB constraint |
business-rules.md |
| P1 | RestTemplate no timeout/retry/circuit |
RestClient + Resilience4j |
tech-stack.md |
| P2 | Boot 3.1.5 EOL + Java 17 | Boot 3.4.x β 4.x, Java 25 virtual threads | decisions.md |
| P2 | No actuator/metrics/logs/rate-limit | spring-boot-starter-actuator + Micrometer |
configuration.md |
Full ADRs (5) β docs/decisions.md Β· Full quality heatmap β docs/code-quality.md
| Symptom | Cause | Fix |
|---|---|---|
FieldNotFound on startup swagger |
springfox + Boot 3 javaxβjakarta |
Remove springfox deps, keep springdoc |
invalid secret / 401 always |
JWT_SECRET not set or < 32 chars |
echo $JWT_SECRET in container; regenerate |
Connection refused to postgres |
Compose health race | depends_on has no healthcheck β docker compose logs postgres, add healthcheck: pg_isready |
| H2 test passes, prod fails | ddl-auto=update drift |
mvn flyway:info, add V1 |
| Balance negative after concurrent tx | No locking | Add @Version + retry, or SELECT FOR UPDATE |
| PGDATA committed to git | .docker/postgres tracked |
git rm -r --cached .docker/postgres, add to .gitignore |
| Build bloat | Duplicate spring-boot-starter-test |
Remove second declaration |
More β docs/deployment.md#troubleshooting & docs/development.md
Branch β commit (feat:/fix:) β mvn verify (once Jacoco gated) β PR checklist (tests + docs + OpenAPI) β review.
See docs/development.md for style (Lombok, MapStruct from() anti-BeanUtils, constructor injection), hooks, and PR template. LICENSE = MIT.
| Guide | Path |
|---|---|
| Hub | docs/README.md |
| Architecture | docs/architecture.md |
| Tech Stack | docs/tech-stack.md |
| Domain | docs/domain.md |
| API | docs/api.md |
| Security | docs/security.md |
| Business Rules | docs/business-rules.md |
| Data Model | docs/data-model.md |
| Configuration | docs/configuration.md |
| Deployment | docs/deployment.md |
| Development | docs/development.md |
| Testing | docs/testing.md |
| Code Quality | docs/code-quality.md |
| Decisions (ADRs) | docs/decisions.md |
| Interactive Diagrams | docs/diagrams/architecture.html |
π‘ Hosted on Render: https://pic-pay.onrender.com/
π Documentation (Swagger UI): https://pic-pay.onrender.com/swagger-ui/index.html
Generated 2026-08-31 Β· Stack: Java 17 Β· Spring Boot 3.1.5 Β· PostgreSQL Β· JWT HMAC256 Β· JPA Β· Docker Β· springdoc Β· Deep audit (party-mode: 6 specialists) Β· Economy OFF for docs
