Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
bc72989
test: define redacted Podman desktop evidence contract
seonghobae Aug 5, 2026
4ee0c0c
feat: register read-only Podman desktop evidence command
seonghobae Aug 5, 2026
d213c33
test: add fail-closed Podman desktop API contract
seonghobae Aug 5, 2026
2032f11
test: cover Podman desktop evidence API and view behavior
seonghobae Aug 5, 2026
6e9d97a
feat: render privacy-safe Podman reclaim evidence
seonghobae Aug 5, 2026
ebc3974
feat: surface Podman evidence in Cleanup
seonghobae Aug 5, 2026
0ba5cc7
test: include Podman desktop contract in 100% coverage gate
seonghobae Aug 5, 2026
59934ad
docs: record Podman desktop evidence integration
seonghobae Aug 5, 2026
2b92e46
docs: add Podman desktop evidence ADR
seonghobae Aug 5, 2026
2724e6c
fix: fail closed on empty Podman issue codes
seonghobae Aug 5, 2026
4e708c1
test: enforce formatting type checks and coverage
seonghobae Aug 5, 2026
dcb7cb6
Merge branch 'main' into feat/podman-desktop-evidence
opencode-agent[bot] Aug 5, 2026
a065ce7
style: apply rustfmt to Podman desktop command registration
seonghobae Aug 5, 2026
4e37646
ci: capture exact rustfmt evidence for PR 133
seonghobae Aug 5, 2026
1b43e52
ci: expose PR rustfmt artifact for exact-head repair
seonghobae Aug 5, 2026
cd9c7ad
style: apply exact rustfmt output for Podman desktop evidence
seonghobae Aug 5, 2026
caab8fd
ci: remove completed PR 133 rustfmt evidence workflow
seonghobae Aug 5, 2026
f9da84c
style: apply exact rustfmt module ordering
seonghobae Aug 5, 2026
4063824
ci: capture complete rustfmt diff for PR 133
seonghobae Aug 5, 2026
e73763f
chore: remove one-shot PR133 rustfmt workflow
seonghobae Aug 5, 2026
05dc825
ci: apply bounded repository rustfmt repair
seonghobae Aug 5, 2026
d0f90c2
style: apply repository-wide rustfmt output
github-actions[bot] Aug 5, 2026
2fb9a8b
ci: remove completed PR 133 rustfmt repair workflow
seonghobae Aug 5, 2026
cbf2672
test: require JSDoc for Podman evidence functions
seonghobae Aug 5, 2026
8bdb84a
docs: complete Podman evidence function JSDoc
seonghobae Aug 5, 2026
06b2ad5
docs: record Podman JSDoc regression contract
seonghobae Aug 5, 2026
950339e
test: require privacy-safe Podman UI errors
seonghobae Aug 5, 2026
62ff743
fix: redact Podman desktop error details
seonghobae Aug 5, 2026
9b8af4f
test: bind Podman error redaction contract
seonghobae Aug 5, 2026
f562e48
fix: redact untrusted Podman UI failures
seonghobae Aug 5, 2026
d39ee60
test: cover Podman error redaction helper
seonghobae Aug 5, 2026
d6e6632
docs: define Podman UI error privacy boundary
seonghobae Aug 5, 2026
b62b9e6
docs: record Podman UI error redaction
seonghobae Aug 5, 2026
c5b2df3
test: reject delimiter-free Podman issue detail
seonghobae Aug 5, 2026
f616bff
fix: constrain Podman desktop issue codes
seonghobae Aug 5, 2026
d68cfc9
docs: record strict Podman issue-code redaction
seonghobae Aug 5, 2026
ad17395
docs: define strict Podman issue-code admission
seonghobae Aug 5, 2026
8ef903c
style: apply rustfmt to Podman issue-code validation
seonghobae Aug 5, 2026
8bed5c2
test: require Podman Rust function documentation
seonghobae Aug 5, 2026
f640e9d
docs: enforce complete Podman Rust documentation
seonghobae Aug 5, 2026
07e0f37
docs: record Podman Rust documentation contract
seonghobae Aug 5, 2026
0d26739
docs: update Podman documentation coverage changelog
seonghobae Aug 5, 2026
f73af0a
test: cover crate-visible Rust function modifiers
seonghobae Aug 5, 2026
bf3efdb
chore: remove unrelated Rust formatting from Podman slice
seonghobae Aug 5, 2026
99c745c
ci: scope Rust formatting to Podman slice
seonghobae Aug 5, 2026
b7f980d
chore: keep Podman registration diff focused
seonghobae Aug 5, 2026
3d012e7
test(ci): require exact-head coverage evidence
seonghobae Aug 7, 2026
93c7f27
ci: emit exact-head Rust coverage evidence
seonghobae Aug 7, 2026
6b5c1b0
docs(ci): document exact-head coverage evidence
seonghobae Aug 7, 2026
378d4b2
docs(changelog): record coverage evidence gate
seonghobae Aug 7, 2026
ba76e31
test: cover Podman desktop validation branches
seonghobae Aug 8, 2026
052aedf
test: require production Rust coverage graph
seonghobae Aug 8, 2026
5a76795
ci: measure production graph in Rust coverage
seonghobae Aug 9, 2026
6fd3c62
ci: keep coverage contract executable
seonghobae Aug 9, 2026
05b4967
test: catch quoted coverage evidence variables
seonghobae Aug 9, 2026
18fc5cb
revert: remove invalid coverage workflow assumption
seonghobae Aug 9, 2026
84e9378
test: require bounded failed-coverage diagnostics
seonghobae Aug 9, 2026
c2a3810
ci: preserve bounded coverage RCA evidence
seonghobae Aug 9, 2026
f3dc01a
test: execute Podman desktop command boundary
seonghobae Aug 9, 2026
abb2399
test: require visible Rust coverage diagnostics
seonghobae Aug 9, 2026
5c57586
ci: surface exact Rust coverage diagnostics
seonghobae Aug 9, 2026
2242736
docs: explain exact coverage diagnostics
seonghobae Aug 9, 2026
8cbb057
chore: record coverage diagnostic observability
seonghobae Aug 9, 2026
a53f4e1
test: tolerate multiline coverage summary call
seonghobae Aug 9, 2026
7d69ffd
test: match escaped coverage summary source
seonghobae Aug 9, 2026
4435838
test: require actionable Rust coverage gap diagnostics
seonghobae Aug 9, 2026
24fe2d4
ci: surface exact Rust coverage gaps without weakening gate
seonghobae Aug 9, 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
164 changes: 164 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ jobs:
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: src-tauri
- name: Podman Rust formatting
run: >-
rustfmt --edition 2021 --check
src-tauri/src/podman_desktop.rs
src-tauri/tests/podman_desktop_documentation_contract.rs
src-tauri/tests/podman_desktop_issue_privacy.rs
- name: Rust tests (includes unix symlink test)
run: cargo test --manifest-path src-tauri/Cargo.toml
- name: Headless cloud planner tests
Expand All @@ -40,8 +46,166 @@ jobs:
node-version: 20.19.0
- run: npm ci
- run: npm test
- run: npm run coverage
- run: npm run check
- run: npm run build

coverage-evidence:
runs-on: ubuntu-latest
env:
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Install Tauri system deps
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30
with:
toolchain: nightly-2026-08-07
components: llvm-tools-preview
- uses: taiki-e/install-action@6c6fd71fe4fb72c3697d269963d0e15df8adedad
with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: src-tauri
- name: Measure exact-head Rust coverage
run: cargo llvm-cov --manifest-path src-tauri/Cargo.toml --branch --json --summary-only --output-path coverage.json --no-cfg-coverage --no-cfg-coverage-nightly
- name: Build exact-head coverage evidence
run: |
node --input-type=module <<'NODE'
import { appendFileSync, readFileSync, writeFileSync } from 'node:fs';

const sha = process.env.HEAD_SHA ?? '';
const repository = process.env.GITHUB_REPOSITORY ?? '';
if (!/^[0-9a-f]{40}$/.test(sha) || repository.length === 0) {
throw new Error('coverage evidence identity is invalid');
}

const report = JSON.parse(readFileSync('coverage.json', 'utf8'));
const coverageData = report?.data?.[0];
const totals = coverageData?.totals;
const safeGap = (value) => {
const count = value?.count;
const covered = value?.covered;
return Number.isSafeInteger(count) &&
Number.isSafeInteger(covered) &&
count >= covered &&
covered >= 0
? count - covered
: 0;
};
const repositoryPath = (filename) => {
const normalized = String(filename ?? '').replaceAll('\\', '/');
const marker = '/src-tauri/';
const markerIndex = normalized.lastIndexOf(marker);
if (markerIndex < 0) return null;
return `src-tauri/${normalized.slice(markerIndex + marker.length)}`;
};
const top_uncovered_files = (coverageData?.files ?? [])
.map((file) => {
const path = repositoryPath(file?.filename);
const summary = file?.summary;
if (!path) return null;
return {
path,
uncovered_regions: safeGap(summary?.regions),
uncovered_branches: safeGap(summary?.branches),
uncovered_functions: safeGap(summary?.functions),
uncovered_lines: safeGap(summary?.lines),
};
})
.filter((entry) => entry && (
entry.uncovered_regions > 0 ||
entry.uncovered_branches > 0 ||
entry.uncovered_functions > 0 ||
entry.uncovered_lines > 0
))
.sort((left, right) => {
const leftGap = left.uncovered_regions + left.uncovered_branches +
left.uncovered_functions + left.uncovered_lines;
const rightGap = right.uncovered_regions + right.uncovered_branches +
right.uncovered_functions + right.uncovered_lines;
return rightGap - leftGap || left.path.localeCompare(right.path);
})
.slice(0, 20);
const diagnostic = {
schema_version: 1,
head_sha: sha,
repository,
regions: totals?.regions ?? null,
branches: totals?.branches ?? null,
functions: totals?.functions ?? null,
lines: totals?.lines ?? null,
top_uncovered_files,
};
writeFileSync(
'coverage-diagnostic.json',
`${JSON.stringify(diagnostic, null, 2)}\n`,
);
console.error(`coverage-diagnostic=${JSON.stringify(diagnostic)}`);
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
if (summaryPath) {
appendFileSync(
summaryPath,
`### Coverage diagnostic for \`${sha}\`\n\n\`\`\`json\n${JSON.stringify(diagnostic, null, 2)}\n\`\`\`\n`,
);
}

const metric = (name, value) => {
if (
!value ||
!Number.isFinite(value.count) ||
!Number.isFinite(value.covered) ||
!Number.isFinite(value.percent) ||
value.count <= 0 ||
value.covered !== value.count ||
value.percent !== 100
) {
throw new Error(`${name} coverage is not exactly 100%`);
}
return value.percent;
};

const evidence = {
schema_version: 1,
head_sha: sha,
commit_sha: sha,
repository,
trust_tier: 'ci-verified',
ci_server: 'github-actions',
ci_workflow: 'Test',
coverage_command: 'cargo llvm-cov',
statement_coverage: metric('statement/region', totals?.regions),
branch_coverage: metric('branch', totals?.branches),
function_coverage: metric('function', totals?.functions),
line_coverage: metric('line', totals?.lines),
passed: true,
};

writeFileSync(
'coverage-evidence.json',
`${JSON.stringify(evidence, null, 2)}\n`,
);
NODE
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Upload bounded coverage diagnostic
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-diagnostic-${{ env.HEAD_SHA }}
path: coverage-diagnostic.json
if-no-files-found: error
- name: Upload coverage evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-evidence
path: coverage-evidence.json
if-no-files-found: error

llm-engine-build:
runs-on: ubuntu-latest
steps:
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and

