Skip to content
CedynGroupPublic

About

Treasury & ALM platform for African banks — six regulatory engines (IRRBB, Liquidity, FX, Basel, FTP, Forecasting), live data engine, and Bank of Ghana regulatory reporting.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

483 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AequorOS

Treasury, ALM and regulatory-reporting infrastructure for African banks. Six calculation modules (Liquidity · Basel Capital · IRRBB · FX · FTP · Balance-Sheet Forecasting) run server-side on tenant-isolated, effective-dated data, each behind an immutable, hash-pinned calculation run. Jurisdiction is data rather than code; the return families built today are the Bank of Ghana BSD set, generated from the official workbook templates.

Repository layout

aequorOS/
├── backend/                  # ── THE PRODUCT ──
│   ├── app/                  #   FastAPI tenant API: the six engines, app/forecasting/ml (LSTM),
│   │                         #   Data Engine, BoG return generation, attestation,
│   │                         #   Postgres + row-level-security tenancy
│   ├── app/operator/         #   staff control plane — a SEPARATE ASGI app (:8100),
│   │                         #   never mounted on the tenant API
│   ├── app/worker.py         #   background worker: live-plane refresh + official runs
│   ├── dashboard/            #   the product UI (Next.js) → bank.aequoros.com
│   └── alembic/ tests/ scripts/ docker-compose.yml
├── console/                  # staff operator console (Next.js) → OPERATOR_API_URL, default :8100
├── frontend/                 # marketing site (Next.js) → aequoros.com
├── packages/
│   └── risk-service-api/     # generated TypeScript client (API ⇄ UI contract)
├── deploy/                   # OpenBao (signing-key custody) compose
├── questions/                # answered scoping questions, kept as a decision record
└── ARCHITECTURE.md           # system map + conventions (start here)

Specs, runbooks and the internal audit register live in docs/, which is private by default; .gitignore publishes only explicitly allow-listed files. Anything cited below that you cannot find here is held privately — ask for it.

Deployables

App Production build Domain
frontend Vercel (see frontend/README.md) aequoros.com
backend/dashboard docker-compose.dashboard.yml — Docker Compose build pack, repo root as build context bank.aequoros.com
backend backend/docker-compose.prod.yml — risk-migrate (one-shot alembic upgrade head), risk-api :8000, risk-worker, risk-operator :8100 api.aequoros.com on risk-api only
console docker-compose.console.yml — Docker Compose build pack, repo root as build context intended console.aequoros.com

backend/.dockerignore excludes dashboard/, so the API image never carries the UI.

The compose files require the coordinated certificate and proxy preparation in the transport deployment contract. The audit-chain migration also requires migration credential and audit ownership preparation.

Prerequisites

  • Python 3.13 and uv. pyproject.toml pins >=3.13,<3.14. Create the environment once: cd backend && uv sync.
  • Node 24 (.nvmrc, engines.node >= 24) and pnpm 11.2.2 — the exact version in package.json packageManager. pnpm-workspace.yaml sets engineStrict: true, so an older pnpm is refused rather than warned about. nvm use && corepack enable && pnpm install.
  • PostgreSQL — either your managed instance or the bundled compose, which runs postgres:17.
  • Environment: cp backend/.env.example backend/.env and fill in the database and object-storage values. Secrets live only in the untracked .env. For the staff console, copy console/.env.example to console/.env.local before starting local development.

Quick start

cd backend

# 1. Schema. DATABASE_URL comes from backend/.env (untracked; shape in .env.example).
uv run alembic upgrade head          # no-op when already at head

# 2. Tenant API on :8000 — the port backend/dashboard defaults to
#    (NEXT_PUBLIC_RISK_API_BASE_URL=http://127.0.0.1:8000/api/v1). Includes the
#    LSTM cash-flow module, which lazy-trains on the first forecast call or
#    reuses backend/artifacts/cashflow/.
uv run fastapi dev app/main.py --port 8000

# 3. Background worker — REQUIRED. It writes current_financial_facts and
#    live_metrics; without it every Treasury/ALM page reads "no computed data
#    yet". On Postgres, configure WORKER_DATABASE_URL following
#    docs/ops/database-roles.md#worker-compatibility-migration. Locally you can
#    instead set RUN_INPROCESS_WORKER=1 (default off) to poll inside the API
#    process; in production it is always a separate container.
uv run python -m app.worker

# 4. Staff operator API on :8100 (optional; never mounted on the tenant API)
uv run uvicorn app.operator.main:app --port 8100
# From the repo root — the UIs.
pnpm install
pnpm --filter @aequoros/dashboard dev   # product dashboard :3001
pnpm --filter @aequoros/console   dev   # operator console  :3002 (proxies to :8100)
pnpm --filter @aequoros/frontend  dev   # marketing site    :3000

Offline/local infrastructure instead of a managed database:

cd backend && docker compose up -d      # Postgres :15432, MinIO :9000 (console :9001)

then point DATABASE_URL at localhost:15432.

There is no seed step. Provision a bank through the staff operator console, then load its financial data through the Data Engine — Excel/CSV upload, API push, or a read-only database extract. See the Data Engine's no-seeding contract. Provisioning creates the starting board parameter register, including IRR, FX and FTP stress assumptions for banks. The FX/FTP defaults are internal calibrations, not regulatory requirements. Applying the migration chain fills missing FX/FTP scenario keys for existing banks while retaining their board values. The hermetic pytest suite builds its own tenants in backend/tests/conftest.py; its fixture financial records are test-only.

Database-direct drivers. The shipped image installs only the Oracle thin driver, which is a core dependency. SQL Server/ODBC, generic JDBC and Snowflake live behind the db-direct extra, which backend/Dockerfile does not install; pyodbc and JDBC additionally need system packages (unixODBC plus a vendor ODBC driver, and a JRE). Those backends are built and tested but not enabled in the default deployment image — see backend/README.md.

Validation

cd backend
uv run pytest                 # hermetic suite
uv run ruff check .
uv run python scripts/type_check_baseline.py check   # basedpyright strict, legacy errors baselined

The hermetic default runs on SQLite with row-level security switched off, so a green run is not evidence about Postgres. Boolean server defaults, String-vs-UUID comparisons, row locks and RLS policies all behave differently there; the Postgres-gated suites opt in explicitly via TEST_DATABASE_URL; see the backend's test database guide for schema isolation and parallel execution. The task inventory is in backend/mise.toml.

For native PostgreSQL 17 and MinIO, install brew install postgresql@17 homebrew/core/minio, then run AQS_LOCAL_SERVICES=native mise run risk-service:test-postgres-suite or AQS_LOCAL_SERVICES=native pnpm --filter @aequoros/dashboard e2e. Standard commands also fall back to native services when Docker is unavailable. Data and ports are isolated per worktree; see the dashboard's local service guide.

# From the repo root — the TypeScript surfaces.
pnpm --filter @aequoros/dashboard typecheck && pnpm --filter @aequoros/dashboard lint \
  && pnpm --filter @aequoros/dashboard test && pnpm --filter @aequoros/dashboard build
pnpm --filter @aequoros/dashboard e2e             # disposable stack; package specs need S3/MinIO
pnpm --filter @aequoros/frontend lint && pnpm --filter @aequoros/frontend build
pnpm --filter @aequoros/risk-service-api test

# Regenerate the client after an API change, then prove it is fresh:
mise run risk-service:openapi-client
mise run risk-service:api-fresh                     # must leave git clean

For console checks and CI coverage, see Architecture §8.

License & security

Proprietary source-available — see LICENSE. Public visibility is for evaluation and due diligence; production or competing use requires a commercial license. Report vulnerabilities to security@aequoros.com.

Status. The platform is built and running against a live database, with no bank in production and no return yet filed with the Bank of Ghana. There is no SOC 2, ISO or other third-party certification, no regulatory approval or accreditation of any kind, and none is claimed. "Built" means computed server-side from ingested data behind an immutable run — it does not mean any figure has been filed with, or accepted by, a regulator.

A database restore drill has been executed end to end against a throwaway target (134 tables / 12,001,905 rows verified by row count and content digest, tenant isolation confirmed on the restored copy, measured RTO floor ~123 s for the database step alone). What is still unproven: no backup schedule is configured, so the effective RPO is unbounded; object storage is inventoried but has never been restored, so filed-artifact recoverability is untested; there is no point-in-time recovery, and the timings come from a local cluster rather than production hardware. The full disclosure register lives in docs/audit/15_known_limitations.md, which is not tracked in this repository (.gitignore:42) — ask for it directly.

About

Treasury & ALM platform for African banks — six regulatory engines (IRRBB, Liquidity, FX, Basel, FTP, Forecasting), live data engine, and Bank of Ghana regulatory reporting.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages