docs(operations): record v1 readiness evidence (#23)
quality-gate / quality (push) Failing after 1m29s
quality-gate / container (push) Has been skipped

This commit is contained in:
KyuubiYoru
2026-07-16 22:39:50 +02:00
parent 00d5ff7764
commit 95c3a4aed6
8 changed files with 327 additions and 69 deletions
+35 -35
View File
@@ -1,7 +1,7 @@
{
"schemaVersion": 2,
"evidenceVersion": "v2",
"generatedAt": "2026-07-16T14:10:53.6981858+00:00",
"generatedAt": "2026-07-16T20:28:43.2873744+00:00",
"profile": "candidate",
"runtime": {
"framework": ".NET 10.0.9",
@@ -14,14 +14,14 @@
"cpuQuota": "not-enforced",
"memoryLimit": "not-enforced",
"garbageCollector": "workstation",
"commitSha": "cf14836d48b0b4aaa67f99433f4fba3585bcd2bb",
"commitSha": "00d5ff776408e7d80ce6648953e62a7233aca35c",
"treeState": "clean",
"command": "RENDEZVOUS_CAPACITY_PROFILE=candidate RENDEZVOUS_CAPACITY_CPUSET=0,1 ./scripts/run-capacity-gate.sh",
"imageDigest": "not-containerized",
"workloadSeed": "fixed-sequences-random-identifiers",
"capacityPhaseAverageCpuPercent": 56.37724115383554,
"peakWorkingSetBytes": 169705472,
"managedBytesAfterCleanup": 35615200
"capacityPhaseAverageCpuPercent": 55.52666859166872,
"peakWorkingSetBytes": 176758784,
"managedBytesAfterCleanup": 35608984
},
"targets": {
"visibleListings": 25000,
@@ -39,10 +39,10 @@
{
"operation": "registration-and-presence",
"samples": 1000,
"p50Milliseconds": 0.003,
"p50Milliseconds": 0.0029,
"p95Milliseconds": 0.0046,
"p99Milliseconds": 0.0054,
"operationsPerSecond": 282453.96000451926,
"p99Milliseconds": 0.0055,
"operationsPerSecond": 287918.9220315559,
"minimumOperationsPerSecond": 200,
"budgetMilliseconds": 200,
"passed": true
@@ -51,9 +51,9 @@
"operation": "lease-renewal",
"samples": 1000,
"p50Milliseconds": 0.0004,
"p95Milliseconds": 0.0009,
"p99Milliseconds": 0.0021,
"operationsPerSecond": 968992.2480620155,
"p95Milliseconds": 0.0007,
"p99Milliseconds": 0.0019,
"operationsPerSecond": 1076426.264800861,
"minimumOperationsPerSecond": 200,
"budgetMilliseconds": 200,
"passed": true
@@ -61,10 +61,10 @@
{
"operation": "visible-session-browse",
"samples": 250,
"p50Milliseconds": 0.9046,
"p95Milliseconds": 3.3704,
"p99Milliseconds": 3.9471,
"operationsPerSecond": 695.5799787597697,
"p50Milliseconds": 1.0232,
"p95Milliseconds": 3.6083,
"p99Milliseconds": 4.2925,
"operationsPerSecond": 650.0325926341947,
"minimumOperationsPerSecond": 200,
"budgetMilliseconds": 200,
"passed": true
@@ -72,10 +72,10 @@
{
"operation": "join-attempt-issuance",
"samples": 1000,
"p50Milliseconds": 0.0029,
"p95Milliseconds": 0.0045,
"p99Milliseconds": 0.0055,
"operationsPerSecond": 296428.042092782,
"p50Milliseconds": 0.0028,
"p95Milliseconds": 0.0042,
"p99Milliseconds": 0.0052,
"operationsPerSecond": 135253.93927098127,
"minimumOperationsPerSecond": 200,
"budgetMilliseconds": 200,
"passed": true
@@ -83,10 +83,10 @@
{
"operation": "simultaneous-punch-pairing",
"samples": 1000,
"p50Milliseconds": 0.0043,
"p95Milliseconds": 0.0073,
"p99Milliseconds": 0.0115,
"operationsPerSecond": 109212.03516627532,
"p50Milliseconds": 0.0039,
"p95Milliseconds": 0.0069,
"p99Milliseconds": 0.0087,
"operationsPerSecond": 110619.46902654869,
"minimumOperationsPerSecond": 2000,
"budgetMilliseconds": 100,
"passed": true
@@ -94,10 +94,10 @@
{
"operation": "principal-revocation",
"samples": 50,
"p50Milliseconds": 0.518,
"p95Milliseconds": 0.7049,
"p99Milliseconds": 11.8557,
"operationsPerSecond": 1320.1773262184577,
"p50Milliseconds": 0.495,
"p95Milliseconds": 0.6508,
"p99Milliseconds": 11.011,
"operationsPerSecond": 1393.258301729591,
"minimumOperationsPerSecond": 50,
"budgetMilliseconds": 200,
"passed": true
@@ -108,7 +108,7 @@
"p50Milliseconds": 0.0001,
"p95Milliseconds": 0.0001,
"p99Milliseconds": 0.0001,
"operationsPerSecond": 1438641.9220256077,
"operationsPerSecond": 1479289.9408284025,
"minimumOperationsPerSecond": 10000,
"budgetMilliseconds": 1,
"passed": true
@@ -116,10 +116,10 @@
{
"operation": "coincident-listing-attempt-expiry",
"samples": 1,
"p50Milliseconds": 29.6882,
"p95Milliseconds": 29.6882,
"p99Milliseconds": 29.6882,
"operationsPerSecond": 33.682962483916384,
"p50Milliseconds": 27.7056,
"p95Milliseconds": 27.7056,
"p99Milliseconds": 27.7056,
"operationsPerSecond": 36.093525543388026,
"minimumOperationsPerSecond": 0,
"budgetMilliseconds": 200,
"passed": true
@@ -134,10 +134,10 @@
"finalReplayMarkers": 0,
"expiryChurn": 94906,
"maintenanceSweeps": 36307,
"soakCyclesCompleted": 75126848,
"soakDurationSeconds": 300.0000015,
"soakCyclesCompleted": 77547145,
"soakDurationSeconds": 300.0000041,
"soakPeakScheduledExpiryEntries": 7,
"soakManagedGrowthBytes": -257288,
"soakManagedGrowthBytes": -263432,
"soakHandleGrowth": 2,
"restartStartedEmpty": true,
"overloadWasTyped": true,
+18 -18
View File
@@ -1,44 +1,44 @@
{
"schemaVersion": 1,
"kind": "rendezvous-production-readiness",
"evaluatedCommit": "6bad659c123ad45ad0d9d07f93217c2e8c42d459",
"evaluatedCommit": "00d5ff776408e7d80ce6648953e62a7233aca35c",
"decision": "not-ready",
"localGates": [
{
"id": "immutable-release-artifacts",
"status": "pending",
"evidenceRef": "docs/operations/production-readiness.md",
"note": "Rebuild after the readiness tooling checkpoint."
"status": "pass",
"evidenceRef": "docs/evidence/releases/v1.0.0-local-candidate.json",
"note": "Clean candidate packages and server archive are byte reproducible and fully verified."
},
{
"id": "debug-and-release-verification",
"status": "pending",
"evidenceRef": "docs/operations/production-readiness.md",
"note": "Re-run after the readiness tooling checkpoint."
"status": "pass",
"evidenceRef": "docs/evidence/releases/v1.0.0-local-candidate.json",
"note": "All 300 tests pass in Debug and Release; the Release build has zero warnings and errors."
},
{
"id": "real-consumer-pilots",
"status": "pending",
"evidenceRef": "docs/integration/spacegame-pilot.md",
"note": "Pin and re-run both real consumer revisions."
"status": "pass",
"evidenceRef": "docs/evidence/releases/v1.0.0-local-candidate.json",
"note": "Pinned real projects restore the candidate and both game launch pilots pass direct traffic."
},
{
"id": "candidate-capacity-resilience",
"status": "pending",
"status": "pass",
"evidenceRef": "docs/evidence/capacity/v2/candidate-2cpu.json",
"note": "Re-run the five-minute candidate on the tooling checkpoint."
"note": "The clean two-CPU five-minute candidate passes all budgets with zero retained state."
},
{
"id": "production-process-recovery",
"status": "pending",
"evidenceRef": "docs/operations/capacity-and-resilience.md",
"note": "Re-run process restart, drain, and rollback gates."
"status": "pass",
"evidenceRef": "docs/evidence/releases/v1.0.0-local-candidate.json",
"note": "All selected restart, drain, socket release, overload, and recovery tests pass."
},
{
"id": "security-privacy-observability",
"status": "pending",
"evidenceRef": "docs/operations/production-readiness.md",
"note": "Re-run the combined release verification matrix."
"status": "pass",
"evidenceRef": "docs/evidence/releases/v1.0.0-local-candidate.json",
"note": "The complete security, privacy, health, audit, telemetry, and release suite passes."
}
],
"externalGates": [
@@ -0,0 +1,58 @@
{
"schemaVersion": 1,
"kind": "rendezvous-local-release-candidate",
"version": "1.0.0",
"sourceCommit": "00d5ff776408e7d80ce6648953e62a7233aca35c",
"treeState": "clean",
"result": "pass",
"artifacts": [
{
"name": "FinalFactory.Rendezvous.Client.1.0.0.nupkg",
"sha256": "f2a4b9727b5faeba284ddcb7fc575c7495f1e29b763faababa7cd71444dc2950"
},
{
"name": "FinalFactory.Rendezvous.Contracts.1.0.0.nupkg",
"sha256": "92317f153911ebf7b8ea04cd3206ec2a17f882cb4eddb26aa8ab094ffdb06627"
},
{
"name": "FinalFactory.Rendezvous.Server.1.0.0.linux-x64.tar.gz",
"sha256": "0dab8cfc696b4a55d6ffba46286c9e532df2c943ed8fd6347fb528516156b3ba"
}
],
"verification": {
"lockedRestore": "pass",
"reportedVulnerabilities": 0,
"format": "pass",
"releaseBuildWarnings": 0,
"releaseBuildErrors": 0,
"debugTestsPassed": 300,
"debugTestsFailed": 0,
"releaseTestsPassed": 300,
"releaseTestsFailed": 0,
"selectedProductionFaultTestsPassed": 17,
"byteReproduciblePackages": "pass",
"byteReproducibleServerArchive": "pass",
"sbomChecksumsAndProvenance": "pass",
"candidateConsumerFixtures": "pass",
"realConsumerRestores": "pass"
},
"consumers": [
{
"name": "SpaceGame",
"revision": "f3f5bc29810c362656cd7143bec1ddc2cfaf9f22",
"candidateRestore": "pass",
"directTrafficPilot": "pass"
},
{
"name": "Unscouted",
"revision": "f0574a7de82aadff6495ca5657dfc19cf7c2f67c",
"candidateRestore": "pass",
"directTrafficPilot": "pass"
}
],
"limitations": {
"publicRegistryRestore": "pending",
"signedPublication": "pending",
"externalNetworkCanaries": "pending"
}
}
+1 -1
View File
@@ -81,7 +81,7 @@ concurrent build, thermal throttling, or oversubscribed CI host.
The checked-in baseline is
[`candidate-2cpu.json`](../evidence/capacity/v2/candidate-2cpu.json). It was
produced on .NET 10.0.9/Linux x64 with CPU affinity restricted to two logical
CPUs. It filled 25,000 listings and 10,000 attempts, peaked at about 162 MiB,
CPUs. It filled 25,000 listings and 10,000 attempts, peaked at about 169 MiB,
and cleared all active/retained state. The five-minute baseline supersedes any
earlier local probe when its timestamp and target duration differ.
+26
View File
@@ -50,6 +50,32 @@ container bridge, or second process on one machine cannot prove it:
Failure or missing evidence is blocking. It is never converted into an accepted
risk by changing the wording of the readiness note.
When an external gate passes, add a redacted repository JSON attestation and
point that gate's `evidenceRef` to it. The checker requires this exact shape and
binds the gate to the evaluated candidate commit. `artifactDigest` is the SHA-256
of the protected evidence bundle or public release record, not a peer endpoint,
listing identifier, account identifier, or credential:
```json
{
"schemaVersion": 1,
"kind": "rendezvous-external-gate-attestation",
"gateId": "replace-with-the-exact-gate-id",
"candidateCommit": "replace-with-the-40-character-candidate-commit",
"result": "pass",
"performedAtUtc": "2026-01-01T00:00:00Z",
"artifactDigest": "replace-with-the-64-character-sha256",
"evidenceLocation": "protected-operations-record",
"reviewerRole": "independent-operator"
}
```
Allowed evidence locations are `protected-operations-record` and
`public-release-record`. Allowed reviewer roles are `release-operator`,
`network-operator`, `security-operator`, and `independent-operator`. The checker
rejects a missing file, wrong gate, wrong candidate, malformed digest, naive
timestamp, extra fields, or sensitive-data-shaped contents.
## Prepare one immutable canary build
Use the exact release candidate on every canary machine. Verify a clean checkout,
+171 -9
View File
@@ -7,6 +7,7 @@ import json
import pathlib
import re
import sys
from datetime import datetime, timedelta
from typing import Any
@@ -47,7 +48,11 @@ FORBIDDEN_KEY_PARTS = {
}
UUID = re.compile(r"\b[0-9a-fA-F]{8}-[0-9a-fA-F-]{27,}\b")
IPV4 = re.compile(r"(?<![0-9])(?:[0-9]{1,3}\.){3}[0-9]{1,3}(?![0-9])")
IPV6 = re.compile(
r"(?i)(?:\b[0-9a-f]{0,4}:[0-9a-f:]*::[0-9a-f:]*\b|\b(?:[0-9a-f]{1,4}:){4,}[0-9a-f:]{1,39}\b)"
)
COMMIT = re.compile(r"[0-9a-f]{40}")
DIGEST = re.compile(r"[0-9a-f]{64}")
class InvalidRecord(ValueError):
@@ -65,11 +70,35 @@ def reject_sensitive(value: Any, path: str = "$") -> None:
for index, child in enumerate(value):
reject_sensitive(child, f"{path}[{index}]")
elif isinstance(value, str):
if UUID.search(value) or IPV4.search(value) or "://" in value or "@" in value:
if UUID.search(value) or IPV4.search(value) or IPV6.search(value) \
or "://" in value or "@" in value:
raise InvalidRecord(f"{path} contains endpoint, identifier, or account-shaped data")
def validate_gate_set(items: Any, expected: set[str], path: str) -> list[dict[str, str]]:
def evidence_path(repository_root: pathlib.Path, value: str, path: str) -> pathlib.Path:
relative = pathlib.PurePosixPath(value)
if relative.is_absolute() or ".." in relative.parts or not value:
raise InvalidRecord(f"{path} must be a repository-relative reference")
candidate = (repository_root / pathlib.Path(*relative.parts)).resolve()
if not candidate.is_relative_to(repository_root.resolve()) or not candidate.is_file():
raise InvalidRecord(f"{path} does not resolve to a repository evidence file")
return candidate
def load_json(path: pathlib.Path, label: str) -> Any:
try:
with path.open("r", encoding="utf-8") as source:
return json.load(source)
except (OSError, json.JSONDecodeError) as error:
raise InvalidRecord(f"{label} is not readable JSON: {error}") from error
def validate_gate_set(
items: Any,
expected: set[str],
path: str,
repository_root: pathlib.Path,
) -> list[dict[str, str]]:
if not isinstance(items, list):
raise InvalidRecord(f"{path} must be an array")
gates: list[dict[str, str]] = []
@@ -80,9 +109,7 @@ def validate_gate_set(items: Any, expected: set[str], path: str) -> list[dict[st
raise InvalidRecord(f"{path}[{index}] fields must be strings")
if item["status"] not in STATUSES:
raise InvalidRecord(f"{path}[{index}] has an invalid status")
evidence = pathlib.PurePosixPath(item["evidenceRef"])
if evidence.is_absolute() or ".." in evidence.parts or not item["evidenceRef"]:
raise InvalidRecord(f"{path}[{index}].evidenceRef must be a repository-relative reference")
evidence_path(repository_root, item["evidenceRef"], f"{path}[{index}].evidenceRef")
if len(item["note"]) > 240:
raise InvalidRecord(f"{path}[{index}].note is too long")
gates.append(item)
@@ -96,7 +123,135 @@ def validate_gate_set(items: Any, expected: set[str], path: str) -> list[dict[st
return gates
def validate(record: Any) -> tuple[bool, list[str]]:
def validate_local_evidence(
record: dict[str, Any],
gates: list[dict[str, str]],
repository_root: pathlib.Path,
) -> None:
if any(gate["status"] != "pass" for gate in gates):
return
commit = record["evaluatedCommit"]
release_path = evidence_path(
repository_root,
"docs/evidence/releases/v1.0.0-local-candidate.json",
"local release evidence",
)
release = load_json(release_path, "local release evidence")
if not isinstance(release, dict) or release.get("schemaVersion") != 1 \
or release.get("kind") != "rendezvous-local-release-candidate" \
or release.get("sourceCommit") != commit \
or release.get("treeState") != "clean" \
or release.get("result") != "pass":
raise InvalidRecord("local release evidence is not a passing clean build of evaluatedCommit")
verification = release.get("verification")
if not isinstance(verification, dict):
raise InvalidRecord("local release evidence has no verification object")
exact_passes = {
"lockedRestore": "pass",
"format": "pass",
"byteReproduciblePackages": "pass",
"byteReproducibleServerArchive": "pass",
"sbomChecksumsAndProvenance": "pass",
"candidateConsumerFixtures": "pass",
"realConsumerRestores": "pass",
}
if any(verification.get(key) != value for key, value in exact_passes.items()) \
or verification.get("reportedVulnerabilities") != 0 \
or verification.get("releaseBuildWarnings") != 0 \
or verification.get("releaseBuildErrors") != 0 \
or verification.get("debugTestsPassed", 0) < 300 \
or verification.get("debugTestsFailed") != 0 \
or verification.get("releaseTestsPassed", 0) < 300 \
or verification.get("releaseTestsFailed") != 0 \
or verification.get("selectedProductionFaultTestsPassed", 0) < 17:
raise InvalidRecord("local release evidence does not satisfy every required verification")
consumers = release.get("consumers")
if not isinstance(consumers, list) or {
item.get("name") for item in consumers if isinstance(item, dict)
} != {"SpaceGame", "Unscouted"} or any(
not isinstance(item, dict)
or item.get("candidateRestore") != "pass"
or item.get("directTrafficPilot") != "pass"
for item in consumers
):
raise InvalidRecord("local release evidence does not prove both required consumers")
capacity_path = evidence_path(
repository_root,
"docs/evidence/capacity/v2/candidate-2cpu.json",
"candidate capacity evidence",
)
capacity = load_json(capacity_path, "candidate capacity evidence")
runtime = capacity.get("runtime") if isinstance(capacity, dict) else None
state = capacity.get("state") if isinstance(capacity, dict) else None
if not isinstance(runtime, dict) or not isinstance(state, dict) \
or capacity.get("schemaVersion") != 2 \
or capacity.get("profile") != "candidate" \
or capacity.get("passed") is not True \
or capacity.get("failures") != [] \
or runtime.get("commitSha") != commit \
or runtime.get("treeState") != "clean" \
or runtime.get("processorCount") != 2 \
or state.get("soakDurationSeconds", 0) < 300 \
or state.get("finalListings") != 0 \
or state.get("finalAttempts") != 0 \
or state.get("finalReplayMarkers") != 0 \
or state.get("restartStartedEmpty") is not True \
or state.get("overloadWasTyped") is not True \
or state.get("recoverySucceeded") is not True:
raise InvalidRecord("candidate capacity evidence does not satisfy the clean evaluated commit")
def validate_external_attestations(
record: dict[str, Any],
gates: list[dict[str, str]],
repository_root: pathlib.Path,
) -> None:
for gate in gates:
if gate["status"] != "pass":
continue
path = evidence_path(repository_root, gate["evidenceRef"], f"{gate['id']} evidence")
attestation = load_json(path, f"{gate['id']} evidence")
if not isinstance(attestation, dict) or set(attestation) != {
"schemaVersion",
"kind",
"gateId",
"candidateCommit",
"result",
"performedAtUtc",
"artifactDigest",
"evidenceLocation",
"reviewerRole",
}:
raise InvalidRecord(f"{gate['id']} requires a complete external-gate attestation")
reject_sensitive(attestation, f"external evidence {gate['id']}")
if attestation["schemaVersion"] != 1 \
or attestation["kind"] != "rendezvous-external-gate-attestation" \
or attestation["gateId"] != gate["id"] \
or attestation["candidateCommit"] != record["evaluatedCommit"] \
or attestation["result"] != "pass" \
or not isinstance(attestation["artifactDigest"], str) \
or not DIGEST.fullmatch(attestation["artifactDigest"]) \
or attestation["evidenceLocation"] not in {
"protected-operations-record",
"public-release-record",
} \
or attestation["reviewerRole"] not in {
"release-operator",
"network-operator",
"security-operator",
"independent-operator",
}:
raise InvalidRecord(f"{gate['id']} external attestation does not match the candidate gate")
try:
performed = datetime.fromisoformat(attestation["performedAtUtc"].replace("Z", "+00:00"))
except (AttributeError, ValueError) as error:
raise InvalidRecord(f"{gate['id']} has an invalid performedAtUtc") from error
if performed.tzinfo is None or performed.utcoffset() != timedelta(0):
raise InvalidRecord(f"{gate['id']} performedAtUtc must be UTC")
def validate(record: Any, repository_root: pathlib.Path) -> tuple[bool, list[str]]:
if not isinstance(record, dict) or set(record) != {
"schemaVersion",
"kind",
@@ -111,8 +266,15 @@ def validate(record: Any) -> tuple[bool, list[str]]:
if not isinstance(record["evaluatedCommit"], str) or not COMMIT.fullmatch(record["evaluatedCommit"]):
raise InvalidRecord("evaluatedCommit must be a full lowercase Git commit")
reject_sensitive(record)
gates = validate_gate_set(record["localGates"], LOCAL_GATES, "$.localGates")
gates += validate_gate_set(record["externalGates"], EXTERNAL_GATES, "$.externalGates")
local_gates = validate_gate_set(
record["localGates"], LOCAL_GATES, "$.localGates", repository_root
)
external_gates = validate_gate_set(
record["externalGates"], EXTERNAL_GATES, "$.externalGates", repository_root
)
validate_local_evidence(record, local_gates, repository_root)
validate_external_attestations(record, external_gates, repository_root)
gates = local_gates + external_gates
blockers = sorted(gate["id"] for gate in gates if gate["status"] != "pass")
ready = not blockers
expected_decision = "ready" if ready else "not-ready"
@@ -130,7 +292,7 @@ def main() -> int:
try:
with open(sys.argv[1], "r", encoding="utf-8") as source:
record = json.load(source)
ready, blockers = validate(record)
ready, blockers = validate(record, pathlib.Path(__file__).resolve().parent.parent)
except (OSError, json.JSONDecodeError, InvalidRecord) as error:
print(f"INVALID: {error}", file=sys.stderr)
return 2
+15 -6
View File
@@ -19,6 +19,7 @@ COORDINATION_FILE="${RENDEZVOUS_CANARY_COORDINATION_FILE:-}"
LISTING_ID="${RENDEZVOUS_CANARY_LISTING_ID:-}"
REQUIRE_CLEAN="${RENDEZVOUS_CANARY_REQUIRE_CLEAN:-true}"
KEEP_RAW="${RENDEZVOUS_CANARY_KEEP_RAW:-false}"
UUID_PATTERN='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
usage() {
printf '%s\n' \
@@ -28,7 +29,7 @@ usage() {
exit 2
}
for command in date dotnet git jq mktemp; do
for command in date dotnet git jq mktemp tail; do
command -v "$command" >/dev/null || {
printf 'Missing required command: %s\n' "$command" >&2
exit 2
@@ -98,12 +99,16 @@ if [[ "$ROLE" == host ]]; then
printf 'The host role requires RENDEZVOUS_CANARY_COORDINATION_FILE.\n' >&2
exit 2
fi
if [[ -e "$COORDINATION_FILE" ]]; then
printf 'The host coordination file already exists; remove it explicitly before a new canary.\n' >&2
exit 2
fi
if [[ -z "${RENDEZVOUS_PUBLISHER_CREDENTIAL:-}" ]]; then
printf 'The host role requires RENDEZVOUS_PUBLISHER_CREDENTIAL.\n' >&2
exit 2
fi
else
if [[ ! "$LISTING_ID" =~ ^[0-9a-fA-F-]{36}$ ]]; then
if [[ ! "$LISTING_ID" =~ $UUID_PATTERN ]]; then
printf 'A client role requires a UUID in RENDEZVOUS_CANARY_LISTING_ID.\n' >&2
exit 2
fi
@@ -168,7 +173,7 @@ if [[ "$ROLE" == host ]]; then
exit 1
fi
observed_listing="$(jq -r 'select(.event == "host.registered") | .listingId' "$raw_log" | tail -n 1)"
if [[ ! "$observed_listing" =~ ^[0-9a-f-]{36}$ ]]; then
if [[ ! "$observed_listing" =~ $UUID_PATTERN ]]; then
printf 'The canary host did not produce a valid coordination identifier.\n' >&2
kill -TERM "$host_pid" 2>/dev/null || true
wait "$host_pid" 2>/dev/null || true
@@ -176,9 +181,8 @@ if [[ "$ROLE" == host ]]; then
fi
coordination_parent="$(dirname "$COORDINATION_FILE")"
mkdir -p "$coordination_parent"
coordination_temp="$COORDINATION_FILE.tmp.$$"
coordination_temp="$(mktemp "$COORDINATION_FILE.tmp.XXXXXXXX")"
printf '%s\n' "$observed_listing" >"$coordination_temp"
chmod 600 "$coordination_temp"
mv "$coordination_temp" "$COORDINATION_FILE"
printf 'Host ready; securely transfer the private coordination file to the client operator.\n'
set +e
@@ -219,6 +223,10 @@ else
fi
mkdir -p "$(dirname "$OUTPUT")"
raw_retention=deleted-after-success
if [[ "$KEEP_RAW" == true ]]; then
raw_retention=retained-private-on-request
fi
jq -n \
--arg commit "$commit" \
--arg treeState "$tree_state" \
@@ -226,8 +234,9 @@ jq -n \
--arg role "$ROLE" \
--arg topology "$TOPOLOGY" \
--arg addressFamily "$ADDRESS_FAMILY" \
--arg rawEvents "$raw_retention" \
--argjson checks "$checks" \
'{schemaVersion:1,kind:"rendezvous-real-network-canary",commit:$commit,treeState:$treeState,timestampUtc:$timestampUtc,role:$role,topology:$topology,addressFamily:$addressFamily,result:"pass",checks:$checks,dataRetention:{rawEvents:"deleted-after-success",identifiers:"not-in-summary",networkEndpoints:"not-in-summary"}}' \
'{schemaVersion:1,kind:"rendezvous-real-network-canary",commit:$commit,treeState:$treeState,timestampUtc:$timestampUtc,role:$role,topology:$topology,addressFamily:$addressFamily,result:"pass",checks:$checks,dataRetention:{rawEvents:$rawEvents,identifiers:"not-in-summary",networkEndpoints:"not-in-summary"}}' \
>"$OUTPUT"
run_succeeded=true
@@ -209,6 +209,9 @@ public sealed class ReleaseCompatibilityTests
Assert.Contains("return 3", checker, StringComparison.Ordinal);
Assert.Contains("FORBIDDEN_KEY_PARTS", checker, StringComparison.Ordinal);
Assert.Contains("decision must be", checker, StringComparison.Ordinal);
Assert.Contains("candidate capacity evidence", checker, StringComparison.Ordinal);
Assert.Contains("rendezvous-external-gate-attestation", checker, StringComparison.Ordinal);
Assert.Contains("does not resolve to a repository evidence file", checker, StringComparison.Ordinal);
}
private static string Property(XDocument document, string name) =>