Skip to content

refactor: tests, rule packs and housekeeping on traust-core; engine kept for three pending ops (XWING-2440) - #291

Merged
smith-xyz merged 17 commits into
traust-security:developmentfrom
smith-xyz:refactor/drop-traust-engine-final
Oct 27, 2026
Merged

smith-xyz merged 17 commits into
traust-security:developmentfrom
smith-xyz:refactor/drop-traust-engine-final

Conversation

@smith-xyz

@smith-xyz smith-xyz commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Plan: plans/traust-standardization/0-continuous-ops/in-review/17-shaun-traust-core-only.md (part)

Stacked on lanes a–e; merge those first: #279 (a, loader) → #286 (b, tools), #284 (c, metrics/registry), #285 (d, reporting/sweep), #283 (e, harnessing). This branch is lane (a)'s branch with b–e merged in (conflicts in pyproject.toml, uv.lock, .ratchet.json, tests/test_engine_imports.py and the pqc-readiness SKILL.md, each kept both sides). Review the commits after b08daa5.

Chain: traust-core #222, #223, #225, #229 (new, stacked on #223) · traust-engine #112 · this PR.

Core pin: 7598d2c on chore/w2-core-doors-combined, a merge-only branch of core #225 + #223 + #222 + #229 (lanes b, c and d each pinned a different core PR head). It has no PR of its own; re-pin to core development once those four merge.

Scope, as decided mid-lane

The plan's lane (f) said to drop traust-engine. It stays a dependency, because three ops are still waiting on a retire-or-port decision from Shaun. The PR keeps "(part)". The final drop is a follow-up once those decisions land.

Still on the engine Marker
sweep collect/draft/sweep/emit/benchmark/rule-lane/verify-draft PENDING(decision: sweep stages — retire or port)
portfolio graph build/query PENDING(decision: portfolio graph layers — retire or port)
metrics history/spend/declare-spend PENDING(decision: metrics journal — retire or port to OpsService timeline)

