TLPT Baseline v1 Contract
Contract ID: CONTRACT-TLPT-BASELINE-V1-024 Version: tlpt-baseline.v1 Status: Draft Owner: Replay Guild Last updated: 2026-04-30
Purpose
TLPT Baseline v1 is the deterministic Replay manifest for freezing Stella Ops state at a chosen point in time (baselineAt). It binds a TLPT scope hash to the frozen advisory feed, policy, dependency graph, and asset-registry state needed for later offline replay and evidence-pack assembly.
This contract is for engineers and white-team auditors implementing or verifying DORA threat-led penetration testing (TLPT) evidence flows. The baseline sits downstream of the TLPT scope document and upstream of the TLPT evidence pack.
The baseline is white-team/evidence-side only. It does not run offensive tooling and does not dereference live regulator, SaaS, or internet resources.
Schema Pinning
- Schema version is pinned to
tlpt-baseline.v1. - Core implementation:
src/Replay/__Libraries/StellaOps.Replay.Core/TlptBaselines/. - Deterministic fixture coverage:
src/Replay/__Tests/StellaOps.Replay.Core.Tests/TlptBaselines/. - Breaking changes require a new schema version; consumers must not auto-follow future TLPT baseline schemas.
Document Shape
Required top-level fields:
schemaVersion:tlpt-baseline.v1.tenantId: tenant whose TLPT scope is frozen.scopeId: optional scope identifier from thetlpt-scope.v1document.scopeHash: SHA-256 hash from thetlpt-scope.v1document.baselineAt: UTC timestamp for the frozen state.feeds: feed bundle hash, point-in-time, and provider snapshot digests with captured/epoch timestamps.policy: policy id, version, digest, and captured timestamp.dependencyGraph: graph id, source, digest, and captured timestamp.assetState: asset source, schema version, digest, and captured timestamp.baselineHash: SHA-256 over the canonical baseline payload excludingbaselineHash.
The list above is the logical field set, not the on-wire order: canonical JSON sorts object properties alphabetically (see Determinism Rules), and the optional scopeId is omitted entirely when null. Each feeds.snapshots[] entry carries providerId, digest, capturedAt, and a separate epochTimestamp. The hashed payload (TlptBaselineHashPayload) is the manifest with baselineHash removed; baselineHash is the SHA-256 of that canonical payload.
Source records: TlptBaselineManifest, TlptFeedBaselineState, TlptFeedSnapshotReference, TlptPolicyBaselineState, TlptDependencyGraphBaselineState, and TlptAssetStateBaselineState in TlptBaselineManifest.cs. Build inputs are the *SnapshotInput records and TlptBaselineBuildRequest in TlptBaselineBuilder.cs.
Determinism Rules
- Output JSON is canonical: object properties are recursively sorted by ordinal property name, arrays preserve insertion order after the caller-side sort below, and there is no insignificant whitespace (
TlptBaselineCanonicalJson). - Feed snapshots are ordered by
providerIdthendigestusing ordinal string ordering before serialization and again when the feed bundle hash is computed. - All hashes use lowercase
sha256:<64 hex>format. The validator (TlptBaselineHashing.IsSha256Digest) requires exactly 71 characters: thesha256:prefix followed by 64 lowercase hex characters; uppercase hex is rejected. Hash output (HashUtf8) is lowercased before emission. - Timestamps are normalized to UTC
yyyy-MM-ddTHH:mm:ssZ. Non-canonical inputs such as+00:00offsets are rejected during verification, not coerced. - The same frozen inputs must produce the same
baselineHashand JSON bytes regardless of the order feed snapshots are supplied.
Build-time invariants (TlptBaselineBuilder.Build)
tenantId,policyId,policy.version,dependencyGraph.graphId,dependencyGraph.source,assetState.source,assetState.schemaVersion, and every snapshotproviderIdmust be non-blank; leading/trailing whitespace is trimmed.scopeHash, the feed bundle hash, and every digest field must already be a validsha256:<64 hex>value (the builder does not compute these for you).- At least one feed snapshot is required, and duplicate
providerIdvalues (after trim, ordinal comparison) are rejected. Blank-provider validation runs before duplicate detection. - The feed bundle hash (
feeds.bundleHash) is derived fromfeeds.pointInTimeplus the ordered snapshot set, so it is recomputed and re-checked during verification.
Offline and Replay Expectations
VerifyOfflinerecomputes the feed bundle hash andbaselineHashand validates every field without network access. It returns aTlptBaselineVerificationResult(isValid,reason,expectedHash,actualHash); success uses reasonok, and failures use a stable machine reason code. The verifier checks, in order: schema version, scope hash, baseline hash format, baseline timestamp, presence of all four frozen-state blocks, feed bundle hash format and point-in-time, at least one feed snapshot, each snapshot digest/timestamps, policy digest/timestamp, dependency-graph digest/timestamp, asset-state digest/timestamp, the recomputed feed bundle hash, and finally the recomputed baseline hash.- Failure reason codes:
schema-version-mismatch,invalid-scope-hash,invalid-baseline-hash,invalid-baseline-timestamp,missing-frozen-state,invalid-feed-bundle-hash,invalid-feed-point-in-time,missing-feed-snapshots,missing-feed-snapshot,invalid-feed-snapshot-digest,invalid-feed-snapshot-timestamp,invalid-policy-digest,invalid-policy-timestamp,invalid-dependency-graph-digest,invalid-dependency-graph-timestamp,invalid-asset-state-digest,invalid-asset-state-timestamp,feed-bundle-hash-mismatch, andbaseline-hash-mismatch. ReplayFrozenStatefirst runsVerifyOfflineand throwsInvalidOperationExceptionif verification fails; otherwise it returns aTlptFrozenStellaStatecontaining only state embedded in the verified baseline, so later replays return identical feed, policy, dependency graph, and asset-state references.- CLI wiring is implemented:
stella replay <baseline>accepts atlpt-baseline.v1file argument and callsTlptBaselineBuilder.VerifyOfflinethenReplayFrozenStatevia the reusable Replay Core contract rather than recomputing hashes in CLI code (src/Cli/StellaOps.Cli/Commands/ReplayCommandGroup.cs,ExecuteTlptBaselineReplayAsync). On verification failure it emits aTlptBaselineReplayFailurepayload; on success aTlptBaselineReplayResult.
Authorization
The Replay Core library is pure and carries no authorization. The governing scopes for replay surfaces (CLI/API) are replay:read and replay:write, defined in the canonical scope catalog (StellaOpsScopes.cs, ReplayRead / ReplayWrite). No TLPT-baseline-specific scope exists.
