The migration path must prefer the current legacy JSON source over older per-account vault leftovers, clean those leftovers after a valid manifest is available, and avoid write operations overwriting a damaged or unreadable vault payload with fallback defaults.
Constraint: credentials.json is migration-only, but it was the previous Tauri source of truth.\nRejected: Use read fallback for mutating updates | can overwrite unreadable vault data with defaults.\nConfidence: high\nScope-risk: narrow\nDirective: Mutating credential operations must propagate chunked vault read errors instead of saving fallback roots.\nTested: cargo check --manifest-path src-tauri/Cargo.toml\nTested: cargo test --manifest-path src-tauri/Cargo.toml credential_payload_chunks_stay_under_windows_blob_limit\nTested: npm run -s build\nTested: git diff --check\nNot-tested: Manual migration with simultaneous JSON and stale per-account vault entries.\nRelated: #230
Credential vault saves now write a fresh generation of chunks before switching the manifest, so failed chunk writes or crashes do not overwrite chunks still referenced by the previous manifest. The same change also migrates documented per-account vault entries into the chunked manifest before falling back to legacy JSON.
Constraint: Windows Credential Manager requires chunking, and legacy credentials may exist either as plaintext JSON or documented per-account vault entries.
Rejected: Overwrite stable chunk names before manifest update | can mix old and new payloads after partial writes.
Confidence: high
Scope-risk: narrow
Directive: Treat the manifest as the commit pointer; write new-generation chunks before updating it and delete old chunks only after manifest write succeeds.
Tested: cargo check --manifest-path src-tauri/Cargo.toml
Tested: cargo test --manifest-path src-tauri/Cargo.toml credential_payload_chunks_stay_under_windows_blob_limit
Tested: npm run -s build
Tested: git diff --check
Not-tested: Manual crash injection during OS vault writes.
Related: #230
Users upgrading from the plaintext credentials file should not lose access to existing settings just because the OS vault backend is temporarily unavailable or migration cannot be written. Keep the old file migration-only, but return its contents as the compatibility source when vault reads or writes fail.
Constraint: credentials.json remains a legacy compatibility source only, not the normal write target.
Rejected: Return defaults on vault read/write errors | hides existing upgrade data and makes configured providers appear empty.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce plaintext writes; fallback reads are only for pre-PR legacy migration compatibility.
Tested: cargo check --manifest-path src-tauri/Cargo.toml
Tested: cargo test --manifest-path src-tauri/Cargo.toml credential_payload_chunks_stay_under_windows_blob_limit
Tested: npm run -s build
Tested: git diff --check
Not-tested: Manual vault-unavailable upgrade run on Windows/macOS/Linux.
Related: #230
The OS vault migration keeps provider state as one logical JSON payload, but Windows Credential Manager limits each credential blob. Store the logical payload as a manifest plus bounded chunks so long API keys, multiple providers, or extra headers do not make future saves fail on Windows.
Constraint: Windows Credential Manager generic credential blob is capped and keyring stores passwords as UTF-16 on Windows.
Rejected: Split each provider field into independent vault entries | broader schema rewrite and more migration surface than needed for this review fix.
Confidence: high
Scope-risk: narrow
Directive: Keep the legacy plaintext credentials.json path migration-only; do not add compatibility for transient PR-internal vault formats unless the release shipped them.
Tested: cargo check --manifest-path src-tauri/Cargo.toml
Tested: cargo test --manifest-path src-tauri/Cargo.toml credential_payload_chunks_stay_under_windows_blob_limit
Tested: npm run -s build
Tested: git diff --check
Not-tested: Live Windows Credential Manager write with oversized real provider payload.
Related: #230
Provider credentials should follow the platform credential-store threat model instead of continuing normal plaintext JSON writes. The vault now stores the existing multi-provider credentials payload in the OS credential store, migrates the legacy JSON file only when the vault has no entry, removes the legacy file after a successful write, and keeps raw credential IPC restricted to the main settings window.
Constraint: User explicitly chose Keychain/Credential Manager/Linux keyring for issue #230.
Constraint: Preserve the existing provider schema and active-provider routing with minimal frontend churn.
Rejected: Keep plaintext JSON as the documented product choice | user rejected this direction.
Rejected: Split every credential field into separate vault entries | larger migration surface and risks losing active provider state.
Confidence: medium
Scope-risk: moderate
Directive: Security-model and storage-strategy choices must be confirmed with the user before implementation.
Tested: cargo check --manifest-path src-tauri/Cargo.toml; npm run -s build; git diff --check; grep for stale plaintext/Keychain fallback wording.
Not-tested: Manual migration on macOS Keychain, Windows Credential Manager, or Linux desktop keyring.
Related: https://github.com/appergb/openless/issues/230
The workflow must keep reviewing every PR and every pushed commit automatically, including fork PRs, so the hardening focuses on pinning the code that actually runs in the secrets-bearing job. The wrapper action commit still delegates to a mutable Docker tag, so the workflow now calls the PR-Agent container by immutable digest directly.
Constraint: Maintainer preference is automatic PR-Agent coverage for each PR and synchronize event.
Constraint: Issue #222 requires removing mutable third-party execution refs from the secrets-bearing path.
Rejected: Pin only the action repository commit | the wrapper Dockerfile still resolves pragent/pr-agent:github_action at runtime.
Rejected: Require trusted comment triggers for fork PRs | too inconvenient because new commits would not be reviewed automatically.
Confidence: medium
Scope-risk: moderate
Directive: If fork PR automation remains required, keep the runtime container digest-pinned and do not checkout PR head code in this workflow.
Tested: Parsed .github/workflows/pr-agent.yml with PyYAML and asserted docker:// sha256 form; git diff --check; grep confirmed no action ref or github_action tag remains in the workflow.
Not-tested: Live GitHub Actions execution or Docker Hub digest pull from this host.
Related: https://github.com/appergb/openless/issues/222