Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Asset Platform Demo

Runnable GitHub showcase project for a multi-tenant asset management architecture.

This is a small .NET demo that maps to the architecture topics you have been preparing:

  • IdentityService / token service
  • JWT creation and validation
  • SecurityFilter-style middleware
  • Human vs machine identity
  • Tenant-aware authorization
  • Trading order submission
  • Reconciliation batch ingestion
  • Outbox pattern
  • Idempotency key
  • AKS/Helm/Argo CD deployment shape
  • Angular frontend
  • SignalR live order saga updates
  • MFA demo flow
  • Optimistic concurrency with SQL rowversion production mapping
  • Dockerfile for container build
  • Terraform module for saga orchestrator autoscaling with KEDA or HPA
  • Packable NuGet package for reusable SecurityFilter/JWT context helpers
  • GitHub Actions templates for CI, NuGet publishing, and container publishing

Why This Fits Your Profile

This project is good to show in interviews because it connects architecture to running code.

You can say:

I built a small asset management platform demo where IdentityService issues JWTs, a SecurityFilter validates claims, trading and reconciliation APIs enforce tenant/permission checks, and the trading API writes an outbox event with idempotency. The same app includes AKS/Helm/Argo deployment notes for blue-green and canary rollout.

Run Locally

$env:DOTNET_CLI_HOME="$PWD\work\.dotnet"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE="1"
dotnet run --project .\src\AssetPlatform.Demo\AssetPlatform.Demo.csproj --urls http://localhost:5080

Health check:

Invoke-RestMethod http://localhost:5080/health/ready

Run Angular Frontend

The frontend is in:

frontend/asset-platform-ui

Install dependencies and run:

cd .\frontend\asset-platform-ui
npm install
npm start

Open:

http://localhost:4200

The Angular UI demonstrates:

  • MFA start and verify flow.
  • In-memory token handling.
  • API calls with bearer token interceptor.
  • SignalR connection using accessTokenFactory.
  • Live order saga updates.
  • Optimistic concurrency conflict demo using If-Match.

Build Container Image

Dockerfile:

Dockerfile

Build:

docker build -t asset-platform-demo:local .

Run:

docker run --rm -p 5080:8080 asset-platform-demo:local

Docker Compose real-time run:

cd .\deploy\compose
docker compose up --build

This starts:

Backend API + SignalR -> http://localhost:5080
Angular UI            -> http://localhost:4200

Build and Publish NuGet Package

NuGet package project:

src/AssetPlatform.Security

Pack locally:

.\scripts\pack-nuget.ps1

Publish to NuGet:

.\scripts\publish-nuget.ps1 -ApiKey "<your-nuget-api-key>"

Package created by local verification:

artifacts/nuget/AssetPlatform.Security.0.1.0.nupkg

GitHub Actions publishing:

.github/workflows/publish-nuget.yml

Required repository secret:

NUGET_API_KEY

Publish Container

Local script:

.\scripts\publish-container.ps1 `
  -Registry "ghcr.io" `
  -Repository "your-org/asset-platform-demo" `
  -Tag "0.1.0"

GitHub Actions publishing:

.github/workflows/publish-container.yml

Default image target:

ghcr.io/<owner>/<repo>/asset-platform-demo:<tag>

Deploy Saga Orchestrator Autoscaling With Terraform

Terraform module:

deploy/terraform/saga-orchestrator

Copy variables:

cd .\deploy\terraform\saga-orchestrator
Copy-Item terraform.tfvars.example terraform.tfvars

Apply:

terraform init
terraform plan -var-file terraform.tfvars
terraform apply -var-file terraform.tfvars

Autoscaling modes:

autoscaling_mode = "keda" # Service Bus / event-driven saga workers
autoscaling_mode = "hpa"  # CPU-based synchronous workload scaling
autoscaling_mode = "none" # fixed replicas

Important:

Do not attach KEDA and a separate HPA to the same deployment by default.
KEDA creates an HPA internally for ScaledObject.
Use KEDA for queue-driven saga workers.
Use HPA for CPU-driven API pods.

Demo Flow

1. Create a Human Token

$human = Invoke-RestMethod -Method Post http://localhost:5080/identity/token/human `
  -ContentType "application/json" `
  -Body '{
    "tenantId": "tenant-pe-firm-001",
    "userId": "user-trader-001",
    "email": "trader@examplepe.com",
    "roles": ["Trader"],
    "permissions": ["Order.Submit", "Order.Read", "Recon.Exception.Read", "Platform.Outbox.Read"],
    "portfolioAccess": ["P1001", "P1002"]
  }'

2. Check Claims

Invoke-RestMethod http://localhost:5080/whoami `
  -Headers @{ Authorization = "Bearer $($human.access_token)" }

