From 74a5b2c9e377cd2afe7f42fede2dea293fa5b203 Mon Sep 17 00:00:00 2001 From: DJAngel973 <189556164+DJAngel973@users.noreply.github.com> Date: Thu, 15 Oct 2026 20:58:39 -0500 Subject: [PATCH 1/3] update gitignore --- .gitignore | 4 +++- src/main/java/com/wallet/secure/user/dto/RegisterRequest.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d82e68e..c4a67e2 100644 --- a/.gitignore +++ b/.gitignore @@ -112,4 +112,6 @@ yarn-error.log* # Virtual environments (if using Python for scripts) venv/ -.venv/ \ No newline at end of file +.venv/ + +QA.md diff --git a/src/main/java/com/wallet/secure/user/dto/RegisterRequest.java b/src/main/java/com/wallet/secure/user/dto/RegisterRequest.java index 37a15dc..9f7962b 100644 --- a/src/main/java/com/wallet/secure/user/dto/RegisterRequest.java +++ b/src/main/java/com/wallet/secure/user/dto/RegisterRequest.java @@ -31,7 +31,7 @@ public class RegisterRequest { * OWASP A07: enforce strong password policy at API entry point. */ @NotBlank(message = "Password is required") - @Size(min = 12, max = 72, message = "Password must be between 8 and 72 characters") + @Size(min = 12, max = 72, message = "Password must be between 12 and 72 characters") @Pattern( regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&_.#^])[A-Za-z\\d@$!%*?&_.#^]{12,}$", message = "Password must contain uppercase, lowercase, number and special character" From 7ac4af01fc903d0f4b6fb03bb288f8025b21b045 Mon Sep 17 00:00:00 2001 From: DJAngel973 <189556164+DJAngel973@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:51:38 -0500 Subject: [PATCH 2/3] docs: align README with implementation project --- README.md | 287 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 178 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index 9a87d9b..82e1db5 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,104 @@ # Secure Wallet API -Multi-currency digital savings wallet — REST API with authentication, transactions, and audit trail. +Educational-professional REST API for a simulated multi-currency savings wallet, with an emphasis on applied security, traceability, and DevSecOps practices. Built with **Java 17**, **Spring Boot 3.4.2**, and **PostgreSQL 16**. -> This is a learning project built with AI assistance to explore how a savings wallet API works under the hood — authentication flows, ACID financial transactions, audit logging, and security practices. Some sections still need review and polish. +> This project is designed for local learning and portfolio demonstration. All balances and operations are simulated: it does not process real money and is not intended for public production deployment. +> +> The project is under active development. Confirmed requirements, detected defects, pending decisions, and verification work are tracked in [`docs/IMPLEMENTATION-PLAN.md`](docs/IMPLEMENTATION-PLAN.md). --- ## What is this -A REST API for a digital savings wallet where users can: +Secure Wallet API explores how the main components of a savings-wallet backend work together: -- Register and manage their profile -- Create savings wallets in multiple currencies (USD, EUR, COP, MXN, ARS) -- Deposit, withdraw, and transfer funds between wallets -- Track authentication, wallet, and transaction events through an audit trail -- Authenticate with access and refresh JWT tokens +- User registration and profile management +- Savings wallets in USD, EUR, COP, MXN, and ARS +- Simulated deposits, withdrawals, and transfers +- JWT authentication with access and refresh tokens +- Role- and ownership-based authorization +- Security and transaction audit trails +- PostgreSQL constraints and ACID transaction boundaries +- Automated build, test, dependency scanning, and static analysis workflows -The idea came from wanting to understand the moving parts of a real savings wallet — not just the happy path, but edge cases, concurrency, token rotation, and what happens when things go wrong. +The goal is to study both successful flows and failure scenarios: unauthorized access, invalid tokens, insufficient balances, concurrent updates, session revocation, and auditability. --- -## Features +## Feature status + +Status labels used below: + +- **Implemented** — code for the capability exists. +- **Verified** — automated or documented functional evidence exists. +- **Partial** — some parts exist, but the complete requirement is not yet satisfied or verified. +- **Planned** — confirmed requirement or candidate decision that has not been fully implemented. ### User Management -- Registration, profile updates, and soft-delete accounts -- Role-based access: `USER`, `ADMIN`, `MANAGER` -- Account lockout after repeated failed login attempts + +- **Implemented:** public registration creates `USER` accounts; profile read/update and soft deactivation are available. +- **Implemented:** the target business roles are `USER` and `ADMIN`; privileged access uses Spring Security method authorization. +- **Planned:** the first `ADMIN` will be created through a controlled one-time bootstrap without public default credentials. +- **Planned:** administrators will manage regular users but will not create other administrators through the public API. +- **Partial:** account-state and failed-login controls exist in the model, but the complete lockout flow still requires correction and functional verification. ### Multi-Currency Savings Wallets -- One wallet per user per currency -- Supported currencies: USD, EUR, COP, MXN, ARS -- Wallet states: `ACTIVE`, `SUSPENDED`, `CLOSED` -- Balance updates with pessimistic locking + +- **Implemented:** one wallet per user and currency. +- **Implemented:** USD, EUR, COP, MXN, and ARS currencies. +- **Implemented:** `ACTIVE`, `SUSPENDED`, and `CLOSED` wallet states. +- **Partial:** ownership and administrative wallet operations are implemented but still require complete authorization tests. ### Financial Transactions -| Operation | Description | -|-----------|-------------| -| Deposit | Add funds from an external source | -| Withdrawal | Move funds out to an external destination | -| Transfer | Move funds between two wallets in the system | -| History | State-change log per transaction | -- Pessimistic locking on balance reads to prevent race conditions -- Unique reference code per transaction +| Operation | Description | Status | +|-----------|-------------|--------| +| Deposit | Add simulated external funds to a wallet | Implemented | +| Withdrawal | Remove simulated funds from a wallet | Implemented | +| Transfer | Move simulated funds between wallets | Implemented | +| History | Read transaction state changes | Implemented | + +- **Implemented:** `BigDecimal`/`DECIMAL(19,4)` amounts, transactional service boundaries, reference codes, and pessimistic balance locking. +- **Partial:** concurrency, rollback, ownership, and complete audit behavior require PostgreSQL-backed and Postman verification. +- **Pending decision:** configurable transaction limits and thresholds must be reviewed before full implementation. ### Authentication & Security -- Dual-token JWT: Access Token (short-lived) + Refresh Token (longer-lived with rotation) -- Refresh token stored as SHA-256 hash — real revocation on logout -- UUID primary keys on all entities (no sequential IDs) -- The default configuration prevents stack traces and internal exception details from reaching clients -- Input validation on every endpoint + +- **Implemented:** short-lived access JWTs and longer-lived refresh JWTs. +- **Implemented:** JWT signature, expiration, issuer, and token-type validation. +- **Implemented:** BCrypt password hashing and Spring Security authentication. +- **Implemented:** refresh-session tracking and revocation support. +- **Partial:** refresh-token rotation and removal of legacy raw-token storage remain required. +- **Partial:** disabled or locked accounts must be rejected consistently during both login and JWT-authenticated requests. +- **Pending decision:** TOTP-based 2FA requires a separate design review before full implementation. ### Audit Trail -- Every sensitive operation generates a log entry -- IP address, User-Agent, timestamp, and contextual details per event -- Database triggers for automatic state-change tracking + +- **Implemented:** authentication, wallet, transaction, and account events have audit-writing support. +- **Implemented:** audit entries can include user, IP address, User-Agent, timestamp, severity, and contextual JSON details. +- **Partial:** complete event coverage and failure resilience still require end-to-end verification. --- ## Architecture -**Pattern:** Domain-Driven Design — code organized by business domain, not by layer type. +**Pattern:** domain-oriented layered architecture inspired by Domain-Driven Design. Code is grouped by business domain rather than by global technical layer. -``` +```text com.wallet.secure/ -├── config/ # SecurityConfig, OpenApiConfig, AuditConfig, JwtConfig -├── auth/ # Authentication: JWT, 2FA, sessions +├── config/ # Security, JWT, OpenAPI, and audit configuration +├── auth/ # Authentication, JWT validation, and sessions │ ├── controller/, dto/, entity/, repository/, security/, service/ ├── user/ # Users and profiles -├── wallet/ # Wallets and balances -├── transaction/ # Transactions and history (business core) -├── audit/ # Security audit log -└── common/ # ApiResponse, exceptions, enums, validators +├── wallet/ # Wallet ownership, balances, and lifecycle +├── transaction/ # Financial operations and state history +├── audit/ # Security and business audit trail +└── common/ # Shared responses, exceptions, enums, and utilities ``` -Each domain owns its controllers, DTOs, entities, repositories, and services. Nothing lives at the root level grouped by type. +Each domain owns its controllers, DTOs, entities, repositories, and services. Controllers handle HTTP concerns, services enforce business rules, repositories provide persistence access, and DTOs limit the data accepted from or returned to clients. --- @@ -87,22 +109,29 @@ Each domain owns its controllers, DTOs, entities, repositories, and services. No | Language | Java 17 | | Framework | Spring Boot 3.4.2 | | Security | Spring Security + jjwt 0.12.6 | -| Database | PostgreSQL 16 (Docker) | +| Database | PostgreSQL 16 | | ORM | Spring Data JPA / Hibernate | -| Logging | Log4j2 | +| Logging | Log4j2 2.25.3 | | Validation | Spring Bean Validation | -| API Docs | SpringDoc OpenAPI 2.8.8 (Swagger) | -| Boilerplate | Lombok | -| Tests | JUnit 5 + Mockito + AssertJ | -| CI/CD | GitHub Actions + CodeQL + OWASP Dependency Check | +| API Docs | SpringDoc OpenAPI 2.8.8 | +| Boilerplate | Lombok 1.18.36 | +| Tests | JUnit 5 + Mockito + AssertJ + H2 security integration test | +| DevSecOps | GitHub Actions + CodeQL + OWASP Dependency Check | +| Local runtime | Docker Compose | --- -## Getting Started +## Getting Started with Docker Compose + +Docker Compose is the primary way to run the complete local environment: PostgreSQL and the Spring Boot API. ### Prerequisites -- Java 17+ -- Docker and Docker Compose + +- Docker Engine or Docker Desktop +- Docker Compose v2 +- Git + +Java and Maven are not required to run the packaged application through Docker Compose. Java 17 is required for local development and for running Maven tests outside the containers. ### Setup @@ -110,99 +139,138 @@ Each domain owns its controllers, DTOs, entities, repositories, and services. No git clone https://github.com/DJAngel973/Secure-Wallet-API.git cd Secure-Wallet-API -# Copy and fill in the environment variables +# Create the local, untracked environment file cp .env.example .env -# Start PostgreSQL -docker compose up -d +# Replace every CHANGE_ME value and configure FILE_DATA_POSTGRES + +# Build and start PostgreSQL and the API +docker compose up -d --build + +# Confirm container health and startup status +docker compose ps + +# Follow API logs when troubleshooting startup +docker compose logs -f wallet-api +``` + +The API is available at `http://localhost:8080` unless `SERVER_PORT` is changed in `.env`. + +> PostgreSQL executes files mounted under `docker-entrypoint-initdb.d` only when initializing an empty data directory. The current development seed is tracked as a remediation item because public default administrative credentials must not be part of the standard initialization path. -# Run the application (dev profile) -./mvnw spring-boot:run -Dspring-boot.run.profiles=dev +### Stop the environment + +```bash +docker compose down ``` -### Run tests +This does not delete the configured PostgreSQL data directory. + +### Run automated tests ```bash -./mvnw test # Complete automated test suite -./mvnw test -Dtest=TransactionServiceTest # Single test class +./mvnw test +./mvnw test -Dtest=TransactionServiceTest ``` -The suite contains Mockito unit tests for the business services and a small Spring Security integration test using H2. PostgreSQL is not required to run the test suite. +The current suite primarily contains Mockito unit tests plus a small Spring Security integration test using H2. It does not yet prove complete PostgreSQL or HTTP end-to-end behavior. + +### Explore with Postman + +Postman is the primary tool for demonstrating complete local API flows. The planned functional verification covers: -### Interactive API docs +1. Register and login as a regular user. +2. Store the access and refresh tokens as environment variables. +3. Send `Authorization: Bearer ` to protected endpoints. +4. Create wallets and perform simulated deposits, withdrawals, and transfers. +5. Verify ownership failures, insufficient-balance failures, refresh, logout, and session revocation. +6. Use a controlled bootstrap administrator to verify `USER` versus `ADMIN` authorization. -Once running: [http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html) +A versioned Postman collection is planned and tracked in the implementation plan. -All responses follow a standard wrapper: +### Interactive API documentation + +Swagger UI is available locally at: + +[http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html) + +All API responses use a standard wrapper: ```json { "success": true, "message": "Operation completed", - "data": { } + "data": {} } ``` --- -**Note:** endpoints listed in Features above have not been tested end-to-end yet. The Swagger UI at `http://localhost:8080/swagger-ui/index.html` lists all available endpoints for exploration when the app is running. - ---- - ## Database -PostgreSQL 16 with schema managed through numbered SQL scripts. The default published configuration uses `ddl-auto: validate`, so Hibernate validates the schema without creating or modifying it. +PostgreSQL 16 is managed through numbered SQL scripts. The published application configuration uses `ddl-auto: validate`, so Hibernate validates the schema instead of creating or updating it. -| # | Script | Purpose | -|---|--------|---------| -| 01 | `extensions.sql` | PostgreSQL extensions (pgcrypto, uuid-ossp) | -| 02 | `types.sql` | Custom ENUMs (roles, currencies, statuses) | -| 03 | `tables.sql` | Core tables with constraints and foreign keys | -| 04 | `index.sql` | Partial, composite, and GIN indexes | -| 05 | `triggers.sql` | Auto-timestamps, balance validation, state-change audit | -| 06 | `functions.sql` | `process_transaction()` with ACID guarantees | -| 07 | `seed.sql` | Development test data | -| 08 | `migrations.sql` | Incremental schema changes | +| # | Script | Purpose | Current status | +|---|--------|---------|----------------| +| 01 | `extensions.sql` | PostgreSQL extensions | Implemented | +| 02 | `types.sql` | Roles, currencies, and status enums | Implemented | +| 03 | `tables.sql` | Tables, constraints, and foreign keys | Implemented | +| 04 | `index.sql` | Partial, composite, and GIN indexes | Implemented | +| 05 | `triggers.sql` | Timestamp, balance, and history triggers | Implemented | +| 06 | `functions.sql` | Database transaction-processing functions | Implemented | +| 07 | `seed.sql` | Current development-only test data | Must be separated from automatic initialization | +| 08 | `migrations.sql` | Incremental schema changes | Implemented | + +The database schema is part of the security boundary: unique constraints, ownership relationships, non-negative balances, transaction consistency, and append-oriented audit/history records complement application-layer validation. --- -## OWASP Top 10 (2025) coverage +## OWASP Top 10:2025 alignment + +OWASP Top 10 is used as an awareness and review framework, not as a certification that every risk has been eliminated. -This project uses the OWASP Top 10 as a guide for security decisions. Here is what is currently addressed: +| Category | Current project alignment | Status | +|----------|---------------------------|--------| +| A01 — Broken Access Control | JWT-derived identity, role checks, ownership-aware repository queries, and non-enumerating `404` patterns | Partial — broader authorization tests required | +| A02 — Security Misconfiguration | Environment-based secrets, controlled error responses, container hardening, and restricted published Actuator exposure | Partial — development settings and seed initialization require review | +| A03 — Software Supply Chain Failures | Pinned key dependency versions, OWASP Dependency Check, and CodeQL workflows | Implemented; scan results remain environment-dependent | +| A04 — Cryptographic Failures | BCrypt passwords, signed JWTs, short access-token lifetime, and hashed session tokens | Partial — legacy raw refresh-token storage must be removed | +| A05 — Injection | DTO validation plus parameterized persistence through Spring Data JPA/Hibernate | Implemented; complete endpoint verification pending | +| A06 — Insecure Design | Transaction boundaries, pessimistic locking, database constraints, audit design, and documented threat decisions | Partial — configurable limits and TOTP remain pending decisions | +| A07 — Authentication Failures | Dual-token authentication, account-state modeling, session revocation, and authentication auditing | Partial — rotation, lockout, and account-state enforcement require correction and tests | +| A08 — Software or Data Integrity Failures | Versioned SQL, CI analysis, controlled schema validation, and transaction-history records | Partial — release and integration verification can be expanded | +| A09 — Security Logging & Alerting Failures | Database audit events, severity levels, IP/User-Agent context, and fallback logging design | Partial — coverage and alert behavior require functional verification | +| A10 — Mishandling of Exceptional Conditions | Centralized exception handling and transactional rollback boundaries | Partial — HTTP failure paths require end-to-end verification | -| # | Risk | How it is handled | -|---|------|-------------------| -| A01 | Broken Access Control | `userId` always from JWT — never from request body. `404` on ownership mismatch. RBAC via Spring Security. | -| A02 | Cryptographic Failures | BCrypt strength 12 for passwords. SHA-256 for token hashing. `DECIMAL(19,4)` for amounts. | -| A03 | Software Supply Chain Failures | OWASP Dependency Check in CI. Pinned dependency versions. | -| A04 | Injection | Hibernate prepared statements. Bean Validation on all inputs. | -| A05 | Security Misconfiguration | No internals exposed in errors. No default credentials. Secure headers. | -| A06 | Insecure Design | Transaction and daily limits. 2FA threshold. Pessimistic locking on balance reads. | -| A07 | Auth Failures | Dual-token JWT with rotation. Account lockout. TOTP 2FA. | -| A08 | Data Integrity Failures | CodeQL in CI. SQL scripts versioned in Git. `ddl-auto: validate`. | -| A09 | Logging & Monitoring | All security events written to `audit_logs`. No passwords or tokens in logs. | -| A10 | Mishandled Exceptions | Centralized exception handler. Never "fail open". | +See [`SECURITY.md`](SECURITY.md) for the threat model. Where that document describes a target control not yet verified, the implementation plan is the authoritative status tracker. --- ## CI/CD -| Job | When | What | -|-----|------|------| -| Build & Test | Push to `main` / PR targeting `main` | Compile and run the automated test suite | -| OWASP Dependency Check | Push to `main` / PR targeting `main` | Scan dependencies for known vulnerabilities | -| CodeQL Analysis | Push to `main`, PR targeting `main`, and weekly | Static security analysis | -| Package | Push to `main` | Generate and upload the application JAR | +| Job | Trigger | Purpose | Status | +|-----|---------|---------|--------| +| Build & Test | Push to `main` / PR targeting `main` | Compile and run automated tests | Implemented | +| OWASP Dependency Check | Push to `main` / PR targeting `main` | Scan dependencies for known vulnerabilities | Implemented | +| CodeQL Analysis | Push/PR to `main` and weekly schedule | Static security analysis | Implemented | +| Package | Push to `main` after prior jobs | Generate and upload the application JAR | Implemented | + +These workflows provide automated evidence, but passing CI does not replace functional security testing or a production-readiness assessment. --- -## Future plans +## Roadmap and implementation status + +The prioritized remediation and verification plan is maintained in: + +[`docs/IMPLEMENTATION-PLAN.md`](docs/IMPLEMENTATION-PLAN.md) + +The plan distinguishes: -- Review and test all endpoints end-to-end -- Polish existing code sections marked for improvement -- Postman collection for easier API exploration -- TOTP-based two-factor authentication for high-value transactions -- Enforcement of configurable per-transaction and daily limits +- Confirmed architectural requirements +- Detected implementation defects +- Decisions that require further review +- Automated and Postman acceptance evidence --- @@ -210,10 +278,11 @@ This project uses the OWASP Top 10 as a guide for security decisions. Here is wh | Document | What it covers | |----------|---------------| -| [`CONTEXT.md`](CONTEXT.md) | Architecture, conventions, full stack details | -| [`DECISIONS.md`](DECISIONS.md) | 8 Architecture Decision Records with reasoning | -| [`SECURITY.md`](SECURITY.md) | Threat model and security decisions in depth | -| [`database/README.md`](database/README.md) | ER diagram, foreign key rules, DB design | +| [`docs/IMPLEMENTATION-PLAN.md`](docs/IMPLEMENTATION-PLAN.md) | Prioritized remediation, implementation, and verification work | +| [`CONTEXT.md`](CONTEXT.md) | Architecture, conventions, and stack context | +| [`DECISIONS.md`](DECISIONS.md) | Architecture Decision Records and rationale | +| [`SECURITY.md`](SECURITY.md) | Threat model and target security controls | +| [`database/README.md`](database/README.md) | Database model, constraints, and local setup | --- From 8e7b85de071f78b422d17b50a56e9b4de10dad6e Mon Sep 17 00:00:00 2001 From: DJAngel973 <189556164+DJAngel973@users.noreply.github.com> Date: Fri, 16 Oct 2026 23:14:50 -0500 Subject: [PATCH 3/3] docs: add the implementation plan file to refine and finalize the project's safety steps --- docs/IMPLEMENTATION-PLAN.md | 552 ++++++++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 docs/IMPLEMENTATION-PLAN.md diff --git a/docs/IMPLEMENTATION-PLAN.md b/docs/IMPLEMENTATION-PLAN.md new file mode 100644 index 0000000..7854d2a --- /dev/null +++ b/docs/IMPLEMENTATION-PLAN.md @@ -0,0 +1,552 @@ +# Secure Wallet API — Implementation Plan + +This plan records the work required to align the implementation, tests, and documentation with the confirmed architecture of Secure Wallet API. An item listed here is not evidence that the behavior is already implemented. + +## Scope and status model + +Secure Wallet API is an educational-professional backend for a simulated multi-currency savings wallet. It runs locally through Docker Compose and demonstrates its HTTP flows primarily with Postman. It does not process real money and is not intended for public production deployment. + +| Label | Meaning | +|-------|---------| +| **Confirmed requirement** | Approved target behavior that implementation must satisfy | +| **Detected defect** | Current behavior contradicts an approved requirement or security expectation | +| **Pending decision** | Design must be confirmed before implementation | + +Priorities: + +- **P0 — Security blocker:** resolve before treating the related control as functional. +- **P1 — Core correctness:** required for reliable authorization, transactions, or evidence. +- **P2 — Verification/documentation:** required for repeatable demonstration and accurate claims. +- **P3 — Future design:** intentionally deferred until its requirements are approved. + +## Dependency order + +```text +Development seed separation + ↓ +First-admin bootstrap + ↓ +Administrative user management + +Session storage cleanup + ↓ +Refresh-token rotation + ↓ +Session and JWT functional tests + +Account lockout correction + ↓ +JWT account-state enforcement + ↓ +Authentication security tests + +Wallet ownership review + ↓ +Transaction/concurrency/audit verification + ↓ +Postman critical-flow collection +``` + +--- + +## P0 — Security blockers + +### SEC-001 — Separate development seed data from automatic initialization + +**Classification:** Detected defect +**Priority:** P0 +**Depends on:** None + +**Current problem** + +`database/07-seed.sql` creates an administrator with publicly know credentials during PostgreSQL initialization. + +**Expected behavior** + +- Remove 07-seed.sql if no application or test dependency requirest it. +- Configure Docker Compose to initialize only the required database schema. +- Do not create default users or administrators during SQL initialization. +- Keep Docker Compose as the primary way to start PostgreSQL and Spring Boot. + +**Acceptance criteria** + +- [ ] No default administrator is created by SQL initialization. +- [ ] No public administrator password remains in the repository's current tracked files. +- [ ] PostgreSQL initializes correctly using Docker Compose. +- [ ] Existing tests continue to pass. + +### SEC-002 — Add controlled one-time bootstrap for the first administrator + +**Classification:** Confirmed requirement +**Priority:** P0 +**Depends on:** SEC-001 + +**Current problem** + +The first administrator is currently supplied only by the public development seed. No controlled bootstrap exists. + +**Expected behavior** + +- The first `ADMIN` is created exactly once through a controlled bootstrap. +- Bootstrap credentials come from an untracked environment or secret input and are never logged. +- Public registration always creates `USER`. +- The bootstrap refuses to create additional administrators after the first valid administrator exists. + +**Possibly affected files** + +- New bootstrap component under the `auth` or `user` domain +- `UserRepository.java` +- Security configuration properties +- `.env.example` +- Bootstrap unit/integration tests +- Docker environment wiring + +**Acceptance criteria** + +- [ ] First startup with valid bootstrap input creates one BCrypt-hashed `ADMIN`. +- [ ] A second startup creates no additional administrator and changes no existing credentials. +- [ ] Missing or invalid bootstrap input fails safely without exposing secrets. +- [ ] Bootstrap secrets are absent from logs, API responses, Git history, and persisted configuration. +- [ ] `POST /auth/register` cannot create an `ADMIN`, including when the JSON includes a `role` field. + +### SEC-003 — Remove original refresh-token storage from the user record + +**Classification:** Detected defect +**Priority:** P0 +**Depends on:** None + +**Current problem** + +`SessionService` stores a SHA-256 token hash in `user_sessions`, but `AuthService` also assigns the original refresh JWT to `User.refreshToken`. This contradicts the requirement that reusable tokens are not stored directly. + +**Expected behavior** + +- Only a non-reusable token identifier or approved one-way representation is persisted. +- Refresh validation and revocation use the session model as the single source of truth. +- Database disclosure does not expose a directly reusable refresh token. + +**Possibly affected files** + +- `AuthService.java` +- `User.java` +- `SessionService.java` +- `SessionRepository.java` +- `database/03-tables.sql` +- `database/08-migrations.sql` +- Authentication/session tests + +**Acceptance criteria** + +- [ ] No database column stores the original refresh JWT. +- [ ] Login, refresh, logout, single-session revocation, and all-session revocation still work. +- [ ] Tests prove that a stored session value cannot be sent as a refresh token. +- [ ] Schema migration preserves or explicitly invalidates existing sessions safely. + +### SEC-004 — Implement and verify refresh-token rotation + +**Classification:** Confirmed requirement +**Priority:** P0 +**Depends on:** SEC-003 + +**Current problem** + +The refresh endpoint issues only a new access token and keeps the same refresh token. Reuse detection and atomic rotation are not implemented. + +**Expected behavior** + +- Every successful refresh returns a new access token and a new refresh token. +- The previous refresh token is invalidated atomically. +- Reuse of an already-rotated token is rejected and produces an auditable security event. +- Concurrent refresh attempts cannot both succeed with the same token. + +**Possibly affected files** + +- `AuthService.java` +- `SessionService.java` +- `Session.java` +- `SessionRepository.java` +- `AuthResponse.java` +- Authentication/session tests +- Database indexes or migration if token-family tracking is selected + +**Acceptance criteria** + +- [ ] A successful refresh returns two new tokens. +- [ ] The previous refresh token fails immediately afterward. +- [ ] Exactly one of two concurrent refresh requests with the same token succeeds. +- [ ] Rotation and reuse failures create audit evidence without logging token values. +- [ ] Logout revokes the current rotated session. + +### SEC-005 — Correct failed-login lockout + +**Classification:** Detected defect +**Priority:** P0 +**Depends on:** None + +**Current problem** + +Failed login events are audited, but the authentication flow does not demonstrably call repository operations that increment attempts and set `lockedUntil`. Values also conflict: application configuration states five attempts while the database constrains the counter to three. + +**Expected behavior** + +- One authoritative, configurable threshold and lock duration are used. +- Failed attempts are incremented atomically. +- Reaching the threshold locks the account for the configured duration. +- A successful login resets the counter. +- Unknown-email and wrong-password responses remain non-enumerating. + +**Possibly affected files** + +- `AuthService.java` +- `UserRepository.java` +- `User.java` +- Security configuration properties +- `application.yml` +- `database/03-tables.sql` +- `database/08-migrations.sql` +- `GlobalExceptionHandler.java` +- Authentication tests + +**Acceptance criteria** + +- [ ] The configured number of consecutive failures locks the account. +- [ ] PostgreSQL accepts every valid counter state under the selected policy. +- [ ] A correct password during the lock period cannot authenticate. +- [ ] Authentication succeeds after expiry according to the chosen unlock policy. +- [ ] Success resets failed attempts to zero. +- [ ] Unit and PostgreSQL-backed tests cover boundary and concurrency cases. + +### SEC-006 — Reject JWT authentication for disabled or locked accounts + +**Classification:** Detected defect +**Priority:** P0 +**Depends on:** SEC-005 + +**Current problem** + +Password authentication maps active/locked state into Spring Security. During access-token authentication, however, `JwtAuthFilter` constructs an authenticated token after loading `UserDetails` without explicitly rejecting disabled or locked state. + +**Expected behavior** + +- Disabled or locked users cannot establish a `SecurityContext`, even with an unexpired access token. +- Account deactivation and administrative suspension revoke relevant refresh sessions. +- Response behavior is consistent and does not expose sensitive account details. + +**Possibly affected files** + +- `JwtAuthFilter.java` +- `UserDetailsServiceImpl.java` +- `UserService.java` +- `SessionService.java` +- Security integration tests + +**Acceptance criteria** + +- [ ] An existing access token fails after its user is disabled. +- [ ] An existing access token fails while its user is locked. +- [ ] Disabling an account revokes all refresh sessions. +- [ ] Active, unlocked users continue to authenticate normally. + +--- + +## P1 — Authorization and financial correctness + +### AUTHZ-001 — Implement controlled management of regular users + +**Classification:** Confirmed requirement +**Priority:** P1 +**Depends on:** SEC-002, SEC-006 + +**Current problem** + +Administrative read/deactivation operations exist, but there is no consolidated and verified administrative user-management contract. The confirmed model allows an administrator to manage regular users but not create or promote other administrators through the API. + +**Expected behavior** + +- `ADMIN` can perform explicitly approved management operations on `USER` accounts. +- `USER` cannot invoke administrative operations. +- No public or administrative API operation creates, promotes, or modifies another `ADMIN`. +- Every administrative action is audited with actor and target identifiers. + +**Possibly affected files** + +- `UserController.java` +- `UserService.java` +- User administration DTOs if approved +- `SecurityConfig.java` +- `AuditService.java` +- Authorization tests + +**Acceptance criteria** + +- [ ] `USER` receives `403` for every administrative endpoint. +- [ ] `ADMIN` can manage only operations explicitly allowed for regular users. +- [ ] API requests containing privileged role changes are rejected or ignored safely and never persisted. +- [ ] No API route can create or promote another administrator. +- [ ] Administrative actions produce immutable audit records. + +### AUTHZ-002 — Review wallet permissions and ownership + +**Classification:** Confirmed requirement +**Priority:** P1 +**Depends on:** AUTHZ-001 + +**Current problem** + +Wallet controllers derive identity from the JWT and services include ownership patterns, but complete endpoint-by-endpoint authorization evidence is missing. + +**Expected behavior** + +- Users can read and operate only their own wallets. +- Ownership mismatches use non-enumerating responses where appropriate. +- Administrative wallet lifecycle operations require `ADMIN` and are audited. +- Request bodies cannot override the authenticated owner. + +**Possibly affected files** + +- `WalletController.java` +- `WalletService.java` +- `WalletRepository.java` +- Wallet DTOs +- `SecurityConfig.java` +- Wallet authorization tests + +**Acceptance criteria** + +- [ ] User A cannot read, debit, close, suspend, or restore User B's wallet. +- [ ] User-controlled input cannot assign a wallet to a different owner. +- [ ] Administrative actions require `ROLE_ADMIN` and generate audit records. +- [ ] Automated tests cover every wallet endpoint with owner, non-owner, anonymous, and admin actors. + +### TX-001 — Verify transactions, concurrency, rollback, and audit behavior + +**Classification:** Confirmed requirement +**Priority:** P1 +**Depends on:** AUTHZ-002 + +**Current problem** + +Transaction services use transactional boundaries and pessimistic locking, but unit tests do not prove real PostgreSQL locking, concurrent updates, trigger behavior, or complete rollback/audit semantics. + +**Expected behavior** + +- Deposits, withdrawals, and transfers preserve financial invariants. +- Concurrent requests cannot lose updates, create negative balances, or double-spend. +- Failed operations leave balances unchanged. +- Ownership, currency, wallet state, and reference-code rules are enforced. +- Success and failure paths create the required audit/history evidence. + +**Possibly affected files** + +- `TransactionService.java` +- `TransactionRepository.java` +- `WalletRepository.java` +- `TransactionHistoryService.java` +- `AuditService.java` +- Transaction and wallet entities +- Database functions, triggers, and migrations if defects are confirmed +- PostgreSQL integration tests + +**Acceptance criteria** + +- [ ] Failed withdrawals and transfers leave all balances unchanged. +- [ ] Concurrent withdrawal/transfer tests preserve balance invariants. +- [ ] Duplicate reference codes are rejected deterministically. +- [ ] Users cannot transact from wallets they do not own. +- [ ] Transaction status history and security audit records match the final outcome. +- [ ] PostgreSQL-backed tests demonstrate locking and rollback behavior. + +--- + +## P2 — Verification and delivery evidence + +### TEST-001 — Expand automated security and integration tests + +**Classification:** Confirmed requirement +**Priority:** P2 +**Depends on:** SEC-004, SEC-005, SEC-006, AUTHZ-001, AUTHZ-002, TX-001 + +**Current problem** + +The suite primarily proves service logic through Mockito and contains limited Spring Security integration coverage. It does not provide complete evidence for PostgreSQL, JWT lifecycle, role matrices, or financial concurrency. + +**Expected behavior** + +- Fast unit tests continue to cover business branches. +- Focused security integration tests prove filter-chain and method-authorization behavior. +- PostgreSQL-backed tests prove schema, locking, and transaction behavior. +- Security regression tests map to confirmed requirements. + +**Possibly affected files** + +- `src/test/java/**` +- `src/test/resources/**` +- `pom.xml` if a PostgreSQL integration-test dependency is approved +- CI workflows if an integration-test job is approved + +**Acceptance criteria** + +- [ ] Tests cover anonymous `401`, authenticated `USER` `403`, and authorized `ADMIN` success. +- [ ] Tests cover tampered, expired, wrong-type, revoked, and rotated JWTs. +- [ ] Tests cover account lockout and access-token rejection after state changes. +- [ ] Tests cover wallet ownership and transaction rollback/concurrency. +- [ ] CI publishes readable unit and integration test results. + +### TEST-002 — Create a functional Postman verification suite + +**Classification:** Confirmed requirement +**Priority:** P2 +**Depends on:** TEST-001 + +**Current problem** + +Postman is the intended local demonstration tool, but no versioned collection currently provides repeatable critical-flow verification. + +**Expected behavior** + +- A collection and local environment exercise the API in dependency order. +- Tests capture identifiers/tokens safely and assert HTTP status plus response contracts. +- Positive and negative scenarios are both represented. +- No real or reusable credentials are committed. + +**Possibly affected files** + +- New Postman collection under a documentation/testing directory +- Sanitized Postman environment template +- `README.md` +- API functional-test instructions + +**Acceptance criteria** + +- [ ] Collection covers register, login, refresh rotation, logout, and revoked-token failure. +- [ ] Collection covers `USER`/`ADMIN` authorization and wallet ownership. +- [ ] Collection covers deposit, withdrawal, transfer, insufficient funds, and history. +- [ ] Collection contains assertions for expected `2xx`, `400`, `401`, `403`, and non-enumerating `404` cases. +- [ ] Exported files contain no tokens, passwords, local paths, or private environment values. + +### DOC-001 — Keep security documentation synchronized with evidence + +**Classification:** Detected defect +**Priority:** P2 +**Depends on:** All completed tasks that change documented behavior + +**Current problem** + +Some documentation currently describes target controls—such as token rotation, lockout, TOTP, and limits—as fully implemented. + +**Expected behavior** + +- Documentation differentiates implemented, verified, partial, and planned capabilities. +- Architecture decisions remain documented even when implementation work is pending. +- OWASP mapping describes evidence and residual work rather than claiming certification. + +**Possibly affected files** + +- `README.md` +- `SECURITY.md` +- `CONTEXT.md` +- `DECISIONS.md` +- `database/README.md` + +**Acceptance criteria** + +- [ ] Every security claim links to implementation or test evidence. +- [ ] Planned controls are not described as active controls. +- [ ] Conflicting documents identify the implementation plan as the current status source. +- [ ] OWASP Top 10:2025 names and ordering match the official release. + +--- + +## P3 — Decisions pending confirmation + +### DESIGN-001 — Review TOTP-based two-factor authentication + +**Classification:** Pending decision +**Priority:** P3 +**Depends on:** Stable authentication, session, and administrative provisioning flows + +**Current problem** + +The model and architecture documents reference TOTP, but enrollment, secret protection, recovery, verification, reauthentication, and administrative policy are not fully designed or implemented. + +**Expected behavior if approved** + +- A written decision defines which operations require TOTP. +- Enrollment requires identity verification and protected secret handling. +- Recovery and reset flows are abuse-resistant and audited. +- Tests prove bypass resistance and recovery behavior. + +**Possibly affected files** + +- `DECISIONS.md` +- Authentication entities, DTOs, controllers, and services +- Encryption/key-management configuration +- Audit actions +- Security and functional tests + +**Acceptance criteria for the decision phase** + +- [ ] Threat model and protected operations are approved. +- [ ] Secret storage and recovery strategy are approved. +- [ ] UX and Postman demonstration flow are documented. +- [ ] Implementation is not started until the decision is accepted. + +### DESIGN-002 — Review configurable financial limits + +**Classification:** Pending decision +**Priority:** P3 +**Depends on:** TX-001 + +**Current problem** + +Configuration contains transaction and daily-limit values, but their semantics, currency handling, enforcement point, concurrency behavior, and administrative ownership are not fully defined. + +**Expected behavior if approved** + +- Limits have an explicit business meaning and currency strategy. +- Enforcement is atomic and cannot be bypassed with concurrent requests. +- Configuration ownership and administrative override rules are documented. +- Limit failures do not change balances and are audited. + +**Possibly affected files** + +- `DECISIONS.md` +- Transaction configuration properties +- `TransactionService.java` +- Transaction repositories/queries +- Database constraints or aggregation queries if selected +- Transaction tests and Postman collection + +**Acceptance criteria for the decision phase** + +- [ ] Per-transaction and daily-limit semantics are approved. +- [ ] Multi-currency handling is defined. +- [ ] Concurrency and reset-window behavior are defined. +- [ ] Implementation is not started until the decision is accepted. + +--- + +## Known decision conflicts + +These conflicts must be resolved explicitly during implementation rather than silently in documentation: + +| Conflict | Current sources | Required resolution | +|----------|-----------------|---------------------| +| Functional roles | PostgreSQL and `UserRole` currently include `MANAGER`; confirmed target business roles are `USER` and `ADMIN` | Decide whether `MANAGER` is removed through migration or retained as a non-functional reserved value | +| Login-attempt threshold | Database allows up to 3; application configuration and security documentation state 5 | Select one policy, migrate schema/configuration, and test it | +| Refresh-token storage | Session model stores SHA-256 hashes; user model stores the original token | Make the session model authoritative and remove legacy storage safely | +| Refresh behavior | Architecture requires rotation; current implementation reuses the refresh token | Define atomic rotation and reuse handling before implementation | +| Email verification | Model/documentation describe verification as required; authentication currently does not consistently enforce it | Confirm whether verification is required for this educational scope | +| Administrative provisioning | Public seed creates an administrator; confirmed architecture requires controlled bootstrap | Separate development data and implement one-time bootstrap | +| TOTP and limits | Architecture documents describe them as controls; current decision marks them pending | Keep them pending until separate design decisions are accepted | + +## Definition of project verification + +The project should not be described as fully verified until all applicable checks are satisfied: + +- [ ] Docker Compose starts a clean local environment without public default administrative credentials. +- [ ] Bootstrap, authentication, authorization, session, wallet, and transaction acceptance criteria pass. +- [ ] Unit, security integration, and PostgreSQL-backed tests pass. +- [ ] The Postman critical-flow collection passes from a clean local environment. +- [ ] README, security documentation, and architecture decisions describe the same behavior. +- [ ] No source, exported collection, logs, or artifacts contain secrets or reusable tokens.