Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

History
316 lines (248 loc) · 15.8 KB

File metadata and controls

316 lines (248 loc) · 15.8 KB

Loyalty Analytics AI Agent

CI Python 3.12 FastAPI PostgreSQL Docker Live Demo

A production-style loyalty intelligence platform that turns customer, transaction, and reward data into an authenticated executive dashboard and grounded AI-assisted analysis.

Open the live demo · Explore the API docs · Follow the demo guide · Read the portfolio case study

The demo runs on Render's free tier. Its first request after inactivity can take about a minute while the service wakes up; availability and response time are not production SLAs.

What this proves

  • Backend/API development with FastAPI, PostgreSQL, migrations, and protected administrator workflows
  • Safe AI integration through approved read-only aggregate tools, grounded analysis, and explicit provider-error handling
  • Auditable analytics delivery across PostgreSQL, Snowflake, and S3-compatible snapshots
  • Practical operational quality with rate limiting, health probes, CI, and structured logs

What it demonstrates

  • A layered FastAPI backend with async-ready SQLAlchemy 2.x patterns and PostgreSQL
  • Versioned database migrations and deterministic demo-data bootstrapping
  • Secure administrator authentication with Argon2 password hashing and signed HttpOnly cookies
  • Responsive executive analytics for revenue, loyalty tiers, and reward activity
  • Administrator workflows for customers, purchases, and reward redemptions
  • Paginated REST resources and streamed CSV exports with spreadsheet-injection protection
  • A constrained AI analyst that can call only approved, read-only aggregate tools
  • A durable LangGraph workflow with routing, retries, PostgreSQL checkpoints, and audited approval
  • Per-user analysis history, configurable rate limiting, and graceful provider error handling
  • Render Blueprint configuration with health probes and structured logs; the public free-tier demo is not presented as a production SLA
  • Automated formatting, linting, strict typing, tests, coverage enforcement, and container builds
  • A versioned agent evaluation suite with safety cases, structured judging, and OpenTelemetry spans
  • Snowflake analytics synchronized by GitHub Actions with PostgreSQL fallback
  • Aggregate JSON snapshots through an S3-compatible API and local MinIO

The deterministic seed starts with 100 customers, 1,000 transactions, and 100 reward redemptions. Authenticated administrator actions can change the live totals.

Product tour

Executive loyalty-program KPIs

Live executive KPIs backed by the configured PostgreSQL or Snowflake analytics provider.

Program analytics Grounded AI analyst
Revenue, membership, and reward analytics AI analyst answering a grounded revenue question

The administrator workspace supports operational data entry without requiring raw API calls:

Customer administration workspace

Purchase and reward administration workspace

Additional implementation and production evidence is available in the portfolio case study.

Architecture

flowchart LR
    Browser["Authenticated dashboard"] -->|HTTPS + HttpOnly session| API["FastAPI application"]
    API --> Auth["Authentication and RBAC"]
    API --> Admin["Data-management service"]
    API --> Analytics["Analytics and exports"]
    API --> Agent["LangGraph AI analyst"]
    API --> Snapshots["Snapshot service"]
    Auth --> PG[("PostgreSQL system of record")]
    Admin --> PG
    Agent --> Tools["Approved aggregate tools"]
    Tools --> Analytics
    Analytics --> Provider{"Configured provider"}
    Provider --> PG
    Provider --> SF[("Snowflake analytics")]
    Agent --> OpenAI["OpenAI Responses API"]
    Snapshots --> S3["S3-compatible storage / MinIO"]
    GHA["GitHub Actions"] -->|Token-protected sync| API
    API -->|Batch synchronization| SF
    Alembic["Alembic migrations"] --> PG
    Render["Render Blueprint"] --> API
Loading

The AI layer never receives arbitrary SQL access. It selects from four server-owned aggregate tools; those tools validate inputs and execute controlled queries. Individual customer records are intentionally unavailable to the model.

Technology

Area Technologies
API Python 3.12, FastAPI, Pydantic v2
Data PostgreSQL, Snowflake, SQLAlchemy 2.x, Alembic
AI LangGraph, OpenAI Responses API, constrained function tools
Security Argon2, signed HttpOnly cookies, security headers, rate limiting
UI Responsive HTML, CSS, and JavaScript served by FastAPI
Storage S3-compatible snapshots with boto3 and local MinIO
Operations Docker Compose, GitHub Actions, Render Blueprint, health probes
Quality pytest, pytest-cov, Ruff, mypy, GitHub Actions