## [Unreleased]

### Added

- Add a read-only Podman evidence panel to Cleanup that separately displays configured VM capacity, raw-image logical size, host allocation, guest filesystem observations, Podman store observations, image/stopped-container/volume logical candidates, evidence completeness, stable issue codes, and a redacted candidate-set fingerprint.
- Add a privacy-safe Tauri contract that removes machine names, local paths, graph-root locations, image identifiers, tags, command output, and dynamic error details before evidence reaches the desktop frontend.
- Add beginner-readable JSDoc for every Podman frontend contract function and a deterministic source-level regression test that fails when any production function loses its adjacent documentation.
- Add module-level Rust `missing_docs` enforcement and a deterministic source-level contract that requires beginner-readable rustdoc for every Podman desktop function, including private helpers and regression tests.

### Changed

- Require the `Test` workflow to produce exact-head, branch-aware, fail-closed Rust coverage evidence from real `cargo llvm-cov` measurements before organization-level review can treat 100% statement-equivalent region, branch, function, and line coverage as passing.
- Surface the same bounded exact-head Rust coverage totals in the failing job log and GitHub step summary before enforcing the 100% gate, while retaining the success-only coverage evidence artifact and privacy-safe diagnostic artifact boundary.
- Require a fresh, exact, human-attributed approval and rationale for cloud copy-only and existing-copy adoption actions, with a 15-minute authorization lifetime bound to the candidate, destination, provider, account scope, and review fingerprint.
- Return the candidate-specific cloud copy approval action, exact confirmation phrase, and maximum approval age from the Rust plan contract; the frontend only displays and submits that backend-authored phrase and fails closed when it is missing or does not match the candidate action.
- Align the frontend toolchain on Vite 8.2 and `@sveltejs/vite-plugin-svelte` 7.2 so the declared peer dependency graph is installable and reproducible.
- Declare the supported Node.js runtime floor as Node.js 20.19 or Node.js 22.12 and later, matching Vite 8 requirements.
- Pin the primary test workflow to Node.js 20.19.0 so the minimum supported runtime is continuously verified.
- Document the iCloud batch operation's local-only versus path-free shareable evidence boundary and map its fail-closed controls to NIST SP 800-53 Release 5.2.0, ISO/IEC 27040:2024, and primary secure-design literature with APA 7th references and deterministic documentation contract tests.
- Keep Podman image, stopped-container, and volume review boundaries independent and advisory; no candidate class grants authority to another class.

### Fixed

Expand All @@ -25,3 +35,6 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
- Persist copy-approval provenance in immutable receipt lineage, reject stale, generic, mismatched, or tampered approvals, and retain explicit backward readability for pre-approval receipt formats.
- Generate the npm lockfile in an exact-head validation job with repository contents read-only and dependency lifecycle scripts disabled, bind the artifact to SHA-256 evidence, and grant `contents: write` only to a separate publication job that verifies the same-run artifact and unchanged branch head before committing the lockfile.
- Removed obsolete one-shot repair workflows and patch scripts so repository automation no longer retains dormant write-capable recovery paths.
- Keep the Podman desktop surface observation-only: it exposes no prune, remove, machine stop/start, VM deletion, TRIM, raw-image mutation, or shell-string construction path, and it never labels Podman logical candidates as verified host physical reclaimability.
- Replace untrusted Tauri, operating-system, and JavaScript failure details with one stable Podman UI error code so account-local paths, machine names, socket locations, and command details cannot leak through the visible desktop evidence boundary.
- Accept Podman probe issue prefixes only as bounded lowercase kebab-case codes; delimiter-free paths, sockets, uppercase text, Unicode, whitespace, underscores, and malformed prefixes collapse to `podman-evidence-error` before desktop IPC serialization.
Loading
Loading