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
41 changes: 41 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# CreditTech Environment Configuration
# Copy to .env and fill in values. NEVER commit .env to git.

# ── Database ────────────────────────────────────────────────
DATABASE_URL=postgresql+asyncpg://credittech:credittech_dev@localhost:5432/credittech
DATABASE_ECHO=false

# ── Application ─────────────────────────────────────────────
APP_NAME=CreditTech
APP_ENV=development
APP_DEBUG=true
APP_VERSION=0.1.0
APP_HOST=0.0.0.0
APP_PORT=8000

# ── Security ────────────────────────────────────────────────
SECRET_KEY=CHANGE_ME_TO_A_RANDOM_64_CHAR_STRING
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60

# ── PII Encryption ──────────────────────────────────────────
PII_ENCRYPTION_KEY=CHANGE_ME_TO_A_32_BYTE_BASE64_KEY

# ── Consent ─────────────────────────────────────────────────
CONSENT_MAX_DURATION_DAYS=365
CONSENT_GENESIS_SALT=credittech-genesis-v1

# ── External Connectors (mocked in dev) ─────────────────────
AA_BASE_URL=http://localhost:8001/mock/aa
AA_CLIENT_ID=mock_client_id
AA_CLIENT_SECRET=mock_client_secret

GEOSPATIAL_BASE_URL=http://localhost:8001/mock/geospatial
GEOSPATIAL_API_KEY=mock_api_key

BUREAU_BASE_URL=http://localhost:8001/mock/bureau
BUREAU_API_KEY=mock_api_key

# ── Logging ─────────────────────────────────────────────────
LOG_LEVEL=INFO
LOG_FORMAT=json
109 changes: 109 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint-typecheck-test:
name: Lint, type-check, test
runs-on: ubuntu-latest

services:
postgres:
image: postgres:15-alpine
env:
POSTGRES_USER: credittech
POSTGRES_PASSWORD: credittech_dev
POSTGRES_DB: credittech_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U credittech -d credittech_test"
--health-interval 5s
--health-timeout 5s
--health-retries 10

env:
APP_ENV: test
DATABASE_URL: postgresql+asyncpg://credittech:credittech_dev@localhost:5432/credittech_test
SECRET_KEY: ci_secret_key_64_characters_long_for_automated_pipeline_run_only
JWT_ALGORITHM: HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: "60"
LOG_LEVEL: INFO
LOG_FORMAT: json

steps:
- uses: actions/checkout@v4

- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev,ml]"

- name: Ruff lint
run: ruff check .

- name: Mypy type-check (services + ml)
run: mypy services ml
continue-on-error: true # non-blocking until strict-mode debt is paid down

- name: Alembic migrations (apply)
run: alembic upgrade head

- name: Pytest
run: pytest --cov=services --cov=ml --cov-report=term-missing

build-container:
name: Build container image
runs-on: ubuntu-latest
needs: lint-typecheck-test
steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build image (no push)
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: credittech/core:ci-${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

security-scan:
name: Dependency + secret scan
runs-on: ubuntu-latest
needs: lint-typecheck-test
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install project (for pip-audit)
run: |
python -m pip install --upgrade pip
pip install -e ".[dev,ml]"

- name: pip-audit
run: |
pip install pip-audit
pip-audit --strict --ignore-vuln GHSA-none || true

- name: gitleaks secret scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57 changes: 57 additions & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Deploy — staging

on:
workflow_run:
workflows: [CI]
types: [completed]
branches: [main]

jobs:
deploy:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4

- name: Set up Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.5

- name: Terraform init (staging)
working-directory: infra/envs/staging
run: terraform init -input=false

- name: Terraform plan
working-directory: infra/envs/staging
run: terraform plan -input=false -out=tfplan

- name: Terraform apply
working-directory: infra/envs/staging
run: terraform apply -input=false -auto-approve tfplan

- name: Smoke test — /health
run: |
set -euo pipefail
for i in 1 2 3 4 5 6 7 8 9 10; do
if curl -fsS "${STAGING_BASE_URL}/health" > /tmp/health.json; then
cat /tmp/health.json
exit 0
fi
sleep 6
done
echo "Health check failed after retries" >&2
exit 1
env:
STAGING_BASE_URL: ${{ vars.STAGING_BASE_URL }}

promote-production:
name: Manual promote to production
needs: deploy
runs-on: ubuntu-latest
environment:
name: production
url: ${{ vars.PRODUCTION_BASE_URL }}
steps:
- run: echo "Production promotion requires manual approval on the 'production' environment."
Loading
Loading