Quick start with Docker

Requirements: Docker with Compose v2 and an OpenAI API key if you want to use the AI analyst.

cp .env.example .env
docker compose up --build -d
docker compose exec api alembic upgrade head
docker compose exec api python scripts/seed.py
docker compose exec api python scripts/create_admin.py --email [email protected]

The dashboard is at http://localhost:8000 and interactive OpenAPI documentation is at http://localhost:8000/docs.

Administrators also receive a Manage data workspace in the dashboard for creating and updating customers, recording purchases, and redeeming rewards. These forms use the protected data-management API and keep points changes tied to transaction or redemption records.

Generate a strong signing key and set it as AUTH_SECRET_KEY in .env:

python -c "import secrets; print(secrets.token_urlsafe(48))"

Set OPENAI_API_KEY in the same untracked file to enable AI analysis. Never commit either secret.

Stop services with docker compose down. Use docker compose down -v only when you also intend to remove the local database volume.

Local development

Create a Python 3.12 virtual environment, then run:

python -m pip install -e ".[dev]"
cp .env.example .env
alembic upgrade head
python scripts/seed.py
uvicorn loyalty_analytics.main:app --reload

DATABASE_URL must point to a reachable PostgreSQL database. The deterministic seed replaces existing loyalty records and is intended only for development or demonstration environments.

API surface