3. Submit a Trading Order

Invoke-RestMethod -Method Post http://localhost:5080/trading/orders `
  -Headers @{
    Authorization = "Bearer $($human.access_token)"
    "Idempotency-Key" = "demo-order-001"
  } `
  -ContentType "application/json" `
  -Body '{
    "portfolioId": "P1001",
    "symbol": "MSFT",
    "side": "BUY",
    "quantity": 100
  }'

Run the same command again with the same Idempotency-Key. It returns the same order instead of creating a duplicate.

4. Create a Machine Token

$system = Invoke-RestMethod -Method Post http://localhost:5080/identity/token/system `
  -ContentType "application/json" `
  -Body '{
    "tenantId": "tenant-pe-firm-001",
    "clientId": "external-oms-prod",
    "sourceSystem": "ExternalOMS",
    "roles": ["OMS"],
    "permissions": ["Recon.FileIngest", "Platform.Outbox.Read"]
  }'

5. Queue a Reconciliation Batch

Invoke-RestMethod -Method Post http://localhost:5080/recon/batches `
  -Headers @{ Authorization = "Bearer $($system.access_token)" } `
  -ContentType "application/json" `
  -Body '{
    "custodianId": "CUST01",
    "businessDate": "2026-07-16"
  }'

6. View Outbox Events

Invoke-RestMethod http://localhost:5080/events/outbox `
  -Headers @{ Authorization = "Bearer $($human.access_token)" }

7. Demo MFA Flow

$mfa = Invoke-RestMethod -Method Post http://localhost:5080/identity/mfa/start `
  -ContentType "application/json" `
  -Body '{ "email": "trader@examplepe.com" }'

$verified = Invoke-RestMethod -Method Post http://localhost:5080/identity/mfa/verify `
  -ContentType "application/json" `
  -Body (@{
    challengeId = $mfa.challengeId
    code = $mfa.demoCode
    tenantId = "tenant-pe-firm-001"
    userId = "user-trader-001"
    email = "trader@examplepe.com"
  } | ConvertTo-Json)

8. Demo Optimistic Concurrency

Every order has a version.

Invoke-RestMethod -Method Patch http://localhost:5080/trading/orders/<order-id>/status `
  -Headers @{
    Authorization = "Bearer $($human.access_token)"
    "If-Match" = "1"
  } `
  -ContentType "application/json" `
  -Body '{ "status": "ManualOverride" }'

If the saga already advanced the order to a newer version, the API returns 409 Conflict.

What To Explain In An Interview

Identity

The identity endpoint simulates IdentityService. It creates internal platform JWTs after external authentication. In production, Okta/Entra would authenticate the user, and IdentityService would enrich claims using tenant and Ewealthmanagement entitlements.

SecurityFilter

The middleware validates the JWT signature, issuer, audience, and expiry, then builds a request security context. APIs do not parse raw tokens directly.

Multi-Tenant Safety

Every order and recon batch is stored with tenantId from the validated token, not from the request body.

Trading Safety

Order submission requires Order.Submit permission, portfolio access, and an idempotency key. The outbox event is created with the order so downstream processing can be reliable.

Reconciliation Safety

Recon ingestion is machine-friendly and partitioned by tenant, custodian, and business date. This maps well to Service Bus, KEDA, and idempotent workers in AKS.

Production Mapping

Demo Concept Production Equivalent
/identity/token/human Okta/Entra login plus IdentityService token exchange
Demo JWT signer Enterprise token service / IdentityService signing keys
Middleware SecurityFilter library
In-memory store Azure SQL / Cosmos DB
Outbox list SQL outbox table + Service Bus publisher
System token Service Principal or Managed Identity
Tenant claim Tenant isolation key
Portfolio access claim EWM entitlement service
Helm/Argo folder AKS deployment pipeline
Angular frontend Trading/recon UI
SignalR hub Live order/trade status stream
Version field Azure SQL rowversion / ETag
Dockerfile AKS container image
Terraform KEDA mode Service Bus queue-depth autoscaling for saga workers
Terraform HPA mode CPU autoscaling for synchronous workloads
AssetPlatform.Security NuGet Reusable SecurityFilter/JWT context package
GitHub Actions CI, NuGet publish, container publish

Repository Name Ideas

Use one of these for GitHub:

asset-platform-identity-trading-recon-demo
fintech-aks-rollout-identity-demo
multi-tenant-asset-management-platform-demo
trading-recon-securityfilter-demo

About

Multi tenant architecture with orchestration saga platform along with consistent database in sql

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages