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 */ }
}
| Section | Purpose |
|---|---|
Details | Model and FOCUS version numbers |
ApplicabilityCriteria | Applicability criteria that gate conditional requirements |
CheckFunctions | Definitions of all check functions (what arguments they take) |
ModelDatasets | Entry point — which root rule to start from |
ModelRules | All 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.json | Model and FOCUS version numbers |
applicability_criteria.json | Provider capability flag definitions |
check_functions.json | Check function signatures |
model_datasets.json | Dataset entry points |
model_rules/datasets/costandusage.json | Dataset-level orchestration (D-000/001/002 composites + D-003..D-068 presence rules) |
model_rules/columns/*.json | 57 per-column rule files |
model_rules/attributes/*.json | 9 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
ModelRuleIdreferenced in a Requirement or ConditionCheckModelRulemust appear in that rule'sDependenciesarray - 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": []
}
}
| Field | Description |
|---|---|
Function | Rule category: Presence, Type, Format, Nullability, Validation, or Composite |
Reference | The column or entity this rule applies to |
EntityType | Dataset (structural checks), Column (value checks), or Attribute (cross-cutting format rules) |
Status | Active or Deprecated |
ApplicabilityCriteria | Applicability criteria required for this rule to apply |
Type | Static (automatable) or Dynamic (requires human judgment) |
ValidationCriteria.MustSatisfy | Human-readable requirement text |
ValidationCriteria.Keyword | RFC 2119 keyword: MUST, MUST NOT, RECOMMENDED, MAY, etc. |
ValidationCriteria.Requirement | The check to perform (function + arguments) |
ValidationCriteria.Condition | Row-level filter — rule only applies to rows matching this condition |
ValidationCriteria.Dependencies | Other rule IDs that must complete before this rule runs |
Rule ID convention
Every rule ID follows the pattern:
{Reference}-{EntityCode}-{SequenceNumber}-{ArtifactStatus}
| Segment | Values | Examples |
|---|---|---|
| Reference | Column name or CostAndUsage | BilledCost, ChargeCategory |
| EntityCode | D = Dataset, C = Column, A = Attribute | — |
| SequenceNumber | 3-digit, zero-padded. 000 = composite root | 000, 001, 005 |
| ArtifactStatus | M = 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 validationBilledCost-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:
| CheckFunction | Expected types |
|---|---|
TypeString | VARCHAR |
TypeDecimal | DECIMAL, DOUBLE, FLOAT |
TypeDateTime | TIMESTAMP, 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:
| CheckFunction | What it validates |
|---|---|
FormatNumeric | Decimal/scientific notation |
FormatString | Non-empty string values |
FormatDateTime | ISO 8601 UTC timestamps |
FormatCurrency | 3-letter uppercase codes (regex) |
FormatUnit | FOCUS unit format (e.g., "GB", "Hours", "Count") |
FormatKeyValue | Valid 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:
| CheckFunction | Purpose |
|---|---|
CheckValue | Column equals a specific value |
CheckNotValue | Column does not equal a specific value |
CheckSameValue | Two columns have the same value |
CheckNotSameValue | Two columns have different values |
CheckDecimalValue | Valid decimal number |
CheckGreaterOrEqualThanValue | Numeric >= threshold |
CheckDistinctCount | Distinct count across column groups |
ColumnByColumnEqualsColumnValue | col_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:
- Structural — composite rules implicitly depend on their children (via
CheckModelRulereferences inItems) - Explicit — rules list other rule IDs in their
Dependenciesarray (e.g., a conditional validation that needs another column's composite to pass first) - 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:
| Criteria | Columns affected |
|---|---|
AVAILABILITY_ZONE_SUPPORTED | AvailabilityZone |
CAPACITY_RESERVATION_SUPPORTED | CapacityReservationId, CapacityReservationStatus |
COMMITMENT_DISCOUNT_SUPPORTED | CommitmentDiscount* (7 columns) |
USAGE_MEASUREMENT_SUPPORTED | ConsumedQuantity, ConsumedUnit |
NEGOTIATED_PRICING_SUPPORTED | ContractedUnitPrice |
PUBLIC_PRICE_LIST_SUPPORTED | ListUnitPrice, Sku* columns |
UNIT_PRICING_SUPPORTED | Sku* columns (combined with above) |
MULTIPLE_PRICING_CATEGORIES_SUPPORTED | PricingCategory |
PRICING_BILLING_CURRENCY_DIFFERENCES_SUPPORTED | PricingCurrency, PricingCurrency* columns |
VIRTUAL_CURRENCY_SUPPORTED | PricingCurrency* columns |
REGION_SUPPORTED | RegionId, RegionName |
BILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTED | ResourceId, ResourceName, ResourceType |
RESOURCE_TYPE_ASSIGNMENT_SUPPORTED | ResourceType (combined with above) |
SUB_ACCOUNT_SUPPORTED | SubAccountId, SubAccountName |
MULTIPLE_SUB_ACCOUNT_TYPES_SUPPORTED | SubAccountType |
MULTIPLE_BILLING_ACCOUNT_TYPES_SUPPORTED | BillingAccountType |
ACCOUNT_NAMING_SUPPORTED | BillingAccountName |
TAGGING_SUPPORTED | Tags |
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
Requirementwith aCheckFunctionand 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:
| Keyword | Rule suffix | Engine behavior |
|---|---|---|
MUST | -M | Always executed. Failure = violation. |
MUST NOT | -M | Always executed. Failure = violation. |
SHOULD / SHOULD NOT | -C | Executed if applicability criteria are met. |
RECOMMENDED | -C or -O | Varies by rule — some conditional, some optional. |
MAY / OPTIONAL | -O | Skipped 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)
| Column | Data Type | Rules |
|---|---|---|
| BilledCost | Decimal | Type, NumericFormat, not null, valid decimal, conditional (=0 for third-party charges) |
| BillingAccountId | String | Type, StringFormat, not null |
| BillingAccountName | String | Type, StringFormat, not null |
| BillingCurrency | String | Type, CurrencyFormat (ISO 4217), not null |
| BillingPeriodEnd | DateTime | Type, DateTimeFormat, not null |
| BillingPeriodStart | DateTime | Type, DateTimeFormat, not null, must be < BillingPeriodEnd |
| ChargeCategory | String | Type, StringFormat, not null, allowed values check |
| ChargeClass | String | Type, StringFormat, conditional nullability |
| ChargeDescription | String | Type, StringFormat, not null |
| ChargePeriodEnd | DateTime | Type, DateTimeFormat, not null |
| ChargePeriodStart | DateTime | Type, DateTimeFormat, not null, must be < ChargePeriodEnd |
| ContractedCost | Decimal | Type, NumericFormat, not null, valid decimal |
| EffectiveCost | Decimal | Type, NumericFormat, not null, valid decimal, commitment discount rules |
| InvoiceIssuerName | String | Type, StringFormat, not null |
| ListCost | Decimal | Type, NumericFormat, not null, valid decimal |
| PricingQuantity | Decimal | Type, NumericFormat, conditional nullability |
| PricingUnit | String | Type, UnitFormat, conditional nullability |
| ProviderName | String | Type, StringFormat, not null |
| PublisherName | String | Type, StringFormat, not null |
| ServiceCategory | String | Type, StringFormat, not null, allowed values check |
| ServiceName | String | Type, StringFormat, not null |
Conditionally required columns (based on provider capabilities)
| Column | Data Type | Criteria | Rules |
|---|---|---|---|
| AvailabilityZone | String | AVAILABILITY_ZONE_SUPPORTED | Type, StringFormat, conditional nullability |
| BillingAccountType | String | MULTIPLE_BILLING_ACCOUNT_TYPES_SUPPORTED | Type, StringFormat, not null |
| CapacityReservationId | String | CAPACITY_RESERVATION_SUPPORTED | Type, StringFormat, conditional nullability |
| CapacityReservationStatus | String | CAPACITY_RESERVATION_SUPPORTED | Type, StringFormat, conditional nullability, allowed values |
| CommitmentDiscountCategory | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, StringFormat, conditional nullability, allowed values |
| CommitmentDiscountId | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, StringFormat, conditional nullability |
| CommitmentDiscountName | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, StringFormat, conditional nullability |
| CommitmentDiscountQuantity | Decimal | COMMITMENT_DISCOUNT_SUPPORTED | Type, NumericFormat, conditional nullability |
| CommitmentDiscountStatus | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, StringFormat, conditional nullability, allowed values |
| CommitmentDiscountType | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, StringFormat, conditional nullability |
| CommitmentDiscountUnit | String | COMMITMENT_DISCOUNT_SUPPORTED | Type, UnitFormat, conditional nullability |
| ConsumedQuantity | Decimal | USAGE_MEASUREMENT_SUPPORTED | Type, NumericFormat, conditional nullability |
| ConsumedUnit | String | USAGE_MEASUREMENT_SUPPORTED | Type, UnitFormat, conditional nullability |
| ContractedUnitPrice | Decimal | NEGOTIATED_PRICING_SUPPORTED | Type, NumericFormat, conditional nullability |
| ListUnitPrice | Decimal | PUBLIC_PRICE_LIST_SUPPORTED | Type, NumericFormat, conditional nullability |
| PricingCategory | String | MULTIPLE_PRICING_CATEGORIES_SUPPORTED | Type, StringFormat, conditional nullability, allowed values |
| PricingCurrency | String | PRICING_BILLING_CURRENCY_DIFFERENCES_SUPPORTED | Type, CurrencyFormat, conditional nullability |
| PricingCurrencyContractedUnitPrice | Decimal | Complex (OR of criteria combos) | Type, NumericFormat, conditional nullability |
| PricingCurrencyEffectiveCost | Decimal | Complex (OR of criteria combos) | Type, NumericFormat, conditional nullability |
| PricingCurrencyListUnitPrice | Decimal | Complex (OR of criteria combos) | Type, NumericFormat, conditional nullability |
| RegionId | String | REGION_SUPPORTED | Type, StringFormat, conditional nullability |
| RegionName | String | REGION_SUPPORTED | Type, StringFormat, conditional nullability |
| ResourceId | String | BILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTED | Type, StringFormat, conditional nullability |
| ResourceName | String | BILLING_BASED_ON_PROVISIONED_RESOURCES_SUPPORTED | Type, StringFormat, conditional nullability |
| ResourceType | String | BILLING_BASED_ON_PROVISIONED_RESOURCES + RESOURCE_TYPE_ASSIGNMENT | Type, StringFormat, conditional nullability |
| SkuId | String | PUBLIC_PRICE_LIST + UNIT_PRICING | Type, StringFormat, conditional nullability |
| SkuMeter | String | PUBLIC_PRICE_LIST + UNIT_PRICING | Type, StringFormat, conditional nullability |
| SkuPriceDetails | KeyValue | PUBLIC_PRICE_LIST + UNIT_PRICING | KeyValueFormat, conditional nullability |
| SkuPriceId | String | PUBLIC_PRICE_LIST + UNIT_PRICING | Type, StringFormat, conditional nullability |
| SubAccountId | String | SUB_ACCOUNT_SUPPORTED | Type, StringFormat, conditional nullability |
| SubAccountName | String | SUB_ACCOUNT_SUPPORTED | Type, StringFormat, conditional nullability |
| SubAccountType | String | MULTIPLE_SUB_ACCOUNT_TYPES_SUPPORTED | Type, StringFormat, conditional nullability |
| Tags | KeyValue | TAGGING_SUPPORTED | KeyValueFormat, conditional nullability |
Optional columns
| Column | Data Type | Rules |
|---|---|---|
| ChargeFrequency | String | Type, StringFormat, allowed values (rules skipped as MAY/OPTIONAL) |
| InvoiceId | String | Type, StringFormat (rules skipped as RECOMMENDED) |
| ServiceSubcategory | String | Type, StringFormat (rules skipped as RECOMMENDED) |