12. Runtime Configuration
12.1 Shumoul.MultiTenancyApi.Host
| Key | Purpose |
|---|---|
DatabaseSettings:ConnectionString | The central Saas database — where all 6 onboarding tables live |
OnboardingApplyBridgeSettings:Enabled | Must be true for apply to do anything other than return a 501-style "bridge not configured" failure |
OnboardingApplyBridgeSettings:BackEndBaseUrl | Base URL of the Shumoul.Api instance to call, e.g. https://erp.api.shumoul.com |
OnboardingApplyBridgeSettings:ApplySettingsPath | Relative path, normally api/internal/onboarding/apply-settings-patch |
OnboardingApplyBridgeSettings:InternalApiKey | Must exactly match Shumoul.Api's InternalServiceAuthSettings:OnboardingApplyApiKey — this is a shared secret between the two hosts, not a per-host value |
OnboardingApplyBridgeSettings:TimeoutSeconds | HTTP client timeout for the bridge call (default 60) |
JwtSettings:key | Must exactly match Shumoul.Api's signing key — this host validates the same JWTs Shumoul.Api issues, it does not issue its own |
12.2 Shumoul.Api
| Key | Purpose |
|---|---|
InternalServiceAuthSettings:OnboardingApplyApiKey | The shared secret the internal bridge presents via X-Shumoul-Internal-Key — must match the MultiTenancy host's OnboardingApplyBridgeSettings:InternalApiKey |
DatabaseSettings:ConnectionString | The root/host database connection |
ConnectionStrings:ApplicationConnection | Application connection string used by Identity/Hangfire |
JwtSettings:key | Same shared signing key as above |
12.3 Secrets convention
Neither key ever appears in plaintext in a committed appsettings.json — both repositories use a
**FROM_ENVIRONMENT** placeholder convention, resolved at runtime from environment variables (standard
KeyName__NestedKey double-underscore binding) or machine-level secret stores. Never commit a real value for
either key.
12.4 Verifying the two hosts agree
If apply fails with "Tenant could not be resolved." in production (as opposed to during a deliberate
tenant-mismatch test), the most common cause is the internal bridge not forwarding the TenantId header
correctly, or the two hosts' JwtSettings:key values having drifted apart. See
Chapter 16 — Operational Notes for the diagnostic sequence.
12.5 AppliedBy verification note
TenantOnboardingApplyLogs.AppliedBy is populated directly from the authenticated caller's JWT
NameIdentifier claim (via OnboardingService.CurrentUserId) — it is never a system or service account
id, even though the write physically happens through the internal bridge. This was explicitly re-verified
against real database rows during the Phase 1.4 and Phase 1.5 hardening passes: the value recorded always
matched the test JWT's NameIdentifier exactly.
