ADR-0022: TCK Static Inspection
Status
Accepted — amended 2026-08-18. .stck no longer exists; <package> is a
.tck, plain or encrypted. testlab inspect also absorbed testlab info and
testlab decompile, which are now its --manifest and --extract sections.
Date
2026-07-20
Context
TestLab users and engine backends need to read
metadata from .tck and .stck packages — Test Name, total step count, total
validation count, and per-step details (name, uses identifier, phase) — without
executing the test. Use cases include:
- Displaying test metadata in a dashboard or UI before scheduling a run
- Validating that a package contains the expected tests before deploying it
- Generating pre-run reports or conformance summaries
Previously, the only way to extract this information was to execute testlab run and
parse the execution trace, which requires a live dataspace environment and leaks no
static summary.
A parallel capability, Tck.all_variables() (implemented in
ADR-0018), already demonstrates the
correct pattern for extracting static metadata from a loaded Tck: a frozen Pydantic
model describes the result, a pure helper function in authoring/_*.py performs the
extraction, and the Tck class exposes a single method that delegates to it.
Decision
1. Method on Tck: inspect()
We add Tck.inspect() -> TckInspectionResult to authoring/test.py, mirroring
the Tck.all_variables() -> list[VariableDefinition] pattern exactly:
Tck.inspect()
└── calls build_inspection_result(self) # authoring/_inspection.py
└── returns TckInspectionResult # models/runtime/inspection.py
The method works on any loaded Tck, whether loaded from a plain .tck or a
decrypted .stck. Decryption is the caller's responsibility (handled by Loader
before inspect() is ever called).
2. Result models in models/runtime/inspection.py
Three frozen Pydantic v2 models capture the static metadata:
class StepMeta(BaseModel):
model_config = ConfigDict(frozen=True)
step_name: str # step.name if set, otherwise falls back to step.uses
uses: str # block identifier (e.g. "connector/consumer/get_catalog")
phase: StepPhase # SETUP | EXECUTION | TEARDOWN
validation_count: int # number of validate: entries on this step
class TestInspection(BaseModel):
model_config = ConfigDict(frozen=True)
name: str
steps: tuple[StepMeta, ...]
class TckInspectionResult(BaseModel):
model_config = ConfigDict(frozen=True)
name: str
total_steps: int
total_validations: int
tests: tuple[TestInspection, ...]
All three are exported through models/runtime/__init__.py and models/__init__.py
so consumers can import them as:
3. Pure helper in authoring/_inspection.py
build_inspection_result(tck) iterates all tests and, for each, maps the three
phase lists (setup, steps, teardown) into StepMeta tuples using _map_steps.
It computes total_steps and total_validations by aggregating across all tests.
The function has no side effects and does not touch the network or filesystem.
4. CLI command: testlab inspect
A new Typer command in cli/inspect.py exposes the feature at the command line:
testlab inspect <package> [--player-keys <path>] [--compiler-pub <path>] [--variables] [--infrastructure] [--json]
<package>accepts both.tck(plain) and.stck(encrypted) files.--player-keysand--compiler-pubare required for.stckpackages; the command rejects.stckwithout keys with a clear error message.--variablesflag: additionally prints the variable list returned byTck.all_variables()(ID, source, scope, type — as a human-readable table or embedded in the JSON envelope).--infrastructureflag: additionally prints the infrastructure requirements returned byTck.infrastructure_requirements()(capability, side, required flag, standard — as a human-readable table or embedded in the JSON envelope).- Default output: human-readable table printed to stdout.
--jsonflag: outputs a JSON envelope{"inspection": ..., "variables": [...], "infrastructure": {...}}— only the sections requested via--variables/--infrastructureare populated in the envelope.
The three sections (inspection, variables, infrastructure) are independently optional.
At least one of the three must be requested or the command prints the inspection table by
default.
5. Amendment (2026-07): Tck.infrastructure_requirements()
Following the same pattern as Tck.inspect() and Tck.all_variables(), a method
Tck.infrastructure_requirements() -> InfrastructureConfig is added to authoring/test.py.
Tck.infrastructure_requirements()
└── calls collect_infrastructure_requirements(self) # authoring/_infrastructure.py
└── returns InfrastructureConfig # models/authoring/infrastructure.py
collect_infrastructure_requirements(tck) applies a two-pass merge:
- If the TCK manifest declares a top-level
infrastructure:block, that block wins as-is. - Otherwise, the function iterates all
Testobjects and merges their per-testinfrastructure:blocks:required: truewins overrequired: false, and the first non-Nonestandardwins.
InfrastructureConfig, CapabilityRequirement, Standard, and DataspaceContext are
all exported from tractusx_testlab.models:
This amendment does not change the decision recorded in the original sections. It extends the pattern documented in § 2 and § 3 with a third static-metadata accessor.
6. StepPhase enum value rename
The StepPhase enum values in models/primitives/enums.py are renamed to align
with user-facing and JSON-serialized terminology:
| Old value | New value |
|---|---|
MAIN |
EXECUTION |
CLEANUP |
TEARDOWN |
SETUP |
SETUP (unchanged) |
This rename is applied to all callers in player/execution/phases/.
Consequences
Positive
- Backends and UIs can query TCK metadata without provisioning a live dataspace environment — significantly reduces onboarding friction.
- The
--jsonoutput oftestlab inspectprovides a stable, machine-readable contract for engine integrations. - Pattern is consistent with
Tck.all_variables()andTck.infrastructure_requirements()— the codebase has one way to extract each kind of static metadata from a loadedTck. --variablesand--infrastructureflags give engine backends a complete pre-run picture (what the TCK does, what variables it needs, what infrastructure it requires) from a singletestlab inspectcall.StepPhasevalues now match the domain language (EXECUTION,TEARDOWN) and serialize correctly to JSON without needing a display mapping.
Negative
StepPhase.MAINandStepPhase.CLEANUPare removed — any downstream code (outside this repository) that imported these enum members must be updated toStepPhase.EXECUTIONandStepPhase.TEARDOWN.
Neutral
- No REST API endpoints are added. The feature is library-level (
tck.inspect()) and CLI-level (testlab inspect). Engine backends consume the library directly. testlab inspecton an.stckfile performs full decryption in memory to load theTckobject; no intermediate cleartext is written to disk.