Requirements Model

The FOCUS Requirements Model (current internal version 1.2.0.1, bundled as model-1.2.json) is a machine-readable representation of FOCUS normative requirements for a given version. It defines applicability criteria, check functions, dataset entry points, and requirement dependencies used to evaluate dataset conformance.

Model structure

The JSON file has five top-level sections:

{
  "Details":                { "ModelVersion": "1.2", "FOCUSVersion": "1.2" },
  "ApplicabilityCriteria":  { /* 20 applicability criteria */ },
  "CheckFunctions":         { /* function definitions */ },
  "ModelDatasets":           { "CostAndUsage": { "ModelRules": ["CostAndUsage-D-000-M"] } },
  "ModelRules":              { /* 621 rule definitions */ }
}
SectionPurpose
DetailsModel and FOCUS version numbers
ApplicabilityCriteriaApplicability criteria that gate conditional requirements
CheckFunctionsDefinitions of all check functions (what arguments they take)
ModelDatasetsEntry point — which root rule to start from
ModelRulesAll 621 rule definitions, keyed by rule ID

Source of truth and build pipeline

The Requirements Model originates from the FOCUS_Spec repository. The upstream source files live under specification/requirements_model/:

Source file(s)Purpose
model_details.jsonModel and FOCUS version numbers
applicability_criteria.jsonProvider capability flag definitions
check_functions.jsonCheck function signatures
model_datasets.jsonDataset entry points
model_rules/datasets/costandusage.jsonDataset-level orchestration (D-000/001/002 composites + D-003..D-068 presence rules)
model_rules/columns/*.json57 per-column rule files
model_rules/attributes/*.json9 attribute rule files

The upstream build_json.py script merges all source files into a single build/model-{version}.json artifact. That built artifact is what ships in the validator.

Requirements Model integrity

The upstream Requirements Model test suite enforces these invariants:

  • Every ModelRuleId referenced in a Requirement or Condition CheckModelRule must appear in that rule's Dependencies array
  • Every -C-000- column composite must list its column's presence rule (CostAndUsage-D-*) in Dependencies
  • Rule IDs follow strict {Reference}-{EntityCode}-{NNN}-{ArtifactStatus} format
  • The artifact status suffix (M/C/O) is consistent with requirement level classification (Mandatory, Conditional, Optional)

These guarantees ensure dependency integrity and referential consistency across the model graph.

Rule anatomy

Every rule has this structure:

"BilledCost-C-001-M": {
  "Function": "Type",
  "Reference": "BilledCost",
  "EntityType": "Column",
  "Notes": "",
  "ModelVersionIntroduced": "1.2",
  "Status": "Active",
  "ApplicabilityCriteria": [],
  "Type": "Static",
  "ValidationCriteria": {
    "MustSatisfy": "BilledCost MUST be of type Decimal.",
    "Keyword": "MUST",
    "Requirement": {
      "CheckFunction": "TypeDecimal",
      "ColumnName": "BilledCost"
    },
    "Condition": {},
    "Dependencies": []
  }
}
FieldDescription
FunctionRule category: Presence, Type, Format, Nullability, Validation, or Composite
ReferenceThe column or entity this rule applies to
EntityTypeDataset (structural checks), Column (value checks), or Attribute (cross-cutting format rules)
StatusActive or Deprecated
ApplicabilityCriteriaApplicability criteria required for this rule to apply
TypeStatic (automatable) or Dynamic (requires human judgment)
ValidationCriteria.MustSatisfyHuman-readable requirement text
ValidationCriteria.KeywordRFC 2119 keyword: MUST, MUST NOT, RECOMMENDED, MAY, etc.
ValidationCriteria.RequirementThe check to perform (function + arguments)
ValidationCriteria.ConditionRow-level filter — rule only applies to rows matching this condition
ValidationCriteria.DependenciesOther rule IDs that must complete before this rule runs

Rule ID convention

Every rule ID follows the pattern:

{Reference}-{EntityCode}-{SequenceNumber}-{ArtifactStatus}
SegmentValuesExamples
ReferenceColumn name or CostAndUsageBilledCost, ChargeCategory
EntityCodeD = Dataset, C = Column, A = Attribute
SequenceNumber3-digit, zero-padded. 000 = composite root000, 001, 005
ArtifactStatusM = Mandatory, C = Conditional, O = Optional

Examples:

  • CostAndUsage-D-006-M — Dataset-level rule #6 for BilledCost presence (MUST)
  • BilledCost-C-001-M — Column-level rule #1 for BilledCost type (MUST)
  • BilledCost-C-005-C — Column-level rule #5 for BilledCost conditional validation
  • BilledCost-C-000-M — Composite root that aggregates all BilledCost column rules

Note: the ArtifactStatus suffix reflects the requirement level classification in the model artifact, not the RFC keyword of an individual requirement statement.

Rule hierarchy

All 621 rules form a single directed acyclic graph (DAG) rooted at one entry point. The hierarchy has four tiers:

Tier 0: CostAndUsage-D-000-M          Root composite (AND)
  |
  +-- Tier 1a: CostAndUsage-D-001-M   Presence composite (AND of all D-003..D-068)
  |     +-- CostAndUsage-D-006-M      ColumnPresent("BilledCost")      [MUST]
  |     +-- CostAndUsage-D-007-C      ColumnPresent("BillingAccountType") [Conditional]
  |     +-- CostAndUsage-D-035-M      ColumnPresent("BillingCurrency")  [MUST]
  |     +-- ... (63 presence rules total, one per column)
  |
  +-- Tier 1b: CostAndUsage-D-002-M   Validation composite (AND of all C-000 composites)
        +-- BilledCost-C-000-M         Column composite (AND)
        |     +-- BilledCost-C-001-M   Type check
        |     +-- BilledCost-C-002-M   Format check
        |     +-- BilledCost-C-003-M   Nullability check
        |     +-- BilledCost-C-004-M   Validation check
        |     +-- BilledCost-C-005-C   Conditional validation
        |     +-- BilledCost-C-006-M   Dynamic (skipped)
        |     +-- BilledCost-C-007-M   Dynamic (skipped)
        |
        +-- BillingCurrency-C-000-M    Column composite (AND)
        |     +-- ...
        +-- ... (one composite per column)

Tier 0 is the single root. Tier 1a checks "are all required columns present?" Tier 1b checks "do column values pass?" Each column composite (Tier 2) groups its leaf rules (Tier 3) with an AND.

Rule types

Presence

Checks whether a column exists in the dataset. These are Dataset-level rules (EntityType: "Dataset").

"CostAndUsage-D-006-M": {
  "Function": "Presence",
  "Reference": "BilledCost",
  "EntityType": "Dataset",
  "ValidationCriteria": {
    "MustSatisfy": "BilledCost MUST be present in a FOCUS dataset.",
    "Requirement": { "CheckFunction": "ColumnPresent", "ColumnName": "BilledCost" }
  }
}

If a column is missing, all downstream rules for that column are automatically failed/skipped.

Type

Checks the column's data type. Three check functions:

CheckFunctionExpected types
TypeStringVARCHAR
TypeDecimalDECIMAL, DOUBLE, FLOAT
TypeDateTimeTIMESTAMP, DATE, or ISO 8601 string patterns
"BilledCost-C-001-M": {
  "Function": "Type",
  "ValidationCriteria": {
    "Requirement": { "CheckFunction": "TypeDecimal", "ColumnName": "BilledCost" }
  }
}

Format

Checks value patterns and formats. Six format check functions:

CheckFunctionWhat it validates
FormatNumericDecimal/scientific notation
FormatStringNon-empty string values
FormatDateTimeISO 8601 UTC timestamps
FormatCurrency3-letter uppercase codes (regex)
FormatUnitFOCUS unit format (e.g., "GB", "Hours", "Count")
FormatKeyValueValid JSON key-value objects

Additional specialized check:

  • CheckNationalCurrency — validates against ISO 4217 currency code list

Nullability

Checks null handling. Reuses CheckNotValue or CheckValue with Value: null:

"BilledCost-C-003-M": {
  "Function": "Nullability",
  "ValidationCriteria": {
    "MustSatisfy": "BilledCost MUST NOT be null.",
    "Keyword": "MUST NOT",
    "Requirement": { "CheckFunction": "CheckNotValue", "ColumnName": "BilledCost", "Value": null }
  }
}

Some nullability rules are conditional — "column MUST be null when another column has a specific value":

"CommitmentDiscountName-C-004-C": {
  "Function": "Nullability",
  "ValidationCriteria": {
    "MustSatisfy": "CommitmentDiscountName MUST be null when CommitmentDiscountId is null.",
    "Requirement": { "CheckFunction": "CheckValue", "ColumnName": "CommitmentDiscountName", "Value": null },
    "Condition": { "CheckFunction": "CheckValue", "ColumnName": "CommitmentDiscountId", "Value": null }
  }
}

Validation

Business logic checks on data values. Uses various check functions:

CheckFunctionPurpose
CheckValueColumn equals a specific value
CheckNotValueColumn does not equal a specific value
CheckSameValueTwo columns have the same value
CheckNotSameValueTwo columns have different values
CheckDecimalValueValid decimal number
CheckGreaterOrEqualThanValueNumeric >= threshold
CheckDistinctCountDistinct count across column groups
ColumnByColumnEqualsColumnValuecol_a * col_b == col_c

Example — conditional cross-column validation:

"BilledCost-C-005-C": {
  "Function": "Validation",
  "ValidationCriteria": {
    "MustSatisfy": "BilledCost MUST be 0 where ProviderName != InvoiceIssuerName.",
    "Requirement": { "CheckFunction": "CheckValue", "ColumnName": "BilledCost", "Value": 0 },
    "Condition": { "CheckFunction": "CheckNotSameValue",
                   "ColumnAName": "ProviderName", "ColumnBName": "InvoiceIssuerName" },
    "Dependencies": ["ProviderName-C-000-M", "InvoiceIssuerName-C-000-M"]
  }
}

Composite

Logical grouping of child rules using AND or OR. Composites reference children via CheckModelRule:

"BilledCost-C-000-M": {
  "Function": "Composite",
  "ValidationCriteria": {
    "Requirement": {
      "CheckFunction": "AND",
      "Items": [
        { "CheckFunction": "CheckModelRule", "ModelRuleId": "BilledCost-C-001-M" },
        { "CheckFunction": "CheckModelRule", "ModelRuleId": "BilledCost-C-002-M" },
        { "CheckFunction": "CheckModelRule", "ModelRuleId": "BilledCost-C-003-M" },
        ...
      ]
    },
    "Dependencies": [
      "CostAndUsage-D-006-M",
      "BilledCost-C-001-M", "BilledCost-C-002-M", "BilledCost-C-003-M", ...
    ]
  }
}
  • AND composites pass only if ALL children pass
  • OR composites pass if ANY child passes (used for complex applicability logic)

Dependencies and execution order

How dependencies work

Dependencies are declared in three ways:

  1. Structural — composite rules implicitly depend on their children (via CheckModelRule references in Items)
  2. Explicit — rules list other rule IDs in their Dependencies array (e.g., a conditional validation that needs another column's composite to pass first)
  3. Presence gating — the engine's post-processing automatically cascades presence failures to all rules for that column

Execution sequence for a column

The dependency graph produces this execution order per column:

1. CostAndUsage-D-006-M    Presence     "Is BilledCost present?"
       | (if absent, everything below cascades to fail/skip)
2. BilledCost-C-001-M      Type         "Is it Decimal?"
3. BilledCost-C-002-M      Format       "Matches NumericFormat?"
4. BilledCost-C-003-M      Nullability  "No nulls?"
5. BilledCost-C-004-M      Validation   "Valid decimal values?"
6. BilledCost-C-005-C      Validation   "BilledCost=0 when ProviderName != InvoiceIssuerName?"
7. BilledCost-C-006-M      Dynamic      --> SKIPPED
8. BilledCost-C-007-M      Dynamic      --> SKIPPED
       | (all results aggregated)
9. BilledCost-C-000-M      Composite    AND of rules 2-8

The engine builds a topological sort of the full DAG and processes rules layer by layer. Rules in the same layer (no dependencies between them) could theoretically run in parallel.

Cross-column dependencies

Some rules depend on other columns being validated first. For example, BilledCost-C-005-C depends on ProviderName-C-000-M and InvoiceIssuerName-C-000-M because its condition references both columns. This means the entire ProviderName and InvoiceIssuerName validation must complete before this rule can execute.

Gating mechanisms

Three mechanisms control whether a rule applies:

1. Applicability criteria (dataset-level gate)

Provider capability flags that enable or disable entire groups of rules. If a provider doesn't support a feature, the related rules are marked non-applicable and skipped.

"CostAndUsage-D-007-C": {
  "Function": "Presence",
  "Reference": "BillingAccountType",
  "ApplicabilityCriteria": ["MULTIPLE_BILLING_ACCOUNT_TYPES_SUPPORTED"]
}

The 20 applicability criteria:

CriteriaColumns affected
AVAILABILITY_ZONE_SUPPORTEDAvailabilityZone
CAPACITY_RESERVATION_SUPPORTEDCapacityReservationId, CapacityReservationStatus
COMMITMENT_DISCOUNT_SUPPORTEDCommitmentDiscount* (7 columns)
USAGE_MEASUREMENT_SUPPORTEDConsumedQuantity, ConsumedUnit
NEGOTIATED_PRICING_SUPPORTEDContractedUnitPrice
PUBLIC_PRICE_LIST_SUPPORTEDListUnitPrice, Sku* columns
UNIT_PRICING_SUPPORTEDSku* columns (combined with above)
MULTIPLE_PRICING_CATEGORIES_SUPPORTEDPricingCategory
PRICING_BILLING_CURRENCY_DIFFERENCES_SUPPORTEDPricingCurrency, PricingCurrency* columns
VIRTUAL_CURRENCY_SUPPORTEDPricingCurrency* columns
REGION_SUPPORTEDRegionId, RegionName
BILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTEDResourceId, ResourceName, ResourceType
RESOURCE_TYPE_ASSIGNMENT_SUPPORTEDResourceType (combined with above)
SUB_ACCOUNT_SUPPORTEDSubAccountId, SubAccountName
MULTIPLE_SUB_ACCOUNT_TYPES_SUPPORTEDSubAccountType
MULTIPLE_BILLING_ACCOUNT_TYPES_SUPPORTEDBillingAccountType
ACCOUNT_NAMING_SUPPORTEDBillingAccountName
TAGGING_SUPPORTEDTags

When a presence rule is non-applicable, ALL downstream rules for that column are also marked non-applicable.

2. Conditions (row-level gate)

A rule can have a Condition that limits which rows it applies to:

"Condition": {
  "CheckFunction": "CheckNotSameValue",
  "ColumnAName": "ProviderName",
  "ColumnBName": "InvoiceIssuerName"
}

The rule is only evaluated on rows where the condition is true. Rows that don't match are excluded from violation counts.

3. Static vs Dynamic (automatable gate)

  • Static rules have a Requirement with a CheckFunction and can be executed automatically via SQL
  • Dynamic rules have an empty Requirement: {} and represent requirements that need human judgment or external data (e.g., "BilledCost MUST be denominated in BillingCurrency" — requires knowing the actual currency of each charge)

Dynamic rules are always skipped during automated validation and reported as informational.

Requirement keywords

The Keyword field uses BCP 14 terminology (RFC 2119 and RFC 8174) and drives skip behavior:

KeywordRule suffixEngine behavior
MUST-MAlways executed. Failure = violation.
MUST NOT-MAlways executed. Failure = violation.
SHOULD / SHOULD NOT-CExecuted if applicability criteria are met.
RECOMMENDED-C or -OVaries by rule — some conditional, some optional.
MAY / OPTIONAL-OSkipped entirely (not a requirement).

Schema-only mode

When schema-only mode is enabled, the engine runs full validation as normal but post-filters the results to keep only Presence (63 rules) and Type (56 rules). All Format, Nullability, Validation, and Composite rules are excluded from the output (see backend/src/services/validation/focus_engine.py, schema-only branch). This provides a quick structural report — useful for verifying schema correctness before reviewing full validation results.

FOCUS 1.2 column reference

FOCUS 1.2 defines 57 columns; the model contains 63 Presence rules due to conditional variants.

Mandatory columns (always required)

ColumnData TypeRules
BilledCostDecimalType, NumericFormat, not null, valid decimal, conditional (=0 for third-party charges)
BillingAccountIdStringType, StringFormat, not null
BillingAccountNameStringType, StringFormat, not null
BillingCurrencyStringType, CurrencyFormat (ISO 4217), not null
BillingPeriodEndDateTimeType, DateTimeFormat, not null
BillingPeriodStartDateTimeType, DateTimeFormat, not null, must be < BillingPeriodEnd
ChargeCategoryStringType, StringFormat, not null, allowed values check
ChargeClassStringType, StringFormat, conditional nullability
ChargeDescriptionStringType, StringFormat, not null
ChargePeriodEndDateTimeType, DateTimeFormat, not null
ChargePeriodStartDateTimeType, DateTimeFormat, not null, must be < ChargePeriodEnd
ContractedCostDecimalType, NumericFormat, not null, valid decimal
EffectiveCostDecimalType, NumericFormat, not null, valid decimal, commitment discount rules
InvoiceIssuerNameStringType, StringFormat, not null
ListCostDecimalType, NumericFormat, not null, valid decimal
PricingQuantityDecimalType, NumericFormat, conditional nullability
PricingUnitStringType, UnitFormat, conditional nullability
ProviderNameStringType, StringFormat, not null
PublisherNameStringType, StringFormat, not null
ServiceCategoryStringType, StringFormat, not null, allowed values check
ServiceNameStringType, StringFormat, not null

Conditionally required columns (based on provider capabilities)

ColumnData TypeCriteriaRules
AvailabilityZoneStringAVAILABILITY_ZONE_SUPPORTEDType, StringFormat, conditional nullability
BillingAccountTypeStringMULTIPLE_BILLING_ACCOUNT_TYPES_SUPPORTEDType, StringFormat, not null
CapacityReservationIdStringCAPACITY_RESERVATION_SUPPORTEDType, StringFormat, conditional nullability
CapacityReservationStatusStringCAPACITY_RESERVATION_SUPPORTEDType, StringFormat, conditional nullability, allowed values
CommitmentDiscountCategoryStringCOMMITMENT_DISCOUNT_SUPPORTEDType, StringFormat, conditional nullability, allowed values
CommitmentDiscountIdStringCOMMITMENT_DISCOUNT_SUPPORTEDType, StringFormat, conditional nullability
CommitmentDiscountNameStringCOMMITMENT_DISCOUNT_SUPPORTEDType, StringFormat, conditional nullability
CommitmentDiscountQuantityDecimalCOMMITMENT_DISCOUNT_SUPPORTEDType, NumericFormat, conditional nullability
CommitmentDiscountStatusStringCOMMITMENT_DISCOUNT_SUPPORTEDType, StringFormat, conditional nullability, allowed values
CommitmentDiscountTypeStringCOMMITMENT_DISCOUNT_SUPPORTEDType, StringFormat, conditional nullability
CommitmentDiscountUnitStringCOMMITMENT_DISCOUNT_SUPPORTEDType, UnitFormat, conditional nullability
ConsumedQuantityDecimalUSAGE_MEASUREMENT_SUPPORTEDType, NumericFormat, conditional nullability
ConsumedUnitStringUSAGE_MEASUREMENT_SUPPORTEDType, UnitFormat, conditional nullability
ContractedUnitPriceDecimalNEGOTIATED_PRICING_SUPPORTEDType, NumericFormat, conditional nullability
ListUnitPriceDecimalPUBLIC_PRICE_LIST_SUPPORTEDType, NumericFormat, conditional nullability
PricingCategoryStringMULTIPLE_PRICING_CATEGORIES_SUPPORTEDType, StringFormat, conditional nullability, allowed values
PricingCurrencyStringPRICING_BILLING_CURRENCY_DIFFERENCES_SUPPORTEDType, CurrencyFormat, conditional nullability
PricingCurrencyContractedUnitPriceDecimalComplex (OR of criteria combos)Type, NumericFormat, conditional nullability
PricingCurrencyEffectiveCostDecimalComplex (OR of criteria combos)Type, NumericFormat, conditional nullability
PricingCurrencyListUnitPriceDecimalComplex (OR of criteria combos)Type, NumericFormat, conditional nullability
RegionIdStringREGION_SUPPORTEDType, StringFormat, conditional nullability
RegionNameStringREGION_SUPPORTEDType, StringFormat, conditional nullability
ResourceIdStringBILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTEDType, StringFormat, conditional nullability
ResourceNameStringBILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTEDType, StringFormat, conditional nullability
ResourceTypeStringBILLING_BASED_ON_PROVISIONED_RESOURCES + RESOURCE_TYPE_ASSIGNMENTType, StringFormat, conditional nullability
SkuIdStringPUBLIC_PRICE_LIST + UNIT_PRICINGType, StringFormat, conditional nullability
SkuMeterStringPUBLIC_PRICE_LIST + UNIT_PRICINGType, StringFormat, conditional nullability
SkuPriceDetailsKeyValuePUBLIC_PRICE_LIST + UNIT_PRICINGKeyValueFormat, conditional nullability
SkuPriceIdStringPUBLIC_PRICE_LIST + UNIT_PRICINGType, StringFormat, conditional nullability
SubAccountIdStringSUB_ACCOUNT_SUPPORTEDType, StringFormat, conditional nullability
SubAccountNameStringSUB_ACCOUNT_SUPPORTEDType, StringFormat, conditional nullability
SubAccountTypeStringMULTIPLE_SUB_ACCOUNT_TYPES_SUPPORTEDType, StringFormat, conditional nullability
TagsKeyValueTAGGING_SUPPORTEDKeyValueFormat, conditional nullability

Optional columns

ColumnData TypeRules
ChargeFrequencyStringType, StringFormat, allowed values (rules skipped as MAY/OPTIONAL)
InvoiceIdStringType, StringFormat (rules skipped as RECOMMENDED)
ServiceSubcategoryStringType, StringFormat (rules skipped as RECOMMENDED)