Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,40 @@ jobs:
retention-days: 14
if-no-files-found: ignore

- name: Prepare Documentation and Coverage Site
- name: Install D2 Diagram Compiler
run: |
curl -fsSL https://d2lang.com/install.sh | sh -s --

- name: Verify D2 Diagrams & Detect Drift
run: |
chmod +x scripts/generate-diagrams.sh
./scripts/generate-diagrams.sh --check

- name: Set up Python for Documentation Build
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'

- name: Install MkDocs Dependencies
run: |
pip install -r requirements.txt

- name: Validate MkDocs Documentation Build (Strict Mode)
run: |
mkdocs build --strict

- name: Package Documentation Portal & JaCoCo Coverage for GitHub Pages
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
mkdir -p public/coverage
cp README.md public/
cp CHANGELOG.md public/
cp SECURITY.md public/
cp -r docs public/
cp -r docs-site/* public/
cp -r target/site/jacoco/* public/coverage/
mkdocs build -d public --strict
mkdir -p public/coverage-report
cp -r target/site/jacoco/* public/coverage-report/
touch public/.nojekyll
python3 -c "
import glob
nav_html = '''<div id=\"payflow-docs-nav\" style=\"background:#0f172a;color:#f8fafc;padding:12px 24px;border-bottom:1px solid #334155;display:flex;align-items:center;justify-content:space-between;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;position:sticky;top:0;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.1);\"><a id=\"payflow-back-link\" href=\"/payflow-api/\" style=\"color:#38bdf8;text-decoration:none;font-weight:600;display:flex;align-items:center;gap:8px;\">&larr; Back to Documentation Portal</a><span style=\"color:#94a3b8;font-size:12px;\">Payflow API &mdash; Automated JaCoCo Code Coverage</span></div><script>(function(){var a=document.getElementById('payflow-back-link');if(!location.pathname.includes('/payflow-api/')){var idx=location.pathname.indexOf('/coverage');if(idx!==-1){a.href=location.pathname.substring(0,idx)+'/';}}})()</script>'''
for path in glob.glob('public/coverage/**/*.html', recursive=True):
nav_html = '''<div id=\"payflow-docs-nav\" style=\"background:#0f172a;color:#f8fafc;padding:12px 24px;border-bottom:1px solid #334155;display:flex;align-items:center;justify-content:space-between;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;position:sticky;top:0;z-index:9999;box-shadow:0 2px 4px rgba(0,0,0,0.1);\"><div style=\"display:flex;align-items:center;gap:16px;\"><a id=\"payflow-back-link\" href=\"/payflow-api/\" style=\"color:#38bdf8;text-decoration:none;font-weight:600;display:flex;align-items:center;gap:6px;\">&larr; Back to Documentation Portal</a><span style=\"color:#475569;\">|</span><a id=\"payflow-gates-link\" href=\"/payflow-api/coverage/\" style=\"color:#38bdf8;text-decoration:none;font-weight:600;\">📊 Coverage Quality Gates</a><span style=\"color:#475569;\">|</span><a id=\"payflow-metrics-link\" href=\"/payflow-api/coverage-report/\" style=\"color:#94a3b8;text-decoration:none;font-weight:500;\">Coverage Dashboard</a></div><span style=\"color:#94a3b8;font-size:12px;\">Payflow API &mdash; Automated JaCoCo Code Coverage (90% Line / 73% Branch)</span></div><script>(function(){var path=window.location.pathname;var root=path.includes('/payflow-api/')?'/payflow-api/':'/';var b=document.getElementById('payflow-back-link');var g=document.getElementById('payflow-gates-link');var m=document.getElementById('payflow-metrics-link');if(b)b.href=root;if(g)g.href=root+'coverage/';if(m)m.href=root+'coverage-report/';})()</script>'''
for path in glob.glob('public/coverage-report/**/*.html', recursive=True):
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
if '<body' in content and 'payflow-docs-nav' not in content:
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/generate-diagrams.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Regenerate D2 Architecture Diagrams

on:
workflow_dispatch:
inputs:
reason:
description: 'Reason for regenerating diagrams'
required: false
default: 'Manual diagram compilation update'

permissions:
contents: write

jobs:
generate-diagrams:
name: Compile D2 Diagrams & Commit
runs-on: ubuntu-latest

steps:
- name: Checkout Source Code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install D2 Diagram Compiler
run: |
curl -fsSL https://d2lang.com/install.sh | sh -s --

- name: Compile D2 Diagrams to SVGs
run: |
chmod +x scripts/generate-diagrams.sh
./scripts/generate-diagrams.sh

