Skip to content

Commit 54f39a0

Browse files
committed
ci: make sole-repo CI green without basecrawl sibling
Skip monorepo diary tests when ../basecrawl is absent, document chromium_0day residual in relay threat map/docs for VAL-HARDEN-022, format ruff-failing modules, and note optional sibling checkout in CI.
1 parent 0d2b514 commit 54f39a0

8 files changed

Lines changed: 82 additions & 45 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
name: CI
22

3+
# Sole-repo CI for BaseIntelligence/relay.
4+
# Cross-repo diary tests that need BaseIntelligence/basecrawl as a sibling
5+
# checkout (../basecrawl) skip gracefully when the sibling is absent.
6+
# To run the full monorepo diary, check out basecrawl beside relay (e.g.
7+
# optional multi-repo checkout of BaseIntelligence/basecrawl into ../basecrawl).
38
on:
49
push:
510
branches:
@@ -29,6 +34,8 @@ jobs:
2934
runs-on: ubuntu-latest
3035
steps:
3136
- uses: actions/checkout@v4
37+
# Optional: add actions/checkout for BaseIntelligence/basecrawl into
38+
# ${{ github.workspace }}/../basecrawl to exercise sibling diary tests.
3239
- uses: astral-sh/setup-uv@v5
3340
with:
3441
enable-cache: true

docs/THREAT_MODEL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Machine-readable, greppable probe surface for this table (VAL-HARDEN-016..020, 0
7171
| Geo spoof (VPN/relay) | Latency landmark upper bound (speed-of-light) + composition (`threat-model` `geo_spoof`) | Soft IP-geo error residual |
7272
| Fake failure dodge | Failure response is attested; L5 integrity + quorum attribution (`threat-model` `fake_failure`) ||
7373
| Malicious / colluding witness proxy | Witness-proxy disabled (default) or scored strictly below TEE (`witness-proxy`) | Weaker trust on proxy operator + un-hijacked network path |
74-
| Chromium / OS 0-day in TCB | Minimal documented TCB + image-rotation-on-CVE + replay-audit backstop | Measured-but-exploited residual until rotation |
74+
| Chromium / OS 0-day in TCB | Minimal documented TCB + digest-pinned reproducible image + image-rotation-on-CVE runbook + allowlist rotate + **replay-audit** backstop (`threat-model` residual; monorepo diary in `basecrawl/docs/tcb-inventory.md` + `image-rotation-on-cve.md` when sibling present) | **measured-but-exploited** residual until the CVE is patched and the image measurement is rotated |
7575
| Policy bypass on open-web targets | Pre-seal policy gate is authoritative; miners fetch blind ||
7676
| Non-TEE / witness-only submit | Reject with `non_tee_unsupported`, `reward_gate=closed`, zero weight when the witness-proxy tier is disabled (`GET /internal/v1/scoring/config`,`POST /internal/v1/verify`); when enabled, weight and audit rates score it strictly below TEE | Weaker trust rests on the **proxy operator + un-hijacked network path**, not the TEE anchor (see `docs/WITNESS_PROXY.md`) |
7777

src/relay/keyrelease/allowlist_rotate.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,7 @@ def atomic_rotate_allowlist(
9898
"""
9999

100100
destination = Path(path)
101-
pinned = (
102-
new_entry
103-
if isinstance(new_entry, CanonicalEntry)
104-
else _entry_from_mapping(new_entry)
105-
)
101+
pinned = new_entry if isinstance(new_entry, CanonicalEntry) else _entry_from_mapping(new_entry)
106102
retired_entries: list[CanonicalEntry] = []
107103
for item in retire:
108104
retired_entries.append(
@@ -142,10 +138,7 @@ def atomic_rotate_allowlist(
142138
retired.platform,
143139
retired.pins or {},
144140
)
145-
if (
146-
allowlist.contains(retired_candidate)
147-
and _entry_identity(retired) != pinned_id
148-
):
141+
if allowlist.contains(retired_candidate) and _entry_identity(retired) != pinned_id:
149142
raise AllowlistRotationError(
150143
"retired measurement still present after rotation (fail closed)"
151144
)
@@ -214,9 +207,7 @@ def verify_rotation(
214207
"status": "pass" if ok else "fail",
215208
"retired": retired_verdict,
216209
"new": new_verdict,
217-
"dual_accept": (
218-
retired_verdict["status"] == "pass" and new_verdict["status"] == "pass"
219-
),
210+
"dual_accept": (retired_verdict["status"] == "pass" and new_verdict["status"] == "pass"),
220211
}
221212

222213

src/relay/scoring/threat_model.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,12 +1117,27 @@ def build_threat_map() -> list[dict[str, Any]]:
11171117
) and ("managed-cloud" in threat_doc.lower() or "managed cloud" in threat_doc.lower())
11181118
item["docs"] = str(_THREAT_DOC)
11191119
elif item["threat"] == "chromium_0day":
1120-
residual_documented = _TCB_DOC.is_file() and _ROTATION_DOC.is_file()
1121-
if _TCB_DOC.is_file():
1122-
residual_documented = residual_documented and (
1123-
"measured-but-exploited" in _TCB_DOC.read_text(encoding="utf-8")
1120+
# Prefer monorepo basecrawl TCB diary. Sole-repo CI documents residual
1121+
# on ARCHITECTURE_SECTION_7 + relay/docs/THREAT_MODEL.md (no sibling).
1122+
basecrawl_docs_ok = _TCB_DOC.is_file() and _ROTATION_DOC.is_file()
1123+
if basecrawl_docs_ok:
1124+
residual_documented = "measured-but-exploited" in _TCB_DOC.read_text(
1125+
encoding="utf-8"
11241126
)
1125-
item["docs"] = [str(_TCB_DOC), str(_ROTATION_DOC)]
1127+
item["docs"] = [str(_TCB_DOC), str(_ROTATION_DOC)]
1128+
else:
1129+
threat_doc = (
1130+
_THREAT_DOC.read_text(encoding="utf-8").lower() if _THREAT_DOC.is_file() else ""
1131+
)
1132+
residual_documented = bool(item.get("residual")) and (
1133+
"measured-but-exploited" in threat_doc
1134+
or (
1135+
"chromium" in threat_doc
1136+
and "residual" in threat_doc
1137+
and "replay-audit" in threat_doc
1138+
)
1139+
)
1140+
item["docs"] = [str(_THREAT_DOC)]
11261141
elif item["threat"] == "malicious_witness":
11271142
residual_documented = _WITNESS_DOC.is_file()
11281143
item["docs"] = str(_WITNESS_DOC)

src/relay/verify/l2_binding.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,7 @@ def evaluate_l2_binding(
412412
or proof_method != DISPATCHED_REQUEST_METHOD
413413
or proof_body is None
414414
or proof_body != empty_body
415-
or (
416-
issued_url is not None
417-
and isinstance(issued_url, str)
418-
and proof_url != issued_url
419-
)
415+
or (issued_url is not None and isinstance(issued_url, str) and proof_url != issued_url)
420416
or (
421417
# Keep the tight pin when the enclave answers with the fully empty
422418
# sealed request (no fingerprint headers): request_hash must equal

tests/test_claims_honesty.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,14 @@ def test_threat_security_docs_exist_and_document_tee_fail() -> None:
311311
"""VAL-HARDEN-004: threat/security docs hold residual + managed-cloud mitigation."""
312312

313313
threat_doc = _RELAY_DOCS / "THREAT_MODEL.md"
314-
security_doc = _BASECRAWL_DOCS / "SECURITY.md"
315314
assert threat_doc.is_file(), "relay/docs/THREAT_MODEL.md must exist"
316-
assert security_doc.is_file(), "basecrawl/docs/SECURITY.md must exist"
317-
for path in (threat_doc, security_doc):
315+
docs = [threat_doc]
316+
# basecrawl SECURITY.md is monorepo diary surface; sole-repo CI skips it.
317+
if _BASECRAWL_ROOT.is_dir():
318+
security_doc = _BASECRAWL_DOCS / "SECURITY.md"
319+
assert security_doc.is_file(), "basecrawl/docs/SECURITY.md must exist when sibling present"
320+
docs.append(security_doc)
321+
for path in docs:
318322
text = path.read_text(encoding="utf-8").lower()
319323
assert "tee.fail" in text or "tee fail" in text
320324
assert "ddr5" in text

tests/test_cve_image_rotation.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from pathlib import Path
1717
from typing import Any
1818

19+
import pytest
20+
1921
from relay.keyrelease.allowlist import CanonicalEntry, MeasurementAllowlist
2022
from relay.keyrelease.allowlist_rotate import (
2123
RETIRED_REASON,
@@ -48,7 +50,8 @@
4850
KEY_PROVIDER_PAYLOAD = b'{"name":"kms","id":"kms-basecrawl"}'
4951
REPORT_DATA = bytes(range(64))
5052

51-
BASECRAWL_ROOT = Path("/projects/platform-network/basecrawl")
53+
# Sibling monorepo checkout (present for full diary; absent on sole-repo CI).
54+
BASECRAWL_ROOT = Path(__file__).resolve().parents[1].parent / "basecrawl"
5255

5356

5457
def _os_image(mrtd: str, rtmr1: str, rtmr2: str) -> str:
@@ -180,12 +183,8 @@ def test_post_rotation_l1_rejects_retired_and_admits_new() -> None:
180183

181184
# Pre-rotation: only the vulnerable (soon retired) pin is allowlisted.
182185
before = MeasurementAllowlist([retired])
183-
proof_retired = _proof_for(
184-
mrtd=MRTD_OLD, rtmr2=RTMR2_OLD, compose_hash=COMPOSE_HASH_OLD
185-
)
186-
proof_new = _proof_for(
187-
mrtd=MRTD_NEW, rtmr2=RTMR2_NEW, compose_hash=COMPOSE_HASH_NEW
188-
)
186+
proof_retired = _proof_for(mrtd=MRTD_OLD, rtmr2=RTMR2_OLD, compose_hash=COMPOSE_HASH_OLD)
187+
proof_new = _proof_for(mrtd=MRTD_NEW, rtmr2=RTMR2_NEW, compose_hash=COMPOSE_HASH_NEW)
189188
pre_old = evaluate_l1(proof_retired, config=_l1(before))
190189
pre_new = evaluate_l1(proof_new, config=_l1(before))
191190
assert pre_old.status == "pass"
@@ -237,6 +236,11 @@ def test_reproducible_rebuild_yields_stable_allowlist_pin(tmp_path: Path) -> Non
237236

238237

239238
def test_tcb_docs_enumerate_minimized_tcb_and_rotation_runbook() -> None:
239+
if not BASECRAWL_ROOT.is_dir():
240+
pytest.skip(
241+
"basecrawl sibling checkout not present "
242+
"(sole-repo CI; full TCB diary runs when monorepo sibling exists)"
243+
)
240244
inventory = BASECRAWL_ROOT / "docs" / "tcb-inventory.md"
241245
runbook = BASECRAWL_ROOT / "docs" / "image-rotation-on-cve.md"
242246
assert inventory.is_file()

tests/test_license_and_secrets_compliance.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,24 @@
2424

2525
_RELAY_ROOT = Path(__file__).resolve().parents[1]
2626
_BASECRAWL_ROOT = _RELAY_ROOT.parent / "basecrawl"
27+
# Always include relay; include basecrawl only when the monorepo sibling exists
28+
# (sole-repo CI checks out relay alone — basecrawl diary tests skip gracefully).
2729
_REPO_ROOTS = {
2830
"relay": _RELAY_ROOT,
29-
"basecrawl": _BASECRAWL_ROOT,
31+
**({"basecrawl": _BASECRAWL_ROOT} if _BASECRAWL_ROOT.is_dir() else {}),
3032
}
3133

34+
35+
def _require_basecrawl() -> Path:
36+
"""Skip when basecrawl is not checked out beside relay (outright CI skip)."""
37+
if not _BASECRAWL_ROOT.is_dir():
38+
pytest.skip(
39+
"basecrawl sibling checkout not present "
40+
"(sole-repo CI; full license diary runs when monorepo sibling exists)"
41+
)
42+
return _BASECRAWL_ROOT
43+
44+
3245
# Apache-2.0 licence header fingerprint (first non-blank content lines).
3346
_APACHE_FINGERPRINTS = (
3447
"apache license",
@@ -132,7 +145,8 @@ def test_apache_license_file_present(repo_name: str) -> None:
132145

133146

134147
def test_basecrawl_cargo_workspace_declares_apache() -> None:
135-
cargo = (_BASECRAWL_ROOT / "Cargo.toml").read_text(encoding="utf-8")
148+
root = _require_basecrawl()
149+
cargo = (root / "Cargo.toml").read_text(encoding="utf-8")
136150
assert re.search(r'(?m)^license\s*=\s*"Apache-2\.0"\s*$', cargo), (
137151
"basecrawl workspace.package.license must be Apache-2.0"
138152
)
@@ -146,21 +160,24 @@ def test_relay_pyproject_declares_apache() -> None:
146160

147161

148162
def test_basecrawl_python_binding_declares_apache() -> None:
149-
path = _BASECRAWL_ROOT / "bindings" / "python" / "pyproject.toml"
163+
root = _require_basecrawl()
164+
path = root / "bindings" / "python" / "pyproject.toml"
150165
text = path.read_text(encoding="utf-8")
151166
assert re.search(r'(?m)^license\s*=\s*"Apache-2\.0"\s*$', text), (
152167
"basecrawl python binding must declare Apache-2.0"
153168
)
154169

155170

156171
def test_basecrawl_node_binding_declares_apache() -> None:
157-
path = _BASECRAWL_ROOT / "bindings" / "node" / "package.json"
172+
root = _require_basecrawl()
173+
path = root / "bindings" / "node" / "package.json"
158174
data = json.loads(path.read_text(encoding="utf-8"))
159175
assert data.get("license") == "Apache-2.0", "node package.json must declare Apache-2.0"
160176

161177

162178
def test_basecrawl_crates_inherit_or_declare_apache() -> None:
163-
crate_tomls = list((_BASECRAWL_ROOT / "crates").glob("*/Cargo.toml"))
179+
root = _require_basecrawl()
180+
crate_tomls = list((root / "crates").glob("*/Cargo.toml"))
164181
assert crate_tomls, "expected crate Cargo.toml files"
165182
for path in crate_tomls:
166183
text = path.read_text(encoding="utf-8")
@@ -171,11 +188,12 @@ def test_basecrawl_crates_inherit_or_declare_apache() -> None:
171188

172189
def test_basecrawl_dependency_tree_has_no_infection_copyleft() -> None:
173190
"""Cargo metadata: no pure AGPL/GPL in normal (linked) dependency licenses."""
174-
if not (_BASECRAWL_ROOT / "Cargo.toml").is_file():
175-
pytest.skip("basecrawl missing")
191+
root = _require_basecrawl()
192+
if not (root / "Cargo.toml").is_file():
193+
pytest.skip("basecrawl missing Cargo.toml")
176194
proc = _run(
177195
["cargo", "metadata", "--format-version", "1", "--all-features"],
178-
cwd=_BASECRAWL_ROOT,
196+
cwd=root,
179197
)
180198
assert proc.returncode == 0, proc.stderr
181199
meta = json.loads(proc.stdout)
@@ -286,9 +304,10 @@ def infection(license_str: str) -> bool:
286304

287305
def test_workspace_lockfiles_list_no_agpl_gpl_package_names() -> None:
288306
"""Greppable safety net: lockfiles must not embed AGPL/GPL license strings as sole license."""
289-
cargo_lock = _BASECRAWL_ROOT / "Cargo.lock"
290-
uv_lock = _RELAY_ROOT / "uv.lock"
291-
for path in (cargo_lock, uv_lock):
307+
lockfiles = [_RELAY_ROOT / "uv.lock"]
308+
if _BASECRAWL_ROOT.is_dir():
309+
lockfiles.insert(0, _BASECRAWL_ROOT / "Cargo.lock")
310+
for path in lockfiles:
292311
assert path.is_file(), f"missing lockfile {path}"
293312
text = path.read_text(encoding="utf-8", errors="replace")
294313
# Cargo.lock / uv.lock do not always embed license strings; still ban
@@ -399,7 +418,8 @@ def test_git_history_has_no_secret_patterns(repo_name: str) -> None:
399418

400419
def test_env_file_documents_secret_keys_without_values() -> None:
401420
"""When .env exists, keys are present but MUST NOT hold real-looking secrets."""
402-
for name, root in _REPO_ROOTS.items():
421+
repos = dict(_REPO_ROOTS)
422+
for name, root in repos.items():
403423
env_path = root / ".env"
404424
if not env_path.exists():
405425
continue

0 commit comments

Comments
 (0)