Skip to content

feat(sccm): add bounded client discovery normalization - #444

Merged
adamgell merged 18 commits into
codex/parser-family-skeletonfrom
codex/sccm319-discovery-restack-r43
Aug 2, 2026
Merged

feat(sccm): add bounded client discovery normalization#444
adamgell merged 18 commits into
codex/parser-family-skeletonfrom
codex/sccm319-discovery-restack-r43

Conversation

@adamgell

@adamgell adamgell commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Scope

Implements the bounded native-side SCCM client discovery normalizer for the accepted additive client-intake manifest contract.

  • normalizes already-observed candidate metadata into deterministic SCCM manifest declarations;
  • preserves opaque root provenance, rotation identity, and cross-root basename collisions;
  • canonicalizes case-equivalent current, .lo_, and numbered rotation identities;
  • coalesces exact duplicates and fails closed on conflicting observations;
  • enforces the public 4,097-observation admission boundary before normalization or construction, with at most 4,096 emitted artifacts;
  • keeps selection fair across noisy sources and deterministic under input reordering;
  • computes logical artifact IDs once per normalized observation rather than inside sort comparisons.

This slice does not enumerate Windows paths, read or write artifacts, capture evidence, mutate generic collection-manifest/ArtifactStatus semantics, add ParserKind::Sccm, perform workflow diagnosis/correlation, or claim live Windows/SCCM validation.

Dependency state

  • Base: reviewed integration 431909709ae3e66bb4c236647af92bd5312bcc90 (native manifest reader merged first).
  • Exact head: de0957d48905d453aa0f0accb03d901a0363d5af.
  • Private capture/publication remains the next client-intake dependency after this discovery contract is accepted.
  • Native Windows lab acceptance remains future work and is not claimed.

Test matrix

  • complete canonical discovery and stable rotation ordering;
  • case-equivalent identity parity for current, .lo_, and numbered rotations;
  • 4,096 accepted output / 4,097 retained-boundary behavior / greater-than-4,097 pre-normalization rejection;
  • deterministic first-omitted coverage and noisy-source fairness;
  • exact-duplicate coalescing and conflict fail-close in both input orders, including conflicts beyond the retained frontier;
  • same-basename/different-root collision preservation;
  • malformed and unsupported basename/privacy-unsafe root skips;
  • zero per-source cap behavior;
  • construction and logical-ID work counters proving defensive and allocation bounds.

Verification

  • cargo test --locked -p app --test sccm_client_discovery — 12 passed;
  • focused discovery unit probes — 5 passed;
  • cargo test --locked -p app --test sccm_client_native_manifest — 21 passed;
  • cargo test --locked -p cmtraceopen-parser — passed;
  • strict Clippy for app and parser — passed;
  • Rust 1.88 all-features workspace check — passed;
  • Rust 1.88 wasm32-unknown-unknown parser check — passed;
  • scoped Rustfmt, git diff --check, exact base/head, and clean-worktree checks — passed;
  • independent adversarial exact-range review — GO, no P0–P3 finding;
  • authenticated CodeRabbit CLI exact committed-range review — 4 files, 0 findings.

Review and merge gate

This is intentionally a draft. The prior hosted review found two valid issues; focused RED 2804a5d4 and GREEN de0957d4 correct them, and both threads have evidence-backed replies. Fresh exact-head CodeRabbit, GitHub Copilot, all CI (including Windows), unresolved-thread review, and a final exact base/head merge guard are required before it can be considered for merge.

Tracks #319. Program board: #317.

Summary by CodeRabbit

  • New Features

    • Added read-only SCCM client-source discovery.
    • Reports discovered, access-denied, not-found, and capped source states.
    • Provides evidence and stable artifact identifiers for discovered sources.
    • Handles duplicate, aliased, conflicting, and malformed observations safely.
    • Applies global and per-source limits with deterministic ordering for consistent results.
  • Tests

    • Added coverage for discovery limits, deduplication, ordering, state handling, identity collisions, caching, and malformed inputs.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a bounded SCCM client-source discovery API. It normalizes and deduplicates observations, rejects conflicts, applies deterministic per-source and global caps, and emits physical or marker declarations with evidence and fingerprints. Tests cover limits, ordering, identity safety, and malformed inputs.

