Skip to content

feat(sccm): add bounded advanced server capture - #500

Merged
adamgell merged 23 commits into
mainfrom
codex/sccm-advanced-server-capture
Aug 8, 2026
Merged

feat(sccm): add bounded advanced server capture#500
adamgell merged 23 commits into
mainfrom
codex/sccm-advanced-server-capture

Conversation

@adamgell

@adamgell adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Closes #497. Supports evidence capture for #475, #476, #477, #478, and #479 without promoting their semantic source cards.

Adds one closed six-source SCCM advanced capture surface across the operator UI, typed IPC, single-use native capability store, bounded collector, manifest writer, and parser intake. Observed and operator-declared provenance remain distinct; operator candidates stay unclassified, parser-ineligible, and non-semantic. Capabilities are random, opaque, expiring, bounded, consumed before read, canceled on abandonment, and nonpersistent. Each logical source is limited to two current/lo_ rotations and 4 MiB total, enforced by both collector and hostile-manifest parser gates.

Independent rework and current-main integration critics: ACCEPT at final SHA d31ae86.

Local gates: full parser/app suites; Rust 1.88; WASM; focused intake, IPC, collector, hierarchy, database, client provenance, and native collection suites; frontend tests; TypeScript; production build; scoped rustfmt and diff checks.

Windows hosted Registry/CIM, reparse-point behavior, real picker/consent states, and fresh SCCM lab capture remain mandatory before merge. No raw lab evidence will be uploaded.

Summary by CodeRabbit

  • New Features
    • Added advanced SCCM server-log capture for six approved sources.
    • Added source discovery, directory selection, rotated-log support, provenance details, and capture status reporting.
    • Added secure authorization, single-use capabilities, cancellation, expiration, and cleanup handling.
    • Added expanded SCCM role and path classifications.
  • Bug Fixes
    • Improved validation for unsupported, missing, duplicate, tampered, and unsafe capture inputs.
    • Added protection against symlink-based access and excessive artifact or byte counts.
  • Documentation
    • Added implementation plans for advanced SCCM server-log capture and integration.

@github-actions github-actions Bot added enhancement New feature or request feature New feature parser Log parser related sccm SCCM/ConfigMgr related labels Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds bounded advanced SCCM server-log capture across the workspace, Tauri commands, native collector, manifest generation, and parser intake. The flow uses allowlisted sources, expiring single-use capabilities, provenance-aware contracts, filesystem safety checks, and parser-ineligible advanced artifacts.

Changes

Advanced SCCM capture

Layer / File(s) Summary
Capture contracts and implementation plan
docs/superpowers/plans/..., src/workspaces/sccm/types.ts, src-tauri/Cargo.toml, library.md
Defines six allowlisted sources, provenance states, capability DTOs, bounded limits, parser-intake requirements, integration plans, and test targets.
Native authorization and bounded collection
src-tauri/src/sccm/collector/..., src-tauri/src/commands/sccm.rs, src-tauri/src/state/..., src-tauri/tests/sccm_advanced_*.rs
Adds discovery, capability storage, authorization, cancellation, safe bounded collection, manifest generation, filesystem checks, and lifecycle tests.
Manifest intake and integrity validation
crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs, crates/cmtraceopen-parser/tests/sccm_server_intake.rs
Validates capture contracts, binds them to artifact and coverage identities, enforces per-source budgets, and keeps advanced artifacts parser-ineligible.
Workspace authorization flow
src/lib/commands.ts, src/lib/commands.test.ts, src/workspaces/sccm/*
Adds picker-based authorization, consent, capability state, cancellation, stale-operation cleanup, source cards, styling, and UI tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant SccmWorkspace
  participant TauriCommands
  participant SccmAdvancedCapabilityStore
  participant AdvancedCollector
  participant Parser
  SccmWorkspace->>TauriCommands: submit selected source and root
  TauriCommands->>SccmAdvancedCapabilityStore: validate and authorize request
  SccmWorkspace->>TauriCommands: submit opaque capability handle
  TauriCommands->>SccmAdvancedCapabilityStore: consume handle
  TauriCommands->>AdvancedCollector: capture allowlisted files
  AdvancedCollector-->>TauriCommands: return bounded bundle and manifest
  TauriCommands-->>SccmWorkspace: return capture result
  Parser->>Parser: validate capture contract and integrity bindings
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits and clearly describes the bounded SCCM advanced server capture change.
Linked Issues check ✅ Passed The implementation covers the linked issue's exact sources, capability lifecycle, provenance separation, bounded capture, path safety, and parser-integrity requirements.
Out of Scope Changes check ✅ Passed The changes support the stated SCCM advanced capture flow, its validation plans, integration, tests, and documentation without unrelated code.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/sccm-advanced-server-capture

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

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Hosted CI rework is active. The failure is confined to cargo test --no-default-features: the new sccm_advanced_ipc and sccm_advanced_server_capture integration targets import the feature-gated SCCM module but lack the existing Cargo required-features metadata pattern. The fix adds only those two test declarations, then reruns no-default and focused feature tests. Product/full-feature checks remain green.

@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.

Actionable comments posted: 19

Caution

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

⚠️ Outside diff range comments (1)
crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs (1)

729-774: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Document the new public items and note the enum variant addition.

SccmServerCaptureContract, SccmServerAdvancedProvenance, SccmServerConfiguredPathClass, and the new SccmServerConfiguredPathState::OperatorDeclared variant are public API of a published crate and carry no rustdoc. Add /// docs that state the meaning of each field and variant, in particular that capability_handle and authorization_handle are opaque digests and never raw values.

Adding OperatorDeclared to SccmServerConfiguredPathState and adding variants to a public enum breaks downstream exhaustive match arms. If external consumers match on these enums, add #[non_exhaustive] now or record the change in the crate changelog.

As per path instructions: "Treat every public item as a semver commitment: flag breaking changes to public types, signatures, or enum variants, and check that new public items are documented."

🤖 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 `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs` around lines 729
- 774, Document the public types SccmServerCaptureContract,
SccmServerAdvancedProvenance, and SccmServerConfiguredPathClass with rustdoc
covering every field and variant, explicitly describing capability_handle and
authorization_handle as opaque digests rather than raw values. Document the
OperatorDeclared variant added to SccmServerConfiguredPathState, and mark
affected public enums #[non_exhaustive] or record the exhaustive-match breaking
change in the crate changelog.

Source: Path instructions

🤖 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.

Inline comments:
In `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs`:
- Around line 2198-2219: Extract the eight-field capture-contract byte
accounting from coverage_string_bytes into a shared
checked_add_capture_contract_bytes helper accepting &mut usize and
&SccmServerCaptureContract and returning Option<()>. Replace the duplicated
inline accounting at both call sites with this helper, preserving existing
checked-add error propagation and provenance string mappings.
- Around line 2858-2863: Update the advancedCapture match arm near the
collection-limit check to compare byte_limit with
ADVANCED_CAPTURE_SOURCE_BYTE_LIMIT and replace the repeated Some(2) value with a
shared named file-limit constant. Reuse those constants in
normalize_advanced_capture_contract and the budget check so all advanced-capture
gates remain consistent.
- Around line 3117-3131: Replace the Debug-based provenance formatting in
capture_contract_identity with a dedicated explicit provenance key function,
following the existing role_sort_key and coverage_sort_key patterns. Reuse that
function for both role_provenance and path_provenance in
capture_contract_identity and in the two checked_add_string_bytes blocks, so
duplicate detection, coverage keys, and integrity digests use stable canonical
values.

In `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs`:
- Around line 133-142: Update the tampered fixture in
advanced_capture_rejects_budget_evasion_by_tampered_handles so both artifacts
use 2 MiB when tamper_handles is true, keeping the total within the byte budget.
Ensure the untampered 2 MiB pair is asserted to succeed, so rejection is
attributable only to the mismatched capabilityHandle and authorizationHandle
values rather than the budget check.
- Around line 19-104: Extend the advanced-capture test fixtures around
advanced_capture_manifest with an observed-provenance case using a recognized
advanced producer role, matching rolesObserved, configured path state, and
pathClass equal to pathClaim. Add behavioral negative tests covering a
mismatched path class and rolesObserved containing an advanced role without a
corresponding advancedCapture artifact, asserting intake rejects each case.
Ensure assertions validate accepted or rejected intake outcomes rather than
merely checking fixture fields.

In `@docs/superpowers/plans/2026-08-04-sccm-advanced-server-capture.md`:
- Line 256: Update the post-SUP action statement to reference only Task 1’s
defined red UI/IPC tests, removing “parser-contract tests” while keeping parser
intake verification assigned to Task 4.
- Line 5: Replace all Unicode em dash and en dash characters in the Markdown
plan with ASCII hyphens or colons, including the issue range and normative UI
labels. Update the corresponding frontend label strings in SccmWorkspace.tsx so
the plan and UI remain identical, and ensure the affected locations at the
referenced lines contain no Unicode dash characters.
- Line 141: Revise Step 2’s rejection tests so they no longer require the
capability store to be empty for every rejection. Keep an explicit empty-store
rejection case, and add a seeded-valid-entry scenario that rejects a second
authorization while asserting the original handle and store count remain
unchanged.
- Around line 109-113: Bind operator-declared roots in
authorize_sccm_advanced_capture to backend-trusted picker consent or a strict
validated-root allowlist before capability creation. Reject any selected_root
without valid backend-issued authorization, and add a negative test proving a
guessed readable directory cannot obtain a capability or capture files.

In `@src-tauri/src/sccm/collector/advanced_capture.rs`:
- Around line 805-809: Update the rotation object’s kind field to call the
existing rotation_segment helper instead of duplicating the inline match on
rotation. Preserve the current mapping and pass the same rotation value/context
required by rotation_segment.
- Around line 970-981: Update the capped calculation in the advanced capture
read flow so a short read caused by concurrent file rotation is treated as an
uncapped bounded fragment rather than byte-limit truncation. Base the final
capped status on the bytes actually read, while retaining take(read_limit) to
bound growth and removing the short-read failure path in this block.

In `@src-tauri/tests/sccm_advanced_ipc.rs`:
- Around line 132-167: Add a focused test alongside
capability_store_is_bounded_and_purges_before_authorize that authorizes the same
root and role twice at the same timestamp, asserting the second
SccmAdvancedCapabilityStore::authorize call fails and pending_count remains 1.
Use a single temporary root so the duplicate-identity rejection path is
exercised.
- Around line 72-76: Update the glob assertion in the advanced IPC test to use
an existing directory whose name contains a glob metacharacter, ensuring
validate_selected_root reaches the metacharacter gate rather than failing
symlink_metadata. Keep the test platform-aware because such names are
unavailable on Windows, gating the case or using an equivalent Unix-only setup.

In `@src-tauri/tests/sccm_advanced_server_capture.rs`:
- Around line 114-119: Replace the ineffective manifest-content and source-path
assertions in the advanced capture test with checks against actual files in the
on-disk bundle. Add a recursive `walk_files` helper and assert that no collected
evidence file has the decoy basenames `CloudMgr.log.1` or `CloudMgr-copy.log`,
while preserving the existing `artifact_count` and `retained_bytes` assertions.

In `@src/lib/commands.test.ts`:
- Around line 159-162: Remove the redundant negative assertion for
"capture_sccm_advanced_diagnostics" and rely on the existing exact
toHaveBeenNthCalledWith assertion that verifies the second invoke call contains
only capabilityHandle.

In `@src/workspaces/sccm/SccmWorkspace.test.tsx`:
- Around line 334-381: Add a test in the SccmWorkspace advanced-capture tests
covering captureSccmAdvancedDiagnostics rejection after
authorizeSccmAdvancedCapture resolves. Assert cancelSccmAdvancedCapture receives
the issued capabilityHandle, the capture error appears in the alert, and
useSccmStore advancedCapability is cleared.

In `@src/workspaces/sccm/SccmWorkspace.tsx`:
- Around line 568-573: Update the button aria-label in the advanced capture UI
near captureAdvanced to include option.sourceId alongside the existing card
label, ensuring each source has a unique accessible name. Preserve the current
fallback behavior for ADVANCED_CARD_LABELS and update all affected button
queries in SccmWorkspace.test.tsx to match the new accessible names.
- Around line 336-340: Update the declined-consent branch in the advanced SCCM
capture flow to await cancelSccmAdvancedCapture with local error handling that
prevents cancellation failures from reaching the capture-failed catch path or
displaying a capture error. Request cancellation before calling
clearAdvancedCapability, while preserving the early return and existing behavior
for accepted consent.

In `@src/workspaces/sccm/types.ts`:
- Around line 84-95: The SccmAdvancedSourceOption contract must expose a
backend-resolved role/path tuple rather than independent roleScopes and
pathClasses arrays. Update the interface and its producers/consumers so each
option provides the exact role and path selected for the observed fact, and
update SccmWorkspace.tsx to use that tuple instead of indexing the separate
arrays, preserving the managementPoint behavior through the resolved value.

---

Outside diff comments:
In `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs`:
- Around line 729-774: Document the public types SccmServerCaptureContract,
SccmServerAdvancedProvenance, and SccmServerConfiguredPathClass with rustdoc
covering every field and variant, explicitly describing capability_handle and
authorization_handle as opaque digests rather than raw values. Document the
OperatorDeclared variant added to SccmServerConfiguredPathState, and mark
affected public enums #[non_exhaustive] or record the exhaustive-match breaking
change in the crate changelog.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1441c4ac-4276-40e5-8e2f-9902c8912f3c

📥 Commits

Reviewing files that changed from the base of the PR and between 1f025d0 and d31ae86.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (20)
  • crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs
  • crates/cmtraceopen-parser/tests/sccm_server_intake.rs
  • docs/superpowers/plans/2026-08-04-sccm-advanced-server-capture.md
  • src-tauri/Cargo.toml
  • src-tauri/src/commands/sccm.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/sccm/collector/advanced_capture.rs
  • src-tauri/src/sccm/collector/discovery.rs
  • src-tauri/src/sccm/collector/mod.rs
  • src-tauri/src/state/app_state.rs
  • src-tauri/tests/sccm_advanced_ipc.rs
  • src-tauri/tests/sccm_advanced_server_capture.rs
  • src/lib/commands.test.ts
  • src/lib/commands.ts
  • src/workspaces/sccm/SccmWorkspace.test.tsx
  • src/workspaces/sccm/SccmWorkspace.tsx
  • src/workspaces/sccm/sccm-store.test.ts
  • src/workspaces/sccm/sccm-store.ts
  • src/workspaces/sccm/sccm-workspace.css
  • src/workspaces/sccm/types.ts

Comment on lines +2198 to +2219
if let Some(contract) = &artifact.capture_contract {
checked_add_string_bytes(&mut total, &contract.card_id)?;
checked_add_string_bytes(&mut total, &contract.card_version)?;
checked_add_string_bytes(&mut total, &contract.capability_handle)?;
checked_add_string_bytes(&mut total, &contract.authorization_handle)?;
checked_add_string_bytes(&mut total, &contract.role_claim)?;
checked_add_string_bytes(&mut total, &contract.path_claim)?;
checked_add_string_bytes(
&mut total,
match contract.role_provenance {
SccmServerAdvancedProvenance::Observed => "observed",
SccmServerAdvancedProvenance::OperatorDeclared => "operatorDeclared",
},
)?;
checked_add_string_bytes(
&mut total,
match contract.path_provenance {
SccmServerAdvancedProvenance::Observed => "observed",
SccmServerAdvancedProvenance::OperatorDeclared => "operatorDeclared",
},
)?;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the capture-contract byte accounting into one helper.

The eight-field accounting here is duplicated verbatim in coverage_string_bytes. A field added to SccmServerCaptureContract later will be counted in one place and missed in the other, which silently changes the integrity digest input without a compile error. Add fn checked_add_capture_contract_bytes(total: &mut usize, contract: &SccmServerCaptureContract) -> Option<()> and call it from both sites.

🤖 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 `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs` around lines
2198 - 2219, Extract the eight-field capture-contract byte accounting from
coverage_string_bytes into a shared checked_add_capture_contract_bytes helper
accepting &mut usize and &SccmServerCaptureContract and returning Option<()>.
Replace the duplicated inline accounting at both call sites with this helper,
preserving existing checked-add error propagation and provenance string
mappings.

Comment on lines +2858 to +2863
_ if artifact.source_kind == "advancedCapture"
&& artifact.collection_limit.as_ref().is_some_and(|limit| {
limit.byte_limit == 4 * 1024 * 1024
&& limit.file_limit == Some(2)
&& !limit.limit_applied
}) => {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use ADVANCED_CAPTURE_SOURCE_BYTE_LIMIT instead of the literal.

normalize_advanced_capture_contract compares byte_limit against ADVANCED_CAPTURE_SOURCE_BYTE_LIMIT. This arm hardcodes 4 * 1024 * 1024. If the constant changes, the two gates disagree and non-physical advanced artifacts fail with UnexpectedPayload for a limit the contract normalizer accepts. Also hoist the file limit to a named constant, since Some(2) is repeated in normalize_advanced_capture_contract and in the budget check.

♻️ Proposed change
         _ if artifact.source_kind == "advancedCapture"
             && artifact.collection_limit.as_ref().is_some_and(|limit| {
-                limit.byte_limit == 4 * 1024 * 1024
-                    && limit.file_limit == Some(2)
+                limit.byte_limit == ADVANCED_CAPTURE_SOURCE_BYTE_LIMIT
+                    && limit.file_limit == Some(ADVANCED_CAPTURE_SOURCE_FILE_LIMIT)
                     && !limit.limit_applied
             }) => {}
🤖 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 `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs` around lines
2858 - 2863, Update the advancedCapture match arm near the collection-limit
check to compare byte_limit with ADVANCED_CAPTURE_SOURCE_BYTE_LIMIT and replace
the repeated Some(2) value with a shared named file-limit constant. Reuse those
constants in normalize_advanced_capture_contract and the budget check so all
advanced-capture gates remain consistent.

Comment on lines +3117 to +3131
fn capture_contract_identity(contract: Option<&SccmServerCaptureContract>) -> String {
contract.map_or_else(String::new, |contract| {
format!(
"{}\0{}\0{}\0{}\0{}\0{}\0{:?}\0{:?}",
contract.card_id,
contract.card_version,
contract.capability_handle,
contract.authorization_handle,
contract.role_claim,
contract.path_claim,
contract.role_provenance,
contract.path_provenance,
)
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not build a canonical identity from Debug output.

capture_contract_identity formats role_provenance and path_provenance with {:?}. This string feeds duplicate detection, the coverage key, and the integrity digest. Debug is not a stability contract. A variant rename or a hand-written Debug impl changes canonical identities and the digest with no compile error and no test failure. Every other identity in this file uses an explicit key function such as role_sort_key or coverage_sort_key. Add one for provenance and use it here and in the two checked_add_string_bytes blocks.

🐛 Proposed fix
+fn advanced_provenance_key(provenance: SccmServerAdvancedProvenance) -> &'static str {
+    match provenance {
+        SccmServerAdvancedProvenance::Observed => "observed",
+        SccmServerAdvancedProvenance::OperatorDeclared => "operatorDeclared",
+    }
+}
+
 fn capture_contract_identity(contract: Option<&SccmServerCaptureContract>) -> String {
     contract.map_or_else(String::new, |contract| {
         format!(
-            "{}\0{}\0{}\0{}\0{}\0{}\0{:?}\0{:?}",
+            "{}\0{}\0{}\0{}\0{}\0{}\0{}\0{}",
             contract.card_id,
             contract.card_version,
             contract.capability_handle,
             contract.authorization_handle,
             contract.role_claim,
             contract.path_claim,
-            contract.role_provenance,
-            contract.path_provenance,
+            advanced_provenance_key(contract.role_provenance),
+            advanced_provenance_key(contract.path_provenance),
         )
     })
 }
🤖 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 `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs` around lines
3117 - 3131, Replace the Debug-based provenance formatting in
capture_contract_identity with a dedicated explicit provenance key function,
following the existing role_sort_key and coverage_sort_key patterns. Reuse that
function for both role_provenance and path_provenance in
capture_contract_identity and in the two checked_add_string_bytes blocks, so
duplicate detection, coverage keys, and integrity digests use stable canonical
values.

Comment on lines +19 to +104
fn advanced_capture_manifest(
state: &str,
include_payload: bool,
) -> (String, Vec<SccmServerArtifactPayload>) {
let digest = "a".repeat(64);
let artifact_id = format!("cmtraceopen.artifact.sha256.v1:{digest}");
let capability = format!(
"cmtraceopen.capture-capability.sha256.v1:{}",
"b".repeat(64)
);
let authorization = format!(
"cmtraceopen.capture-authorization.sha256.v1:{}",
"c".repeat(64)
);
let root_handle = format!("root-{}", "d".repeat(64));
let relative_path = include_payload.then(|| {
format!(
"evidence/sccm/server/unclassified/advanced-osd-pxe/{root_handle}/current/smspxe.log"
)
});
let manifest = serde_json::json!({
"sccmManifestVersion": 1,
"syntheticFixture": false,
"proposalOnly": null,
"privacy": { "synthetic": false, "rawPaths": "redacted" },
"bundleRole": "server",
"topology": {
"captureHost": format!("cmtraceopen.host.sha256.v1:{}", "e".repeat(64)),
"siteCode": format!("cmtraceopen.site.sha256.v1:{}", "f".repeat(64)),
"rolesObserved": ["siteServer"],
"hierarchyLinks": []
},
"inputOrderIsDeliberatelyUnsorted": null,
"artifacts": [{
"artifactId": artifact_id,
"producerRole": "unclassified",
"producerHostHandle": format!("cmtraceopen.host.sha256.v1:{}", "e".repeat(64)),
"workflowSubject": null,
"sourceId": "advanced-osd-pxe",
"sourceKind": "advancedCapture",
"sourceVersion": "5.00.9141.1000",
"originalPath": "REDACTED",
"originalBasename": "smspxe.log",
"configuredPathProvenance": {
"state": "operatorDeclared",
"pathClass": null,
"pathFingerprint": format!("cmtraceopen.path.sha256.v1:{}", "1".repeat(64))
},
"captureContract": {
"cardId": "osd-pxe",
"cardVersion": "1.0.0",
"capabilityHandle": capability,
"authorizationHandle": authorization,
"roleClaim": "distributionPointPxe",
"pathClaim": "configuredRoleLogRoot",
"roleProvenance": "operatorDeclared",
"pathProvenance": "operatorDeclared"
},
"defaultCandidateState": null,
"rotation": {
"kind": "current",
"value": null,
"lineageId": format!("cmtraceopen.lineage.sha256.v1:{}", "2".repeat(64))
},
"captureState": state,
"collectionDetail": null,
"skipReason": null,
"unsupportedReason": (state == "unsupported").then(|| format!("cmtraceopen.unsupported-reason.sha256.v1:{}", "3".repeat(64))),
"encoding": include_payload.then_some("unknown"),
"collectionLimit": { "byteLimit": 4194304, "fileLimit": 2, "limitApplied": false },
"truncated": null,
"fragmentComplete": null,
"collectedUtc": "2026-08-04T20:00:00Z",
"relativePath": relative_path,
"bytesCopied": if include_payload { 8 } else { 0 }
}]
});
let payloads = include_payload
.then(|| SccmServerArtifactPayload {
manifest_artifact_id: artifact_id,
bytes: b"captured".to_vec(),
})
.into_iter()
.collect();
(serde_json::to_string(&manifest).unwrap(), payloads)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add an observed-provenance fixture.

Every advanced fixture in this file uses roleProvenance and pathProvenance of operatorDeclared. The observed branch of normalize_advanced_capture_contract is never executed. That branch carries the strictest checks in the change: role_sort_key(producer_role) == role_claim, path state limited to configured or supplied, and path_class == path_claim. The advanced-role topology gate at intake.rs lines 855 to 867 and the new SccmServerConfiguredPathClass variants are also unexercised.

Add a fixture with producerRole set to a recognized advanced role, that role present in rolesObserved, configuredPathProvenance.state of configured, and pathClass equal to the pathClaim. Then add negative cases for a mismatched pathClass and for an advanced role in rolesObserved with no advancedCapture artifact.

As per path instructions: "Verify assertions test real behavior rather than restating the implementation."

🤖 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 `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs` around lines 19 - 104,
Extend the advanced-capture test fixtures around advanced_capture_manifest with
an observed-provenance case using a recognized advanced producer role, matching
rolesObserved, configured path state, and pathClass equal to pathClaim. Add
behavioral negative tests covering a mismatched path class and rolesObserved
containing an advanced role without a corresponding advancedCapture artifact,
asserting intake rejects each case. Ensure assertions validate accepted or
rejected intake outcomes rather than merely checking fixture fields.

Source: Path instructions

Comment on lines +133 to +142
if tamper_handles {
overflow["captureContract"]["capabilityHandle"] = json!(format!(
"cmtraceopen.capture-capability.sha256.v1:{}",
"e".repeat(64)
));
overflow["captureContract"]["authorizationHandle"] = json!(format!(
"cmtraceopen.capture-authorization.sha256.v1:{}",
"f".repeat(64)
));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

The tamper test does not test the handle check.

With tamper_handles == true the overflow artifact still carries 4 MiB and the base artifact carries 8 bytes. The group total is 4194312 bytes, so the byte cap at intake.rs line 1096 rejects the bundle on its own. Delete the handle equality check at intake.rs lines 1085 to 1089 and advanced_capture_rejects_budget_evasion_by_tampered_handles still passes. The test restates a rejection it cannot attribute.

Make the tampered fixture fit inside the budget so only the handle mismatch can reject it. Set both artifacts to 2 MiB when tamper_handles is true, and assert the untampered 2 MiB pair succeeds.

As per path instructions: "Verify assertions test real behavior rather than restating the implementation."

🤖 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 `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs` around lines 133 -
142, Update the tampered fixture in
advanced_capture_rejects_budget_evasion_by_tampered_handles so both artifacts
use 2 MiB when tamper_handles is true, keeping the total within the byte budget.
Ensure the untampered 2 MiB pair is asserted to succeed, so rejection is
attributable only to the mismatched capabilityHandle and authorizationHandle
values rather than the budget check.

Source: Path instructions

Comment thread src/lib/commands.test.ts
Comment on lines +159 to +162
expect(invoke).not.toHaveBeenCalledWith(
"capture_sccm_advanced_diagnostics",
expect.objectContaining({ selectedRoot: expect.anything() }),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

This negative assertion is redundant and keyed on one field name.

Line 151-155 already pins the second invoke call to exactly { capabilityHandle: capability.capabilityHandle }. toHaveBeenNthCalledWith is an exact match, so any extra key already fails it. The objectContaining({ selectedRoot }) guard adds no coverage.

It also implies a stronger property than it enforces. If captureSccmAdvancedDiagnostics started forwarding the path under any other key, such as rootPath or root, this assertion would still pass. Delete it and rely on the exact-match assertion above.

♻️ Proposed change
     expect(invoke).toHaveBeenNthCalledWith(3, "cancel_sccm_advanced_capture", {
       capabilityHandle: capability.capabilityHandle,
     });
-    expect(invoke).not.toHaveBeenCalledWith(
-      "capture_sccm_advanced_diagnostics",
-      expect.objectContaining({ selectedRoot: expect.anything() }),
-    );
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(invoke).not.toHaveBeenCalledWith(
"capture_sccm_advanced_diagnostics",
expect.objectContaining({ selectedRoot: expect.anything() }),
);
expect(invoke).toHaveBeenNthCalledWith(3, "cancel_sccm_advanced_capture", {
capabilityHandle: capability.capabilityHandle,
});
🤖 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/lib/commands.test.ts` around lines 159 - 162, Remove the redundant
negative assertion for "capture_sccm_advanced_diagnostics" and rely on the
existing exact toHaveBeenNthCalledWith assertion that verifies the second invoke
call contains only capabilityHandle.

Comment on lines +334 to +381
it("cancels a capability when final consent is declined", async () => {
const advancedDiscovery: SccmEnvironmentDiscovery = {
...DISCOVERY,
advancedSources: [
{
cardId: "client-notification-bgb",
cardVersion: "1.0.0",
sourceId: "advanced-client-notification-bgb",
roleScopes: ["clientNotificationServer", "managementPoint"],
pathClasses: ["configuredRoleLogRoot", "siteServerLogs"],
sourceVersion: null,
availability: "observed",
maxBytes: 4_194_304,
maxFiles: 2,
rotations: ["current", "lo_"],
},
],
};
const capability = {
capabilityHandle: `cmtraceopen.capture-capability.sha256.v1:${"b".repeat(64)}`,
cardId: "client-notification-bgb",
cardVersion: "1.0.0",
sourceId: "advanced-client-notification-bgb",
roleScope: "managementPoint",
pathClass: "configuredRoleLogRoot",
sourceVersion: null,
};
vi.mocked(discoverSccmEnvironment).mockResolvedValue(advancedDiscovery);
vi.mocked(open).mockResolvedValue("C:\\private-root");
vi.spyOn(window, "confirm").mockReturnValueOnce(true).mockReturnValueOnce(false);
vi.mocked(authorizeSccmAdvancedCapture).mockResolvedValue(capability);
render(<SccmWorkspace />);

fireEvent.click(screen.getByRole("button", { name: "Discover SCCM environment" }));
fireEvent.click(
await screen.findByRole("button", {
name: "Authorize Client notification / BGB bounded capture",
}),
);

await waitFor(() =>
expect(cancelSccmAdvancedCapture).toHaveBeenCalledWith(
capability.capabilityHandle,
),
);
expect(captureSccmAdvancedDiagnostics).not.toHaveBeenCalled();
expect(useSccmStore.getState().advancedCapability).toBeNull();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the capture-failure cancellation branch.

The four new tests cover declined consent, unmount, and operation replacement. They do not cover the catch branch at lines 346-355 of src/workspaces/sccm/SccmWorkspace.tsx. That branch is the only path that cancels a capability after captureSccmAdvancedDiagnostics rejects, and it depends on issuedCapabilityHandle being assigned before the failure.

A rejected capture leaves a live single-use capability in the native store until its five-minute TTL expires. That is the exact condition this PR is built to prevent, so the branch deserves a test.

💚 Proposed test
it("cancels the capability when advanced capture fails", async () => {
  const advancedDiscovery: SccmEnvironmentDiscovery = {
    ...DISCOVERY,
    advancedSources: [
      {
        cardId: "reporting",
        cardVersion: "1.0.0",
        sourceId: "advanced-reporting",
        roleScopes: ["reportingServicesPoint"],
        pathClasses: ["configuredRoleLogRoot"],
        sourceVersion: null,
        availability: "operatorDeclaredCandidate",
        maxBytes: 4_194_304,
        maxFiles: 2,
        rotations: ["current", "lo_"],
      },
    ],
  };
  const capability = {
    capabilityHandle: `cmtraceopen.capture-capability.sha256.v1:${"f".repeat(64)}`,
    cardId: "reporting",
    cardVersion: "1.0.0",
    sourceId: "advanced-reporting",
    roleScope: "reportingServicesPoint",
    pathClass: "configuredRoleLogRoot",
    sourceVersion: null,
  };
  vi.mocked(discoverSccmEnvironment).mockResolvedValue(advancedDiscovery);
  vi.mocked(open).mockResolvedValue("C:\\private-root");
  vi.spyOn(window, "confirm").mockReturnValue(true);
  vi.mocked(authorizeSccmAdvancedCapture).mockResolvedValue(capability);
  vi.mocked(captureSccmAdvancedDiagnostics).mockRejectedValue(
    new Error("Capture destination is unavailable."),
  );
  render(<SccmWorkspace />);

  fireEvent.click(
    screen.getByRole("button", { name: "Discover SCCM environment" }),
  );
  fireEvent.click(
    await screen.findByRole("button", {
      name: "Authorize Reporting services bounded capture",
    }),
  );

  await waitFor(() =>
    expect(cancelSccmAdvancedCapture).toHaveBeenCalledWith(
      capability.capabilityHandle,
    ),
  );
  expect(await screen.findByRole("alert")).toHaveTextContent(
    "Capture destination is unavailable.",
  );
  expect(useSccmStore.getState().advancedCapability).toBeNull();
});
🤖 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/workspaces/sccm/SccmWorkspace.test.tsx` around lines 334 - 381, Add a
test in the SccmWorkspace advanced-capture tests covering
captureSccmAdvancedDiagnostics rejection after authorizeSccmAdvancedCapture
resolves. Assert cancelSccmAdvancedCapture receives the issued capabilityHandle,
the capture error appears in the alert, and useSccmStore advancedCapability is
cleared.

Comment on lines +336 to +340
if (!window.confirm("Authorization is ready. Capture this bounded source now?")) {
clearAdvancedCapability();
await cancelSccmAdvancedCapture(capability.capabilityHandle);
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

A failing cancel after a declined consent shows a capture-failed error to the operator.

This await cancelSccmAdvancedCapture(...) has no .catch(), unlike the same call on line 330 and on line 348. If it rejects, control reaches the catch on line 346. issuedCapabilityHandle is already set on line 328, so the code cancels a second time and then calls fail(errorMessage(error, "Advanced SCCM capture failed.")).

The operator declined the capture. They then see a red "Native operation failed" banner claiming the capture failed. No capture was attempted.

Also swap the order so the cancel is requested before the local state is cleared. That keeps the store and the native capability consistent if the component unmounts between the two statements.

🐛 Proposed fix
       completeAdvancedAuthorization(capability);
       if (!window.confirm("Authorization is ready. Capture this bounded source now?")) {
-        clearAdvancedCapability();
-        await cancelSccmAdvancedCapture(capability.capabilityHandle);
+        await cancelSccmAdvancedCapture(capability.capabilityHandle).catch(
+          () => undefined,
+        );
+        clearAdvancedCapability();
         return;
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!window.confirm("Authorization is ready. Capture this bounded source now?")) {
clearAdvancedCapability();
await cancelSccmAdvancedCapture(capability.capabilityHandle);
return;
}
completeAdvancedAuthorization(capability);
if (!window.confirm("Authorization is ready. Capture this bounded source now?")) {
await cancelSccmAdvancedCapture(capability.capabilityHandle).catch(
() => undefined,
);
clearAdvancedCapability();
return;
}
🤖 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/workspaces/sccm/SccmWorkspace.tsx` around lines 336 - 340, Update the
declined-consent branch in the advanced SCCM capture flow to await
cancelSccmAdvancedCapture with local error handling that prevents cancellation
failures from reaching the capture-failed catch path or displaying a capture
error. Request cancellation before calling clearAdvancedCapability, while
preserving the early return and existing behavior for accepted consent.

Comment on lines +568 to +573
<Button
appearance={observed ? "primary" : "secondary"}
disabled={isBusy || option.availability === "blocked"}
onClick={() => void captureAdvanced(option)}
aria-label={`Authorize ${ADVANCED_CARD_LABELS[option.cardId] ?? option.cardId} bounded capture`}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Two cards produce the same accessible button name.

advanced-cloud-manager and advanced-cloud-proxy-connector share cardId: "cloud-service-connection" in ADVANCED_SOURCE_CONTRACTS at lines 69-92 of src-tauri/src/sccm/collector/advanced_capture.rs. ADVANCED_CARD_LABELS maps that one id to "Cloud service connection", so both buttons render aria-label="Authorize Cloud service connection bounded capture".

A screen reader user hears two identical button names in the same grid and cannot tell which source each one captures. The visible <strong>{option.sourceId}</strong> disambiguates for sighted users only.

Include the source id in the accessible name.

🐛 Proposed fix
                       <Button
                         appearance={observed ? "primary" : "secondary"}
                         disabled={isBusy || option.availability === "blocked"}
                         onClick={() => void captureAdvanced(option)}
-                        aria-label={`Authorize ${ADVANCED_CARD_LABELS[option.cardId] ?? option.cardId} bounded capture`}
+                        aria-label={`Authorize ${ADVANCED_CARD_LABELS[option.cardId] ?? option.cardId} (${option.sourceId}) bounded capture`}
                       >

Update the two button queries in src/workspaces/sccm/SccmWorkspace.test.tsx at lines 308, 370, 429, and 518 to match the new name.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Button
appearance={observed ? "primary" : "secondary"}
disabled={isBusy || option.availability === "blocked"}
onClick={() => void captureAdvanced(option)}
aria-label={`Authorize ${ADVANCED_CARD_LABELS[option.cardId] ?? option.cardId} bounded capture`}
>
<Button
appearance={observed ? "primary" : "secondary"}
disabled={isBusy || option.availability === "blocked"}
onClick={() => void captureAdvanced(option)}
aria-label={`Authorize ${ADVANCED_CARD_LABELS[option.cardId] ?? option.cardId} (${option.sourceId}) bounded capture`}
>
🤖 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/workspaces/sccm/SccmWorkspace.tsx` around lines 568 - 573, Update the
button aria-label in the advanced capture UI near captureAdvanced to include
option.sourceId alongside the existing card label, ensuring each source has a
unique accessible name. Preserve the current fallback behavior for
ADVANCED_CARD_LABELS and update all affected button queries in
SccmWorkspace.test.tsx to match the new accessible names.

Comment on lines +84 to +95
export interface SccmAdvancedSourceOption {
cardId: string;
cardVersion: string;
sourceId: string;
roleScopes: string[];
pathClasses: string[];
sourceVersion: string | null;
availability: SccmAdvancedSourceAvailability;
maxBytes: number;
maxFiles: number;
rotations: ["current", "lo_"];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Expose the resolved role and path tuple.

SccmAdvancedSourceOption exposes independent roleScopes and pathClasses arrays. SccmWorkspace.tsx selects option.roleScopes[0], except for one managementPoint case, and always selects option.pathClasses[0]. The plan allows alternatives such as configuredRoleLogRoot and siteServerLogs for BgbServer.log, and multiple role scopes for cloud sources. If the observed fact uses another allowed value, observed_fact_for does not match. Authorization then rejects or downgrades the capture to operatorDeclared, which loses observed provenance.

Return one backend-selected tuple per option, or make the UI select an explicit tuple tied to the observed fact.

🤖 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/workspaces/sccm/types.ts` around lines 84 - 95, The
SccmAdvancedSourceOption contract must expose a backend-resolved role/path tuple
rather than independent roleScopes and pathClasses arrays. Update the interface
and its producers/consumers so each option provides the exact role and path
selected for the observed fact, and update SccmWorkspace.tsx to use that tuple
instead of indexing the separate arrays, preserving the managementPoint behavior
through the resolved value.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Integration-risk gate: do not collect final Windows/MSI evidence from the current 0788929 artifact. PR #500 predates current main and overlaps PR #508/#409 in parser intake ownership. Required order: (1) accept/merge #508, establishing catalog-owned normal source IDs and privacy-safe synthetic grammars; (2) integrate #500 onto that main with serial manual judgment in intake.rs, sccm_server_intake.rs, and src-tauri/Cargo.toml; preserve advanced IDs only behind a valid advancedCapture contract and keep them parser-ineligible/out of the normal catalog; (3) rerun combined parser/native/UI/timestamp gates; (4) build a new Windows MSI from the frozen integrated SHA; (5) collect sanitized server evidence against that exact artifact. The existing MSI remains attributable only to 0788929 and cannot serve as final evidence after integration.

@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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs (1)

661-680: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add Rustdoc for the capture-contract API.

Document SccmServerCaptureContract, its public fields, SccmServerAdvancedProvenance, and its variants. Define their stable meanings for this published crate.

🤖 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 `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs` around lines 661
- 680, Add Rustdoc documenting the published meanings of
SccmServerCaptureContract and every public field, including the distinction
between role and path claims and their provenance. Also document
SccmServerAdvancedProvenance and both Observed and OperatorDeclared variants
with stable API semantics.

Source: Path instructions

♻️ Duplicate comments (2)
crates/cmtraceopen-parser/tests/sccm_server_intake.rs (2)

133-142: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the handle-tamper case inside the byte budget.

The over-budget fixture can reject before the capability-handle comparison runs. The test then cannot prove that tampered capabilityHandle or authorizationHandle values fail integrity binding.

Set both artifacts to 2 MiB in the tampered branch. Assert that the same untampered pair succeeds before asserting each handle mismatch fails.

🤖 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 `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs` around lines 133 -
142, Update the tampered branch in the SCCM intake test to configure both
artifacts at 2 MiB so validation reaches capabilityHandle and
authorizationHandle comparisons within the byte budget. Before checking each
tampered-handle failure, assert that the corresponding untampered handle pair
succeeds, then retain separate assertions that each handle mismatch is rejected.

19-104: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add an observed-provenance advanced-capture fixture.

The fixture builder covers operator-declared provenance only. It does not execute the observed-provenance checks for role matching, configured path state, and matching pathClass.

Add one observed artifact with its advanced role in rolesObserved. Add rejection cases for a mismatched pathClass and an observed advanced role with no advancedCapture artifact.

🤖 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 `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs` around lines 19 - 104,
Extend advanced_capture_manifest to support an observed-provenance fixture,
including an advanced role in topology.rolesObserved and an artifact whose role
and configured path provenance are observed with matching pathClass and
advancedCapture metadata. Add test cases covering rejection of a mismatched
pathClass and rejection when the observed advanced role has no advancedCapture
artifact, while preserving the existing operator-declared fixture behavior.
🤖 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.

Inline comments:
In `@docs/superpowers/plans/2026-08-05-sccm-advanced-capture-main-integration.md`:
- Around line 134-143: Update the “Step 3: Run strict quality gates” checklist
so it does not claim completion while the listed full-repository cargo fmt check
fails. Either leave the checklist item unchecked or replace that command with
the scoped rustfmt command that passed, and ensure the recorded results
accurately match the commands shown.

---

Outside diff comments:
In `@crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs`:
- Around line 661-680: Add Rustdoc documenting the published meanings of
SccmServerCaptureContract and every public field, including the distinction
between role and path claims and their provenance. Also document
SccmServerAdvancedProvenance and both Observed and OperatorDeclared variants
with stable API semantics.

---

Duplicate comments:
In `@crates/cmtraceopen-parser/tests/sccm_server_intake.rs`:
- Around line 133-142: Update the tampered branch in the SCCM intake test to
configure both artifacts at 2 MiB so validation reaches capabilityHandle and
authorizationHandle comparisons within the byte budget. Before checking each
tampered-handle failure, assert that the corresponding untampered handle pair
succeeds, then retain separate assertions that each handle mismatch is rejected.
- Around line 19-104: Extend advanced_capture_manifest to support an
observed-provenance fixture, including an advanced role in
topology.rolesObserved and an artifact whose role and configured path provenance
are observed with matching pathClass and advancedCapture metadata. Add test
cases covering rejection of a mismatched pathClass and rejection when the
observed advanced role has no advancedCapture artifact, while preserving the
existing operator-declared fixture behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ebef49a4-c82a-4f77-b90f-1b0883b467ef

📥 Commits

Reviewing files that changed from the base of the PR and between 0788929 and 9f9bbf3.

📒 Files selected for processing (5)
  • crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs
  • crates/cmtraceopen-parser/tests/sccm_server_intake.rs
  • docs/superpowers/plans/2026-08-05-sccm-advanced-capture-main-integration.md
  • library.md
  • src-tauri/Cargo.toml

Comment on lines +134 to +143
- [x] **Step 3: Run strict quality gates**

```bash
cargo fmt --all -- --check
cargo clippy --locked -p cmtraceopen-parser --all-targets -- -D warnings
cargo clippy --locked -p cmtrace-open --all-targets --all-features -- -D warnings
git diff --check
```

Result: both clippy commands, the scoped rustfmt check over the PR Rust delta, and `git diff --check` pass. Full-repository `cargo fmt --all -- --check` remains red on pre-existing out-of-scope Intune, Jamf, and elevation formatting drift; no unrelated files were reformatted for this integration.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Do not mark the strict quality gate complete while its listed command fails.

Line 137 runs full cargo fmt --all -- --check. Line 143 records that this command remains red. Leave this task unchecked, or replace the command list with the scoped command that actually passed. The current status makes the evidence pack state that a failed gate completed.

🤖 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 `@docs/superpowers/plans/2026-08-05-sccm-advanced-capture-main-integration.md`
around lines 134 - 143, Update the “Step 3: Run strict quality gates” checklist
so it does not claim completion while the listed full-repository cargo fmt check
fails. Either leave the checklist item unchecked or replace that command with
the scoped rustfmt command that passed, and ensure the recorded results
accurately match the commands shown.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Frozen main integration evidence — 2026-08-05

UPDATE — Target

  • PR head: 9f9bbf354c89f9f518bc0e6a20cdf7c00bacc832
  • Base: e59aed306b4f8f5ee1b862970169a26b24886f4d
  • Merge parents: 18d6d923c3b85f13b72fad78241f2d53966cc675 + e59aed306b4f8f5ee1b862970169a26b24886f4d
  • Branch and GitHub pull API both resolve to the frozen head. No merge performed.

UPDATE — Integration decisions

  • intake.rs: normal source membership remains catalog-owned through is_declared_server_source_id; advanced IDs remain isolated behind the closed captureContract validator and never enter the normal source catalog.
  • Preserved exact synthetic:<domain>:sha256.v1:<64 lowercase hex> identity grammar, ASCII-only synthetic host validation, and Unicode/personal-name fail-closed behavior from intake.rs hardcodes test-fixture string literals in production source #409.
  • Preserved advanced provenance (observed vs operatorDeclared), source-local 4 MiB / two-file budgets, integrity-bound capability and authorization handles, and parser_eligible=false semantics.
  • sccm_server_intake.rs retains both intake.rs hardcodes test-fixture string literals in production source #409 regressions (alice-smith, ALC-CM01) and the advanced contract/provenance/budget suites.
  • src-tauri/Cargo.toml retains current-main chrono, PR getrandom = 0.3, and all native/advanced test registrations; Cargo.lock binds cmtrace-open to getrandom 0.3.4.
  • The only textual merge conflict was library.md; both the current-main intake.rs hardcodes test-fixture string literals in production source #409 route and this integration route were retained. Git auto-merged the three overlapping code files, and each result was audited explicitly.

UPDATE — Privacy/catalog assertions

  • Exact privacy regressions: 2/2 pass.
  • Advanced card catalog: 8/8 pass.
  • Full server intake: 74/74 pass.
  • Production normal-source catalog contains no advanced source IDs/basenames.
  • Production intake contains no intake.rs hardcodes test-fixture string literals in production source #409 personal-name or Unicode fixture literals.
  • No raw SCCM/server evidence was collected, printed, committed, or uploaded.

UPDATE — Local verification

UPDATE — Exact Windows x64 artifact

  • CI: run 30999084899, all jobs green for head 9f9bbf354c89f9f518bc0e6a20cdf7c00bacc832.
  • Artifact: cmtrace-open-Windows-x64, ID 8928344708, 18,030,326-byte artifact archive.
  • MSI: CMTrace Open_1.5.1_x64_en-US.msi, 10,665,984 bytes.
  • MSI SHA-256: 3867174a8576153bd6f1deb162b9f7b6d0aecfb179489dc0f039045e399a355d.
  • Provenance schema v2 records sourceCommit = frozen head, target x86_64-pc-windows-msvc, package 1.5.1, and the same MSI size/hash. This is not the old 078892 artifact.

ASK — Windows-only acceptance still required

Run the frozen MSI on an installed SCCM server and inspect the real Registry/CIM role facts, configured roots, Windows reparse/no-follow behavior, observed-vs-operator-declared labels, single-use capability lifecycle, and bounded current/lo_ capture. Keep any captured evidence local and sanitized; do not attach raw logs, paths, identities, certificates, tenant data, or endpoints.

@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.

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@src-tauri/src/sccm/collector/advanced_capture.rs`:
- Around line 1030-1036: Update the read handling in the advanced capture flow
near validate_opened_source so a short read from
input.take(read_limit).read_to_end is accepted instead of returning
CopyAdvancedFailure::Failed; retain map_copy_error handling for actual read
errors and the existing read_limit bound.
- Around line 1160-1169: Update the Windows path normalization used by
windows_path_key() so it strips the same verbatim prefixes handled by
windows_final_path(), ensuring canonicalize() results and captured paths compare
in the same form instead of being rejected as CopyAdvancedFailure::Unsafe. Keep
the existing non-Windows behavior unchanged, and add a Windows-gated regression
test that covers a canonicalize() output with a \\?\-prefixed path comparing
successfully against the final path.

In `@src-tauri/src/sccm/collector/discovery.rs`:
- Around line 518-519: Update the manifest assertion in the surrounding test to
parse the file contents as JSON and assert the deserialized manifest’s
roleProvenance field equals "observed". Replace the formatted substring check
while preserving the existing file read and failure behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ba116062-1a7d-4b61-bb37-fcb2b665faca

📥 Commits

Reviewing files that changed from the base of the PR and between 9f9bbf3 and e566984.

📒 Files selected for processing (5)
  • docs/superpowers/plans/2026-08-05-sccm-advanced-server-validation-rework.md
  • library.md
  • src-tauri/src/sccm/collector/advanced_capture.rs
  • src-tauri/src/sccm/collector/discovery.rs
  • src-tauri/tests/sccm_advanced_server_capture.rs

Comment on lines +1030 to +1036
input
.take(read_limit)
.read_to_end(&mut bytes)
.map_err(map_copy_error)?;
if bytes.len() as u64 != read_limit {
return Err(CopyAdvancedFailure::Failed);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

A concurrent truncation still turns a benign short read into a total capture failure.

opened.len is read from the handle before read_to_end. The site server appends to and rotates smspxe.log, CloudMgr.log, and BgbServer.log continuously. If the file is truncated after opened_source_facts returns and before the read completes, bytes.len() is below read_limit and line 1035 returns CopyAdvancedFailure::Failed. capture_advanced_authorized then propagates SccmCollectorError::CaptureFailed, the bundle root is removed, and the capability was already consumed by store.consume. The operator must repeat the picker and both consent prompts.

The identity checks in validate_opened_source narrow this window but do not close it. take(read_limit) already bounds growth, so accepting a short read remains safe: extra bytes can never be read.

🐛 Proposed fix
-    let capped = opened.len > byte_limit;
     let read_limit = opened.len.min(byte_limit);
     let mut bytes =
         Vec::with_capacity(usize::try_from(read_limit).map_err(|_| CopyAdvancedFailure::Failed)?);
     input
         .take(read_limit)
         .read_to_end(&mut bytes)
         .map_err(map_copy_error)?;
-    if bytes.len() as u64 != read_limit {
-        return Err(CopyAdvancedFailure::Failed);
-    }
+    // The source can shrink between the validated open and the read. A short
+    // read is a bounded fragment, not a failure. Growth stays bounded by take().
+    let capped = opened.len > byte_limit && bytes.len() as u64 == read_limit;
     Ok((bytes, capped))
🤖 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/collector/advanced_capture.rs` around lines 1030 - 1036,
Update the read handling in the advanced capture flow near
validate_opened_source so a short read from input.take(read_limit).read_to_end
is accepted instead of returning CopyAdvancedFailure::Failed; retain
map_copy_error handling for actual read errors and the existing read_limit
bound.

Comment thread src-tauri/src/sccm/collector/advanced_capture.rs
Comment on lines +518 to +519
let manifest = fs::read_to_string(bundle.join("sccm-server-manifest.json")).unwrap();
assert!(manifest.contains("\"roleProvenance\": \"observed\""));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the parsed manifest field, not a formatted JSON substring.

Line 519 matches the literal "roleProvenance": "observed", including the space after the colon. That spacing is an artifact of pretty serialization. If the manifest writer switches to serde_json::to_string, the substring disappears and the test fails without any behavior change. If a different field ever carries the same literal text, the test passes for the wrong reason.

Parse the manifest and assert the field.

♻️ Proposed change
-        let manifest = fs::read_to_string(bundle.join("sccm-server-manifest.json")).unwrap();
-        assert!(manifest.contains("\"roleProvenance\": \"observed\""));
+        let manifest: serde_json::Value =
+            serde_json::from_reader(fs::File::open(bundle.join("sccm-server-manifest.json")).unwrap())
+                .unwrap();
+        let artifacts = manifest["artifacts"].as_array().unwrap();
+        assert!(!artifacts.is_empty());
+        assert!(artifacts
+            .iter()
+            .all(|artifact| artifact["roleProvenance"] == "observed"));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let manifest = fs::read_to_string(bundle.join("sccm-server-manifest.json")).unwrap();
assert!(manifest.contains("\"roleProvenance\": \"observed\""));
let manifest: serde_json::Value =
serde_json::from_reader(fs::File::open(bundle.join("sccm-server-manifest.json")).unwrap())
.unwrap();
let artifacts = manifest["artifacts"].as_array().unwrap();
assert!(!artifacts.is_empty());
assert!(artifacts
.iter()
.all(|artifact| artifact["roleProvenance"] == "observed"));
🤖 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/collector/discovery.rs` around lines 518 - 519, Update the
manifest assertion in the surrounding test to parse the file contents as JSON
and assert the deserialized manifest’s roleProvenance field equals "observed".
Replace the formatted substring check while preserving the existing file read
and failure behavior.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Server-validation rework evidence

UPDATE — Target

UPDATE — Claims inspected

  1. Production native discovery now clears any pre-populated advanced facts and derives the closed, currently supportable mapping only when both trusted observations exist: a managementPoint role plus its matching configured log root produces the BGB observed fact. Missing role, missing root, mismatched-role root, and injected/tampered facts do not produce observed provenance. The production assembly test drives the public card to observed and a generated manifest to roleProvenance: observed; the other five cards remain operator-declared candidates because discovery has no genuine role/PXE-enable evidence for them.
  2. Advanced capture now snapshots the approved file, reopens with non-follow/reparse semantics, and validates the opened handle before any read: volume/file identity, size/change marker, single-link status, reparse status, final resolved path, exact expected path, and approved-root membership must all match. Deterministic tests cover swap/identity change, final-path mismatch, root escape, hardlink/external target, reparse point, and zero reader calls before successful validation.
  3. Windows extended (\\?\) and DOS final-path spellings normalize to one comparison key. This was caught by the first hosted Windows full-workspace attempt and is covered by a Windows-only regression on the final head.
  4. Existing capture contracts remain unchanged: current + lo_ only, 4 MiB shared per-source budget, two-file limit, provenance retained, and advanced payloads remain parser_eligible=false.

UPDATE — Reproduce / verification

  • Focused native gates: production assembly 3/3; opened-handle seam 4/4; advanced capture 12/12; native collection 22/22; IPC 5/5.
  • Parser/privacy gates: server intake 74/74; advanced roles catalog 8/8; Unicode panic regressions 7/7; explicit timestamp regressions pass; full parser workspace passes.
  • Current-main integration gates: Device Inventory framing 28/28; watcher tail 29/29; full app workspace passes.
  • Frontend: SCCM focused Vitest 41/41; tsc --noEmit and production frontend build pass.
  • Quality: parser/app clippy with warnings denied, scoped rustfmt for all changed PR Rust files, and git diff --check pass. Repository-wide rustfmt remains red only on the pre-existing unrelated Intune/Jamf/elevation formatting baseline; those files were not reformatted here.
  • Hosted exact-head gates all pass, including Rust 1.88 on Windows, Windows full application workspace, Windows clippy, E2E, CodeQL, and all three package jobs.
  • Both SCCM integration/rework library routes are present exactly once after merging current main.

UPDATE — Windows artifact provenance

  • Workflow run: 31005298101
  • Artifact: cmtrace-open-Windows-x64 (artifact id 8930943227)
  • Downloaded with gh run download 31005298101 -n cmtrace-open-Windows-x64 into a fresh SHA-keyed review directory.
  • MSI: CMTrace Open_1.5.1_x64_en-US.msi
  • MSI size: 10,694,656 bytes
  • MSI SHA-256: 3f04a004a3b610460f656c6d86f0b1d32e0a78ab5b8f7d69992a93e9cd776317
  • Downloaded windows-build-provenance.json independently reports sourceCommit=2cd715720db9568754a6aa942c6b785ead58baff and the same MSI size/hash.

DECISION — Scope boundary

No new speculative advanced-role inference was added. Sources without genuinely observed native role/root/PXE evidence remain operator-declared candidates rather than receiving manufactured observed provenance.

ASK — Critic gate

Please re-review the frozen target and exact hosted artifact above. No raw SCCM/server evidence is included in this comment.

Out of scope: merging PR #500 or publishing raw environment evidence.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Configured-root provenance rework evidence

UPDATE — Target

  • Frozen head: f4d353602fa7ff757eced26768248b953f60af27
  • Parent 1 (PR rework plus prior main integration): 76b6f6b563a2a51aea94402dd94bedf2538437b5
  • Parent 2 / current base: 83351b2910e97438c1e39a727f74495f94a8f873
  • PR state: open, unmerged
  • Exact-head hosted run: https://github.com/adamgell/cmtraceopen/actions/runs/31013113555 — success
  • This evidence supersedes the earlier acec6ef4 run/artifact, which predated the final main integrations and was not used for acceptance.

UPDATE — Claims inspected

  1. Native discovery now keeps explicit private provenance on every capture root: configured role Log Directory, site-server installation root, service executable root, site-install fallback, or default role location. Provenance is assigned at path selection and is never reconstructed from path shape or existence.
  2. Production advanced assembly clears injected advanced facts and emits advanced-client-notification-bgb observed evidence only for an observed management-point role plus a management-point root whose origin is ConfiguredRoleLogDirectory.
  3. Missing or unreadable MP Log Directory with no site install and an existing default root remains operatorDeclaredCandidate; a site-install-derived MP root also remains a candidate. Forged injected facts are erased. Duplicate equal roots deterministically retain the stronger configured origin when genuine configured evidence also exists.
  4. Genuine configured MP evidence produces manifest roleProvenance: observed, pathProvenance: observed, and pathClaim: configuredRoleLogRoot. The existing opened-handle TOCTOU validation and all capture limits/contracts remain unchanged.

UPDATE — Reproduce / verification

  • Production discovery assembly: 14/14, including configured, missing/unreadable + existing default, site fallback, duplicate-origin precedence, and forged-fact cases.
  • Native advanced matrix: advanced capture 12/12; IPC 5/5; native collection 22/22.
  • Parser/privacy matrix: server intake 74/74; advanced roles catalog 8/8; Unicode panic regressions 7/7; full parser workspace passes.
  • Integrated-main matrix: Device Inventory framing 28/28; watcher tail 29/29; full app workspace and no-default-features workspace pass.
  • Frontend after locked dependency refresh: focused SCCM/IPC/registry Vitest 68/68; tsc --noEmit; production build; npm audit with zero vulnerabilities.
  • Quality: parser/app clippy with warnings denied, scoped rustfmt for every changed SCCM Rust file, and merge-range git diff --check pass.
  • Required library routes for feat(sccm): add bounded advanced server capture #500 integration, feat(sccm): add bounded advanced server capture #500 server-validation rework, this BGB provenance rework, and SCCM Client: diagnose co-management, scripts, notifications, and Software Center #326 each occur exactly once.
  • Repository-wide rustfmt remains red only on the pre-existing unrelated Intune/Jamf/elevation formatting baseline; those files were not reformatted here.
  • Hosted exact-head gates all pass, including Rust 1.88 on Windows, Windows full application workspace, Windows clippy, E2E, security/audit gates, and all three package jobs.

UPDATE — Windows artifact provenance

  • Workflow run: 31013113555
  • Artifact: cmtrace-open-Windows-x64 (artifact id 8934412684)
  • Downloaded into a fresh directory keyed by f4d353602fa7ff757eced26768248b953f60af27.
  • MSI: CMTrace Open_1.5.1_x64_en-US.msi
  • MSI size: 10,678,272 bytes
  • MSI SHA-256: c2e0ac65aa2af6c5c81804675c0fea552646ea1cf6512c8f5373f9d47366b04f
  • Downloaded windows-build-provenance.json independently reports sourceCommit=f4d353602fa7ff757eced26768248b953f60af27 and the same MSI size/hash.

DECISION — Scope boundary

Inferred/site/default roots remain usable for normal native collection but can never self-promote BGB to observed. Only a successfully read trusted MP Log Directory fact can do that.

ASK — Critic gate

Please re-review the frozen target and exact hosted artifact above.

Out of scope: merging PR #500 or publishing raw SCCM/server evidence.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Windows lab merge gate — blocked

Independent code review: ACCEPT at f4d353602fa7ff757eced26768248b953f60af27. Exact-head CI is green. Artifact 8934412684 contains CMTrace Open_1.5.1_x64_en-US.msi (10,678,272 bytes; SHA-256 c2e0ac65aa2af6c5c81804675c0fea552646ea1cf6512c8f5373f9d47366b04f; provenance sourceCommit exact). Current main advanced only by docs PR #513, so the reviewed product code is unchanged; any later product-code advance requires a new freeze/artifact.

Remaining mandatory Setup-CM lab evidence:

Disposition: keep PR open; do not merge or close #497 until this checklist is satisfied on the exact artifact.

@adamgell

adamgell commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

PR #500 MSI policy diagnosis — BLOCKED

  • Commit: f4d353602fa7ff757eced26768248b953f60af27
  • Artifact: 8934412684
  • MSI SHA-256 verification: PASS.
  • Shell elevation: NOT elevated.
  • MSI storage: local NTFS volume.
  • msiexec exit code: 1625 (captured in a private local verbose installer log; log not uploaded).
  • Effective DisableMSI: unset; source: neither Local nor Domain Group Policy.
  • Effective DisableUserInstalls: unset; source: neither Local nor Domain Group Policy.
  • AppLocker effective Windows Installer rules: none.
  • AppLocker relevant blocking event IDs: none observed.
  • WDAC/Code Integrity MSI enforcement: no MSI-related block observed; unrelated Code Integrity event IDs 3033 and 3089 were present.
  • MSI Authenticode status: NotSigned.
  • Mark-of-the-Web: absent.
  • MSI source: local.
  • Existing CMTrace Open version: 1.5.1.
  • Existing install context: per-machine.
  • Product-code equality: false.
  • Upgrade-code equality: true.

Blocker classification: elevation/source.

Sanitized blocker: The shell was not elevated, so the exact machine MSI install returned 1625.

Narrowest lab-safe remediation: rerun the exact MSI from its local NTFS source in an elevated administrator lab session; do not change installer policy or uninstall the existing product.

@adamgell

adamgell commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Sanitized MSI policy diagnosis for commit f4d353602fa7ff757eced26768248b953f60af27 / artifact 8934412684:

  • Elevation: elevated=true
  • MSI storage: local=true; filesystem=NTFS; SHA-256 matches expected=true
  • msiexec probe: exit_code=0; private local /L*V log=true; log not uploaded
  • Windows Installer policy: machine DisableMSI=unset (source=none; neither Local nor Domain Group Policy); user DisableMSI=unset (source=none; neither Local nor Domain Group Policy); machine DisableUserInstalls=unset (source=none; neither Local nor Domain Group Policy); user DisableUserInstalls=unset (source=none; neither Local nor Domain Group Policy)
  • AppLocker: effective policy=none; relevant recent event IDs=none
  • WDAC/Code Integrity: active enforcement indicator=false; relevant recent event IDs=3033, 3089 (historical; no policy-block correlation established)
  • Authenticode status: NotSigned
  • Mark-of-the-Web: false; source=local
  • Existing CMTrace Open: version=1.5.1; context=per-machine; product-code-match=true; upgrade-code-match=true
  • Blocker classification: unknown
  • Narrowest lab-safe remediation: none; do not change policy or uninstall software. If the original block is reproduced, capture a fresh private verbose MSI log and correlate its timestamp with AppLocker/Code Integrity events before any remediation.

Copilot AI lite review requested due to automatic review settings August 8, 2026 02:23

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 an end-to-end, bounded “advanced SCCM server capture” flow that lets an operator authorize a directory once (via picker + consent), receive a short-lived single-use opaque capability, and then perform a tightly allowlisted capture of six specific server logs while keeping operator-declared provenance distinct from observed provenance. This extends across the React workspace UI, typed IPC commands, a non-persistent in-memory capability store, a bounded native collector that writes a provenance-safe manifest, and parser intake validation/gating.

Changes:

  • Frontend: renders advanced source options, runs picker + consent, and performs authorize/capture/cancel with store-backed phase handling.
  • Backend: adds capability issuance/consumption/cancel commands + AppState store, and implements bounded collector + discovery provenance assembly for advanced sources.
  • Parser: extends server intake schema to validate and integrity-bind captureContract, enforce per-source capped budgets, and keep advanced artifacts parser-ineligible.

Reviewed changes

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

Show a summary per file
File Description
src/workspaces/sccm/types.ts Adds advanced source option / authorization request / capability DTOs and expanded SCCM role union.
src/workspaces/sccm/SccmWorkspace.tsx Implements picker + consent UI and wires advanced authorize/capture/cancel flow.
src/workspaces/sccm/SccmWorkspace.test.tsx Adds UI tests covering advanced flow, cancellation on decline/unmount/replacement.
src/workspaces/sccm/sccm-workspace.css Styles the new “advanced sources” panel and status indicator.
src/workspaces/sccm/sccm-store.ts Extends Zustand state machine with authorizing / capturingAdvanced and capability storage.
src/workspaces/sccm/sccm-store.test.ts Adds store behavior test for advanced capability lifecycle clearing on failure.
src/lib/commands.ts Adds typed IPC wrappers for advanced authorization/capture/cancel commands.
src/lib/commands.test.ts Verifies IPC boundary stays capability-only (no raw path returned / reused).
src-tauri/tests/sccm_native_collection.rs Updates fixtures to include capture-root provenance origin.
src-tauri/tests/sccm_advanced_server_capture.rs New native tests covering allowlist contract, bounded capture, provenance, and hostile-file defenses.
src-tauri/tests/sccm_advanced_ipc.rs New tests for DTO strictness, capability lifecycle (TTL/capacity/cancel), and symlink-root rejection.
src-tauri/src/state/app_state.rs Adds sccm_advanced_capabilities store to AppState under sccm-diagnostics.
src-tauri/src/sccm/collector/mod.rs Exposes advanced capture module/types; extends discovery DTO and root provenance origin tracking.
src-tauri/src/sccm/collector/discovery.rs Assembles native environment with controlled advanced facts and publishes sanitized advanced options.
src-tauri/src/sccm/collector/advanced_capture.rs New advanced collector owner: allowlist contracts, capability store, bounded copy, manifest emission.
src-tauri/src/lib.rs Registers new SCCM advanced IPC commands behind sccm-diagnostics.
src-tauri/src/commands/sccm.rs Adds Tauri commands and helpers for authorize/capture/cancel backed by AppState capability store.
src-tauri/Cargo.toml Adds getrandom dependency and registers new SCCM advanced integration tests.
library.md Adds links to SCCM advanced capture integration/validation plans.
docs/superpowers/plans/2026-08-05-sccm-bgb-configured-root-provenance.md New plan doc for BGB configured-root provenance gating.
docs/superpowers/plans/2026-08-05-sccm-advanced-server-validation-rework.md New plan doc for server-validation gaps and verification steps.
docs/superpowers/plans/2026-08-05-sccm-advanced-capture-main-integration.md New plan doc for merging advanced capture work onto main and verifying boundaries.
docs/superpowers/plans/2026-08-04-sccm-advanced-server-capture.md New frozen implementation plan/spec for advanced server capture feature.
crates/cmtraceopen-parser/tests/sccm_server_intake.rs Adds parser tests for advanced-capture contract validation, provenance, and budget enforcement.
crates/cmtraceopen-parser/src/sccm/server/windows/intake.rs Extends intake schema to support/validate captureContract and enforce advanced-capture constraints.
Cargo.lock Updates lockfile for the new dependency.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +101 to +116
#[tauri::command]
pub fn authorize_sccm_advanced_capture(
state: State<'_, AppState>,
request: SccmAdvancedCaptureAuthorizationRequest,
) -> Result<SccmAdvancedCaptureCapability, AppError> {
let mut store = state
.sccm_advanced_capabilities
.lock()
.map_err(|_| collector_error(SccmCollectorError::AdvancedAuthorizationRejected))?;
authorize_advanced_with_provider(
&NativeDiscoveryProvider,
&mut store,
request,
Instant::now(),
)
}
Comment on lines +3047 to +3061
fn capture_contract_identity(contract: Option<&SccmServerCaptureContract>) -> String {
contract.map_or_else(String::new, |contract| {
format!(
"{}\0{}\0{}\0{}\0{}\0{}\0{:?}\0{:?}",
contract.card_id,
contract.card_version,
contract.capability_handle,
contract.authorization_handle,
contract.role_claim,
contract.path_claim,
contract.role_provenance,
contract.path_provenance,
)
})
}
@adamgell
adamgell merged commit cf327bd into main Aug 8, 2026
17 checks passed
adamgell added a commit that referenced this pull request Aug 13, 2026
…under Unreleased (#530)

Catch up the Unreleased section with all ten commits merged since the
last changelog update (54d539e / #513):

- Microsoft Store app evidence lane (#358 / #518)
- Reducer Framework v1 governance, ADRs, and charters (#519)
- Windows Autopilot evidence parser outside ESP (#362 / #450)
- Company Portal Windows LocalState logs (#366 / #460)
- Bounded advanced SCCM server capture (#500), folded into the
  existing native SCCM diagnostics path bullet
- Agent tooling / Clairvoyance staff org scaffolding (#516)
- Dependency bumps (quick-xml, time, install-action) and the
  GitHub Sponsors funding link

No version bump: package.json/Cargo.toml/tauri.conf.json remain at
1.5.1 with no new tag, so this stays purely an Unreleased catch-up.


Claude-Session: https://claude.ai/code/session_01A8z5Ysfa5Afts6gVPmHQZj

Co-authored-by: Claude <noreply@anthropic.com>
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SCCM Server capture: authorize bounded advanced-role source roots

2 participants