- name: Check for SVG Changes
id: git-diff
run: |
if [ -n "$(git status --porcelain docs/assets/diagrams)" ]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "Detected SVG changes."
else
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No diagram changes detected."
fi

- name: Commit and Push Updated Diagrams
if: steps.git-diff.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/assets/diagrams/
git commit -m "docs(diagrams): regenerate D2 architecture diagrams [skip ci]"
git push
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ build/
### VS Code ###
.vscode/

### Python & Virtual Environments ###
.venv/
venv/
ENV/
env/
__pycache__/
*.py[cod]

### MkDocs & Documentation Build Artifacts ###
site/
.cache/

### Internal docs (not committed) ###
internal/
internal/*
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added - Documentation Modernization & D2 Engine Migration
- Replaced legacy Docsify single-page app with **Material for MkDocs** static site generator (`mkdocs-material` 9.5+) featuring instantaneous client search, dark/light theme switching, and responsive design.
- Redrew and modernized all 12 architectural topology, sequence, and data flow diagrams across `docs/ARCHITECTURE.md`, `README.md`, and `docs/index.md` using the declarative **D2 diagramming engine** (`docs/diagrams/*.d2`) with offline vector icons and Eclipse Layout Kernel (ELK) collision-free routing.
- Implemented **Option 1 Hybrid Pre-rendered SVG + Collapsible D2 Source** pattern: pre-rendered self-contained SVGs (`docs/assets/diagrams/*.svg`) with embedded `<details><summary>📐 View Declarative D2 Diagram Source</summary>...` blocks, guaranteeing crisp, zero-flicker rendering across GitHub web, IDE previewers, and the documentation portal.
- Authored automated compilation script `scripts/generate-diagrams.sh` with dual light/dark theme compilation (`--theme=0 --dark-theme=200`) and `--check` drift detection.
- Configured enterprise CI/CD quality gates in `.github/workflows/ci.yml`:
- Enforced zero diagram drift on PR and push via `./scripts/generate-diagrams.sh --check`.
- Enforced strict documentation compilation on PR and push via `mkdocs build --strict`.
- Automated deployment of the documentation portal alongside JaCoCo test coverage reports to GitHub Pages on `main` merge.
- Created `.github/workflows/generate-diagrams.yml` enabling 1-click manual workflow dispatch to recompile D2 diagrams and automatically commit changes without requiring local D2 installation.
- Created `requirements.txt` specifying deterministic Python dependencies (`mkdocs>=1.6.1`, `mkdocs-material>=9.5.0`, `mkdocs-d2-plugin>=1.6.0`).
- Created offline SVG icon library under `docs/assets/icons/` (16 scalable vector icons) for zero-dependency compilation.
- Eliminated redundant documentation files and deduplicated governance markdowns (`CHANGELOG.md`, `CONTRIBUTING.md`, `SECURITY.md`, `LICENSE`) via single-source relative symlinks in `docs/`.
- Hardened `.gitignore` to prevent committing build artifacts (`site/`, `.cache/`, `.venv/`, Python bytecode).
- Corrected API endpoint routes and verified complete parity with Java 25 & Spring Boot 4.1.0 codebase (191 tests, 90% line / 73% branch coverage).

### Added - Phase 11A (Multi-Stage Containerization & Full-Stack Docker Compose)
- Created hardened multi-stage `Dockerfile`:
- Stage 1: Build stage utilizing OpenJDK 25 (`eclipse-temurin:25-jdk`) and Maven layer caching.
Expand Down Expand Up @@ -40,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Integrated `jacoco-maven-plugin:0.8.15` enforcing minimum 80% line coverage and 70% branch coverage across core business and security packages; achieved **90% line coverage** and **73% branch coverage** across 191 unit tests with 0 missed classes.
- Created comprehensive unit test suites: `JwtAccessDeniedHandlerTest`, `JwtAuthenticationEntryPointTest`, `JwtAuthenticationFilterTest`, `SecurityUtilsTest`, and `IdempotencyCleanupServiceTest`.
- Hardened `.github/workflows/ci.yml` executing `mvn clean verify -B` with automated artifact upload for JaCoCo coverage reports and SpotBugs analysis (14-day retention).
- Added automated GitHub Pages deployment for the Docsify public documentation portal (`https://shashankch.github.io/payflow-api/`) and live interactive JaCoCo coverage reports (`https://shashankch.github.io/payflow-api/coverage/`).
- Added automated GitHub Pages deployment for the Material for MkDocs public documentation portal (`https://shashankch.github.io/payflow-api/`), Code Coverage Quality Gate summary (`https://shashankch.github.io/payflow-api/coverage/`), and live interactive JaCoCo coverage reports (`https://shashankch.github.io/payflow-api/coverage-report/`).
- Authored ADR-030 (*Automated CI/CD Quality Gates, JaCoCo Coverage Enforcement, and SpotBugs Static Analysis*).
- Added `spring-modulith-events-kafka`, `spring-kafka`, `spring-kafka-test`, and Testcontainers `kafka` dependencies to `pom.xml`.
- Marked domain event `TransferCompletedEvent` with `@Externalized` and configured programmatic dynamic routing via `EventExternalizationConfiguration` in `KafkaConfig.java`, routing to `${payflow.kafka.transfers-topic}` partitioned by `senderUpi` for strict chronological delivery per account.
Expand Down
133 changes: 88 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

[![CI Build](https://img.shields.io/badge/CI-Passing-brightgreen?logo=githubactions&logoColor=white&style=flat-square)](https://github.com/shashankch/payflow-api/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/badge/Coverage-90%25%20Line%20%7C%2073%25%20Branch-brightgreen?style=flat-square)](https://shashankch.github.io/payflow-api/coverage/)
[![Docs](https://img.shields.io/badge/Docs-MkDocs%20Material-526cfe?logo=materialformkdocs&logoColor=white&style=flat-square)](https://shashankch.github.io/payflow-api/)
[![Java 25](https://img.shields.io/badge/Java-25-ED8B00?logo=openjdk&logoColor=white&style=flat-square)](https://dev.java/)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-4.1.0-6DB33F?logo=springboot&logoColor=white&style=flat-square)](https://spring.io/projects/spring-boot)
[![Docker](https://img.shields.io/badge/Docker-Multi--stage%20Temurin%2025-2496ED?logo=docker&logoColor=white&style=flat-square)](Dockerfile)
Expand Down Expand Up @@ -52,59 +53,101 @@ Payflow API evolves through a structured, 12-phase capability roadmap advancing

## 🏗️ System Architecture Overview

```mermaid
graph TD
subgraph ClientLayer["📱 Client & Interface Layer"]
Client["HTTP Client / Ingress"] -->|"POST /api/v1/transactions"| Filter["RequestIdFilter (MDC X-Request-Id)"]
Filter --> Controller["TransactionController (@Valid DTO)"]
end

subgraph DomainLayer["🔒 Core Transaction Domain & Lock Manager"]
Controller -->|"sendMoney()"| TxService["TransactionService (@Transactional)"]
TxService --> LockOrder["Alphabetical Lock Ordering (Deadlock Avoidance)"]
LockOrder --> UserDomain["User Entity (Domain Invariants: debit / credit)"]
end

subgraph PersistenceLayer["🗄️ Persistence & Double-Entry Ledger"]
UserDomain -->|"Pessimistic Lock (SELECT FOR UPDATE)"| UserRepo["UserRepository"]
TxService -->|"Append Immutable DEBIT & CREDIT Audit Entries"| LedgerRepo["BalanceLedgerRepository"]
UserRepo --> DB[("PostgreSQL 17 Database")]
LedgerRepo --> DB
end

subgraph OutboxStreaming["⚡ Event Outbox & Kafka Streaming"]
TxService -->|"Atomic Outbox Publication"| Outbox[("Event Publication Registry")]
Outbox --> Kafka["Apache Kafka 3.9 (KRaft)"]
end

subgraph ObservabilityStack["📊 Telemetry & Monitoring"]
Controller -.-> Prom["Prometheus (/actuator/prometheus)"]
Prom -.-> Grafana["Grafana Dashboards (Port 3000)"]
end

classDef clientStyle fill:#1e293b,stroke:#475569,stroke-width:2px,color:#f8fafc;
classDef webStyle fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#f8fafc;
classDef domainStyle fill:#1e1b4b,stroke:#6366f1,stroke-width:2px,color:#f8fafc;
classDef dbStyle fill:#064e3b,stroke:#10b981,stroke-width:2px,color:#f8fafc;
classDef streamStyle fill:#701a75,stroke:#d946ef,stroke-width:2px,color:#f8fafc;
classDef obsStyle fill:#14532d,stroke:#22c55e,stroke-width:2px,color:#f8fafc;

class Client clientStyle;
class Filter,Controller webStyle;
class TxService,LockOrder,UserDomain domainStyle;
class UserRepo,LedgerRepo,DB dbStyle;
class Outbox,Kafka streamStyle;
class Prom,Grafana obsStyle;
![System Architecture Overview](docs/assets/diagrams/system-overview.svg)

<details>
<summary>📐 View Declarative D2 Diagram Source</summary>

```d2
direction: down

client: Client / Mobile App {
shape: rectangle
icon: "docs/assets/icons/client.svg"
}

ingress: Ingress / API Gateway {
shape: rectangle
icon: "docs/assets/icons/gateway.svg"
}

security: Spring Security (JWT Filter) {
shape: rectangle
icon: "docs/assets/icons/shield.svg"
}

idemp: Idempotency Filter (SHA-256) {
shape: rectangle
icon: "docs/assets/icons/lock.svg"
}

controller: TransactionController {
shape: rectangle
icon: "docs/assets/icons/spring.svg"
}

service: TransactionService {
shape: rectangle
icon: "docs/assets/icons/java.svg"
}

client -> ingress: "HTTP POST (Idempotency-Key)"
ingress -> security: "TLS 1.3"
security -> idemp: "Bearer JWT"
idemp -> controller: "Validated Request"
controller -> service: "sendMoney()"

core_storage: Core Concurrency & Storage {
postgres: PostgreSQL 17 {
shape: cylinder
icon: "docs/assets/icons/postgresql.svg"
}
redis: Redis 7 (Redlock & Cache) {
shape: cylinder
icon: "docs/assets/icons/redis.svg"
}
}

async_events: Asynchronous Messaging & Events {
outbox: Transactional Outbox {
shape: cylinder
icon: "docs/assets/icons/queue.svg"
}
kafka: Apache Kafka (KRaft) {
shape: queue
icon: "docs/assets/icons/kafka.svg"
}
outbox -> kafka: "spring-modulith-events-kafka"
}

ai_resilience: AI & Resilience {
ai: Ollama Gen-AI {
shape: rectangle
icon: "docs/assets/icons/ai.svg"
}
r4j: Resilience4j {
shape: rectangle
icon: "docs/assets/icons/shield.svg"
}
}

service -> core_storage.postgres: "Row Lock & Ledger Entries"
service -> core_storage.redis: "Redlock & Cache-Aside"
service -> async_events.outbox: "Atomically Persist Event"
service -> ai_resilience.ai: "Spend Insights"
service -> ai_resilience.r4j: "Rate Limiting Guard"
```
</details>

---

## 📚 Project Documentation Hub

| Document | Description |
| :--- | :--- |
| 🚀 **[Live Documentation Hub](https://shashankch.github.io/payflow-api/)** | Interactive Docsify portal with full-text search, dark mode, and dynamic markdown rendering |
| 📊 **[JaCoCo Code Coverage Report](https://shashankch.github.io/payflow-api/coverage/)** | Live interactive code coverage report (90% Line, 73% Branch) generated per-build |
| 🚀 **[Live Documentation Hub](https://shashankch.github.io/payflow-api/)** | Material for MkDocs documentation portal with full-text search, D2 diagram rendering, and dark mode |
| 📊 **[Code Coverage & Quality Gates](https://shashankch.github.io/payflow-api/coverage/)** | Automated CI/CD quality gates, bundle-level line/branch thresholds, and SpotBugs audit |
| 🚀 **[Interactive JaCoCo Report](https://shashankch.github.io/payflow-api/coverage-report/)** | Live interactive code coverage drilldown (90% Line, 73% Branch) generated per-build |
| 📘 **[System Architecture](docs/ARCHITECTURE.md)** | Deep-dive concurrency models, pessimistic locking mechanics, test pyramid |
| 🛡️ **[Security Architecture & Threat Model](docs/ARCHITECTURE.md#18-security-architecture-and-threat-model)** | Zero-Trust filter chain, STRIDE threat model, IAM policy matrix, financial concurrency controls |
| 🔒 **[Security Policy](SECURITY.md)** | Open-source vulnerability reporting guidelines and project security posture |
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Security Policy — Payflow API

> **Project Status**: Payflow API is an open-source educational and reference architecture project licensed under the [MIT License](LICENSE). The project is currently under active development and is not deployed to production environments.
> **Project Status**: Payflow API is an open-source educational and reference architecture project licensed under the [MIT License](https://github.com/shashankch/payflow-api/blob/main/LICENSE). The project is currently under active development and is not deployed to production environments.

---

## Architectural Security Model

Payflow API implements defense-in-depth security principles for financial ledger integrity, including Zero-Trust request validation, STRIDE threat mitigations, deterministic row locking, immutable double-entry balance ledgers, and SHA-256 payload verification.

For full architectural specifications, see [Security Architecture & Threat Model](docs/ARCHITECTURE.md#18-security-architecture-and-threat-model).
For full architectural specifications, see [Security Architecture & Threat Model](ARCHITECTURE.md#18-security-architecture-and-threat-model).

---

Expand Down
6 changes: 0 additions & 6 deletions docs-site/_navbar.md

This file was deleted.

24 changes: 0 additions & 24 deletions docs-site/_sidebar.md

This file was deleted.

Loading
Loading