Changes

SCCM client discovery

Layer / File(s) Summary
Discovery contract and module wiring
src-tauri/src/sccm/discovery.rs, src-tauri/src/sccm/mod.rs, src-tauri/Cargo.toml
Adds public discovery types, states, errors, limits, the discovery function, module re-exports, and a feature-gated integration test target.
Observation normalization and bounded selection
src-tauri/src/sccm/discovery.rs
Validates limits and roots, canonicalizes and deduplicates observations, detects conflicting states, orders candidates, and applies per-source and global caps.
Declaration and artifact identity generation
src-tauri/src/sccm/discovery.rs
Builds declarations with physical or marker artifact IDs, evidence identifiers, path fingerprints, and observation metadata.
Behavior and defensive-limit validation
src-tauri/src/sccm/discovery.rs, src-tauri/tests/sccm_client_discovery.rs
Tests caps, deterministic output, duplicate and alias coalescing, collision-safe identities, conflict rejection, observation limits, and malformed input handling.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant discover_client_sources
  participant ObservationNormalization
  participant DeclarationConstruction
  Caller->>discover_client_sources: Submit SCCM observations
  discover_client_sources->>ObservationNormalization: Validate, canonicalize, and deduplicate
  ObservationNormalization-->>discover_client_sources: Ordered candidates
  discover_client_sources->>DeclarationConstruction: Apply caps and build declarations
  DeclarationConstruction-->>discover_client_sources: Bounded declarations and result
  discover_client_sources-->>Caller: Return discovery result or error
Loading

Possibly related PRs

Suggested labels: test

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the bounded SCCM client discovery normalization added by the pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added enhancement New feature or request feature New feature parser Log parser related sccm SCCM/ConfigMgr related labels Aug 2, 2026
@adamgell adamgell self-assigned this Aug 2, 2026
@adamgell

adamgell commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@adamgell

adamgell commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Exact-head review request for c778b3cd66d3969eb5f8f87c407f8964f7d520e4 against target 431909709ae3e66bb4c236647af92bd5312bcc90.

@coderabbitai review
@copilot-pull-request-reviewer review

Please review the complete committed range and generated merge ref. Focus on pre-normalization CPU/allocation bounds, exact 4,096/4,097 behavior, deterministic conflict handling, duplicate identity safety, source fairness, opaque-root privacy, malformed input fail-close behavior, wasm32 parser purity, and the absence of capture/I/O or generic manifest-status changes. Report actionable findings against this head only; do not push code changes.

This is discovery normalization over already-observed metadata. It does not enumerate paths, capture or publish evidence, or claim native/live Windows SCCM acceptance. The PR remains draft until exact-head hosted CI, both review systems, unresolved-thread checks, and a final merge guard pass.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='c778b3cd66d3969eb5f8f87c407f8964f7d520e4'

printf '%s\n' '== Exact revisions =='
git rev-parse "$base" "$head"
printf '%s\n' '== Ancestry and merge base =='
git merge-base "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base-is-ancestor=yes'
printf '%s\n' '== Changed paths =='
git diff --name-status "$base...$head"
printf '%s\n' '== Diff stat =='
git diff --stat "$base...$head"
printf '%s\n' '== Candidate Rust files =='
git diff --name-only --diff-filter=ACMR "$base...$head" | grep -E '\.rs$' || true
printf '%s\n' '== AST outlines for changed Rust files =='
git diff --name-only --diff-filter=ACMR "$base...$head" | grep -E '\.rs$' | while IFS= read -r file; do
  echo "--- $file"
  ast-grep outline "$file" --items all --view expanded || true
done
printf '%s\n' '== Full committed diff =='
git diff --find-renames --find-copies --no-ext-diff "$base...$head"

Length of output: 50016


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='c778b3cd66d3969eb5f8f87c407f8964f7d520e4'

printf '%s\n' '== Locate contract and parser rotation definitions =='
fd -t f 'contract\.rs|sccm.*\.rs' src-tauri/src src-tauri/tests . | sort

printf '%s\n' '== SCCM contract outline =='
ast-grep outline src-tauri/src/sccm/contract.rs --items all --view expanded

