Portal Community

FormGroupDefinition Type

// packages/types-js/src/FormGroupDefinition.ts

interface FormGroupDefinition {
  /** Stable kebab-case identifier — matches CategoryName in the database */
  formGroupId:  string;

  /** Human-readable label shown in Studio */
  label:        string;

  /** The owning application's package or project name */
  ownerApp:     string;

  /** Database FormCategoryID — must equal formIdRange.start / 100 */
  categoryId:   number;

  /** Inclusive FormID range owned by this group */
  formIdRange: {
    start: number;   // Inclusive
    end:   number;   // Inclusive
  };

  /** Allow the AI generation pipeline to create forms in this group */
  aiGenerationEnabled: boolean;

  /** Allow tenant-level overrides on forms in this group */
  tenantOverrideable:  boolean;

  /** Optional: default PrimaryUsage written to all new forms in this group */
  defaultPrimaryUsage?: string;
}

GuardRails — Complete Example

// src/formGroups/guardRailsGroup.ts
import type { FormGroupDefinition } from '@atlas-forms/types-js';

export const guardRailsGroup: FormGroupDefinition = {
  formGroupId:          'guard-rails',
  label:                'GuardRails',
  ownerApp:             'BizFirst.Ai.ProcessSecurity',
  categoryId:           130,
  formIdRange: {
    start: 13000,
    end:   13099,
  },
  aiGenerationEnabled:  true,
  tenantOverrideable:   true,
  defaultPrimaryUsage:  'guardrails',
};

Field Reference

FieldRequiredConstraintNotes
formGroupIdYesUnique, kebab-caseStable — never rename after first form is created
labelYesShown in Studio UI dropdowns
ownerAppYesIdentifies the responsible team for support routing
categoryIdYesMust equal formIdRange.start / 100Validated at registration time
formIdRange.startYesMultiple of 100; non-overlappingChecked against registry at startup
formIdRange.endYes= start + 99Each group always gets exactly 100 IDs
aiGenerationEnabledYesBooleanWhen false the AI pipeline refuses to generate in this group
tenantOverrideableYesBooleanWhen false, tenant override rows are rejected
defaultPrimaryUsageNoPre-fills PrimaryUsage in Atlas Forms Studio when creating a new form in this group

Validation at Registration

registerFormGroup() validates the definition before writing it to the registry. Violations throw immediately at application startup so they cannot go unnoticed:

// Validations performed by registerFormGroup()
// 1. formGroupId is unique in the registry
// 2. categoryId === Math.floor(formIdRange.start / 100)
// 3. formIdRange.end === formIdRange.start + 99
// 4. formIdRange does not overlap any already-registered group
// 5. formGroupId matches /^[a-z][a-z0-9-]*$/ (kebab-case)

// If any check fails:
// throw new Error(`[AtlasForms] registerFormGroup: ${reason}`);
Keep the Definition File Small The FormGroupDefinition JSON contract should contain only group-level metadata. Individual form schemas belong in separate SQL data files, not in this definition. The definition is loaded at startup; form schemas are loaded on demand.