Schema validation¶
Sphinx-Needs (≥ 6.0) includes a powerful schema validation system based on JSON Schema. It lets you define declarative rules that validate individual need properties (local validation) and relationships between needs (network validation).
ubCode supports schema validation directly and can provide diagnostics in the editor as you type.
For the full sphinx-needs schema validation reference, see the sphinx-needs schema documentation.
Overview¶
Schema validation operates at multiple levels:
Field-level schemas — defined inline on
[needs.fields]or[needs.links], these validate every value entered for that field globally (see Field schemas).Schema definitions — defined in a
schemas.jsonfile (viaschema_definitions_from_json), these provide advanced validation including type-specific rules, conditional constraints, and cross-need (network) validation.
Both levels complement each other: field-level schemas enforce global constraints for a field, while schema definitions allow complex, type-specific validation logic.
Configuration¶
- schema_definitions_from_json
Type:
string(default:"")Path to a JSON file containing schema definitions. Available since sphinx-needs 6.0.
[needs] schema_definitions_from_json = "schemas.json"
The schemas.json file¶
The schema file has two top-level keys:
"$defs"(optional): Reusable schema components referenced via$ref"schemas"(required): Array of validation rule objects
{
"$defs": {
"type-spec": {
"properties": {
"type": { "const": "spec" }
}
},
"safe-need": {
"properties": {
"asil": { "enum": ["A", "B", "C", "D"] }
},
"required": ["asil"]
}
},
"schemas": [
{
"id": "spec-id-pattern",
"severity": "warning",
"message": "Spec IDs must be uppercase",
"select": {
"$ref": "#/$defs/type-spec"
},
"validate": {
"local": {
"properties": {
"id": { "pattern": "^SPEC_[A-Z0-9_]+$" }
}
}
}
}
]
}
Each schema object in the schemas array supports:
id(optional): Identifier for the schema rule (used in error messages)severity(optional):"violation"(default),"warning", or"info"message(optional): Custom message shown when validation failsselect(optional): JSON Schema that filters which needs this rule applies to. If omitted, the rule applies to all needs.validate(required): Validation rules with two subsections:local: Validates properties of the need itselfnetwork: Validates relationships with linked needs
Type system¶
Sphinx-Needs supports the following types for need fields,
defined via schema.type in [needs.fields]:
Primitive types:
string,boolean,integer,numberArray types:
arraywith typed items (e.g.schema = {type = "array", items = {type = "string"}})
Type information from [needs.fields] is automatically injected
into schemas.json rules,
so you don’t need to repeat "type": "string" in every schema.
If you do specify a type in the schema file,
it must match the field definition.
Local validation¶
Local validation checks properties of a single need without any information from other needs. This makes it suitable for instant feedback in IDEs.
Example: enforce that efforts is between 0 and 20,
and that approval is required when efforts exceed 15:
{
"schemas": [
{
"id": "efforts-range",
"select": {
"properties": { "type": { "enum": ["spec", "feat"] } }
},
"validate": {
"local": {
"properties": {
"efforts": {
"minimum": 0,
"maximum": 20
}
}
}
}
},
{
"id": "approval-required-for-high-effort",
"severity": "violation",
"message": "Approval required when efforts > 15",
"select": {
"properties": {
"type": { "enum": ["spec", "feat"] },
"efforts": { "minimum": 16 }
},
"required": ["efforts"]
},
"validate": {
"local": {
"required": ["approval"]
}
}
}
]
}
The select filter narrows which needs the rule applies to.
The validate.local section uses standard JSON Schema properties:
properties, required, allOf, anyOf, oneOf, not,
unevaluatedProperties, etc.
Network validation¶
Network validation checks relationships between linked needs. After link resolution, the validator follows outgoing links and validates properties of the target needs.
Example: a safe implementation must link to at least one safe, approved specification:
{
"id": "safe-impl-links",
"message": "Safe impl must link to approved safe specs",
"select": {
"allOf": [
{ "$ref": "#/$defs/type-impl" },
{ "$ref": "#/$defs/safe-need" }
]
},
"validate": {
"network": {
"links": {
"contains": {
"local": {
"allOf": [
{ "$ref": "#/$defs/type-spec" },
{ "$ref": "#/$defs/safe-need" },
{
"properties": {
"approval": { "const": true }
}
}
]
}
},
"minContains": 1
}
}
}
}
Key network validation properties:
validate.network.<link_type>.items— schema that all linked needs must matchvalidate.network.<link_type>.contains— schema that some linked needs must matchminContains/maxContains— how many linked needs must satisfy thecontainsschemavalidate.local.properties.<link_type>.minItems/maxItems— total link count constraints (checked locally since links are ID lists)
Network validation can be nested to validate multi-hop chains (e.g. impl → spec → feat), up to 4 levels deep.
Reusable definitions ($defs)¶
Define common schema fragments in $defs and reference them with $ref:
{
"$defs": {
"type-impl": {
"properties": { "type": { "const": "impl" } }
},
"type-spec": {
"properties": { "type": { "const": "spec" } }
},
"safe-need": {
"properties": {
"asil": { "enum": ["A", "B", "C", "D"] }
},
"required": ["asil"]
},
"safe-spec": {
"allOf": [
{ "$ref": "#/$defs/safe-need" },
{ "$ref": "#/$defs/type-spec" }
]
}
},
"schemas": []
}
$ref must be the only key in the object where it appears.
Recursive references are not allowed.
Severity levels¶
Each schema rule can specify a severity:
"info"— informational, logged as a Sphinx warning"warning"— logged as a Sphinx warning"violation"— logged as a Sphinx error (default)
{
"severity": "warning",
"message": "Consider adding a priority field",
"validate": {
"local": {
"required": ["priority"]
}
}
}
Validation messages can be suppressed using Sphinx’s suppress_warnings:
# In conf.py
suppress_warnings = [
"sn_schema_violation", # all violations
"sn_schema_warning", # all warnings
"sn_schema_info", # all info messages
"sn_schema_violation.local_fail", # only local failures
]
Supported field constraints¶
The following JSON Schema constraints are available per type.
These can be used both in [needs.fields] inline schemas
and in schemas.json validation rules.
String:
minLength, maxLength, pattern, format, enum, const
Integer / Number:
minimum, maximum, exclusiveMinimum, exclusiveMaximum,
multipleOf, enum, const
Boolean:
const
Array:
items (with sub-schema), minItems, maxItems,
uniqueItems, contains, minContains, maxContains
String format values:
"date", "date-time", "time", "duration",
"email", "uri", "hostname", "uuid", "regex"
Note
Regex pattern values must be cross-engine compatible
(Python, Rust, SQLite).
Avoid lookaheads, lookbehinds, backreferences,
and nested quantifiers.
Complete example¶
The following shows a ubproject.toml with typed fields
and a schemas.json that validates them:
ubproject.toml:
[needs]
id_required = true
schema_definitions_from_json = "schemas.json"
[[needs.types]]
directive = "feat"
title = "Feature"
prefix = "FEAT_"
[[needs.types]]
directive = "spec"
title = "Specification"
prefix = "SPEC_"
[[needs.types]]
directive = "impl"
title = "Implementation"
prefix = "IMPL_"
[needs.links.implements]
outgoing = "implements"
incoming = "implemented by"
[needs.fields.efforts]
schema = {type = "integer", minimum = 0, maximum = 100}
[needs.fields.approval]
schema = {type = "boolean"}
[needs.fields.asil]
schema = {type = "string", enum = ["QM", "A", "B", "C", "D"]}
schemas.json:
{
"$defs": {
"type-impl": {
"properties": { "type": { "const": "impl" } }
},
"type-spec": {
"properties": { "type": { "const": "spec" } }
},
"safe-need": {
"properties": {
"asil": { "enum": ["A", "B", "C", "D"] }
},
"required": ["asil"]
}
},
"schemas": [
{
"id": "effort-limits",
"message": "Efforts must be between 0 and 20 for specs",
"select": {
"properties": { "type": { "const": "spec" } }
},
"validate": {
"local": {
"properties": {
"efforts": { "maximum": 20 }
}
}
}
},
{
"id": "safe-impl-chain",
"message": "Safe impl must link to safe spec",
"select": {
"allOf": [
{ "$ref": "#/$defs/type-impl" },
{ "$ref": "#/$defs/safe-need" }
]
},
"validate": {
"network": {
"implements": {
"contains": {
"local": {
"allOf": [
{ "$ref": "#/$defs/type-spec" },
{ "$ref": "#/$defs/safe-need" }
]
}
},
"minContains": 1
}
}
}
}
]
}
Further reading¶
For the complete reference including all validation options, error message formats, debug tooling, and migration guides, see the sphinx-needs schema validation documentation.