printf '%s\n' '== Relevant SCCM contract implementations =='
rg -n -A45 -B5 \
  'fn (root_handle_digest|source_identity_digest|canonical_client_source|rotation_segment|rotation_order|expected_physical_artifact_id|expected_marker_artifact_id|logical_artifact_ids_for_basename|catalog_entry_id)\b|enum SccmRotation\b' \
  src-tauri/src/sccm/contract.rs src-tauri 2>/dev/null || true

printf '%s\n' '== Parser SCCM rotation declarations and uses =='
rg -n -A30 -B8 'enum SccmRotation\b|SccmRotation::(Unknown|Timestamped|Numbered|LoUnderscore|Current)' \
  --glob '*.rs' . | head -n 900

printf '%s\n' '== Changed-range prohibited-scope indicators =='
git diff --unified=3 "$base...$head" -- \
  'src-tauri/**/*.rs' 'src-tauri/Cargo.toml' \
  | rg -n -i -C2 \
    '\b(std::fs|tokio::fs|File::|OpenOptions|read_dir|write_all|remove_file|create_dir|Command::|reqwest|ureq|tauri::|ArtifactStatus|ParserKind|capture|publish|evidence file|windows|winapi)\b' \
  || true

printf '%s\n' '== Direct imports and calls in discovery implementation =='
rg -n -C2 \
  '^(use |pub use )|\b(root_handle_digest|canonical_client_source|rotation_segment|source_identity_digest|candidate_from_observation|declaration_from_candidate|normalize_observations|selection_state)\s*\(' \
  src-tauri/src/sccm/discovery.rs

Length of output: 121756


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Find parser source files that define SCCM rotations and classification =='
rg -n -l --glob '*.rs' \
  'enum SccmRotation\b|fn classify_artifact_name\b|struct .*Artifact.*Name|supported_for_diagnosis' \
  crates/cmtraceopen-parser src-tauri/src | sort

printf '%s\n' '== AST map of parser SCCM source files =='
fd -t f -e rs . crates/cmtraceopen-parser/src | while IFS= read -r file; do
  if rg -q 'enum SccmRotation\b|fn classify_artifact_name\b' "$file"; then
    echo "--- $file"
    ast-grep outline "$file" --items all --view expanded
  fi
done

printf '%s\n' '== Exact definitions and classifier call path =='
rg -n -A90 -B10 --glob '*.rs' \
  'enum SccmRotation\b|fn classify_artifact_name\b|fn .*rotation|supported_for_diagnosis' \
  crates/cmtraceopen-parser/src src-tauri/src/sccm/contract.rs

printf '%s\n' '== Exact-range final integrity checks =='
base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='c778b3cd66d3969eb5f8f87c407f8964f7d520e4'
git diff --check "$base...$head"
printf 'changed-files='
git diff --name-only "$base...$head" | wc -l
printf 'merge-base='
git merge-base "$base" "$head"

Length of output: 211980


@adamgell Reviewed 431909709ae3e66bb4c236647af92bd5312bcc90...c778b3cd66d3969eb5f8f87c407f8964f7d520e4.

I found no actionable findings in the committed range.

The range contains four changed files. The defensive 4,097-observation rejection occurs before normalization and construction. The output remains bounded to 4,096 declarations. Conflict detection occurs before selection. Duplicate coalescing, deterministic ordering, per-source capping, opaque root validation, and cross-root identity derivation are consistent with the stated contract.

The changed range contains no detected capture, I/O, generic ArtifactStatus, ParserKind, or Windows-specific implementation changes. git diff --check passed.

The sandbox did not provide a generated merge-ref revision. I reviewed the exact requested base-to-head range. I did not execute compilation or tests in this environment.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (6)
src-tauri/src/sccm/discovery.rs (4)

543-609: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for a zero per-source cap.

No test supplies max_found_fragments_per_source: 0. With that value, selection_state never takes the increment branch, so the first Found observation for each source becomes Capped and every later fragment is dropped. That behavior is reasonable, but it is unverified and it is the boundary a caller is most likely to reach by accident.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/sccm/discovery.rs` around lines 543 - 609, Add a test covering
discover_client_sources with max_found_fragments_per_source set to 0. Verify
that the first Found observation for each source is reported as Capped and
subsequent fragments are omitted, while preserving the existing declaration and
construction limits.

339-346: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the shared hex helper.

contract::sha256_bytes already performs this digest-and-hex-encode step (src-tauri/src/sccm/contract.rs:394-399) and is pub(crate). Call it here to keep one hex encoding in the SCCM module.

♻️ Proposed deduplication
-    let digest = Sha256::digest(value.as_bytes());
-    format!(
-        "sccm-evidence:v1:sha256:{}",
-        digest
-            .iter()
-            .map(|byte| format!("{byte:02x}"))
-            .collect::<String>()
-    )
+    format!("sccm-evidence:v1:sha256:{}", sha256_bytes(value.as_bytes()))

Then drop the now-unused sha2 import and add sha256_bytes to the super::contract import list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/sccm/discovery.rs` around lines 339 - 346, Update the evidence
formatting logic to call the shared `contract::sha256_bytes` helper for
digest-and-hex encoding instead of using `Sha256` directly. Add `sha256_bytes`
to the `super::contract` imports and remove the now-unused `sha2` import,
preserving the existing `sccm-evidence:v1:sha256:` output format.

349-365: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Precompute the logical artifact IDs instead of recomputing them per comparison.

compare_observation_order calls logical_artifact_ids_for_basename twice on every invocation. That helper scans declared_client_source_groups(), allocates a Vec<String>, and sorts it (src-tauri/src/sccm/contract.rs:419-432). The comparator runs from two places: the tie-break at Line 192 and the sort_by at Line 199. With the 4,097-observation admission bound, the sort alone performs about 49,000 comparisons, so this allocates roughly 100,000 vectors of owned strings per call.

NormalizedObservation already caches canonical_basename. Cache the derived IDs next to it in normalize_observation, then compare the cached field. candidate_from_observation can also reuse the cached value instead of recomputing it at Line 254.

♻️ Proposed caching of the ordering key
 struct NormalizedObservation<'a> {
     observation: &'a SccmClientDiscoveryObservation,
     canonical_basename: String,
