Atlas Forms
Tenant-Specific Forms
When a tenant needs an entirely new form that has no equivalent in the base group, it is declared as an addition. Additions live in the tenant's private FormID range and are invisible to all other tenants.
When to Use Additions
Use an addition (not a control-level override) when:
- The tenant requires a completely different form structure that cannot be derived from the base form
- The tenant has a regulatory requirement for a unique form that does not apply globally (e.g., GDPR consent form only required in the EU)
- The tenant has a product module that other tenants do not have access to
Addition FormIDs
Tenant-specific forms use FormIDs from the tenant's private range. See Tenant FormID Ranges for the formula. For Tenant 9 overriding the GuardRails group (range start 13000):
// Tenant 9 private FormID range for GuardRails:
// tenantId × 100000 + groupStart = 9 × 100000 + 13000 = 913000
// FormIDs 913000–913099 are Tenant 9's private GuardRails range
Declaring an Addition
const acmeAdditions: FormGroupOverride = {
baseCategoryId: 130,
tenantId: 9,
overrides: [], // No modifications to base forms
additions: [
{
formId: 913001,
formCode: 'Acme_GuardRail_GdprConsent_Edit',
formTypeId: 2,
primaryUsage: 'guardrails',
nodeUsage: 'acme-guardrail-gdpr-consent',
schema: {
"metadata": {
"formId": 913001,
"title": "GDPR Consent Configuration"
},
"sections": [
{ "id": "consent-text", "title": "Consent Text", "order": 1 },
{ "id": "settings", "title": "Settings", "order": 2 }
],
"controls": [
{
"id": "consentLanguage", "type": "select", "sectionId": "consent-text", "order": 1,
"label": "Language",
"options": [
{ "value": "en", "label": "English" },
{ "value": "de", "label": "German" },
{ "value": "fr", "label": "French" }
],
"binding": { "source": "$json", "path": "consentLanguage" }
},
{
"id": "consentText", "type": "textarea", "sectionId": "consent-text", "order": 2,
"label": "Consent Statement",
"binding": { "source": "$json", "path": "consentText" },
"validation": { "required": true, "minLength": 50 }
}
],
"actions": [
{ "id": "save", "label": "Save", "type": "submit", "config": { "endpoint": "/api/acme/guardrails/gdpr-consent/save" } },
{ "id": "cancel", "label": "Cancel", "type": "navigate", "config": { "target": "GuardRail_List" } }
]
}
}
]
};
Addition vs Override
| Scenario | Use |
|---|---|
| Change an existing field's label for this tenant | Override (overrideSchema) |
| Add a new field to an existing form | Override (overrideSchema with an additions key) |
| Completely different form structure | Addition (new FormID in tenant range) |
| Regulatory-mandated form only for this tenant | Addition (new FormID in tenant range) |
| Tenant-specific workflow node form | Addition with nodeUsage set |
Additions Are Not Visible to Other Tenants
A form with
FormID = 913001 and TenantID = 9 is only returned when the form loader queries with TenantID = 9. Other tenants querying the same group will never see this form in their list or in routing.