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
14 changes: 14 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,17 @@
.local
**/target
**/__pycache__

# Only the four packaged service JARs enter application build contexts.
!payguard-identity-service/target/
payguard-identity-service/target/*
!payguard-identity-service/target/payguard-identity-service-1.0.0-SNAPSHOT.jar
!payguard-wallet-service/target/
payguard-wallet-service/target/*
!payguard-wallet-service/target/payguard-wallet-service-1.0.0-SNAPSHOT.jar
!payguard-loan-service/target/
payguard-loan-service/target/*
!payguard-loan-service/target/payguard-loan-service-1.0.0-SNAPSHOT.jar
!payguard-collateral-service/target/
payguard-collateral-service/target/*
!payguard-collateral-service/target/payguard-collateral-service-1.0.0-SNAPSHOT.jar
18 changes: 15 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
# Secrets are generated into ignored protected files by scripts/local/prepare.py.
# No runtime database passwords or HMAC keys belong here.
# Non-secret deployment identity. Never put passwords or tokens here.
COMPOSE_PROJECT_NAME=payguard
VAULT_PORT=8200
KAFKA_PORT=9092
PAYGUARD_LOCAL_UID=1000
PAYGUARD_LOCAL_GID=1000
PAYGUARD_DOCKER_GID=1000
# Set to the SAME absolute path on the host and operations container.
PAYGUARD_REPO_ROOT=/workspace/payguard
PAYGUARD_RUNTIME_ROOT=/dev/shm/payguard
# PostgreSQL 18 image default. Inspect existing PG_VERSION locations before adoption.
PAYGUARD_PGDATA=/var/lib/postgresql/18/docker
# Existing volume names are explicit and external; they are never auto-created on startup.
PAYGUARD_POSTGRES_IDENTITY_VOLUME=payguard_postgres_identity_data
PAYGUARD_POSTGRES_WALLET_VOLUME=payguard_postgres_wallet_data
PAYGUARD_POSTGRES_LOAN_VOLUME=payguard_postgres_loan_data
PAYGUARD_POSTGRES_COLLATERAL_VOLUME=payguard_postgres_collateral_data
PAYGUARD_VAULT_DATA_VOLUME=payguard_vault_data
PAYGUARD_VAULT_AUDIT_VOLUME=payguard_vault_audit
PAYGUARD_KAFKA_DATA_VOLUME=payguard_kafka_data
95 changes: 60 additions & 35 deletions .github/workflows/_database-security.yml
Original file line number Diff line number Diff line change
@@ -1,55 +1,80 @@
name: PostgreSQL and Vault verification

name: Native infrastructure verification
on:
workflow_call:

permissions:
contents: read

jobs:
real-dependencies:
isolated-dependencies:
runs-on: ubuntu-latest
timeout-minutes: 25
timeout-minutes: 35
env:
COMPOSE_PROJECT_NAME: payguard-it-ci
PAYGUARD_RUNTIME_ROOT: /dev/shm/payguard-it-ci
PAYGUARD_POSTGRES_IDENTITY_VOLUME: payguard-it-ci_identity
PAYGUARD_POSTGRES_WALLET_VOLUME: payguard-it-ci_wallet
PAYGUARD_POSTGRES_LOAN_VOLUME: payguard-it-ci_loan
PAYGUARD_POSTGRES_COLLATERAL_VOLUME: payguard-it-ci_collateral
PAYGUARD_VAULT_DATA_VOLUME: payguard-it-ci_vault
PAYGUARD_VAULT_AUDIT_VOLUME: payguard-it-ci_audit
PAYGUARD_KAFKA_DATA_VOLUME: payguard-it-ci_kafka
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: '25'
cache: maven
- name: PostgreSQL migrations and competing transactions
run: >-
./mvnw -B -ntp -pl payguard-identity-service,payguard-loan-service,payguard-collateral-service -am
-Dtest=PostgreSqlTlsTest,PostgresqlMigrationRehearsalTest,SanitizedDependencyErrorTest,OtpInfrastructureIntegrationTest,OtpApplicationContractsTest,LoanServiceApplicationTests,CollateralServiceApplicationTests
-Dsurefire.failIfNoSpecifiedTests=false clean test
- name: Build protected migration and integration runners
run: >-
./mvnw -B -ntp -pl payguard-identity-service,payguard-wallet-service,payguard-loan-service,payguard-collateral-service -am -DskipTests package dependency:copy-dependencies -DincludeScope=test
- name: Verify synthetic export and approved identifier mapping
run: python3 -m unittest discover -s scripts/migration -p 'test_*.py'
- name: Prepare isolated TLS infrastructure
- name: Install native Ansible dependencies and offline test dependencies
run: |
python3 scripts/local/prepare.py
docker compose --env-file .env.example up -d --wait postgres-wallet postgres-loan postgres-collateral postgres-identity vault
python3 scripts/local/vault_bootstrap.py
- name: Apply separately privileged Flyway migrations
python3 -m venv /tmp/payguard-ansible
/tmp/payguard-ansible/bin/pip install -r infrastructure/operations/requirements.txt -r infrastructure/tests-requirements.txt
/tmp/payguard-ansible/bin/ansible-galaxy collection install -r infrastructure/operations/requirements.yml
echo /tmp/payguard-ansible/bin >> "$GITHUB_PATH"
echo "PAYGUARD_REPO_ROOT=$GITHUB_WORKSPACE" >> "$GITHUB_ENV"
echo "PAYGUARD_LOCAL_UID=$(id -u)" >> "$GITHUB_ENV"
echo "PAYGUARD_LOCAL_GID=$(id -g)" >> "$GITHUB_ENV"
echo "PAYGUARD_DOCKER_GID=$(stat -c %g /var/run/docker.sock)" >> "$GITHUB_ENV"
mkdir -m 700 "$PAYGUARD_RUNTIME_ROOT"
- name: Verify source contracts and build applications
run: |
python3 scripts/local/migrate.py identity
python3 scripts/local/migrate.py loan
python3 scripts/local/migrate.py collateral
- name: Verify actual pools, scoped secrets and Vault audit
run: python3 scripts/local/verify_vault.py
- name: Boot actual packaged services with scoped credentials
run: python3 scripts/local/verify_applications.py
- name: Preserve test reports
python3 -m unittest discover -s infrastructure/tests -v
./mvnw -B -ntp -pl payguard-identity-service,payguard-wallet-service,payguard-loan-service,payguard-collateral-service -am test package
- name: Prepare isolated fixture and allocate only new explicit volumes
run: |
ansible-playbook -i localhost, -c local infrastructure/operations/prepare.yml -e fresh_target=true
ansible-playbook -i localhost, -c local infrastructure/operations/allocate.yml -e fresh_target=true
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml --profile operations build operations
docker compose up -d --wait postgres-identity postgres-wallet postgres-loan postgres-collateral
docker compose up -d vault
- name: Initialize and provision the new fixture through Ansible
run: |
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/vault-lifecycle.yml -e operation=initialize -e fresh_target=true -e local_rehearsal=true
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/site.yml -e fresh_target=true
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml up -d agent-operator
- name: Run all four CLI migrations twice
run: |
for pass in 1 2; do
for service in identity wallet loan collateral; do
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/migrate.yml -e service="$service"
done
done
- name: Verify privilege boundaries and native Agent security
run: |
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/tests/integration.yml
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/tests/agent.yml -e isolated_target=true
- name: Boot and verify actual packaged applications
run: |
docker compose --profile applications up -d --build
docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/tests/applications.yml
- name: Rehearse an isolated Vault outage and recovery
run: docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml run --rm --no-deps operations infrastructure/operations/tests/recovery.yml
- name: Preserve Java test reports
if: always()
uses: actions/upload-artifact@v7
with:
name: database-security-reports
path: |
**/target/surefire-reports/TEST-*.xml
payguard-shared/target/vault-test-reports/*.xml
name: native-infrastructure-java-reports
path: '**/target/surefire-reports/TEST-*.xml'
if-no-files-found: warn
- name: Stop isolated infrastructure
- name: Stop only this isolated fixture
if: always()
run: docker compose --env-file .env.example stop
run: docker compose -f docker-compose.yaml -f infrastructure/compose.operations.yaml --profile applications --profile operations stop
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ Domain rules remain in the domain, use-case coordination in application code, an

## Build and local rehearsal

Use JDK **25**, Docker/Compose, Python 3 and OpenSSL. The Maven wrapper is included. Database integration tests start real PostgreSQL containers; they do not require an unset opt-in flag.
Use JDK **25**, Docker/Compose, Ansible and OpenSSL. The Maven wrapper is included. Database integration tests start real PostgreSQL containers; they do not require an unset opt-in flag.

```bash
./mvnw -B -ntp clean verify
```

The committed Identity integration passed full Maven verification with 91 tests and zero failures, errors or skips, including the existing domain regressions and real PostgreSQL tests. Formatting and static-analysis checks also passed. See [the publication repair log](docs/tasks/identity-publication-repair.md) for the exact source revision and evidence.
Historical Identity verification is recorded in [the publication repair log](docs/tasks/identity-publication-repair.md). It does not validate the new Vault Agent lifecycle; see [current infrastructure validation](docs/infrastructure-validation.md).

For the isolated, persistent TLS PostgreSQL/Vault rehearsal, follow [the implementation guide](docs/guides/postgresql-vault-migration.md). It gives the exact preparation, initialization, migration and test commands. Generated credentials, certificates and unseal material live under ignored `.local/payguard` with protected permissions. `.env.example` contains only public settings. Never copy secrets into an image or publish that directory.
For the Compose, Vault Agent, Ansible and Flyway CLI deployment, follow [the infrastructure runbook](docs/infrastructure.md). It gives the exact preparation, initialization, migration and test commands. Generated credentials, certificates and unseal material live under ignored `.local/payguard` with protected permissions. `.env.example` contains only public settings. Never copy secrets into an image or publish that directory.

Runtime Flyway is disabled: apply migrations using the migration identity before starting applications. The `applications` Compose profile is separate from the database/Vault infrastructure. Provider delivery, customer enrollment, external authentication, production certificate issuance, HA/auto-unseal and durable event delivery are not implemented by this migration.

Expand Down
Loading
Loading