What

  1. Rule packs ship in packs/security/. opengrep-rules/ (with its licence note) and gitleaks-rules/gitleaks-default.toml (with its calibration fixtures) are copied from traust-engine 7c6aa58; the only edits are the README's location lines. They are the conventional defaults for locations.opengrep_rules and locations.gitleaks_config (traust.paths.OPENGREP_RULES_DIR / GITLEAKS_CONFIG). The bundled pack's pack_version is traust's version; a configured pack stays local:{pack}. Both PENDING(pack: …) branches are deleted, and so is src/traust/_tools.py. The sweep stages also default to load().rule_pack, so one copy is the only one in use. The single-rule-pack gate (check_docs_consistency) now names packs/security/. The ruff exclude covers the pack's deliberately vulnerable fixtures, as the engine's did.
  2. The last contracts imports are gone. reporting rate-threats gets risk_rating from core models.values (core build(deps): pin traust-core to development 0f3fa0c (XWING-2440) #229). scripts/install_traust --doctor step 4 now runs traust.context.load().
  3. Storage-free doors (core build(deps): pin traust-core to development 0f3fa0c (XWING-2440) #229): the live spend view and attribute-spend use ctx.spend_views, and registry products uses ctx.product_lookup, so none of them creates traust.db any more. collect-spend --append and --reconcile still record. New test: tests/test_storage_free_views.py.
  4. Tests moved onto core doors (below). The engine-loop tests moved to traust-engine chore(deps): pin traust-engine 0.39.0 (LLM-application rules); 0.37.0 #112.
  5. Import guard: tests/test_engine_imports.py now covers traust_engine, traust_contracts and traust_ledger, static and importlib.import_module, under src/, harnessing/ and scripts/. Its baseline holds only the pending engine hits: _registry.py 1 (load_engine), portfolio.py 1, sweep.py 5, each tagged with its decision.
  6. Housekeeping:
    • Gate texts: S10 and the S4 note now say traust-core's safe-exec; A12 says ctx.model_catalog.
    • Config comments: feeds.yaml osv consumers, external-tools.yaml toolchain consumer, *.example.yaml "Schema: contracts … (through traust-core)", sla-policy.example.yaml, config/README.md rows whose reader is known.
    • Docs and SKILL.md lines on where the rule pack lives (kind-1 fact changes; docs/skills.md regenerated and unchanged).
    • The compliance-mapping.yaml comments named retired scripts and failed test_check_reference_integrity on lane (d)'s branch; they now name the live homes.
    • The build-pinned-wheels.py docstring now says why PACKAGES keeps all four: the image installs with --no-deps, core imports contracts and ledger, and the engine stays.
    • Text that is correct is unchanged: packs/security/assets.yaml, ops/router.py (the engine runs the pack), the ledger cosign notes and A18 (load_engine still exists).

Behaviour changes

  1. Default rule packs come from packs/security/, with content identical to the engine copy. Detection quality's pack_version for the bundled pack is traust's version (0.38.0) instead of traust-engine's (0.39.2).
  2. adapters govulncheck, osv and osv --sbom: metadata.harness_version is traust's version instead of traust-engine's. _tools.harness_version was the engine's version, and that re-export is gone.
  3. Sweep stages: the default pack is load().rule_pack; locations.opengrep_rules still wins. A pack that isn't a directory exits 2 with the engine's "opengrep rule pack required" message. The engine's separate "no local path form" message for a remote URI is gone.
  4. The live spend view, attribute-spend and registry products no longer create the record store.
  5. install_traust --doctor step 4 reports signing from core.yaml's ledger.public_key_path, where contracts read ledger-signing-key.pub. Required-file gating is step 5 (core's completeness audit).

Changed tests

Test Old → new Why
tests/conftest.py contracts config helpers → core resolve_config_home, Locations.from_home no contracts import; same values
tests/compliance_paths.py engine compliance_data_dir / contracts config_path → SECURITY_PACK_DIR/compliance, traust.paths.config_path the mapping ships in the pack (lane d)
test_compliance_config, test_isolation_review, test_isolation_tagging, test_pqc_wiring, test_llm_app_review contracts schema_path/schema_dir → traust.paths (core) import only; assertions unchanged
test_event_time contracts TimestampError → core models.values import only
test_check_drift::test_argus_pack_is_not_the_default_rules_source reads the engine's opengrep source → reads core's opengrep provider and asserts load().rule_pack is the pack's traust-authored rules with no supplements the engine source is no longer what runs
test_fetch_feeds: …_happy, …_raises_on_missing_key → …_is_unavailable_on_missing_key, …_raises_on_wrong_type → …_is_unavailable_on_wrong_type engine loader raises ValueError → core's snapshot is unavailable, its detail naming ps_modules the engine loader isn't called; the intent ("a shape change must not read as no contacts") holds
test_check_content_licenses::TestValidatorCisTextWarning (3) engine strict_checks → load().reporting.validate_reports(strict=True) core has the same strict check; assertions unchanged
test_security_pack (7) engine Pack.load → core validate_config("pack") on the YAML traust keeps pack validation through core; tuple → list in two comparisons
test_engine_providers: …_resolve_to_the_bundled_file → …_to_the_packs_file, …_bundled_pack_at_the_engine_version → …_packs_rules_at_the_traust_version engine paths/version → pack paths / traust version behaviour change 1 (decided)
test_default_rule_packs::test_default_opengrep_run_reports_a_current_rule config_paths names traust_engine → names packs/security/opengrep-rules behaviour change 1
test_docs_consistency::TestSingleRulePack docstring only the gate names the pack
test_engine_imports rewritten: three packages, dynamic imports, scripts/; baseline only the pending hits step 3 of lane (f)
test_validate_report, test_validate_report_cloud_config, test_validate_triage, test_validate_vuln_findings engine-function tests deleted (table below); the schema tests stay, their helper on core contracts.schema_errors assertions of kept tests unchanged
test_adapters_core_parity, test_context_locations, test_metrics_spend_views, test_registry_doors comment # delete with the engine (final-drop follow-up) parity tests kept while the engine is a dependency
test_p2_hardening::test_p3_sweep_engine_dir_prefix, test_target_attestation, test_sweep_regression_drafts comment PENDING(decision: sweep stages — retire or port) sweep tests kept

Deleted tests

Signed off by Shaun, 2026-10-27: tests of code traust doesn't own.

File Tests Engine function it tested Covered now by
test_validate_report.py 59 (TestCrossValidation 9, TestStrictConventions 13, TestVerificationCrossChecks 14, TestDispositionCrossChecks 6, TestConsistencyGates 4, TestRenderer 5, TestRendererNumbering 1, TestDirectoryValidation 2, round trips 5) reporting.validate (cross_validate, strict_checks, cross_validate_verification, collect_report_files), reporting.render.render_report core tests/v1/services/reporting/test_checks_audit_report.py, test_checks_families.py, test_checks_review_surfaces.py, test_report_markdown.py, tests/v1/services/test_reporting.py; the reporting parity replay in core #213/#215 (all 862 engine-suite and 139 traust-suite reporting calls, identical)
test_validate_report_cloud_config.py 19 cloud-config cross-checks, detect_schema_path test_checks_families.py::test_cloud_config_current_*, ::test_a_cumulative_stamp_routes_to_cloud_config, ::test_a_sibling_cloud_config_audit_routes_an_unstamped_cumulative, ::test_code_and_container_cumulatives_keep_the_report_route
test_validate_triage.py 15 cross_validate_triage, detect_schema_path test_checks_families.py::test_triage_*, ::test_file_names_pick_the_schema
test_validate_vuln_findings.py 8 cross_validate_vuln_findings, autodetect test_checks_families.py::test_vuln_findings_errors, ::test_a_valid_vuln_findings_passes, ::test_file_names_pick_the_schema
test_check_fix_propagation.py 3 cross_validate_verification (cross_repo) test_checks_families.py::test_cross_repo_fixes_must_be_consumed_elsewhere
test_scan_k8s_hardening.py 30 adapters.checkov.Scanner core tests/v1/providers/tools/test_k8s_hardening.py (ported in core #212)
test_cloud_config_audit.py 1 corpus.resolver report-kind tagging corpus/ is retired; core keeps cloud-config audits their own artifact (CloudConfigAuditArtifact, ResultKind.CLOUD_CONFIG_AUDIT): tests/v1/models/test_cloud_config.py, tests/v1/providers/test_report_files.py
test_p1_hardening.py 2 adapters.opengrep.resolve_rules core tests/v1/providers/tools/test_opengrep.py::test_an_unpinned_or_non_https_rules_source_is_refused, ::test_a_git_source_is_pinned_to_a_commit, ::test_a_git_source_is_cloned_once_at_its_pin
test_security_router_engine.py, test_shadow_run.py 7 + 2 the engine loop over the security pack moved: traust-engine #112 maps each onto its loop tests over the pack fixture and adds the one missing case; the router's decisions stay in tests/test_security_router.py
  • A person reviewed each changed test and the behaviour change is intended

Validation

$ TRAUST_TEST_DATABASE_URL=…/traust_test_w2_f make lint-fix && make test
2654 passed, 2 skipped
$ uv run traust check docs-consistency
✓ docs are consistent with the tree
$ git show upstream/development:.ratchet.json > /tmp/ref.json
$ uvx --from "$RATCHET" python -m traust_core.v1.checks.ratchet src harnessing --rules consumer --baseline .ratchet.json --reference /tmp/ref.json
(clean; baseline only shrank, incl. reporting.py contracts 1→0)
$ git grep -nE '(from|import) traust_(engine|contracts|ledger)|import_module\("traust_(engine|contracts|ledger)' -- src harnessing tests scripts bin
src: _registry.py 1, portfolio.py 1, sweep.py 5 (pending decisions); tests: the tagged parity/sweep tests,
     A16/A18 rule fixtures (strings), the guard's own fixture

Pre-commit and pre-push hooks passed. The done-when ("suite and hooks pass without traust-engine installed; the grep is empty") is not claimed here because the engine stays (see Scope). I didn't watch CI.

Wave 3 must keep (traust-engine)

The engine modules the remaining hits need, once the facade is slimmed to the three ops:

  • engine.py (HarnessEngine: ctx, sweep, portfolio, metrics; sweep/rule_lane.py builds it too), _ops_base.py, locations.py, storage.py, assets.py (harness_version, default_rule_pack_dir) and data/secure-code-audit/ (the default pack that sweep/mining.py resolves when given none)
  • sweep/: ops, engine, benchmark, rule_lane, mining, calibration
  • adapters/opengrep.py (sweep stages, verify-draft), adapters/_contract_bridge.py, adapters/checkov.py (the portfolio graph's K8s scanner)
  • corpus/resolver.py (sweep/engine.py)
  • portfolio/: ops, graph, parsers
  • metrics/: ops, history, spend, collect_spend, attribute_spend; registry/models.py (what they price with)
  • ops/ (the continuous-ops service)

Also keep until the final drop: the parity tests tagged # delete with the engine read _util/safe_exec, _util/elf, the other adapters/*, registry/products, locations, metrics.

What's left (final-drop follow-up)

Quality checklist

  • Comments only for the non-trivial
  • Docstrings don't bloat
  • Don't reinvent (core doors; pack content copied, no engine code)
  • Shared logic is a helper, in one place (traust.paths pack paths)
  • Tests cover the edges (no-store doors incl. the recording path; guard counts dynamic imports)
  • Integration tests on SQLite and Postgres (traust_test_w2_f)
  • Minimal, clean code
  • Queries: none new
  • Tests change only on purpose (table above; deletions signed off)
  • Auto-merge: not set; this PR edits and deletes existing tests

Updated 2026-10-27 (after #279 merged)

  • development and lanes b–e merged in; pins: core → core#237's head (re-lands build(deps): pin traust-core to development 0f3fa0c (XWING-2440) #229, which had merged into a stale branch), engine → development (past engine#113).
  • Deleted tests (engine side gone in engine#113), same rule as above (tests of code traust doesn't own, signed off by Shaun 2026-10-27):
    • tests/test_adapters_core_parity.py (10 tests, 27 cases): engine _util / adapters vs core's tool doors. Parity was proven when lane (b) landed (27/27 equal); core#225's tests/v1/context/test_tool_reports.py owns the behaviour.
    • tests/test_registry_doors.py: the 4 products-parity tests (engine registry/products.py, deleted). Core's product-definition tests own it; the models parity tests stay (engine registry/models.py is kept).
  • test_validate_report.py keeps _canonical_report (development's other tests import it).
  • Merge order: core#237 and lanes b–e are merged; this is the last one.

Layout (2026-10-27, decided with Shaun and Michele)

  • Detection content moved: it's now under packs/security/detection/{opengrep-rules,gitleaks-rules}. That's traust's default stack, the baseline every adopter starts from. packs/security/compliance/ stays where it is, and assets.yaml stays the ops pack.
  • Loader: the defaults in traust.paths point at the new location.
  • Single-copy gate: the docs-consistency gate's home is now packs/security/detection/.
  • mine-ledger promotion text: it now says promoted rules go into the adopter's own pack, in the location its config home sets (Red Hat: traust-internal/config), never into traust's baseline. Adopter packs are tracked in progress-tracker plan Rule mining as an app feature (0-continuous-ops/20-shaun-rule-mining-adopter-packs.md).
  • Stale text fixed: compliance-check SKILL.md now says the mapping ships in packs/security/compliance/, not in traust-engine.

…-on-core' into refactor/drop-traust-engine-final

# Conflicts:
#	.ratchet.json
#	pyproject.toml
#	tests/test_engine_imports.py
#	uv.lock
…on-core' into refactor/drop-traust-engine-final

# Conflicts:
#	pyproject.toml
#	tests/test_engine_imports.py
#	uv.lock
…re' into refactor/drop-traust-engine-final

# Conflicts:
#	harnessing/3-audit/pqc-readiness/SKILL.md
#	tests/test_engine_imports.py
… import guard covers contracts and ledger (XWING-2440)
…pack's rules; sweep stages use the one rule pack (XWING-2440)
@smith-xyz
smith-xyz requested a review from a team as a code owner October 27, 2026 17:38
@openshift-ci

openshift-ci Bot commented Oct 27, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: smith-xyz

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Oct 27, 2026
…p-traust-engine-final

# Conflicts:
#	pyproject.toml
#	src/traust/cli/groups/metrics.py
#	src/traust/cli/session.py
#	tests/test_validate_report.py
#	uv.lock
…nto refactor/drop-traust-engine-final

# Conflicts:
#	pyproject.toml
#	uv.lock
…-on-core' into refactor/drop-traust-engine-final

# Conflicts:
#	pyproject.toml
#	src/traust/cli/groups/metrics.py
#	uv.lock
…on-core' into refactor/drop-traust-engine-final

# Conflicts:
#	packs/security/compliance/compliance-mapping.yaml
#	pyproject.toml
#	uv.lock
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 27, 2026
…ore#237 merged); pin core and engine development
…ine-ledger promotes into the adopter's own pack (XWING-2440)
@smith-xyz
smith-xyz merged commit 9085ced into traust-security:development Oct 27, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant