Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
64c39e2
test: expose missing Podman desktop evidence boundary
seonghobae Aug 10, 2026
15e895d
feat: add privacy-safe Podman desktop projection
seonghobae Aug 10, 2026
9fc8cc0
feat: register read-only Podman desktop command
seonghobae Aug 10, 2026
f60997d
feat: validate privacy-safe Podman desktop evidence
seonghobae Aug 10, 2026
14bcf45
feat: redact Podman desktop failures
seonghobae Aug 10, 2026
4cbb142
feat: render read-only Podman evidence panel
seonghobae Aug 10, 2026
d18e60d
feat: integrate Podman evidence into cleanup
seonghobae Aug 10, 2026
360af50
test: lock Podman failure redaction
seonghobae Aug 10, 2026
8ec7d8d
test: enforce Podman evidence JSDoc
seonghobae Aug 10, 2026
faefa1c
test: enforce Podman desktop rustdoc
seonghobae Aug 10, 2026
6012f0e
test: prove Podman issue privacy boundary
seonghobae Aug 10, 2026
fa62786
docs: record Podman desktop evidence boundary
seonghobae Aug 10, 2026
ed11694
docs: record Podman desktop evidence slice
seonghobae Aug 10, 2026
d8bd132
test(podman): preserve stale branch edge-case regressions
seonghobae Aug 10, 2026
a2ad5c5
test: require Podman frontend production coverage
seonghobae Aug 10, 2026
7016d29
fix: measure Podman frontend production coverage
seonghobae Aug 10, 2026
6eb54de
docs: reconcile Podman slice with current main
seonghobae Aug 10, 2026
9551d2c
test: expose Podman assessment privacy and coverage cfg gaps
seonghobae Aug 10, 2026
4cade23
test: reject hostile Podman assessment codes
seonghobae Aug 10, 2026
9ad22dd
fix: fail closed on Podman desktop assessment evidence
seonghobae Aug 10, 2026
64ffc12
fix: validate Podman assessment codes at IPC boundary
seonghobae Aug 10, 2026
53b7d53
Merge branch 'main' into feat/podman-desktop-evidence-v3
opencode-agent[bot] Aug 10, 2026
10f65c8
test: reject unverified physical reclaim claims
seonghobae Aug 10, 2026
8073bb1
fix: reject unverified physical reclaim claims
seonghobae Aug 10, 2026
8d3ff71
feat: converge Podman desktop evidence onto current main
seonghobae Aug 10, 2026
6f2ac44
test(podman): reject privacy-unsafe desktop notices
seonghobae Aug 10, 2026
f0374f6
fix(podman): fail closed on desktop notice drift
seonghobae Aug 10, 2026
6767d4d
feat: refresh Podman evidence onto CUDA-toolkit main
seonghobae Aug 10, 2026
9731717
feat: refresh Podman evidence onto base64 main
seonghobae Aug 10, 2026
40c7b16
feat: refresh Podman evidence onto Node types main
seonghobae Aug 10, 2026
fa5c5ce
test(podman): reject unverified physical reclaim claims
seonghobae Aug 10, 2026
e0c03ce
fix(podman): clear unverified physical reclaim claims
seonghobae Aug 10, 2026
081fff1
docs: record Podman IPC fail-closed hardening
seonghobae Aug 10, 2026
fd72b3c
docs: specify Podman projection fail-closed claims
seonghobae Aug 10, 2026
6fe5e0f
test(podman): reject platform and completeness contradictions
seonghobae Aug 10, 2026
0989408
test(podman): fail completeness closed when issues exist
seonghobae Aug 10, 2026
9d39ad9
fix(podman): validate platform and completeness consistency
seonghobae Aug 10, 2026
ad29638
fix(podman): fail completeness closed on projected issues
seonghobae Aug 10, 2026
d02ad4c
docs: define Podman platform and completeness invariants
seonghobae Aug 10, 2026
a618830
docs: record Podman platform and completeness hardening
seonghobae Aug 10, 2026
f8da00f
test(podman): reject candidate and review contradictions
seonghobae Aug 10, 2026
ffb26ab
test(podman): derive review boundaries from observed candidates
seonghobae Aug 10, 2026
ccc8dfe
fix(podman): reject candidate and review contradictions
seonghobae Aug 10, 2026
067e093
fix(podman): derive review boundaries from observed candidates
seonghobae Aug 10, 2026
b3b7c97
docs: define Podman candidate-review consistency
seonghobae Aug 10, 2026
038e5ff
docs: record Podman candidate-review integrity
seonghobae Aug 10, 2026
2c75e95
test: align Podman review coverage with fail-closed candidates
seonghobae Aug 10, 2026
473dade
test: keep Podman privacy fixture semantically partial
seonghobae Aug 11, 2026
8c09cce
Merge 473dade75e07784c1aec778297b39d04edf02514 into 2b891d2c5c50073b7…
seonghobae Aug 11, 2026
3080199
merge: converge Podman desktop evidence with current main
seonghobae Aug 12, 2026
8dd2231
merge: converge Podman desktop evidence with current main
seonghobae Aug 12, 2026
e02a0c5
test: reject sparse-block placeholder inference regression
seonghobae Aug 12, 2026
0608349
fix: preserve sparse-placeholder rollback on Podman line
seonghobae Aug 12, 2026
eeac97b
Merge protected main into Podman desktop evidence
seonghobae Aug 20, 2026
2bc3c2f
chore: reconstruct Podman slice on protected main
seonghobae Aug 20, 2026
8267c32
fix: preserve current cleanup surfaces on Podman line
seonghobae Aug 20, 2026
6c42074
merge: converge Podman desktop evidence onto current main
seonghobae Aug 23, 2026
f7ee17b
merge: converge Podman desktop evidence onto current main
seonghobae Aug 26, 2026
5f89fac
fix: separate privacy-safe Podman evidence command
seonghobae Aug 26, 2026
185ed5a
fix: register privacy-safe Podman evidence command
seonghobae Aug 26, 2026
7a63eaf
test: keep Podman evidence in exact frontend coverage
seonghobae Aug 26, 2026
312e4f1
fix: keep Podman evidence notice contract canonical
seonghobae Aug 26, 2026
7ebfaf4
fix: call distinct privacy-safe Podman evidence command
seonghobae Aug 26, 2026
e61d2d7
feat: surface privacy-safe Podman evidence panel
seonghobae Aug 26, 2026
41fafa9
test: exercise privacy-safe Podman bridge command
seonghobae Aug 26, 2026
cb14a28
test: reject raw Podman errors and contradictory cleanup copy
seonghobae Aug 26, 2026
b56eb1b
fix: bound legacy Podman cleanup feedback
seonghobae Aug 26, 2026
0174d49
Merge remote-tracking branch 'origin/main' into HEAD
seonghobae Aug 26, 2026
b797cee
fix: keep Podman status copy customer focused
seonghobae Aug 26, 2026
cb46e94
fix: keep Podman evidence readable across themes
seonghobae Aug 26, 2026
cb3267f
fix: align Podman desktop reader command
seonghobae Aug 26, 2026
1f26957
fix: complete Podman evidence fixtures
seonghobae Aug 26, 2026
6065ddd
fix: verify Windows release artifact namespace
seonghobae Aug 26, 2026
1e77fc6
fix: bind release artifacts to platform directories
seonghobae Aug 26, 2026
dce1c4f
fix: verify tag artifacts before sbom
seonghobae Aug 26, 2026
f961ca3
fix: hide standing Podman review notice
seonghobae Aug 26, 2026
c650be4
chore: keep release verification with canonical owner
seonghobae Aug 27, 2026
0568827
chore: restore release verifier file mode
seonghobae Aug 27, 2026
d233931
test: require actionable privacy-safe Podman prune failures
seonghobae Aug 28, 2026
e5217da
fix: map Podman prune failures to bounded recovery guidance
seonghobae Aug 28, 2026
d93a863
test: bind Cleanup error mapper to stable prune recovery
seonghobae Aug 28, 2026
4bb87f3
fix: preserve actionable Podman prune recovery at privacy boundary
seonghobae Aug 28, 2026
207916f
test: require dedicated Podman prune recovery mapping
seonghobae Aug 28, 2026
2088f27
test: drop naming-only Podman recovery assertion
seonghobae Aug 28, 2026
e982693
test: require deliberate Podman prune confirmation entry
seonghobae Aug 28, 2026
0ceca3e
fix: require deliberate Podman prune phrase entry
seonghobae Aug 28, 2026
a8797cd
test(podman): cover recommended action customer labels
seonghobae Aug 28, 2026
37c14e6
fix(podman): bound recommended action labels
seonghobae Aug 28, 2026
321bc7c
fix(podman): hide internal recommended action details
seonghobae Aug 28, 2026
460c768
test: reject inherited Podman error keys
seonghobae Aug 28, 2026
4288e57
fix: fail closed on Podman error lookup
seonghobae Aug 28, 2026
d77f1f5
test: cover partial Podman evidence view
seonghobae Aug 28, 2026
83968b1
test: separate Podman inspection recovery from prune guidance
seonghobae Aug 28, 2026
87fa860
test: require resilient Podman evidence style fallbacks
seonghobae Aug 28, 2026
4b2a76d
fix: isolate Podman inspection recovery from prune errors
seonghobae Aug 28, 2026
affbe95
fix: add resilient Podman evidence style fallbacks
seonghobae Aug 28, 2026
2418e73
test: cover Podman evidence validator failures
seonghobae Aug 28, 2026
6990d8d
test: enforce coverage for Podman action labels
seonghobae Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions docs/architecture/podman-desktop-evidence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# ADR: Privacy-safe Podman desktop evidence

