Needs

The [needs] section is the heart of your ubproject.toml. It tells ubCode how to identify, validate, and relate the need objects in your reStructuredText files — types, link types, custom fields, statuses, tags, and external needs.

See also

Key Concepts

Minimal example

[needs]
id_required = true
id_regex = "^[A-Z]{3}_[0-9]{3}$"

[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "REQ_"

[needs.links.implements]
outgoing = "implements"
incoming = "implemented by"

[needs.fields.priority]
description = "Priority level"

Core options

id_required

Type: boolean (default: false)

If true, every need must have an explicit ID. If false, IDs will be auto-generated when not provided.

id_regex

Type: string (default: "^[A-Z0-9_]{5,}")

Regular expression pattern to validate need IDs against. Only applies when id_required is true.

id_length

Type: integer (default: 5)

Length of auto-generated IDs when not explicitly provided.

id_from_title

Type: boolean (default: false)

When true, auto-generated IDs will be based on the need title instead of being random.

title_optional

Type: boolean (default: false)

When true, allows needs to be created without a title.

title_from_content

Type: boolean (default: false)

When true, auto-generates titles from the first line of need content when no title is provided.

Need types

The types array defines the available need directives in your project:

[[needs.types]]
directive = "requirement"  # The RST directive name
title = "Requirement"     # Human-readable title
prefix = "REQ_"          # Prefix for auto-generated IDs
color = "#BFD8D2"        # Color for diagrams
style = "node"           # Style for diagrams

Each type supports:

  • directive (required): The reStructuredText directive name

  • title (required): Human-readable title for the need type

  • prefix (required): Prefix used for auto-generated need IDs

  • color (optional, default: "#000000"): Color used in need diagrams

  • style (optional, default: "node"): Style used in need diagrams

Fields

Every need carries fields — named pieces of metadata such as status, tags, or any custom attribute you define. Some fields are built in (id, title, status, tags); you can add your own through the configuration.

ubCode supports two formats: the dict-based [needs.fields] format (aligned with sphinx-needs ≥ 7) and the list-based extra_options format (for sphinx-needs < 7).

Dict-based format (recommended)

Note

The dict-based [needs.fields] format requires sphinx-needs ≥ 7.0. It replaces the older list-based needs_extra_options and also allows specializing core fields (e.g. status, tags) by narrowing their type constraints.

Use [needs.fields.<name>] to define each custom field:

[needs.fields.priority]
description = "Priority level"
default = "medium"

[needs.fields.assignee]
description = "Assigned team member"

[needs.fields.effort]
description = "Story points"
schema = {type = "integer", minimum = 1, maximum = 13}

Each field supports:

  • description (optional): Human-readable description

  • default (optional): Default value if not specified on a need

  • schema (optional): JSON Schema to validate values (see Field schemas below). Schema support for fields was introduced in sphinx-needs 6.0 (via ``needs_extra_options``) and carried forward to ``needs_fields`` in sphinx-needs 7.0.

  • nullable (optional): Whether the field accepts null values. sphinx-needs ≥ 7.0.

  • predicates (optional): Conditional defaults (see Global options). sphinx-needs ≥ 7.0.

  • parse_variants (optional): Whether to parse variant functions in this field’s values. sphinx-needs ≥ 7.0.

  • parse_dynamic_functions (optional): Whether to parse dynamic functions in this field’s values. sphinx-needs ≥ 6.3.

Once declared, these fields can be used on any need:

.. req:: Encrypt data at rest
   :id: REQ_002
   :status: open
   :priority: high
   :assignee: alice
   :effort: 5

List-based format (sphinx-needs < 7)

Deprecated since version 0.25.0: The list-based extra_options format (needs_extra_options in sphinx-needs) was deprecated in sphinx-needs 7.0 in favour of the dict-based format. It remains supported for backward compatibility. For new projects, prefer the dict-based [needs.fields] format.

Simple format (string list):

extra_options = ["priority", "effort", "assignee", "component"]

Detailed format (with descriptions and schemas):

extra_options = [
    {name = "priority", description = "Priority level"},
    {name = "effort", description = "Story points", schema = {type = "integer", minimum = 1, maximum = 13}},
    {name = "assignee", description = "Assigned team member"},
]

Field schemas

The schema key on a field applies JSON Schema validation to every value entered for that field. Invalid data is caught at index time, before the docs are built.

String schemas:

[needs.fields.contact]
schema = {type = "string", format = "email"}

[needs.fields.id_pattern]
schema = {type = "string", pattern = "^[A-Z]{3}-[0-9]{4}$"}

[needs.fields.severity]
schema = {type = "string", enum = ["low", "medium", "high", "critical"]}

String format options:

The format property supports various predefined formats:

  • "date": RFC 3339 date format (e.g., 2023-10-22)

  • "date-time": RFC 3339 date-time format (e.g., 2023-10-22T14:30:00Z)

  • "time": RFC 3339 time format (e.g., 14:30:00Z)

  • "email": RFC 5322 email address (e.g., user@example.com)

  • "hostname": RFC 1123 hostname (e.g., example.com)

  • "uri": RFC 3986 URI (e.g., https://example.com/path)

  • "uuid": RFC 4122 UUID (e.g., 550e8400-e29b-41d4-a716-446655440000)

  • "regex": ECMAScript regular expression

Integer and number schemas:

[needs.fields.priority]
schema = {type = "integer", minimum = 1, maximum = 10}

[needs.fields.rating]
schema = {type = "number", minimum = 0.0, maximum = 5.0}

[needs.fields.fibonacci]
schema = {type = "integer", enum = [1, 2, 3, 5, 8, 13, 21]}

Boolean schemas:

[needs.fields.approved]
schema = {type = "boolean"}

Array schemas:

[needs.fields.reviewers]
schema = {type = "array", items = {type = "string", format = "email"}, minItems = 1, maxItems = 3}

[needs.fields.categories]
schema = {type = "array", items = {type = "string"}, uniqueItems = true}

Usage in need directives:

Once defined, these fields can be used in your need directives:

.. requirement:: User Authentication
    :priority: 5
    :effort: 8
    :assignee: developer@company.com
    :due_date: 2024-12-31
    :tags: security, authentication
    :component: auth, backend
    :active: true

    Users must be able to authenticate using their corporate credentials.

Statuses and tags

You can constrain the allowed values for a need’s status and tags fields. The recommended approach depends on your sphinx-needs version.

Legacy list-based constraints (sphinx-needs < 7)

Deprecated since version 0.25.0: The [[needs.statuses]] and [[needs.tags]] list formats (needs_statuses / needs_tags in sphinx-needs) were deprecated in sphinx-needs 7.0 in favour of schema enum constraints on the status and tags fields (see above). They remain supported for backward compatibility.

[[needs.statuses]]
name = "draft"
description = "Work in progress"

[[needs.statuses]]
name = "approved"
description = "Reviewed and approved"

[[needs.tags]]
name = "security"
description = "Security-related needs"

External needs

Load needs from external sources (JSON files or URLs):

# From local file
[[needs.external_needs]]
json_path = "external/project_needs.json"
id_prefix = "EXT"
base_url = "https://external-project.com"
target_url = "docs/{{ id }}.html"

# From remote URL
[[needs.external_needs]]
json_url = "https://api.example.com/needs.json"
id_prefix = "REMOTE"

Each external needs source supports:

  • json_path: Path to a local JSON file

  • json_url: URL to a remote JSON file

  • id_prefix: Prefix prepended to external need IDs

  • base_url: Base URL for linking back to the source project

  • target_url: URL template for individual need links (supports {{ id }} placeholder)

  • css_class: CSS class applied to external needs

  • version: Version string for the external needs source

  • skip_in_ubcode (default: false): When true, skip loading these external needs in ubCode analysis

Variants

The [needs.variants] section defines named filter expressions that can be referenced from need fields using the <<name: value, fallback>> syntax. This implements the Sphinx-Needs variant functions feature.

[needs.variants]
is_open = "status == 'open'"
is_html = "'html' in build_tags"
is_production = "environment == 'production'"

With these variants defined, need fields can use them:

.. req:: My requirement
   :id: REQ_001
   :status: <<is_open: active, inactive>>
   :extra: <<is_html: web_only, general>>

You can also use inline bracketed expressions without pre-defining a variant:

.. req:: Another requirement
   :id: REQ_002
   :status: <<[status == 'open']: active, inactive>>

The last comma-separated value is always the fallback when no expression matches.

Note

Variant syntax is only parsed for fields that opt in. In sphinx-needs ≥ 7.0, set parse_variants = true on individual fields in [needs.fields]. For older versions, use the deprecated variant_options list (see Deprecated needs options).

Parse and evaluation errors are surfaced as needs.variant diagnostics.

Dynamic functions

ubCode resolves some built-in dynamic functions using the [[...]] syntax from sphinx-needs.

Three built-in functions are supported:

  • echo("text") — returns the given string unchanged

  • test(*args, **kwargs) — returns a debug string with the need ID and arguments

  • copy("field") — copies a field value from the current need (also supports lower and upper kwargs)

For example:

.. req:: My requirement
   :id: REQ_001
   :status: [[copy("priority")]]

Dynamic function parsing is enabled by default and can be controlled globally or per-field/per-link:

[needs]
parse_dynamic_functions = false  # disable globally (sphinx-needs ≥ 7.0)

[needs.fields.my_field]
parse_dynamic_functions = true   # re-enable for this field (sphinx-needs ≥ 6.3)

[needs.links.implements]
parse_dynamic_functions = true   # re-enable for this link (sphinx-needs ≥ 6.3)
parse_dynamic_functions

Type: boolean (default: true)

Whether dynamic functions are parsed by default. Applies to extra fields and links unless overridden per-field/per-link. Core fields are not affected by this global setting.

The global parse_dynamic_functions option was added in sphinx-needs 7.0 (needs_parse_dynamic_functions). Per-field and per-link parse_dynamic_functions was added in sphinx-needs 6.3.

filter_data

Type: object (default: {})

Additional context variables that can be referenced in filter expressions throughout your needs configuration. This allows you to define custom variables for conditional logic in multiple contexts.

Where filter_data can be used:

  1. Predicate default filters — in global_options predicates (or predicates on individual fields/links in sphinx-needs ≥ 7.0) to conditionally set default values

  2. needimport item filters — to filter which needs are imported from external sources

  3. needextend filters — to conditionally extend or modify needs based on context

[needs]
filter_data = { environment = "production", team = "backend", version = "2.0" }

# Using predicates on a field directly (sphinx-needs ≥ 7.0, recommended)
[needs.fields.priority]
default = "medium"
predicates = [
  ["environment == 'production'", "high"],
  ["team == 'backend'", "high"]
]

# Or via global_options (sphinx-needs < 7, deprecated)
# [needs.global_options.priority]
# default = "medium"
# predicates = [
#   ["environment == 'production'", "high"],
#   ["team == 'backend'", "high"]
# ]

Example with needimport:

.. needimport:: external_needs.json
   :filter: environment == 'production' and version == '2.0'

Example with needextend:

.. needextend:: team == 'backend'
   :status: critical

Common use cases:

  • Setting environment-specific defaults (development, staging, production)

  • Filtering imported needs based on release version or team ownership

  • Applying team or project-specific configurations

  • Conditional formatting or validation based on build context

  • Dynamic behaviour in CI/CD pipelines

import_keys

Type: object (default: {})

Mapping of keys for needimport directives, allowing short keys to reference longer file paths. Available since sphinx-needs 4.2.

[needs.import_keys]
backend = "/path/to/backend_needs.json"
frontend = "/path/to/frontend_needs.json"