docs: define workspace evidence registry contract
This commit is contained in:
@@ -12,6 +12,7 @@ trap 'rm -f "$output" "$verifier_functions"; rm -rf "$negative_root"' EXIT HUP I
|
||||
|
||||
for fixture in \
|
||||
"internal semantic infrastructure documentation contract" \
|
||||
"workspace Evidence documentation contract" \
|
||||
"local installation guide contract" \
|
||||
"source update fail-closed semantics" \
|
||||
"Windows line-ending recovery guide contract" \
|
||||
@@ -430,6 +431,126 @@ if [[ $adapted_status -eq 0 ]] || ! grep -Fq "Caddy adapted frontend path bypass
|
||||
fi
|
||||
|
||||
negative_failures=0
|
||||
expect_evidence_fixture_rejected() {
|
||||
local label="$1" target="$2" mutation="$3" expected_error="$4"
|
||||
local fixture_root="$negative_root/evidence-${label// /-}"
|
||||
local fixture_output="$fixture_root/output"
|
||||
|
||||
# Before Task 7's dedicated verifier exists, every mutation is deliberately accepted. This
|
||||
# makes the complete Evidence test matrix RED without allowing command-not-found to abort it.
|
||||
if ! declare -F verify_workspace_evidence_contract >/dev/null; then
|
||||
echo "negative fixture accepted: $label (Evidence verifier missing)" >&2
|
||||
negative_failures=$((negative_failures + 1))
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir -p \
|
||||
"$fixture_root/deploy/workspaces" \
|
||||
"$fixture_root/docs/contracts" \
|
||||
"$fixture_root/docs/install/examples"
|
||||
cp "$root/deploy/workspaces/example.yaml" "$fixture_root/deploy/workspaces/example.yaml"
|
||||
cp "$root/deploy/workspaces/psd.yaml.example" "$fixture_root/deploy/workspaces/psd.yaml.example"
|
||||
cp "$root/docs/contracts/workspace-evidence-v3.md" \
|
||||
"$fixture_root/docs/contracts/workspace-evidence-v3.md"
|
||||
cp "$root/docs/install/local-workspace-registry.md" \
|
||||
"$fixture_root/docs/install/local-workspace-registry.md"
|
||||
cp "$root/docs/install/server-workspace-registry.md" \
|
||||
"$fixture_root/docs/install/server-workspace-registry.md"
|
||||
cp "$root/docs/install/examples/workspace-bindings.env.example" \
|
||||
"$fixture_root/docs/install/examples/workspace-bindings.env.example"
|
||||
|
||||
python3 - "$fixture_root/$target" "$mutation" <<'PY'
|
||||
import pathlib, sys, yaml
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
mutation = sys.argv[2]
|
||||
original = path.read_text()
|
||||
changed = original
|
||||
if mutation == "layout-omitted":
|
||||
changed = original.replace("│ ├── example/evidence/...\n", "", 1)
|
||||
elif mutation == "same-commit-omitted":
|
||||
changed = original.replace(
|
||||
"| Revision identity | The descriptor blob and filesystem Evidence root tree are checked at the same 40-hex Git commit. |\n",
|
||||
"",
|
||||
1,
|
||||
)
|
||||
elif mutation in {"absolute-filesystem", "cross-workspace"}:
|
||||
document = yaml.safe_load(original)
|
||||
document["evidence"]["source"]["uri"] = (
|
||||
"/srv/evidence" if mutation == "absolute-filesystem"
|
||||
else "workspace-content/example/evidence"
|
||||
)
|
||||
changed = yaml.safe_dump(document, sort_keys=False)
|
||||
elif mutation == "wrong-docs-directory":
|
||||
changed = original.replace(
|
||||
"workspace-docs/\n ├── example/{contract.env.example,README.md}\n └── another/{contract.env.example,README.md}",
|
||||
"workspaces/<id>.env.example\nworkspaces/<id>.md",
|
||||
1,
|
||||
)
|
||||
elif mutation == "http-file-boundary-omitted":
|
||||
changed = original.replace(
|
||||
"| Signed HTTP | `THT_WS_<NAMESPACE>_EVIDENCE_SIGNED_URLS_FILE` | Required for `signed_urls_file`; nonempty JSON string array in declared-URI order; query-stripped identities must match `uris`. |\n",
|
||||
"",
|
||||
1,
|
||||
)
|
||||
elif mutation == "s3-pair-boundary-omitted":
|
||||
changed = original.replace(
|
||||
"| Static S3 pair | `THT_WS_<NAMESPACE>_EVIDENCE_ACCESS_KEY_FILE` and `THT_WS_<NAMESPACE>_EVIDENCE_SECRET_KEY_FILE` | Required together for `static_files`. |\n",
|
||||
"",
|
||||
1,
|
||||
)
|
||||
elif mutation == "s3-token-boundary-omitted":
|
||||
changed = original.replace(
|
||||
"| Static S3 session | `THT_WS_<NAMESPACE>_EVIDENCE_SESSION_TOKEN_FILE` | Optional, and valid only with the required access/secret pair. |\n",
|
||||
"",
|
||||
1,
|
||||
)
|
||||
elif mutation == "credential-literal":
|
||||
changed = original + "\nTHT_WS_STATIC_S3_EVIDENCE_SECRET_KEY=AKIAEXAMPLECREDENTIAL\n"
|
||||
elif mutation == "signed-query-example":
|
||||
signed_query = "https://evidence.example.invalid/report" + "?X-Amz-Signature=unsafe"
|
||||
changed = original + f"\nTHT_EVIDENCE_URI={signed_query}\n"
|
||||
elif mutation == "unsafe-placeholder":
|
||||
changed = original.replace(
|
||||
"/run/secrets/signed-http-evidence-urls.json", "changeme", 1
|
||||
)
|
||||
elif mutation == "p1-scope-inversion":
|
||||
changed = original.replace(
|
||||
"P1 performs no acquisition, extraction, preprocessing/indexing, embeddings, Qdrant writes, `ACTIVE` publication, retention, or GC.",
|
||||
"P1 materializes, extracts, and indexes Evidence before publication.",
|
||||
1,
|
||||
)
|
||||
elif mutation == "config-ordering":
|
||||
changed = original.replace(
|
||||
"tht config check -c <path>", "tht -c <path> config check", 1
|
||||
)
|
||||
elif mutation == "acceptance-conflation":
|
||||
changed = original.replace("manual acceptance: PENDING\n", "", 1)
|
||||
elif mutation == "curator-order":
|
||||
second = "2. Add source bytes below `workspace-content/<id>/evidence`, then commit and push."
|
||||
third = "3. Validate and publish the descriptor against that base commit."
|
||||
changed = original.replace(second + "\n" + third, third + "\n" + second, 1)
|
||||
else:
|
||||
raise SystemExit(f"unknown Evidence mutation: {mutation}")
|
||||
if changed == original:
|
||||
raise SystemExit(f"Evidence mutation made no change: {mutation}")
|
||||
path.write_text(changed)
|
||||
PY
|
||||
|
||||
set +e
|
||||
verify_workspace_evidence_contract "$fixture_root" >"$fixture_output" 2>&1
|
||||
local status=$?
|
||||
set -e
|
||||
if [[ $status -eq 0 ]]; then
|
||||
echo "negative fixture accepted: $label" >&2
|
||||
cat "$fixture_output" >&2
|
||||
negative_failures=$((negative_failures + 1))
|
||||
elif ! grep -Fq -- "$expected_error" "$fixture_output"; then
|
||||
echo "negative fixture failed for the wrong reason: $label" >&2
|
||||
cat "$fixture_output" >&2
|
||||
negative_failures=$((negative_failures + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
expect_guide_rejected() {
|
||||
local label="$1" validator="$2" source_guide="$3" relative_path="$4"
|
||||
local mutation="$5" expected_error="$6"
|
||||
@@ -784,6 +905,52 @@ expect_guide_rejected \
|
||||
"$root/docs/install/windows-line-endings.md" docs/install/windows-line-endings.md powershell-crlf-failure \
|
||||
"PowerShell CRLF repair lacks failure propagation: Assert-NativeSuccess 'index export'"
|
||||
|
||||
expect_evidence_fixture_rejected \
|
||||
"canonical Evidence layout omitted" docs/contracts/workspace-evidence-v3.md layout-omitted \
|
||||
"missing canonical Evidence layout"
|
||||
expect_evidence_fixture_rejected \
|
||||
"same revision ownership omitted" docs/contracts/workspace-evidence-v3.md same-commit-omitted \
|
||||
"missing same-revision ownership"
|
||||
expect_evidence_fixture_rejected \
|
||||
"absolute filesystem Evidence path" deploy/workspaces/example.yaml absolute-filesystem \
|
||||
"noncanonical filesystem Evidence URI"
|
||||
expect_evidence_fixture_rejected \
|
||||
"cross-workspace Evidence path" deploy/workspaces/psd.yaml.example cross-workspace \
|
||||
"Evidence namespace mismatch"
|
||||
expect_evidence_fixture_rejected \
|
||||
"generated docs in wrong directory" docs/contracts/workspace-evidence-v3.md wrong-docs-directory \
|
||||
"generated docs path invalid"
|
||||
expect_evidence_fixture_rejected \
|
||||
"signed HTTP file boundary omitted" docs/contracts/workspace-evidence-v3.md http-file-boundary-omitted \
|
||||
"missing signed HTTP file boundary"
|
||||
expect_evidence_fixture_rejected \
|
||||
"static S3 pair boundary omitted" docs/contracts/workspace-evidence-v3.md s3-pair-boundary-omitted \
|
||||
"missing static S3 file boundary"
|
||||
expect_evidence_fixture_rejected \
|
||||
"static S3 optional token boundary omitted" docs/contracts/workspace-evidence-v3.md s3-token-boundary-omitted \
|
||||
"missing static S3 session-token boundary"
|
||||
expect_evidence_fixture_rejected \
|
||||
"credential literal in public bindings" docs/install/examples/workspace-bindings.env.example credential-literal \
|
||||
"credential literal forbidden"
|
||||
expect_evidence_fixture_rejected \
|
||||
"signed query in public bindings" docs/install/examples/workspace-bindings.env.example signed-query-example \
|
||||
"query-bearing public URI forbidden"
|
||||
expect_evidence_fixture_rejected \
|
||||
"unsafe Evidence file placeholder" docs/install/examples/workspace-bindings.env.example unsafe-placeholder \
|
||||
"unsafe file placeholder/path"
|
||||
expect_evidence_fixture_rejected \
|
||||
"P1 Evidence scope inversion" docs/contracts/workspace-evidence-v3.md p1-scope-inversion \
|
||||
"P1 scope violation"
|
||||
expect_evidence_fixture_rejected \
|
||||
"config check option reordered" docs/contracts/workspace-evidence-v3.md config-ordering \
|
||||
"exact config-check ordering missing"
|
||||
expect_evidence_fixture_rejected \
|
||||
"acceptance states conflated" docs/contracts/workspace-evidence-v3.md acceptance-conflation \
|
||||
"separate automated/manual states missing"
|
||||
expect_evidence_fixture_rejected \
|
||||
"local curator flow reordered" docs/install/local-workspace-registry.md curator-order \
|
||||
"curator flow out of order"
|
||||
|
||||
if (( negative_failures != 0 )); then
|
||||
echo "$negative_failures unsafe installation-document fixtures were accepted" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user