Skip to content

Specifications

What the Digital Twin service must do. Everything here is a requirement: a statement about behaviour that a test can be pointed at.

The rest of docs/ describes and teaches. This directory constrains. Where a description elsewhere disagrees with a requirement here, the requirement is the one that was checked.

The documents

Document Covers
runtime.md domain registration, route mounting, entity resolution, authentication, discovery and API documentation, startup, the access audit
values.md value fetcher registration, execution, validation, pagination; the service identity a fetcher may declare, and what the Digital Twin logs; the reference-boundary fetchers
query-templates.md the two rendering phases and the boundary between them
grid.md the it-grid domain: its fetchers, which operator's network every read names, and who may name it
participant.md the it-participant domain: whose twin a caller reads, and which meters it may name
community.md the it-energy-community domain: every REC read names the community in the URL

Identifiers

Requirements are numbered REQ-####, the harness default.

Numbers are allocated in blocks from REQ-1000 upward (ADR-0001), and a retired requirement's number is never reused:

Block Subject
REQ-10xx runtime: registration, routing, entity resolution, authentication, discovery, startup, access audit
REQ-11xx values
REQ-12xx query templates
REQ-13xx grid domain fetchers
REQ-14xx participant domain scoping
REQ-15xx community domain scoping

Starting at 1000 is not arbitrary. AGENTS.md and the harness rulebook are issued by the agent harness and cite its own rule identifiers in the same four-digit form — REQ-0003 for the closed directory set, REQ-0012 for an altered standard file, REQ-0303 for a home path in committed material. Those constrain this repository's structure; the ones here constrain the service. Keeping this repository's block above them means one number never means two things.

How a requirement is verified

A test declares what it covers with a @verifies tag in its docstring or in a comment directly above it:

def test_entity_resolution_reject(self):
    """@verifies REQ-1031"""
    ...

The mapping from requirement to test is generated from these tags, never written down. A hand-maintained matrix is stale within a week, which is the whole reason the tag lives next to the assertion instead.

Two consequences worth stating, because both are easy to get wrong:

  • A requirement with no tag is unverified, and that is a finding rather than a formatting slip. tests/test_traceability.py fails on it, unless the requirement is marked planned (below).
  • A tag naming a requirement that does not exist is also a failure. Renumbering a requirement without moving its tags breaks the trace silently otherwise.

tests/test_traceability.py enforces both directions in the ordinary suite, so the answer to "is this verified?" is available from uv run pytest alone — the harness checker (python -m harness .) is not installed in every checkout.

Planned requirements

A requirement may be written ahead of the code, marked planned (ADR-0002): a line **Status:** planned directly under its heading, and no @verifies tag yet. The change that makes it true lands its tests with their tags and removes the status line in the same change. A requirement with no status line is implemented. A planned one is a design commitment, not something a caller may use yet.

tests/test_traceability.py exempts a planned requirement from the "no tag" check, fails on a tag naming one, and fails on a status line that says anything but planned. The harness checker does not read the status line and reports a planned requirement as uncovered, which is the honest reading: nothing verifies it yet.

Writing one

  • State behaviour, not implementation. "An unknown fetcher id answers 404", not "fetch_values_get catches KeyError". The implementation is free to move; the requirement is what must survive the move.
  • One testable claim per requirement. If a statement needs "and" to hold two independent behaviours, it is two requirements.
  • MUST is the only modal. A requirement that something should happen cannot fail.
  • If it cannot be tested, it is not a requirement — it is a description, and belongs in the document that describes.