Core Module Development
The Core module is where your business logic lives. Unlike standard modules (AuthProxy, TrexWallet, Chat, CRM), the Core module is written by the project team for each customer.
Architecture
Internet → AuthProxy (reverse proxy + auth)
│
├─→ Core Module (your code)
│ ├── REST API controllers
│ ├── Admin pages (Razor)
│ └── Business logic
│
├─→ TrexWallet (optional)
├─→ Chat (optional)
└─→ CRM (optional)
AuthProxy handles authentication and proxies requests to your Core module. Your Core module receives authenticated requests with user context in HTTP headers.
Request Headers
Every request proxied by AuthProxy includes these headers (only those relevant to the route are added):
| Header | Wire format | Description |
|---|---|---|
X-Crm | string of long (TimeTick) — read as string in TS / JSON | User's CRM ID (universal identifier). Platform int64 ids stay as string end-to-end; never Number(...) them. |
X-Project | numeric string | Project number (Config.Project). |
X-KeyType | numeric string of LoginMethod enum | Authentication method (Cookie, Fido2Key, UserKey, AppLogin, Mcp*, etc.). |
X-Scopes | comma-separated list | List of route paths the user is allowed to call (used by RouteFlags.ScopeCheck). |
X-AppId | numeric string | Validated application identifier when the route has CheckAppId and an app_id is supplied. |
X-MCP-App-Id | numeric string | Application bound to an MCP session. |
X-Pkey-Crm | numeric string | CRM resolved from the public key (header pkey) when the route has CheckPubKey. |
X-Country | ISO country code | Geo enrichment from the GeoIp cache when the route has GeoEnrich. |
X-SignResult | valid (only when set) | Signature on the request body was verified by AuthProxy (paired with X-Signature on the inbound side). |
X-API-Key | shared secret | Internal API key for private endpoints (route flag InternalApi). |
There is no X-User-Id or X-UserId header — read identity from X-Crm.
Project Setup
1. Create ASP.NET Core project
Create a standard ASP.NET Core project for your customer Core module.
2. Add ItBuild.Shared
Add the shared ItBuild project reference. This gives you access to all platform
infrastructure: ApiResponse, DbCore, TimeTick, inter-module clients, etc.
3. Configure Startup
Core startup should load ItBuild configuration, register logging and telemetry, enable controllers/Razor Pages, configure Swagger for development, enable the standard API error envelope, and protect private module endpoints.
4. Configure Runtime Settings
The generated settings include service identity, database connection strings, module URLs, private API key, and observability options. Keep environment-specific values outside the repository and deploy them with the project configuration.
API Development
Controller Pattern
Core APIs are ordinary ASP.NET controllers under the project API prefix. They receive authenticated identity from AuthProxy headers, call platform services through shared module services, and return the standard platform API envelope.
ApiResponse Pattern
All API responses use the ApiResponse<T> wrapper. Success data and structured
errors use the same envelope so PWA clients can handle responses consistently.
Response format:
// Success
{ "result": { "id": "123", "name": "John" } }
// Error
{ "error": { "code": -1100, "message": "Account not found" } }
Null Semantics (Updates)
When updating records, null fields are skipped — they don't overwrite the existing value:
Use the platform update helpers so null fields are skipped instead of clearing existing values. This is especially important for partial profile, settings, and admin edits.
Database
Conventions
| Convention | Rule |
|---|---|
| Table/column names | lowercase_snake_case |
| Primary key | timetick BIGINT (TimeTick ID) |
| No NULLs | All columns NOT NULL with DEFAULT |
| Model class | lowercase matching table name |
Example Table
Tables follow the platform conventions: TimeTick primary key, lowercase snake_case columns, no nullable database columns, and default values for every column.
Example Model
Entity classes mirror the table naming convention. Keep entities internal to Core and expose DTOs from public APIs.
Database Operations
Use DbCore helpers for create/read/update/delete operations and reserve raw SQL for cases where a query shape genuinely needs it. Keep mutations behind service methods so business rules stay in one place.
Using Platform Modules
TrexWallet (Payments)
Use the TrexWallet client for balances, payment orders, transfers, and exchange rates. Core should pass business intent; TrexWallet remains the source of truth for wallet state and settlement.
Chat (Messaging)
Use the shared message service for SMS, email, and chat notifications. Keep message templates and user-facing text in the project layer.
CRM (User Data)
Use the CRM client for profile and contact data. Do not duplicate identity data inside Core unless it is project-specific business state.
Admin Pages
Create Razor Pages in Pages/ for the admin interface:
Admin pages should check admin scopes before rendering data, use shared admin UI helpers, and call Core services rather than embedding business logic directly in the page.
Admin pages are accessible through AuthProxy at /adm/ (configured in route map).
Deployment
The Core module is deployed as a Docker container alongside other modules:
services:
core:
image: mcr.microsoft.com/dotnet/aspnet:10.0-alpine
container_name: project-core
volumes:
- ./Core/1.0.0:/app
- ./configs/core.json:/app/appsettings.json
entrypoint: ["dotnet", "Core.dll"]
networks:
- project-network
AuthProxy routes requests to Core based on the route_map configuration.
Related Documentation
- Platform Overview — architecture and module roles
- AuthProxy — Module Integration — how AuthProxy routes to Core
- AuthProxy — User Scopes — access control
- Real-time Events — SSE and webhooks