- **Status:** Proposed
- **Date:** 2026-08-05
- **Decision owners:** DiskSage maintainers
- **Related issue:** #107
- **Related headless contract:** #105 and `src-tauri/src/podman_reclaim.rs`

## Context

DiskSage already has a Rust-first, read-only Podman evidence probe that distinguishes VM configuration, raw-image logical size, host allocation, guest filesystem usage, Podman graph-root observations, and Podman-reported logical cleanup candidates. The desktop Cleanup experience previously had no supported way to inspect that evidence.

The UI must not turn evidence into authority. Podman documents that image reclaimable values can overstate what a prune would actually free when layers are shared. DiskSage therefore treats all `podman system df` candidate values as logical review evidence rather than verified host physical reclaimability.

The headless report also contains local-only details such as machine names, configuration paths, raw-image paths, graph-root paths, and dynamic command errors. Those details are useful for local diagnosis but are unnecessary for the desktop summary and unsafe for telemetry or shareable evidence. Tauri transport failures and arbitrary JavaScript rejection values can also contain account-local paths, socket names, or command detail, so the UI error boundary must redact them independently of the Rust projection.

## Decision

### 1. Add a separate privacy projection

`src-tauri/src/podman_desktop.rs` converts `PodmanReclaimPlan` into `PodmanDesktopEvidence`.

The projection includes only:

- configured machine disk bytes;
- raw-image logical bytes;
- host allocated bytes;
- guest total, used, and available bytes;
- Podman graph-root allocated and used bytes;
- image, stopped-container, and volume logical candidate bytes;
- unused-image and stopped-container counts;
- the SHA-256 commitment to the exact unused-image candidate set;
- evidence completeness, elapsed time, stable reason codes, and stable issue codes;
- separate image, stopped-container, and volume review boundaries;
- `physically_reclaimable_bytes`, which remains unknown until a before-and-after host observation proves it.

The projection excludes machine names and states; configuration, raw-image, and graph-root paths; image identifiers and tags; account-local context; command output and dynamic error details; and any mutation command or approval record.

Issue strings are reduced to the prefix before the first colon only when that prefix is a bounded lowercase kebab-case code: it must start with a lowercase ASCII letter, contain only lowercase ASCII letters, digits, or hyphens, and be no longer than 96 bytes. Delimiter-free paths, sockets, whitespace, uppercase text, Unicode, underscores, empty prefixes, and malformed values collapse to `podman-evidence-error`. Invalid candidate fingerprints fail closed: the fingerprint is removed, the evidence is marked incomplete, and a stable issue code is added.

A complete exact-image observation must contain both the exact unused-image record count and the SHA-256 commitment to that candidate set. The frontend rejects complete evidence when either member is missing and rejects a fingerprint that has no exact record observation. Partial evidence may retain safe exact-record counts after Rust removes an invalid fingerprint and emits an issue; this remains explicitly incomplete rather than being mislabeled as a complete candidate set.

Any projected issue code forces `evidence_complete` to false, even when an upstream caller incorrectly supplies `true`. The frontend independently rejects a response that combines `evidence_complete: true` with one or more issue codes. This keeps completeness as an integrity assertion rather than a cosmetic label.

The only assessment status admitted by schema version 1 is `unverified`. If a contradictory headless plan supplies a concrete `physically_reclaimable_bytes` value while the assessment remains unverified, the Rust projection clears that value before IPC, marks the evidence incomplete, and emits `podman-desktop-unverified-physical-reclaim-claim`. A future verified physical-reclaim contract requires an explicit schema and evidence-authority change; it cannot appear by silently forwarding a new headless value.

The two user-facing safety notices are also part of schema version 1 rather than arbitrary display text. The frontend accepts only those two exact statements in the defined order and count. Any modified, duplicated, reordered, additional, path-bearing, or otherwise noncanonical notice fails closed with `invalid-notices` instead of being rendered.

The platform field is also schema-bound because it appears in the user interface. Schema version 1 admits only the Tauri desktop targets `linux`, `macos`, and `windows`. Unsupported, path-bearing, machine-specific, or account-specific platform text fails closed with `invalid-platform` rather than becoming visible evidence.

### 2. Keep the Tauri command read-only and argv-based

`inspect_podman_reclaim` invokes the existing Rust probe using an executable plus an argument vector. It does not construct a shell string. The desktop surface exposes no prune, remove, machine start/stop, VM deletion, TRIM, raw-image mutation, or generic command execution path.

### 3. Keep review domains independent and conservative

Images, stopped containers, and local volumes have separate review booleans and separate UI sections. A review signal for one domain never authorizes another domain. This preserves future compatibility with distinct approval records and least-privilege workflows.

A positive candidate observation itself conservatively requires review in its own domain, even if an upstream assessment accidentally omits the corresponding recommended-action record. Rust derives the image, stopped-container, and volume review booleans from both the action list and the observed candidates. The frontend independently rejects a candidate domain whose required review boolean is false. An extra conservative `true` remains advisory only and never creates mutation authority.

### 4. Keep visual semantics explicit, accessible, and privacy-safe

The panel uses semantic headings, definition lists, buttons, `role="status"` for progress and results, and `role="alert"` for errors. The UI never uses color as the only carrier of completeness. Text labels always state whether evidence is complete or partial.

The UI never renders `String(reason)` or another untrusted exception representation. `podmanEvidenceErrorMessage` discards every transport, operating-system, and JavaScript failure detail and returns only `podman-evidence-unavailable`. Detailed diagnosis remains confined to trusted local logs and does not cross into the desktop evidence, telemetry, or shareable-evidence boundary.

### 5. Preserve standalone and MSA compatibility

The desktop response is a versioned JSON contract with no dependency on Naruon or another CWL service. DiskSage runs independently. A future Naruon or fleet-management adapter may consume the same privacy-safe schema without receiving local paths or identifiers.

## Consequences

### Positive

- Buyers can inspect a concrete Podman storage gap from the main Cleanup workflow.
- Logical size, host allocation, guest use, and verified physical reclaimability cannot be silently conflated.
- Contradictory unverified physical-reclaim claims are removed in Rust before IPC rather than relying on frontend refusal.
- Local identifiers stay outside the frontend contract, telemetry, and shareable evidence boundary.
- Malformed or delimiter-free probe issues cannot masquerade as safe codes or serialize local path content.
- Any issue forces partial evidence in Rust, and the frontend refuses contradictory complete-plus-issues payloads.
- Complete exact-image evidence cannot omit or detach its candidate-set commitment.
- Positive candidates cannot be displayed with a false no-review signal in their own domain.
- Arbitrary notice or platform text cannot become a path, machine-name, or account-detail display channel.
- Transport and JavaScript failures cannot leak machine names, paths, sockets, or command detail through the visible error region.
- The architecture can later add separate governed image, container, and volume approval records without changing the read-only evidence contract.
- Module-level `missing_docs` enforcement and source-level documentation contracts keep the Podman desktop functions beginner-readable.

### Negative

- The UI intentionally cannot perform cleanup. Operators must use a separate reviewed workflow until a mutation design includes exact candidate binding, independent approval, rollback evidence, and before-and-after host verification.
- Some evidence remains unavailable when Podman is absent, the machine is stopped, or the API is unhealthy. Unknown values remain `null`; the UI never converts missing evidence to zero.
- Visible failures intentionally use a stable generic code; sensitive operational detail must be inspected through trusted local diagnostics rather than the shareable desktop surface.
- Notice wording, supported platform identifiers, candidate/fingerprint relations, and review-boundary semantics are schema-bound; changing them requires coordinated Rust/frontend contract review rather than a copy-only UI edit.

## Verification matrix

| Invariant | Deterministic evidence |
|---|---|
| No machine names or paths in desktop JSON | Rust serialization tests search for private fixture values |
| Delimiter-free or malformed issue text cannot cross IPC | Rust unit and integration tests expect `podman-evidence-error` |
| Any projected issue forces partial evidence | `podman_desktop_issue_privacy.rs` contradicts upstream completeness and requires false |
| Complete-plus-issues payloads are rejected | TypeScript parser regression expects `inconsistent-evidence-completeness` |
| Complete exact-image evidence requires its fingerprint | TypeScript parser regression expects `inconsistent-image-candidate-fingerprint` |
| A fingerprint cannot exist without exact image records | TypeScript parser regression rejects detached commitments even for partial evidence |
| Observed candidates conservatively require domain review | `podman_desktop_candidate_review_consistency.rs` omits actions and requires all three review booleans |
| Candidate-plus-false-review payloads are rejected | TypeScript parser regressions cover image, stopped-container, and volume domains separately |
| Unverified physical-reclaim claims cannot cross IPC | `podman_desktop_physical_reclaim_claim.rs` requires removal, incomplete evidence, and a stable issue code |
| Arbitrary or duplicated notices cannot reach the UI | TypeScript parser regression requires the exact schema-v1 notice sequence |
| Unsupported or path-bearing platform values cannot reach the UI | TypeScript parser regression admits only `linux`, `macos`, and `windows` |
| Image/container/volume review separation | Rust projection tests and TypeScript view-model tests |
| Invalid fingerprint fails closed | Rust and TypeScript malformed-fingerprint tests |
| Missing observations stay unknown | Rust and TypeScript null-preservation tests |
| Exact Tauri command contract | Rust public-command integration test and mocked TypeScript invoke test |
| Schema/type/range drift rejected | TypeScript parser tests |
| Untrusted failure details never reach visible UI | `podmanEvidence.error.test.ts` supplies path, socket, object, null, and undefined failures and expects one stable code |
| Progress and errors announced | Svelte markup uses `role="status"` and `role="alert"` |
| No mutation surface | Registered command list exposes inspection only |
| Beginner-readable frontend function documentation | Source-level JSDoc regression test checks every production function declaration |
| Beginner-readable Rust function documentation | `missing_docs` plus `podman_desktop_documentation_contract.rs` |

## Release acceptance

This slice is release-eligible only after the exact integrated head passes Rust formatting and tests; frontend unit tests and exact coverage; Svelte type checking and production build; security and SAST workflows; current-head review with no unresolved actionable finding; actual repository/governance review policy; and packaging, provenance, and release acceptance.

## References

Podman. (n.d.). *podman-machine-inspect—Inspect one or more virtual machines*. Retrieved August 5, 2026, from https://docs.podman.io/en/stable/markdown/podman-machine-inspect.1.html

Podman. (n.d.). *podman-system-df—Show Podman disk usage*. Retrieved August 5, 2026, from https://docs.podman.io/en/latest/markdown/podman-system-df.1.html

Tauri Programme within The Commons Conservancy. (2026). *Calling Rust from the frontend*. https://v2.tauri.app/develop/calling-rust/

World Wide Web Consortium. (2024, December 12). *Web Content Accessibility Guidelines (WCAG) 2.2*. https://www.w3.org/TR/WCAG22/

World Wide Web Consortium. (2025). *Understanding Success Criterion 4.1.3: Status messages*. https://www.w3.org/WAI/WCAG22/Understanding/status-messages
7 changes: 6 additions & 1 deletion src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ pub mod naruon_cloud_copy_readiness;
pub mod naruon_lineage;
/// Path-free ontology organization lineage handoff for Naruon/semantic-data-portal.
pub mod organization_lineage;
/// Privacy-safe desktop projection of read-only Podman reclaim evidence.
pub mod podman_desktop;
/// Distinct IPC registration for the privacy-safe Podman evidence contract.
pub mod podman_desktop_bridge;
/// Read-only evidence plus exact-identity-bound Podman reclaim execution authority.
#[path = "podman_reclaim_public.rs"]
pub mod podman_reclaim;
Expand Down Expand Up @@ -138,6 +142,7 @@ pub fn run() {
commands::reason_unknown_extensions,
commands::plan_brew_cleanup,
commands::inspect_podman_reclaim,
podman_desktop_bridge::inspect_podman_desktop_evidence,
commands::execute_podman_dangling_image_prune,
commands::judge_brew_cleanup,
commands::validate_judge_calibration,
Expand Down Expand Up @@ -171,4 +176,4 @@ pub fn run() {
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
}
Loading
Loading