Files
AdPlatform-Server/Registration
Grae Jones 7ce747ce48
All checks were successful
Registration / build-deploy (push) Successful in 1m13s
Reg Fix 1
2026-03-23 14:02:58 -07:00
..
2026-03-22 09:37:28 -07:00
2026-03-23 14:02:58 -07:00
2026-03-22 09:37:28 -07:00
2026-03-14 13:50:09 -07:00
2026-03-22 21:02:03 -07:00
2026-03-23 08:48:32 -07:00
2026-03-17 18:23:32 -07:00
2026-03-22 21:02:03 -07:00
2026-03-22 21:02:03 -07:00
2026-03-22 09:37:28 -07:00
2026-03-22 09:37:28 -07:00
2026-03-22 09:37:28 -07:00

Registration Service

ASP.NET Core (.NET 8) service for managing prospect registration in AdPlatform. Self-hosted via docker-compose as registration:8080 behind nginx / Gateway.

Architecture

Client SPA (client.positivespend.com)
  └─► Gateway (portal.positivespend.com)
        └─► Registration API (regapi.positivespend.com → registration:8080)
              ├─► dbRegistration  (10.10.99.212 — Registrations table, spRegistration)
              └─► CIAM            (PositiveSpendClients.ciamlogin.com — token validation)

Management API (mgmt.positivespend.com)
  └─► Registration API  (admin endpoints, x-functions-key auth)
        └─► dbRegistration

The Registration service never touches dbAdPlatform. Management never touches dbRegistration. Approval provisioning into dbAdPlatform is the Management API's responsibility, called after the complete action marks a registration as Approved.

Endpoints

Method Route Auth Description
POST /api/registration/register Bearer (CIAM JWT) New prospect signup
GET /api/registration/pending x-functions-key List pending applicants
GET /api/registration/item/{id} x-functions-key Get single applicant
POST /api/registration/action/{id}/reject x-functions-key Reject applicant
POST /api/registration/action/{id}/complete x-functions-key Mark approved
GET /api/health Anonymous Health check

entraSubjectId is never read from the request body on /register — it is extracted from the validated CIAM Bearer token (OID claim). The client cannot spoof it.

Authentication

Client-facing endpoint (/register): Bearer token issued by PositiveSpendClients.ciamlogin.com (tenant cbf8b7d7). Validated by Microsoft.Identity.Web against the CIAM tenant. The Client SPA acquires this token via MSAL after the user signs in with Google, Apple, or Microsoft.

Admin endpoints (pending / item / reject / complete): x-functions-key header validated by ApiKeyAuthFilter. Key must match Registration__FunctionKey env var. These endpoints are called by the Management API, not the browser.

CIAM Tenant Reference

Field Value
Tenant Positive Spend Clients
Tenant ID cbf8b7d7-1e13-486d-b5b0-287ba79fdf0b
Client SPA App ID c426967f-bfcc-46af-b4e5-d69dc01cbf75
Authority https://PositiveSpendClients.ciamlogin.com/cbf8b7d7.../

This is the client-facing CIAM tenant — separate from the internal positivespend.com org tenant (f56a3c51) used by Management and the Tech/Admin consoles.

Mock Mode

Switch in Program.cs to run without a database (seeds 4 test applicants in memory):

services.AddSingleton<IRegistrationDataService, MockDataService>();

State resets on container restart — by design.

Database Setup

Run dbo.spRegistration.sql against dbRegistration on 10.10.99.212 once. It is idempotent (CREATE OR ALTER PROCEDURE, IF OBJECT_ID ... IS NULL guard on the table).

docker-compose Environment Variables

# SQL Server
ConnectionStrings__Sql=Server=10.10.99.212;Database=dbRegistration;User Id=appAdPlatformReg;Password=...;TrustServerCertificate=True;

# CIAM — already correct in .env
AzureAd__Instance=https://PositiveSpendClients.ciamlogin.com/
AzureAd__TenantId=cbf8b7d7-1e13-486d-b5b0-287ba79fdf0b
AzureAd__ClientId=c426967f-bfcc-46af-b4e5-d69dc01cbf75

# CORS — already in .env
CORS__AllowedOrigins=https://client.positivespend.com,https://portal.positivespend.com,...

# Admin key — already in .env
Registration__FunctionKey=mra0B2boC5m36E7CUn-Urhwp7k3t3QvPZKjJvtNVEdVgAzFuuaAyRA==

Health Check

curl https://regapi.positivespend.com/api/health
# {"ok":true,"service":"registration","mode":"database","timestamp":"..."}

SSL

sudo certbot --nginx -d regapi.positivespend.com

Host Swap — Restore Azure Functions

Three files change. Everything else (Data layer, Mock layer, models, SQL) is identical.

File Change
Registration.csproj Comment ASP.NET Core ItemGroup, uncomment Functions ItemGroup, restore <AzureFunctionsVersion>v4</AzureFunctionsVersion>, change Sdk to Microsoft.NET.Sdk
Program.cs Comment ASP.NET Core block, uncomment Functions HostBuilder block
Functions/RegistrationFunctions.cs Swap class declaration, swap each method signature (all marked ◄ INACTIVE)

Client changes when restoring Functions:

  • authConfig.js: set API_BASE_URL to the Azure Function App URL, set API_FUNCTION_KEY from Azure Portal → App Keys → default

Run locally in Functions mode:

func start
curl http://localhost:7071/api/health