Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
221 commits
Select commit Hold shift + click to select a range
fcb1679
test: define cloud CLI help process contract
seonghobae Aug 13, 2026
34866eb
ci: run cloud CLI help process contracts
seonghobae Aug 13, 2026
ad25cac
test: gate cloud help contract by feature
seonghobae Aug 13, 2026
6c68832
fix: make iCloud sync health help successful
seonghobae Aug 13, 2026
44b60eb
fix: make provider OAuth help successful
seonghobae Aug 13, 2026
ab2c29b
test: require exact and bounded cloud CLI help
seonghobae Aug 14, 2026
2dc16bb
test: reject non-UTF8 cloud CLI arguments
seonghobae Aug 14, 2026
418d298
fix: bound iCloud sync health unknown arguments
seonghobae Aug 14, 2026
68e2122
fix: fail closed on non-UTF8 sync-health arguments
seonghobae Aug 14, 2026
4439d60
fix: fail closed on non-UTF8 provider OAuth arguments
seonghobae Aug 14, 2026
1a1ba65
test: reject non-UTF-8 argument reflection
seonghobae Aug 15, 2026
dd12e04
refactor: extract provider oauth platform entry
seonghobae Aug 20, 2026
550193e
test: require Windows OAuth USERPROFILE authority
seonghobae Aug 20, 2026
c3868f0
fix: use Windows USERPROFILE for provider OAuth
seonghobae Aug 20, 2026
2ff8b89
fix: isolate provider OAuth implementation from bin discovery
seonghobae Aug 20, 2026
779afa4
fix: keep provider oauth help contract executable
seonghobae Aug 24, 2026
81c44e4
test: exercise mixed cli errors after argument parsing
seonghobae Aug 24, 2026
75d728e
Merge branch 'main' into fix/cli-help-batch-health-oauth-v1
opencode-agent[bot] Aug 24, 2026
9b2b0d1
Merge remote-tracking branch 'origin/main' into pr-212
seonghobae Aug 29, 2026
4d0cc91
docs(cli): guide cloud health and connection actions
seonghobae Aug 29, 2026
5e2e54b
test: reject invalid negative paths-ignore filters
seonghobae Sep 3, 2026
47d16e0
fix(ci): use valid ordered path filters for contract docs
seonghobae Sep 3, 2026
439431a
test: reproduce paths-ignore parser blind spots
seonghobae Sep 3, 2026
80c8971
fix(test): inspect every paths-ignore list item
seonghobae Sep 3, 2026
bf8be64
merge: restack path-filter repair on release verifier
seonghobae Sep 3, 2026
5b005dd
merge: restack path-filter repair on release contract inheritance
seonghobae Sep 3, 2026
ab68124
test: require real Windows provider OAuth process evidence
seonghobae Sep 3, 2026
20a5fb3
test: exercise provider OAuth USERPROFILE boundary
seonghobae Sep 3, 2026
b85e160
ci: run provider OAuth process contract on Windows
seonghobae Sep 3, 2026
c3f7b62
merge(ci): retain current docs path filters
seonghobae Sep 3, 2026
92c6522
merge(stack): restack provider OAuth process owner on current main
seonghobae Sep 3, 2026
7dd152d
merge(stack): inherit canonical release verifier into provider OAuth …
seonghobae Sep 3, 2026
45dc68c
test(security): reject unknown OAuth authority fields
seonghobae Sep 3, 2026
84151bf
fix(security): reject unknown OAuth document fields
seonghobae Sep 3, 2026
1728e74
test(security): reject duplicate durable OAuth identities
seonghobae Sep 3, 2026
037a4fc
fix(security): reject duplicate durable OAuth identities
seonghobae Sep 3, 2026
9dcde2c
test(security): reject shared-writable OAuth parents
seonghobae Sep 3, 2026
ea66c2b
test(security): require private OAuth metadata files
seonghobae Sep 3, 2026
2e5de50
test(security): reject symlinked OAuth parent authority
seonghobae Sep 3, 2026
3dc8bc5
fix(security): bind OAuth metadata to private directory authority
seonghobae Sep 3, 2026
dd9b265
test(security): bound OAuth document publication
seonghobae Sep 3, 2026
9f5ce29
fix(security): bound OAuth document publication before filesystem mut…
seonghobae Sep 3, 2026
a56a3d9
test(security): preserve OAuth retry credential on stale disconnect f…
seonghobae Sep 3, 2026
5bc16fe
test(security): remove all matching OAuth identities on disconnect
seonghobae Sep 3, 2026
a7b1646
fix(security): disconnect every matching OAuth credential safely
seonghobae Sep 3, 2026
31a52f5
test(security): reject incomplete OAuth loopback framing
seonghobae Sep 3, 2026
456c80d
fix(security): require complete OAuth loopback HTTP framing
seonghobae Sep 3, 2026
6f223cb
test(oauth): inherit durable publication authority regressions
seonghobae Sep 3, 2026
b31bff4
test(oauth): inherit canonical legacy identity migration regressions
seonghobae Sep 3, 2026
a6ca57f
test(oauth): reject pre-delete Windows replacement
seonghobae Sep 3, 2026
765716e
fix(oauth): preserve Windows document until replace
seonghobae Sep 3, 2026
a7fdcd0
test(oauth): keep failed legacy cleanup retry-visible
seonghobae Sep 3, 2026
63cb5e2
fix(oauth): keep failed legacy cleanup retry-visible
seonghobae Sep 3, 2026
347ea5f
test(oauth): cover reauthorization cleanup recovery edges
seonghobae Sep 3, 2026
f690f83
test(oauth): reserve recovery slot for legacy migration
seonghobae Sep 3, 2026
0b15d64
fix(oauth): reserve retry-visible migration capacity
seonghobae Sep 3, 2026
624e26d
test(oauth): inherit ancestor authority regression
seonghobae Sep 3, 2026
bab02a2
test(oauth): inherit durable connection capacity boundary
seonghobae Sep 3, 2026
727c752
test(oauth): inherit persisted identity field matrix
seonghobae Sep 3, 2026
9b65717
test(oauth): inherit public document admission matrix
seonghobae Sep 3, 2026
f4cf233
test(oauth): inherit durable metadata validation edges
seonghobae Sep 3, 2026
13ce4d7
test(oauth): inherit permission IO edge evidence
seonghobae Sep 3, 2026
510d832
test(oauth): inherit token response admission coverage
seonghobae Sep 3, 2026
390e3cc
test(oauth): inherit authorization preparation boundary coverage
seonghobae Sep 3, 2026
87f2cce
test(oauth): inherit callback parser edge coverage
seonghobae Sep 3, 2026
f7be4d7
test(oauth): require case-sensitive OAuth scope tokens
seonghobae Sep 3, 2026
d564572
fix(oauth): compare granted scope tokens exactly
seonghobae Sep 3, 2026
aa167f4
test(oauth): require object-bound connection document reads
seonghobae Sep 4, 2026
5a0f364
chore(oauth): keep object-binding contract with domain owner
seonghobae Sep 4, 2026
5793cb6
test(oauth): require object-bound connection document reads
seonghobae Sep 4, 2026
c43b454
fix(oauth): bind connection reads to opened file object
seonghobae Sep 4, 2026
ef7a037
test(oauth-cli): inherit selected-root fail-closed process evidence
seonghobae Sep 4, 2026
b47f08f
test(oauth): reproduce nonblocking callback stream race
seonghobae Sep 4, 2026
f707e7e
fix(oauth): normalize callback streams before bounded reads
seonghobae Sep 4, 2026
e774044
test(oauth): inherit public fail-before-side-effect boundaries
seonghobae Sep 4, 2026
4fa21fe
test(oauth): reject malformed loopback Host authority
seonghobae Sep 4, 2026
891d538
fix(oauth): bind loopback callback Host authority
seonghobae Sep 4, 2026
d7cf6b7
test(oauth): adapt stream-mode fixture to Host-bound reader
seonghobae Sep 4, 2026
44847ad
test(oauth): preserve native CLI host boundaries
seonghobae Sep 4, 2026
b26348c
fix(oauth): isolate native CLI host admission
seonghobae Sep 4, 2026
58bc7e4
fix(oauth): route CLI through host adapter
seonghobae Sep 4, 2026
fb3fd00
test(oauth): bind host adapter home precedence
seonghobae Sep 4, 2026
9826839
test(oauth): execute host adapter contracts in default Rust suite
seonghobae Sep 4, 2026
45e328d
fix(oauth): harden native CLI host boundary
seonghobae Sep 4, 2026
3444f4b
fix(oauth): keep canonical CLI entrypoint direct
seonghobae Sep 4, 2026
01b22d2
test(oauth): exercise canonical CLI entrypoint in default suite
seonghobae Sep 4, 2026
66f346e
refactor(oauth): remove superseded host wrapper
seonghobae Sep 4, 2026
1eed543
test(oauth): inherit CLI connection-document process evidence
seonghobae Sep 4, 2026
2583e89
test(oauth): preserve native non-UTF8 path operands
seonghobae Sep 4, 2026
f67d8da
fix(oauth): preserve native filesystem path operands
seonghobae Sep 4, 2026
ba95612
test(oauth-cli): preserve native filesystem path operands
seonghobae Sep 4, 2026
45a7dbc
fix(oauth-cli): keep filesystem operands platform-native
seonghobae Sep 4, 2026
22f6af5
fix(oauth-cli): keep host adapter imports canonical
seonghobae Sep 4, 2026
3dfaf47
repair(oauth): return CLI host boundary to canonical owner
seonghobae Sep 4, 2026
d870361
test(oauth-cli): inherit durable list process evidence
seonghobae Sep 4, 2026
9380adb
test(oauth-cli): require XDG data-home authority
seonghobae Sep 4, 2026
b2a283e
fix(oauth-cli): honor XDG data-home authority
seonghobae Sep 4, 2026
04bc9b3
ci(oauth-cli): execute Linux XDG process contract
seonghobae Sep 4, 2026
7abeaab
test(oauth-cli): preserve explicit home over XDG default
seonghobae Sep 4, 2026
7f9b39a
fix(oauth-cli): keep explicit home above XDG default
seonghobae Sep 4, 2026
e63aec8
test(oauth-cli): require redirected Windows APPDATA authority
seonghobae Sep 4, 2026
edb7d7f
fix(oauth-cli): honor redirected Windows APPDATA
seonghobae Sep 4, 2026
be39f16
docs(oauth): record platform data-home authority
seonghobae Sep 4, 2026
17e6fad
docs(changelog): record OAuth platform data-home repair
seonghobae Sep 4, 2026
5a4cecb
chore(oauth): restack CLI on domain owner
seonghobae Sep 4, 2026
c347503
test: require XDG data-home listing without HOME
seonghobae Sep 4, 2026
8a424ca
fix(test): preserve XDG fixture variable
seonghobae Sep 4, 2026
7b13dd9
fix(test): restore XDG document serialization
seonghobae Sep 4, 2026
0faac1c
test: require APPDATA listing without USERPROFILE
seonghobae Sep 4, 2026
46f16dd
fix(test): restore provider OAuth connection hash fixture
seonghobae Sep 4, 2026
fab72c8
fix: allow data-home-only OAuth listing
seonghobae Sep 4, 2026
49db658
restack(oauth): adopt current release foundation
seonghobae Sep 4, 2026
9fbb2e1
restack(cli): adopt current provider OAuth owner
seonghobae Sep 4, 2026
9aa6cef
restack(oauth): adopt rerun-safe release foundation
seonghobae Sep 4, 2026
55a44d4
restack(cli): adopt rerun-safe release foundation
seonghobae Sep 4, 2026
210215c
restack(oauth): adopt release rerun RCA
seonghobae Sep 4, 2026
2132c6e
restack(cli): adopt release rerun RCA
seonghobae Sep 4, 2026
5e09c36
restack(oauth): adopt stable release identity naming
seonghobae Sep 4, 2026
3f12969
restack(cli): adopt stable release identity naming
seonghobae Sep 4, 2026
8633229
restack(ci): adopt current release foundation
seonghobae Sep 4, 2026
e0bf338
chore(stack): adopt bounded Vitest worker foundation
seonghobae Sep 4, 2026
bc39b5a
chore(stack): adopt bounded Vitest worker foundation
seonghobae Sep 4, 2026
6baf055
chore(stack): adopt bounded Vitest worker foundation
seonghobae Sep 4, 2026
7440ceb
chore(stack): restack path-filter repair on release owner
seonghobae Sep 4, 2026
61f6e59
chore(stack): restack provider OAuth on release foundation
seonghobae Sep 4, 2026
87c7fbf
chore(stack): restack CLI process boundary on OAuth owner
seonghobae Sep 4, 2026
9e236eb
chore(stack): adopt exact release test repair
seonghobae Sep 4, 2026
a72a4fa
chore(stack): adopt exact release contract repair
seonghobae Sep 4, 2026
0e9137b
chore(stack): restack CLI boundary on exact OAuth owner
seonghobae Sep 4, 2026
9ec8d17
test: require descriptor-bound OAuth publication
seonghobae Sep 4, 2026
24a03c5
chore(stack): inherit OAuth publication RED contract
seonghobae Sep 4, 2026
464f96b
chore: adopt current release foundation without force
seonghobae Sep 4, 2026
cfb8452
chore: restack provider OAuth CLI on current domain owner
seonghobae Sep 4, 2026
7523243
chore: restack path-filter owner on current release foundation
seonghobae Sep 4, 2026
5c8552b
chore: adopt object-bound publication foundation
seonghobae Sep 4, 2026
383de55
chore: restack provider OAuth CLI on publication foundation
seonghobae Sep 4, 2026
c05b5da
chore: adopt atomic publication foundation
seonghobae Sep 4, 2026
9dbf81a
chore: restack CLI on atomic publication foundation
seonghobae Sep 4, 2026
ac130fa
test(security): require OAuth publication owner consumption
seonghobae Sep 5, 2026
4ec4f8e
fix(security): bind OAuth publication to canonical object authority
seonghobae Sep 5, 2026
5298a44
chore: restack CLI on object-bound OAuth publication
seonghobae Sep 5, 2026
9cbb642
chore: adopt repaired provider publication owner
seonghobae Sep 5, 2026
c764c84
chore(stack): adopt private mode publication hardening
seonghobae Sep 5, 2026
5117277
chore(stack): inherit private mode publication hardening
seonghobae Sep 5, 2026
42c89e2
chore(stack): restack OAuth domain on current private publication owner
seonghobae Sep 5, 2026
7266560
chore(stack): restack CLI boundary on current OAuth owner
seonghobae Sep 5, 2026
eb255b9
chore(stack): restack path-filter owner on current release foundation
seonghobae Sep 5, 2026
ef4ff78
refactor(oauth): adopt private publication facade
seonghobae Sep 5, 2026
60caa4d
chore(oauth): restack on current private publication owner
seonghobae Sep 5, 2026
a4443f3
chore(stack): restack CLI boundary on current OAuth owner
seonghobae Sep 5, 2026
b973889
chore(oauth): preserve canonical publication module registration
seonghobae Sep 5, 2026
6afe249
chore(stack): adopt current OAuth publication registration
seonghobae Sep 5, 2026
67b816e
merge: adopt current private publication owner
seonghobae Sep 5, 2026
b7423fd
merge: adopt current OAuth and publication parent
seonghobae Sep 5, 2026
bf78121
merge: adopt post-write parent-mode repair
seonghobae Sep 5, 2026
1e99591
merge: adopt current OAuth/publication lineage
seonghobae Sep 5, 2026
28fe9cf
merge: adopt staging identity repair from #344
seonghobae Sep 5, 2026
b9d8dbf
merge: adopt current OAuth publication lineage
seonghobae Sep 5, 2026
bfb75d4
merge(security): adopt exact private-publication owner special-mode r…
seonghobae Sep 5, 2026
7f51536
merge(security): adopt current OAuth publication lineage
seonghobae Sep 5, 2026
f2e0d3b
test(oauth): make private harness compile against publication owner
seonghobae Sep 5, 2026
bb38c01
docs(oauth): preserve module rustdoc for include-safe source
seonghobae Sep 5, 2026
4ff7cb0
test(oauth): bind rollback harness to publication owner
seonghobae Sep 5, 2026
96f726a
test(oauth): bind callback harness to publication owner
seonghobae Sep 5, 2026
62c4a9c
test(oauth): bind write-bound harness to publication owner
seonghobae Sep 5, 2026
05f4eae
test(oauth): bind disconnect harness to publication owner
seonghobae Sep 5, 2026
27ddaa1
test(oauth): stop compiling production module in source-only Windows …
seonghobae Sep 5, 2026
8f3fa6a
test(oauth): bind loopback private harness to publication owner
seonghobae Sep 5, 2026
afe50a7
test(oauth): bind publication authority harness to owner module
seonghobae Sep 5, 2026
33c72b3
test(oauth): bind reauthorization harness to publication owner
seonghobae Sep 5, 2026
3859fc1
test(oauth): bind token parser harness to publication owner
seonghobae Sep 5, 2026
a252962
test(oauth): require fail-closed existing document updates
seonghobae Sep 5, 2026
60a1e68
fix(oauth): fail closed on existing document replacement
seonghobae Sep 5, 2026
071c674
test(oauth): align durable update coverage with fail-closed replacement
seonghobae Sep 5, 2026
adbe7b1
test(oauth): keep disconnect credentials intact when replacement is u…
seonghobae Sep 5, 2026
0863aaa
test(oauth): fail disconnect before stale credential mutation
seonghobae Sep 5, 2026
98fc25a
test(oauth): bound stale cleanup recovery when replacement is unavail…
seonghobae Sep 5, 2026
1b17e0b
merge(filesystem): adopt exact #344 publication owner
seonghobae Sep 5, 2026
0a38f9e
fix(oauth): consume create-new owner and refuse replacement
seonghobae Sep 5, 2026
ff21318
test(oauth): require exact private connection document mode
seonghobae Sep 5, 2026
b0c523a
fix(oauth): require exact private connection document mode
seonghobae Sep 5, 2026
7702d3c
merge: adopt current filesystem publication owner
seonghobae Sep 6, 2026
7ac4ccc
merge: adopt current filesystem publication owner
seonghobae Sep 6, 2026
fe20596
test(ci): require canonical Windows agent-state regression
seonghobae Sep 6, 2026
29aaf64
fix(ci): own Windows agent-state regression in Test workflow
seonghobae Sep 6, 2026
f339ee4
fix(ci): run source-present macOS cache owner regressions
seonghobae Sep 6, 2026
dad7832
test: quote workflow command fixture correctly
seonghobae Sep 6, 2026
f8ddd54
merge: adopt current filesystem publication owner
seonghobae Sep 6, 2026
1bfc279
test: require pre-existing private OAuth parent
seonghobae Sep 7, 2026
dafe817
test: require canonical OAuth publication owner
seonghobae Sep 7, 2026
eaf1bc8
refactor: use canonical OAuth publication owner
seonghobae Sep 7, 2026
871a527
test(provider-oauth): track canonical publication dependency
seonghobae Sep 7, 2026
54d0eb5
merge: adopt exact-head filesystem foundation
seonghobae Sep 7, 2026
9fb90cb
fix(oauth): preserve permission failure taxonomy
seonghobae Sep 8, 2026
6b83caf
fix(oauth): keep percent decoder allocation unchanged
seonghobae Sep 8, 2026
37046e6
test(oauth): align publication contract with create-new owner
seonghobae Sep 8, 2026
47a5ec0
test(oauth): use private roundtrip fixture
seonghobae Sep 8, 2026
59ab000
test(oauth): make reauthorization publication parent private
seonghobae Sep 8, 2026
102b1de
test(oauth): make disconnect publication parent private
seonghobae Sep 8, 2026
450772c
test(oauth): make rollback publication parent private
seonghobae Sep 8, 2026
f32eba1
test(security): make OAuth object-binding contract rustfmt-stable
seonghobae Sep 9, 2026
8b1edb0
merge(security): adopt exact OAuth owner head
seonghobae Sep 9, 2026
5b4e656
merge(ci): adopt current release/Test foundation
seonghobae Sep 9, 2026
13aa167
test(ci): require provider OAuth Windows process contract
seonghobae Sep 9, 2026
8b0e2b5
fix(ci): run provider OAuth process contract on Windows
seonghobae Sep 9, 2026
0e53be7
test(ci): require explicit agent-state skip evidence
seonghobae Sep 9, 2026
e17c2ad
fix(ci): make agent-state source absence explicit
seonghobae Sep 9, 2026
8a10edc
test(ci): make exact-head checkout contract lane-extensible
seonghobae Sep 9, 2026
02a95a6
chore: adopt current release foundation into Test owner
seonghobae Sep 9, 2026
c00e11e
Merge #358: adopt current filesystem owner into provider OAuth
seonghobae Sep 9, 2026
7f85e01
chore: adopt current provider OAuth owner into CLI
seonghobae Sep 9, 2026
0d3adf2
chore: adopt canonical Test owner into provider OAuth CLI
seonghobae Sep 9, 2026
e3d78cd
fix: keep iCloud recovery UID lookup macOS-only
seonghobae Sep 9, 2026
ca4003b
test(recovery): expose plan replacement race
seonghobae Sep 9, 2026
f6c1d9a
fix(ci): isolate Ubuntu dependency refresh
seonghobae Sep 9, 2026
f5a7402
test(ci): lock Ubuntu apt isolation contract
seonghobae Sep 9, 2026
3ff1f47
Merge shared Test owner into #212 integration
seonghobae Sep 9, 2026
6589e0f
Merge current shared Test owner into #212
seonghobae Sep 9, 2026
658e5af
Merge validated CLI/process owner into provider OAuth
seonghobae Sep 9, 2026
961e736
test(provider): reject malformed bearer credentials
seonghobae Sep 10, 2026
1e3f434
fix(provider): validate RFC 6750 bearer grammar
seonghobae Sep 10, 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
109 changes: 83 additions & 26 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,31 @@ name: Test
on:
push:
branches: [main]
paths-ignore:
- "docs/**"
- "*.md"
# Content-checked by contract tests (vitest + cargo test) — must still run CI.
- "!docs/doctoring/release-artifact-provenance.md"
- "!docs/doctoring/tauri-content-security-policy.md"
- "!docs/doctoring/model-artifact-integrity.md"
- "!docs/doctoring/model-load-handle-binding.md"
- "!docs/development/icloud-local-eviction-batch.md"
- "!docs/architecture/goals/cloud-offload-goal.json"
- "!CHANGELOG.md"
paths:
- "**"
- "!docs/**"
- "!*.md"
# GitHub supports re-inclusion only with ordered positive patterns under `paths`.
- "docs/doctoring/release-artifact-provenance.md"
- "docs/doctoring/tauri-content-security-policy.md"
- "docs/doctoring/model-artifact-integrity.md"
- "docs/doctoring/model-load-handle-binding.md"
- "docs/development/icloud-local-eviction-batch.md"
- "docs/architecture/goals/cloud-offload-goal.json"
- "CHANGELOG.md"
pull_request:
paths-ignore:
- "docs/**"
- "*.md"
# Content-checked by contract tests (vitest + cargo test) — must still run CI.
- "!docs/doctoring/release-artifact-provenance.md"
- "!docs/doctoring/tauri-content-security-policy.md"
- "!docs/doctoring/model-artifact-integrity.md"
- "!docs/doctoring/model-load-handle-binding.md"
- "!docs/development/icloud-local-eviction-batch.md"
- "!docs/architecture/goals/cloud-offload-goal.json"
- "!CHANGELOG.md"
paths:
- "**"
- "!docs/**"
- "!*.md"
# GitHub supports re-inclusion only with ordered positive patterns under `paths`.
- "docs/doctoring/release-artifact-provenance.md"
- "docs/doctoring/tauri-content-security-policy.md"
- "docs/doctoring/model-artifact-integrity.md"
- "docs/doctoring/model-load-handle-binding.md"
- "docs/development/icloud-local-eviction-batch.md"
- "docs/architecture/goals/cloud-offload-goal.json"
- "CHANGELOG.md"

permissions:
contents: read
Expand All @@ -49,7 +51,12 @@ jobs:
persist-credentials: false
- name: Install Tauri system deps
run: |
sudo apt-get update
for source_file in /etc/apt/sources.list.d/*; do
if [[ -f "$source_file" ]] && grep -q 'dl.google.com/linux/chrome' "$source_file"; then
sudo rm -f "$source_file"
fi
done
sudo apt-get -o Acquire::Retries=3 update
sudo apt-get install -y libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev lsof
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
Expand Down Expand Up @@ -80,9 +87,34 @@ jobs:
- run: npm test
- run: npm run build

macos-cache-cleanup:
runs-on: macos-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
with:
workspaces: src-tauri
cache-targets: false
- name: macOS cache cleanup regressions when owner source is present
env:
TMPDIR: ${{ runner.temp }}
run: |
for test_name in cache_cleanup_corepack_scope cache_cleanup_cli_permanent_gradle generated_cache_staged_activity; do
if [[ -f "src-tauri/tests/${test_name}.rs" ]]; then
cargo test --manifest-path src-tauri/Cargo.toml --test "$test_name"
else
printf 'SKIP %s: owner test source absent; no runtime regression executed\n' "$test_name"
fi
done

windows-home-resolution:
runs-on: windows-latest
timeout-minutes: 10
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -95,6 +127,26 @@ jobs:
New-Item -ItemType Directory -Force target | Out-Null
rustc --edition=2021 --test src-tauri/tests/home_resolution_contract.rs -o target/home-resolution-contract.exe
& .\target\home-resolution-contract.exe
- name: Windows agent-state regression when owner source is present
shell: pwsh
run: |
if (Test-Path 'src-tauri/src/agent_state_guard.rs') {
rustc --edition=2021 --test src-tauri/src/agent_state_guard.rs -o target/agent-state-guard.exe
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
& .\target\agent-state-guard.exe --nocapture
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
} else {
Write-Output 'SKIP agent_state_guard: owner source absent; no runtime regression executed'
}
- name: Windows provider OAuth process contract when owner source is present
shell: pwsh
run: |
if (Test-Path 'src-tauri/tests/provider_oauth_cli_process.rs') {
cargo test --manifest-path src-tauri/Cargo.toml --locked --features cloud-cli --test provider_oauth_cli_process
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
} else {
Write-Output 'SKIP provider_oauth_cli_process: owner source absent; no runtime regression executed'
}

llm-engine-build:
runs-on: ubuntu-latest
Expand All @@ -106,12 +158,17 @@ jobs:
persist-credentials: false
- name: Install build deps (llama.cpp native + tauri)
run: |
sudo apt-get update
for source_file in /etc/apt/sources.list.d/*; do
if [[ -f "$source_file" ]] && grep -q 'dl.google.com/linux/chrome' "$source_file"; then
sudo rm -f "$source_file"
fi
done
sudo apt-get -o Acquire::Retries=3 update
sudo apt-get install -y cmake clang libclang-dev libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2
with:
workspaces: src-tauri
cache-targets: false
- name: Build with llm-engine (compiles real llama.cpp CPU + engine.rs FFI)
run: cargo test --manifest-path src-tauri/Cargo.toml --features llm-engine --lib --no-run
run: cargo test --manifest-path src-tauri/Cargo.toml --features llm-engine --lib --no-run
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and

### Fixed

- Resolve the provider OAuth descriptor's platform data-home authority before entering the domain:
honor absolute Linux `$XDG_DATA_HOME` and redirected Windows `%APPDATA%`, ignore invalid relative
environment paths, keep explicit `--connections` and `--home` authoritative, and preserve native
non-UTF-8 filesystem operands while leaving macOS Application Support behavior unchanged.
- Use macOS `NSFileManager` for reversible Trash moves so cleanup does not wait on Finder
AppleEvents or inherit a stalled Finder copy queue.
- Permit fully current-user-owned real children of the shared Unix temporary root while retaining
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,22 @@ DiskSage displays this before consent. It does not silently fall back to a broad

`disksage-provider-oauth` exposes the same Rust PKCE and credential lifecycle outside the Tauri
webview so an operator can prepare a headless `disksage-cloud-plan` run without pasting a bearer or
refresh token. The default descriptor path is the DiskSage application-data path; an explicit
`--connections` value must be absolute and can be shared with `disksage-cloud-plan`.
refresh token. An explicit `--connections` value must be absolute and is the highest descriptor-path
authority. An explicit `--home` is next and derives the platform default from that supplied home;
this keeps hermetic operator/test roots independent of ambient environment data-home variables.
Without either explicit option, the shipped host entrypoint resolves the default descriptor path as
follows:

- Linux/non-macOS Unix: an absolute, non-empty `$XDG_DATA_HOME`, otherwise
`$HOME/.local/share/com.contextualwisdomlab.disksage/cloud-oauth-connections.json`. Relative XDG
values are invalid authority and are ignored.
- Windows: an absolute, non-empty `%APPDATA%` so redirected roaming AppData remains authoritative;
otherwise `%USERPROFILE%\AppData\Roaming\com.contextualwisdomlab.disksage\cloud-oauth-connections.json`.
- macOS: `$HOME/Library/Application Support/com.contextualwisdomlab.disksage/cloud-oauth-connections.json`.

The entrypoint resolves these process/platform values and passes one explicit path into the OAuth
domain. The domain does not read process-global environment state. `--list` remains read-only: a
missing descriptor returns an empty list and does not create the app-data directory or document.

```bash
cargo run --locked --features cloud-cli --bin disksage-provider-oauth -- --list
Expand Down Expand Up @@ -128,6 +142,8 @@ this design.

## Primary references

- [XDG Base Directory Specification 0.8](https://specifications.freedesktop.org/basedir/latest/)
- [Windows Folder Redirection with Group Policy](https://learn.microsoft.com/en-us/windows-server/storage/folder-redirection/folder-redirection-using-group-policy)
- [Microsoft identity platform authorization-code flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow)
- [Microsoft redirect URI restrictions and native loopback behavior](https://learn.microsoft.com/en-us/entra/identity-platform/reply-url)
- [Microsoft Graph permission reference](https://learn.microsoft.com/en-us/graph/permissions-reference)
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ path = "src/bin/disksage-container-orphan-plan.rs"

[[bin]]
name = "disksage-provider-oauth"
path = "src/bin/disksage-provider-oauth.rs"
path = "src/bin/disksage-provider-oauth-entry.rs"
required-features = ["cloud-cli"]

[[bin]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Headless OAuth lifecycle for OneDrive and Google Drive evidence and explicit API uploads.
//!
//! Refresh tokens remain in the operating-system credential store. This command emits only
//! non-secret connection descriptors and provider capacity evidence; this command itself never
//! performs a cloud file write or source eviction.
// Headless OAuth lifecycle for OneDrive and Google Drive evidence and explicit API uploads.
//
// Refresh tokens remain in the operating-system credential store. This command emits only
// non-secret connection descriptors and provider capacity evidence; this command itself never
// performs a cloud file write or source eviction.

#[cfg(not(coverage))]
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -94,7 +94,9 @@ fn usage() -> String {
"[--connections ABSOLUTE_PATH] ",
"(--list | --connect --cloud-root ABSOLUTE_PATH --client-id ID ",
"[--manual-browser] [--write-access] | --verify-capacity --cloud-root ABSOLUTE_PATH | ",
"--disconnect --cloud-root ABSOLUTE_PATH)"
"--disconnect --cloud-root ABSOLUTE_PATH)\n",
"다음 단계: 먼저 --list로 연결을 확인하세요. --connect는 동의 후 자격 증명을 로컬 보안 저장소에 보관하며, ",
"--write-access는 명시적으로 선택할 때만 요청됩니다. 출력에는 토큰이 포함되지 않습니다."
)
.into()
}
Expand Down Expand Up @@ -388,30 +390,6 @@ fn execute(args: Args) -> Result<Output, String> {
}
}

#[cfg(not(coverage))]
fn run() -> Result<(), String> {
let args = std::env::args().skip(1).collect::<Vec<_>>();
let parsed = parse_args(&args, std::env::var_os("HOME").map(PathBuf::from))?;
let output = execute(parsed)?;
println!(
"{}",
serde_json::to_string_pretty(&output)
.map_err(|_| "provider-oauth-output-serialization-failed".to_string())?
);
Ok(())
}

#[cfg(not(coverage))]
fn main() {
if let Err(error) = run() {
eprintln!("{error}");
std::process::exit(1);
}
}

#[cfg(coverage)]
fn main() {}

#[cfg(all(test, not(coverage)))]
mod tests {
use super::*;
Expand Down
77 changes: 75 additions & 2 deletions src-tauri/src/bin/disksage-icloud-provider-recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,39 @@ fn now_ms() -> Result<u64, String> {
u64::try_from(value).map_err(|_| "system-time-overflow".into())
}

fn read_plan(path: &Path) -> Result<IcloudFileProviderRecoveryPlan, String> {
#[cfg(target_os = "macos")]
fn current_user_uid() -> Result<u32, String> {
Ok(unsafe { libc::getuid() })
}

#[cfg(not(target_os = "macos"))]
fn current_user_uid() -> Result<u32, String> {
Err("icloud-recovery-platform-unsupported".into())
}

fn read_plan_with_hook<F>(
path: &Path,
before_read: F,
) -> Result<IcloudFileProviderRecoveryPlan, String>
where
F: FnOnce(),
{
let metadata = std::fs::symlink_metadata(path)
.map_err(|_| "icloud-recovery-plan-unavailable".to_string())?;
if !metadata.is_file() || metadata.file_type().is_symlink() || metadata.len() > 64 * 1024 {
return Err("icloud-recovery-plan-unsafe".into());
}
before_read();
serde_json::from_slice(
&std::fs::read(path).map_err(|_| "icloud-recovery-plan-read-failed".to_string())?,
)
.map_err(|_| "icloud-recovery-plan-json-invalid".into())
}

fn read_plan(path: &Path) -> Result<IcloudFileProviderRecoveryPlan, String> {
read_plan_with_hook(path, || {})
}

fn run() -> Result<(), String> {
let home = std::env::var_os("HOME")
.map(PathBuf::from)
Expand All @@ -104,7 +125,7 @@ fn run() -> Result<(), String> {
serde_json::to_value(plan_icloud_file_provider_recovery(
&health,
daemon,
unsafe { libc::getuid() },
current_user_uid()?,
now,
))
}
Expand Down Expand Up @@ -160,4 +181,56 @@ mod tests {
)
.is_ok());
}

#[cfg(unix)]
#[test]
fn execution_plan_read_rejects_path_replacement_after_admission() {
use disksage_lib::icloud_provider_recovery::IcloudFileProviderDaemonIdentity;

fn plan(observed_at_ms: u64) -> IcloudFileProviderRecoveryPlan {
IcloudFileProviderRecoveryPlan {
schema_version: 1,
observed_at_ms,
health_evidence_fingerprint_sha256: "a".repeat(64),
stale_error_count: 1,
oldest_stale_error_age_ms: 15 * 60 * 1_000,
daemon: IcloudFileProviderDaemonIdentity {
uid: 501,
pid: 1234,
service_label: "com.apple.FileProvider".into(),
executable_path: "/System/Library/Frameworks/FileProvider.framework/Support/fileproviderd".into(),
executable_object_id: "b".repeat(64),
apple_signature_valid: true,
},
blockers: Vec::new(),
eligible: true,
plan_fingerprint_sha256: "c".repeat(64),
exact_approval_phrase: "test approval".into(),
mutation_performed: false,
}
}

let temp = tempfile::tempdir().expect("tempdir");
let plan_path = temp.path().join("plan.json");
let replacement_path = temp.path().join("replacement.json");
let admitted_path = temp.path().join("admitted.json");
std::fs::write(
&plan_path,
serde_json::to_vec(&plan(1)).expect("serialize admitted plan"),
)
.expect("write admitted plan");
std::fs::write(
&replacement_path,
serde_json::to_vec(&plan(2)).expect("serialize replacement plan"),
)
.expect("write replacement plan");

let error = read_plan_with_hook(&plan_path, || {
std::fs::rename(&plan_path, &admitted_path).expect("move admitted object");
std::fs::rename(&replacement_path, &plan_path).expect("install replacement object");
})
.expect_err("path replacement must not switch execution-plan authority");

assert_eq!(error, "icloud-recovery-plan-object-changed");
}
}
Loading