+    logical_artifact_ids: Vec<String>,
 }
     root_handle_digest(&observation.root_handle)?;
     let canonical_basename = canonical_client_source(&observation.basename, &observation.rotation)?;
     Some(NormalizedObservation {
         observation,
+        logical_artifact_ids: logical_artifact_ids_for_basename(&canonical_basename),
         canonical_basename,
     })
 fn compare_observation_order(
     left: &NormalizedObservation<'_>,
     right: &NormalizedObservation<'_>,
 ) -> Ordering {
-    logical_artifact_ids_for_basename(&left.canonical_basename)
-        .cmp(&logical_artifact_ids_for_basename(
-            &right.canonical_basename,
-        ))
+    left.logical_artifact_ids
+        .cmp(&right.logical_artifact_ids)
         .then_with(|| {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/sccm/discovery.rs` around lines 349 - 365, Cache the result of
logical_artifact_ids_for_basename while constructing each NormalizedObservation
in normalize_observation, storing it alongside canonical_basename. Update
compare_observation_order to compare the cached IDs directly, and update
candidate_from_observation to reuse the cached value instead of calling the
helper again.

132-132: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Reserve capacity from the input size, not the global cap.

Vec::with_capacity(MAX_SCCM_CLIENT_DISCOVERY_DECLARATIONS) allocates 4,096 declaration slots on every call. SccmClientDiscoveryDeclaration holds seven owned fields, so this reserves roughly a megabyte even when the caller supplies one observation. The output can never exceed the observation count, so bound the reservation by both values.

♻️ Proposed capacity bound
-    let mut declarations = Vec::with_capacity(MAX_SCCM_CLIENT_DISCOVERY_DECLARATIONS);
+    let mut declarations = Vec::with_capacity(
+        input
+            .observations
+            .len()
+            .min(MAX_SCCM_CLIENT_DISCOVERY_DECLARATIONS),
+    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/sccm/discovery.rs` at line 132, Update the declarations
initialization in the SCCM discovery flow to reserve capacity based on the input
observation count, capped at MAX_SCCM_CLIENT_DISCOVERY_DECLARATIONS. Keep the
existing global limit for output enforcement while ensuring small inputs do not
preallocate the full cap.
src-tauri/tests/sccm_client_discovery.rs (2)

482-490: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the error variant, not only that an error occurs.

This test checks that both orders return an error, but it never checks which error. SccmClientDiscoveryError::ObservationLimitExceeded would satisfy the assertion equally. The sibling tests at Lines 452 and 547 pin the variant. Pin it here as well so the test cannot pass for the wrong reason.

💚 Proposed assertion
     let error = discover_client_sources(&input)
         .expect_err("canonical aliases with conflicting state fail closed");
+    assert_eq!(error, SccmClientDiscoveryError::ConflictingObservation);
     let mut reversed = input;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/tests/sccm_client_discovery.rs` around lines 482 - 490, Update the
test around discover_client_sources to assert that both the original and
reversed observation orders return
SccmClientDiscoveryError::ConflictingCanonicalAlias, rather than only asserting
that an error occurs. Preserve the existing order-independence check while
pinning the expected error variant.

555-579: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Also cover the unsupported-basename skip path.

This test covers the malformed-root skip at Line 208 of src-tauri/src/sccm/discovery.rs. normalize_observation has a second silent skip at Line 209, when canonical_client_source rejects a basename that is not a supported client source. No test covers that path. Add an observation with a valid root and an unsupported basename, and assert that discovery skips it and still returns the valid declaration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/tests/sccm_client_discovery.rs` around lines 555 - 579, Extend
discovery_skips_supported_observations_with_malformed_root_handles to include an
observation with a valid root handle and an unsupported basename. Keep the
existing valid observation, then assert discovery succeeds with only the valid
declaration, confirming normalize_observation skips unsupported basenames
without affecting supported sources.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src-tauri/src/sccm/discovery.rs`:
- Around line 543-609: Add a test covering discover_client_sources with
max_found_fragments_per_source set to 0. Verify that the first Found observation
for each source is reported as Capped and subsequent fragments are omitted,
while preserving the existing declaration and construction limits.
- Around line 339-346: Update the evidence formatting logic to call the shared
`contract::sha256_bytes` helper for digest-and-hex encoding instead of using
`Sha256` directly. Add `sha256_bytes` to the `super::contract` imports and
remove the now-unused `sha2` import, preserving the existing
`sccm-evidence:v1:sha256:` output format.
- Around line 349-365: Cache the result of logical_artifact_ids_for_basename
while constructing each NormalizedObservation in normalize_observation, storing
it alongside canonical_basename. Update compare_observation_order to compare the
cached IDs directly, and update candidate_from_observation to reuse the cached
value instead of calling the helper again.
- Line 132: Update the declarations initialization in the SCCM discovery flow to
reserve capacity based on the input observation count, capped at
MAX_SCCM_CLIENT_DISCOVERY_DECLARATIONS. Keep the existing global limit for
output enforcement while ensuring small inputs do not preallocate the full cap.

In `@src-tauri/tests/sccm_client_discovery.rs`:
- Around line 482-490: Update the test around discover_client_sources to assert
that both the original and reversed observation orders return
SccmClientDiscoveryError::ConflictingCanonicalAlias, rather than only asserting
that an error occurs. Preserve the existing order-independence check while
pinning the expected error variant.
- Around line 555-579: Extend
discovery_skips_supported_observations_with_malformed_root_handles to include an
observation with a valid root handle and an unsupported basename. Keep the
existing valid observation, then assert discovery succeeds with only the valid
declaration, confirming normalize_observation skips unsupported basenames
without affecting supported sources.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ec24dd18-5d8f-44a2-b58a-4fc5319d0870

📥 Commits

Reviewing files that changed from the base of the PR and between 4319097 and c778b3c.

📒 Files selected for processing (4)
  • src-tauri/Cargo.toml
  • src-tauri/src/sccm/discovery.rs
  • src-tauri/src/sccm/mod.rs
  • src-tauri/tests/sccm_client_discovery.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a native-side SCCM client discovery normalizer that turns bounded, already-observed client source candidates into deterministic manifest-style declarations, including duplicate coalescing, conflict fail-close behavior, and explicit “capped” gap signaling.

Changes:

  • Introduces src-tauri/src/sccm/discovery.rs with bounded normalization + deterministic ordering + per-source/global caps.
  • Exposes the discovery API via src-tauri/src/sccm/mod.rs.
  • Adds a feature-gated integration test suite (sccm_client_discovery) and wires it into src-tauri/Cargo.toml.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src-tauri/tests/sccm_client_discovery.rs New integration tests covering cap boundaries, dedup/conflict behavior, ordering determinism, and ID stability expectations.
src-tauri/src/sccm/mod.rs Registers and re-exports the new discovery module in the SCCM surface area.
src-tauri/src/sccm/discovery.rs Implements the bounded discovery normalization pipeline and related types/constants.
src-tauri/Cargo.toml Adds the new feature-gated test target for SCCM discovery.

Comment thread src-tauri/src/sccm/discovery.rs
Comment thread src-tauri/src/sccm/discovery.rs Outdated
@adamgell

adamgell commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Exact-head re-review request for de0957d48905d453aa0f0accb03d901a0363d5af against target 431909709ae3e66bb4c236647af92bd5312bcc90.

@coderabbitai review

Please review the complete committed range and generated merge ref, including the fixes for canonical physical/evidence identities and bounded logical-ID work. Focus on exact 4,096/4,097 behavior, deterministic conflict handling, case-equivalent current/.lo_/numbered aliases, source fairness, opaque-root privacy, malformed input fail-close behavior, wasm32 parser purity, and the absence of capture/I/O or generic manifest-status changes. Report findings against this exact head only; do not push code changes.

Focused RED: 2804a5d4. GREEN: de0957d4. Local owner gates, independent adversarial review, and a full committed-range CodeRabbit CLI scan have passed. The pull request remains draft until hosted review systems, all exact-head CI including Windows, unresolved-thread checks, and a final merge guard pass.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='de0957d48905d453aa0f0accb03d901a0363d5af'

echo '== exact revisions and ancestry =='
git rev-parse "$base" "$head"
git merge-base "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base-is-ancestor=yes'

echo '== merge-ref availability =='
git show-ref --head | rg -n -i 'merge|pull|444' || true

echo '== changed paths and integrity =='
git diff --name-status "$base...$head"
git diff --stat "$base...$head"
git diff --check "$base...$head"

echo '== changed Rust outlines =='
git diff --name-only --diff-filter=ACMR "$base...$head" -- '*.rs' | while IFS= read -r file; do
  echo "--- $file"
  ast-grep outline "$file" --items all --view expanded || true
done

echo '== discovery definitions and normalization flow =='
ast-grep outline src-tauri/src/sccm/discovery.rs --items all --view expanded
rg -n -A70 -B12 --glob '*.rs' \
  'pub fn discover_client_sources\b|fn normalize_observations\b|fn candidate_from_observation\b|fn declaration_from_candidate\b|fn selection_state\b|MAX_SCCM_CLIENT_DISCOVERY_(DECLARATIONS|OBSERVATIONS)\b|logical_artifact_ids|root_handle_digest|source_identity_digest|canonical_client_source|rotation_(segment|order)' \
  src-tauri/src/sccm/discovery.rs src-tauri/src/sccm/contract.rs crates 2>/dev/null || true

echo '== focused tests =='
ast-grep outline src-tauri/tests/sccm_client_discovery.rs --items all --view expanded
rg -n -A35 -B8 --glob '*.rs' \
  '409[67]|case|alias|[Ll][Oo]_|Current|Numbered|conflict|fair|opaque|malformed|logical.*id|physical.*id|evidence.*id|determin' \
  src-tauri/tests/sccm_client_discovery.rs src-tauri/src/sccm/discovery.rs

echo '== prohibited scope indicators in exact changed range =='
git diff --unified=4 "$base...$head" -- 'src-tauri/**/*.rs' 'src-tauri/Cargo.toml' |
  rg -n -i -C3 \
  '\b(std::fs|tokio::fs|File::|OpenOptions|read_dir|write_all|remove_file|create_dir|Command::|reqwest|ureq|tauri::|ArtifactStatus|ParserKind|capture|publish|windows|winapi)\b' || true

echo '== exact committed diff =='
git diff --find-renames --find-copies --no-ext-diff "$base...$head" -- \
  src-tauri/Cargo.toml \
  src-tauri/src/sccm/discovery.rs \
  src-tauri/src/sccm/mod.rs \
  src-tauri/tests/sccm_client_discovery.rs

Length of output: 134713


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='de0957d48905d453aa0f0accb03d901a0363d5af'

echo '== exact revision metadata =='
git rev-parse "$base" "$head"
echo -n 'merge-base='
git merge-base "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base-is-ancestor=yes'
echo '== possible generated merge refs =='
git show-ref --head | rg -n -i 'refs/(pull|merge)|pull/444|merge' || true

echo '== contract validation functions and comments =='
ast-grep outline src-tauri/src/sccm/contract.rs --items all --view expanded
rg -n -A80 -B15 --glob '*.rs' \
  'fn root_handle_digest\b|fn canonical_client_source\b|fn logical_artifact_ids_for_basename\b|fn source_identity_digest\b|invalid root|malformed root|unsupported basename|fail.?close|skip' \
  src-tauri crates tests 2>/dev/null || true

echo '== malformed-input contract references in repository text =='
rg -n -i -C4 \
  'sccm.{0,80}(malformed|invalid|unsupported|fail.?close|root handle)|\
   (malformed|invalid|unsupported|fail.?close).{0,80}sccm' \
  --glob '!target/**' --glob '!node_modules/**' .

echo '== complete discovery range around validation and errors =='
git show "$head:src-tauri/src/sccm/discovery.rs" | nl -ba | sed -n '80,230p'
echo '== complete integration test around malformed input =='
git show "$head:src-tauri/tests/sccm_client_discovery.rs" | nl -ba | sed -n '630,710p'

Length of output: 202105


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base='431909709ae3e66bb4c236647af92bd5312bcc90'
head='de0957d48905d453aa0f0accb03d901a0363d5af'

echo '== revisions =='
printf 'base='; git rev-parse "$base"
printf 'head='; git rev-parse "$head"
printf 'merge-base='; git merge-base "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base-is-ancestor=yes'

echo '== merge refs =='
git for-each-ref --format='%(refname) %(objectname)' |
  rg -i 'pull/444|merge' || echo 'none-found'

echo '== changed files =='
git diff --name-only "$base...$head"
echo '== diff check =='
git diff --check "$base...$head" && echo 'passed'

echo '== prohibited APIs in changed implementation =='
git diff --unified=0 "$base...$head" -- src-tauri/src/sccm/discovery.rs src-tauri/src/sccm/mod.rs |
  rg -n -i \
  '\b(std::fs|tokio::fs|File::|OpenOptions|read_dir|write_all|remove_file|create_dir|Command::|reqwest|ureq|tauri::|ArtifactStatus|ParserKind|winapi|windows)\b' \
  || echo 'none-found'

echo '== malformed observation handling =='
git show "$head:src-tauri/src/sccm/discovery.rs" |
  nl -ba | sed -n '122,160p'
git show "$head:src-tauri/tests/sccm_client_discovery.rs" |
  nl -ba | sed -n '662,691p'

Length of output: 2005


@adamgell Reviewed 431909709ae3e66bb4c236647af92bd5312bcc90...de0957d48905d453aa0f0accb03d901a0363d5af.

I found one actionable finding.

  • P1 — Fail closed for malformed observations. normalize_observations silently discards an observation when normalize_observation returns None. This includes an invalid opaque root handle and an unsupported or malformed basename. The current test at src-tauri/tests/sccm_client_discovery.rs, Line 662 explicitly requires this behavior. A valid observation in the same input then produces Ok(...), with no declaration, coverage marker, or error for the invalid observation. This prevents the caller from distinguishing complete discovery from incomplete discovery. Return a privacy-safe validation error for malformed observations, and change the test to require rejection.

The exact base is an ancestor of the requested head. git diff --check passed. The changed range contains no detected capture, filesystem, network, ArtifactStatus, ParserKind, or Windows-specific implementation changes.

No generated merge ref was available in the sandbox. I reviewed the requested committed range only. I did not run compilation or tests in this environment.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src-tauri/src/sccm/discovery.rs (1)

209-216: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject malformed observations instead of silently omitting them.

Line 211 returns None for an invalid root handle or unsupported basename. The caller then receives Ok with incomplete discovery results and cannot detect the invalid input. Return a privacy-safe validation error and abort the batch.

  • src-tauri/src/sccm/discovery.rs#L209-L216: Return a sanitized malformed-observation error instead of None.
  • src-tauri/tests/sccm_client_discovery.rs#L662-L686: Require that malformed roots and unsupported basenames return that error. Do not expect the valid observation to succeed alone.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src-tauri/src/sccm/discovery.rs` around lines 209 - 216, Update
normalize_observation in src-tauri/src/sccm/discovery.rs (lines 209-216) to
return a sanitized privacy-safe malformed-observation error for invalid root
handles or unsupported basenames, propagating it so the batch aborts instead of
returning None and producing incomplete results. Update the
malformed-observation assertions in src-tauri/tests/sccm_client_discovery.rs
(lines 662-686) to require that both malformed roots and unsupported basenames
return this error, without expecting the valid observation to succeed
independently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src-tauri/src/sccm/discovery.rs`:
- Around line 209-216: Update normalize_observation in
src-tauri/src/sccm/discovery.rs (lines 209-216) to return a sanitized
privacy-safe malformed-observation error for invalid root handles or unsupported
basenames, propagating it so the batch aborts instead of returning None and
producing incomplete results. Update the malformed-observation assertions in
src-tauri/tests/sccm_client_discovery.rs (lines 662-686) to require that both
malformed roots and unsupported basenames return this error, without expecting
the valid observation to succeed independently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c333527-9f0d-485e-88a7-a85bec5a7961

📥 Commits

Reviewing files that changed from the base of the PR and between c778b3c and de0957d.

📒 Files selected for processing (2)
  • src-tauri/src/sccm/discovery.rs
  • src-tauri/tests/sccm_client_discovery.rs

@adamgell

adamgell commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

The fresh exact-head CodeRabbit observation is accepted as exposing a real coverage-integrity gap, but the suggested whole-batch abort is not the contract-correct repair.

At de0957d4, normalize_observations silently omits both invalid root handles and unsupported supplied candidates, then returns Ok for the remaining declarations. That can make a supplied candidate disappear without an explicit malformed/unsupported coverage outcome. The SCCM program contract requires missing, access-denied, capped, skipped, malformed, and unsupported sources to remain coverage states—not evidence of success or failure.

The correction must distinguish:

  • arbitrary directory entries outside the curated allow-list, which must be filtered before they become observations;
  • a valid-root unsupported candidate already supplied to this API, which must remain bounded unsupported metadata with no workflow membership;
  • a known source with malformed opaque-root provenance, which must become a privacy-safe noncapture coverage issue without echoing or hashing the unvalidated raw value;
  • intentional optional-source disablement, which remains a distinct skipped state.

A fresh isolated TDD worktree is active from exact de0957d4. It will preserve valid observations instead of aborting the batch, add bounded deterministic coverage outcomes, and rerun the full discovery/native-manifest/parser/Clippy/Rust 1.88/wasm/format gates plus independent and CodeRabbit review. This draft is not merge-ready, regardless of otherwise green CI or the no-new-comment Copilot re-review.

@adamgell
adamgell marked this pull request as ready for review August 2, 2026 20:05
@adamgell
adamgell merged commit c622c9e into codex/parser-family-skeleton Aug 2, 2026
11 checks passed
adamgell added a commit that referenced this pull request Aug 4, 2026
* test(sccm): define bounded client discovery contract

* test(sccm): pin discovery budget and privacy boundaries

* feat(sccm): normalize bounded client discovery

* test(sccm): expose discovery bound and conflict gaps

* test(sccm): isolate discovery construction probes

* test(sccm): pin bounded discovery source fairness

* fix(sccm): bound deterministic client discovery

* test(sccm): expose late discovery conflicts

* fix(sccm): reject all conflicting discovery observations

* test(sccm): preserve malformed root discovery skip

* fix(sccm): skip malformed discovery root handles

* perf(sccm): short-circuit discovery conflict checks

* test(sccm): pin conflict error privacy

* style(sccm): satisfy bounded discovery lint

* test(sccm): expose discovery work bound

* fix(sccm): bound client discovery normalization work

* test(sccm): expose discovery review regressions

* fix(sccm): stabilize discovery normalization identities
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request feature New feature parser Log parser related sccm SCCM/ConfigMgr related test Testing related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants