Phase 8 ยท Architecture & Data Model
Intelli Backoffice Architecture
ASP.NET Core on an Azure VM, shared Azure SQL data, and a secured OutSystems provisioning API.
1. Components
| Component | Responsibility |
|---|---|
| ASP.NET Core MVC | Three management pages, validation, authorisation, and audit logic. |
| Azure VM | Hosts the published .NET application behind HTTPS and a reverse proxy. |
| Azure SQL | Shared Tenant and UserExtended tables plus the Backoffice-owned BackofficeUser table. |
| OutSystems API | Creates the platform user and assigns the IntelliCampus administrator role. |
2. Simple data model
Existing shared table: Tenant
| Column | Type | Rule |
|---|---|---|
| Id | bigint | Primary key |
| Name | nvarchar(150) | Required, unique |
| Domain | nvarchar(150) | Optional |
| IsActive | bit | Default true |
Existing shared table: UserExtended
| Column | Type | Rule |
|---|---|---|
| Id | bigint | Primary key |
| OutSystemsUserId | nvarchar(100) | Nullable until provisioning succeeds |
| TenantId | bigint | FK to Tenant |
| Name | nvarchar(100) | Required |
| nvarchar(200) | Required, unique within tenant | |
| RoleId | int | 3 (IC_Admin) for a tenant admin |
| ProvisioningStatus | nvarchar(20) | Pending, Provisioned, or Failed |
| IsActive | bit | Default true |
New table: BackofficeUser
| Column | Type | Rule |
|---|---|---|
| Id | bigint | Primary key |
| Name | nvarchar(100) | Required |
| nvarchar(200) | Required, unique | |
| PasswordHash | nvarchar(500) | Never store a plain password |
| Role | nvarchar(30) | SuperAdmin or BackofficeAdmin |
| IsActive | bit | Default true |
Relationship: Tenant 1 โ many UserExtended. BackofficeUser is intentionally independent because Norvia operators are not members of a customer tenant.
3. Tenant admin creation flow
- Validate tenant, name, and email.
- Create UserExtended with TenantId, IC_Admin, and ProvisioningStatus=Pending.
- Call the idempotent OutSystems provisioning API using a server-held credential and the UserExtended ID as the external reference.
- OutSystems creates the platform user, assigns IC_Admin, and returns its UserId.
- Update UserExtended with OutSystemsUserId and ProvisioningStatus=Provisioned; record Failed when the call cannot complete.
- Write an audit entry and show the result.
Production design should use an idempotency key and retry-safe API. If the API succeeds but the database write fails, the operation must be reconcilable.