Method Path Purpose
GET /health, /health/live, /health/ready Health and platform probes
GET /api/v1/customers Paginated customers
GET /api/v1/customers/{id} Customer by UUID
GET /api/v1/transactions Paginated transactions
GET /api/v1/rewards Paginated reward redemptions
POST /api/v1/admin/customers Create a customer (administrator only)
PATCH /api/v1/admin/customers/{id} Update customer profile data (administrator only)
POST /api/v1/admin/transactions Record a purchase and credit points (administrator only)
POST /api/v1/admin/rewards Redeem a reward and deduct points (administrator only)
GET /api/v1/analytics/overview Program-wide KPIs
GET /api/v1/analytics/loyalty-tiers Membership metrics by tier
GET /api/v1/analytics/spending-by-category Revenue metrics by category
GET /api/v1/analytics/reward-redemptions Redemption metrics by reward
POST /api/v1/agent/query Ask a grounded analytics question
POST /api/v1/agent/workflows/{id}/approval Resume a sensitive workflow
GET /api/v1/agent/history Retrieve the signed-in user's analyses
GET /api/v1/exports/*.csv Stream summary or resource reports
POST /api/v1/auth/login, /api/v1/auth/logout Manage a dashboard session
GET /api/v1/auth/me Retrieve the authenticated user

Collection endpoints accept page (default 1) and page_size (default 20, maximum 100). They return items, total, page, page_size, and pages. Validation failures use structured 422 responses, unknown resources return 404, and unexpected failures include an X-Request-ID correlation value.

Customer, transaction, reward, analytics, export, and AI routes require authentication. Health probes and static login assets remain public.

Data-management routes require an administrator session. Transaction and reward writes lock the affected customer row and update the points balance in the same database transaction. Customer points cannot be edited directly, which preserves the transaction and redemption audit trail.

Security and operational choices

  • Passwords are Argon2-hashed and are never logged or stored in plaintext.
  • Sessions use signed HttpOnly, SameSite cookies; production requires secure cookies over HTTPS.
  • CSV values with spreadsheet formula prefixes are escaped before streaming.
  • AI requests are rate-limited and restricted to aggregate, read-only business tools.
  • Every response receives defensive browser headers and an X-Request-ID.
  • Request logs are structured JSON with method, path, status, and duration.
  • Secrets are injected through environment variables and .env is excluded from version control.

See SECURITY.md for reporting and credential-handling guidance.

The agent's golden dataset, deterministic regression scoring, optional structured LLM judge, and privacy-conscious tracing design are documented in the evaluation guide. The routing graph and human-in-the-loop safety boundary are documented in the workflow guide.

Quality gates

make format
make lint
make typecheck
make test
# all non-mutating checks
make check

GitHub Actions runs formatting verification, linting, strict type checking, tests with coverage, and a production container build for pull requests and pushes to main. Tests use an isolated SQLite database; production uses PostgreSQL. Schema changes are applied through Alembic.

Verified production workflow

The deployed system has been validated end to end:

  1. An administrator created a customer through the protected dashboard.
  2. A purchase credited points in the PostgreSQL system of record.
  3. A reward redemption deducted points in the same transaction boundary.
  4. The token-protected GitHub Actions workflow synchronized the data to Snowflake.
  5. The dashboard refreshed from Snowflake and reflected the new activity and balances.

This path exercises authentication, validation, row locking, persistence, scheduled integration, warehouse permissions, and analytics rendering rather than relying only on seeded screenshots.

Automated delivery Warehouse integration
Successful CI and Snowflake synchronization workflows Snowflake analytics tables

Deployment

render.yaml provisions the Docker web service and managed PostgreSQL database, generates the session secret, runs migrations, bootstraps an administrator, and seeds an empty demo database. See the deployment runbook for configuration and free-tier limitations.

Snowflake analytics

The dashboard and AI tools can read aggregate metrics from Snowflake while PostgreSQL remains the system of record and automatic fallback. Run infra/snowflake/bootstrap.sql in Snowsight after replacing YOUR_SNOWFLAKE_USERNAME, configure the SNOWFLAKE_* secrets, run python scripts/sync_snowflake.py, and set ANALYTICS_PROVIDER=snowflake. The bootstrap grants the application role synchronization access to existing and future analytics tables so scheduled data refreshes remain operational as the schema grows.

The warehouse is X-Small, starts suspended, and auto-suspends after 60 seconds. The authenticated GET /api/v1/integrations/snowflake/health endpoint verifies the deployed connection. Never commit Snowflake credentials; for long-lived production use, migrate from a password to key-pair authentication.

On a private hosted network where an interactive shell is unavailable, set SNOWFLAKE_SYNC_ON_START=true for one deployment to copy PostgreSQL data into Snowflake. Confirm the Synced ... to Snowflake log entry, then immediately restore the flag to false.

For ongoing synchronization, .github/workflows/snowflake-sync.yml calls a narrowly scoped, token-protected Render endpoint every day at 07:17 UTC and also supports manual runs. Set the same random value as Render's SNOWFLAKE_SYNC_TOKEN and the GitHub Actions repository secret RENDER_SYNC_TOKEN. The workflow receives no database or Snowflake credentials.

Snowflake key-pair authentication

For deployed environments, generate an encrypted key pair outside the repository with python scripts/generate_snowflake_keypair.py --output-directory <secure-directory>. Register only the public key with the Snowflake user. Store the encrypted .p8 private key as a Render secret file, then set SNOWFLAKE_PRIVATE_KEY_FILE and SNOWFLAKE_PRIVATE_KEY_PASSPHRASE. Key-pair settings take precedence over SNOWFLAKE_PASSWORD, allowing a verified migration before the password is removed.

S3-compatible analytics snapshots

Authenticated administrators can write aggregate-only JSON snapshots through the AWS S3 API with POST /api/v1/object-storage/snapshots, audit them with GET /api/v1/object-storage/snapshots, and request a 15-minute download URL. Snapshots intentionally exclude customer-level PII.

Local development uses MinIO at http://localhost:9001. The same boto3 implementation supports AWS S3 or an S3-compatible provider by changing OBJECT_STORAGE_ENDPOINT_URL, bucket, region, and credentials. No AWS resource is required for local development, and no AWS account is configured by this repository.

Project layout

src/loyalty_analytics/         application, models, schemas, routes, and services
src/loyalty_analytics/static/  responsive dashboard and AI analyst interface
migrations/                    Alembic environment and versioned migrations
scripts/                       seed, bootstrap, and administrator utilities
tests/                         API, service, configuration, integration, and security tests
docs/                          deployment, demo, evaluation, workflow, and portfolio guides
.github/workflows/ci.yml       continuous integration quality gates
.github/workflows/snowflake-sync.yml  scheduled warehouse synchronization
Dockerfile                     non-root, multi-stage production image
compose.yaml                   local API, PostgreSQL, and MinIO services
render.yaml                    managed deployment Blueprint

Project status

Version 1.0 is a complete portfolio release: operational writes, PostgreSQL and Snowflake analytics, constrained AI workflows, S3-compatible snapshots, authentication, CI, scheduled synchronization, and a public free-tier demo. Future iterations could add multi-tenant organizations, change-data capture, richer hosted observability, and distributed rate limiting.