Skip to content

fix(continuous-ops): never-audited heads, windowed views in a refresh, no ToolInspector NEED without tools (XWING-2440) - #322

Merged
smith-xyz merged 2 commits into
developmentfrom
fix/continuous-ops-live-run-gaps
Oct 31, 2026
Merged

smith-xyz merged 2 commits into
developmentfrom
fix/continuous-ops-live-run-gaps

Conversation

@smith-xyz

Copy link
Copy Markdown
Contributor

Plan: plans/traust-standardization/0-continuous-ops/in-progress/18-shaun-live-runs.md (part)

Plan 18, step 1 ("anything that needed a manual step becomes a code fix"): what the local rig (make ops-smoke, engine 779471d, Postgres) turned up in traust-core, plus the one NEED SCI sees on traust-server. The traust half is traust-security/traust (pinned to this commit).

What

Found Before After
repo_state on a never-audited repository observe_forge_facts returned never-audited before any forge call; no head, no repo-state assessment, so manifest_sbom refused every never-audited repository (no observed default head) and below-range never ran for them. On a fresh estate (SCI) that is every repository a never-audited repository is observed (repo info + default-branch head, no comparison, no quota or patch call) and kept as a repo-state assessment; its status stays never-audited, so the router's rule-1 bootstrap is unchanged. Without network it is still not observed
dashboards asset InsightService.refresh(None, ViewFilter()) always failed program and spend ("needs a window"), so every dashboards order degraded on them a view marked windowed refreshed with no window gets TimeWindow.month_of(as_of or now), the month the budget is kept in; a given window is kept; REST/build without a window still refuses
GET /v1/insights/freshness on traust-server (no tools registered) tool-databases and toolchain rows "unavailable: … NEED(engine: ToolInspector)" no tools means an empty stamp and no database rows; a registered tool that can't report itself still names the missing inspector

Behaviour changes

  1. Never-audited repositories cost two forge calls per observation (info + head), against plan 09's decision 2 ("never-audited derived from the inventory, no forge call"). Plan 19 (manifest SBOM sweep) needs a head for every inventory repository ("every repository's default head has a dependency SBOM"), so the two decisions conflicted; this keeps plan 19's. ~3.5k repositories ≈ 7k calls/day against the 1,000/h forge:{host} bucket. The contracts definition of never-audited still says "Not observed"; its wording wants a contracts follow-up (Michele): "observed; no audit to compare against (bootstrap)".
  2. Spend and program dashboards render the current month in a batch refresh instead of failing.
  3. Liveness reason for a never-audited, not-yet-observed repository: "no audit and no forge observation yet; observe it".

Changed tests

Test Old → new Why
tests/v1/services/test_insight_freshness.py::test_renders_through_context asserted | unavailable | toolchain | → asserts it's absent and "No toolchain inspected." a Context with no tools has nothing to inspect; the row was the NEED(engine: ToolInspector) error
tests/v1/services/test_provider_catalog.py::test_stale_reports_unfetched_and_uninspectable_databases the empty catalog's stale() was [("tool-databases", unavailable)] with the NEED text → [] same
tests/v1/services/test_portfolio_liveness.py::test_an_unobserved_repository_says_why[unaudited] reason "audited repositories only" → "no audit and no forge observation yet" never-audited repositories are observed now
  • A person reviewed each changed test and the behaviour change is intended

New tests: never-audited observed with exactly info, head and its head kept; not observed without network; a forge refusal keeps nothing; windowed views get the month of as_of (or now) and keep a given window; an empty catalog stamps no tools.

Reviewer checks (from the plan)

  • Each explained difference names its cause (router rule, admission, bug PR).
  • No group cut over before the previous one finished its cycle.

Quality checklist

  • 1. Comments only for the non-trivial
  • 2. Docstrings don't bloat
  • 3. Don't reinvent (TimeWindow.month_of, the per_item view-attribute pattern)
  • 4. Shared logic is a helper, in one place (OBSERVED in observation.py, used by portfolio._keep)
  • 5. Tests cover the edges (no network, forge refusal, given window, no tools)
  • 6. Integration: the rig end to end on Postgres (below)
  • 7. Minimal, clean code
  • 8. Queries: none new or changed (default_ref and the repo-state publish are existing paths)
  • 9. Tests change only on purpose, and a person said so (three listed above)

Verification

make lint && make test: 8152 passed. The rig (traust branch pinned here, engine 779471d, Postgres 16, octocat/Hello-World, never audited): before, manifest_sbom refused not_found every pass and dashboards degraded on program/spend; after, repo_state keeps the head, manifest_sbom succeeds, below-range-scan succeeds, dashboards degrades only on pqc-vendors (no claims recorded, expected).

Legacy files

File Verdict Where it went / why it's gone
none — no legacy file touched

…ndowed views, no ToolInspector NEED without tools (XWING-2440)
@qodo-for-traust-security

Copy link
Copy Markdown

PR Summary by Qodo

Observe never-audited heads and fix dashboard and tool freshness gaps

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes


AI Description

• Observe never-audited repository heads so their default refs can support manifest SBOM sweeps.
• Refresh spend and program dashboards for the current month when no window is supplied.
• Report empty tool freshness results, rather than requiring an inspector, when no tools are
 registered.
Diagram

graph TD
  Callers["Service callers"] --> Observe["Repository observation"] --> Forge["Forge API"] --> Store[("Refs and assessments")]
  Callers --> Refresh["Insight refresh"] --> Views["Spend and program"]
  Callers --> Catalog["Provider catalog"] --> Freshness["Freshness output"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Fetch heads only during the SBOM sweep
  • ➕ Avoids additional forge calls during routine observation.
  • ➖ Leaves default heads unavailable to other consumers until the sweep runs.
  • ➖ Moves forge retrieval and failure handling into the sweep.

Recommendation: Keep head retrieval in repository observation so default refs are available to the SBOM sweep and other consumers without changing never-audited routing status. Account for the extra forge calls in scheduling and rate limits.

Files changed (10) +77 / -16

Bug fix (5) +19 / -11
insight.pyDefault windowed refreshes to the current month +8/-3

Default windowed refreshes to the current month

• Refresh supplies the month of as_of, or the service clock, to windowed views lacking a window. Explicit windows and non-windowed views retain their original filters; ProgramView is marked windowed.

src/traust_core/v1/services/insight.py

insight_spend.pyMark spend dashboards as windowed +1/-0

Mark spend dashboards as windowed

• Marks SpendView as windowed so batch refresh can provide its missing month filter.

src/traust_core/v1/services/insight_spend.py

observation.pyFetch heads for never-audited repositories +5/-2

Fetch heads for never-audited repositories

• Permits network observation of never-audited repositories to retrieve repository information and the default head. It retains never-audited status and returns before comparison or quota calls; network-disabled observations still make no forge calls.

src/traust_core/v1/services/observation.py

portfolio.pyPersist never-audited observations and clarify liveness +3/-2

Persist never-audited observations and clarify liveness

• Allows observed never-audited facts to retain their default ref and repo-state assessment. Revises the unobserved liveness reason to request forge observation.

src/traust_core/v1/services/portfolio.py

provider_catalog.pyDo not require an inspector for an empty tool registry +2/-4

Do not require an inspector for an empty tool registry

• Returns empty inspection results when no tools are registered. Registered tools that cannot inspect themselves still trigger a missing-inspector configuration error.

src/traust_core/v1/services/provider_catalog.py

Tests (5) +58 / -5
test_insight.pyCover default and explicit refresh windows +22/-0

Cover default and explicit refresh windows

• Tests month selection from as_of and the clock, preservation of an explicit window, and unchanged filters for non-windowed views.

tests/v1/services/test_insight.py

test_insight_freshness.pyExpect no unavailable toolchain without tools +2/-1

Expect no unavailable toolchain without tools

• Updates the rendered freshness assertion to expect an empty-toolchain message instead of an unavailable toolchain row.

tests/v1/services/test_insight_freshness.py

test_portfolio_liveness.pyExpect the revised never-audited liveness reason +1/-1

Expect the revised never-audited liveness reason

• Updates the assertion for a never-audited repository that has not yet been observed at the forge.

tests/v1/services/test_portfolio_liveness.py

test_portfolio_observation.pyCover never-audited head persistence and failure paths +27/-0

Cover never-audited head persistence and failure paths

• Verifies that successful observation retains a head without comparison, network-disabled observation makes no source calls, and forge refusal retains no default ref.

tests/v1/services/test_portfolio_observation.py

test_provider_catalog.pyCover empty tool inspection and freshness results +6/-3

Cover empty tool inspection and freshness results

• Asserts that an empty registry yields an empty tool stamp and database lists, and no stale tool-database entry.

tests/v1/services/test_provider_catalog.py

@qodo-for-traust-security

qodo-for-traust-security Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Code Review by Qodo


Resolved findings
1. Repository observations can leave split state ✓ Resolved
Description
_keep commits repository metadata through one self._uow context, then commits the default
repository reference through a second context. When the newly included NEVER_AUDITED path reaches
this code and the second write fails, the metadata remains committed while the head and repo-state
assessment are absent.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `NEVER_AUDITED` observation path now enters `_keep`, but repository metadata and the default repository reference are committed through separate unit-of-work contexts. A failure in the second write can leave the inventory partially updated.

## Fix Focus Areas
- src/traust_core/v1/services/portfolio.py[346-363]

## Recommended Fix
Use one unit-of-work instance and one commit for the repository metadata and default repository reference writes in `_keep`. Keep any post-commit logging and document processing outside that transaction.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unaudited repos appear freshly observed ✓ Resolved
Description
RepoStateQuery._observed() returns synthetic NEVER_AUDITED facts before consulting the
observation that _keep() now persists, because it reads storage only for NETWORK_SKIPPED. After
a head-only observation, repo_state() and list() report the query time as observed_at and omit
the stored push date, assigning a dormant repository the active P2 tier instead of P3.
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Head-only observations for never-audited repositories are persisted, but repository-state reads return synthetic facts instead of the stored facts.

## Fix Focus Areas
- src/traust_core/v1/services/portfolio.py[1240-1247]
- src/traust_core/v1/services/portfolio.py[346-349]

## Recommended Fix
Allow `_observed()` to load persisted facts for `NEVER_AUDITED` as well as `NETWORK_SKIPPED`. Preserve the synthetic `NEVER_AUDITED` result when no observation exists, so never-observed repositories retain their bootstrap behavior. Test both states, including the stored push date's effect on risk tier and the returned observation time.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



@smith-xyz

Copy link
Copy Markdown
Contributor Author

Qodo review resolved at ca2a4ba: (1) repository metadata and default ref commit atomically for successful observations; a forced ref-write failure now rolls both back, and (2) never-audited reads use stored facts when present, preserving the real push date, P3 dormancy tier and observation time while synthetic bootstrap behavior remains for no record/old audited facts. Both regressions failed before the fix and pass after it. Local gates: make lint-fix && make test (8,154 passed, 1 skip), make db-up && make test-repositories (988 passed, 2 skips), pre-push coverage 96.71%. Qodo marked implemented; human changed-test/behavior review remains unticked and CI must rerun before merge.

@smith-xyz
smith-xyz requested a review from chubirka October 31, 2026 14:01
@smith-xyz
smith-xyz merged commit 7bccb82 into development Oct 31, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant