soft-canonicalize 0.5.5

Path canonicalization that works with non-existing paths.
Documentation
# Junction Crate Analysis - Implementation Summary


## What We Learned


After analyzing the [`junction`](https://github.com/tesuji/junction) crate (v1.3.0), we identified several valuable patterns for improving our test infrastructure:

### Key Insights


1. **Junction points don't require admin privileges** on Windows (unlike symlinks)
2. **"Ask for forgiveness" pattern** for privilege escalation (only elevate when needed)
3. **Junction fallback strategy** enables better test coverage in restricted environments

## What We Implemented


### 1. New Test Helper: `create_symlink_or_junction()`


**File:** `tests/test_helpers/symlink_or_junction.rs`

**Strategy:**
```
Try symlink → (if permission denied) → Try junction → (if both fail) → Skip gracefully
```

**Benefits:**
- ✅ Tests run on non-admin Windows (junction fallback)
- ✅ Tests run on admin Windows (symlink preferred)
- ✅ Tests run on Unix (symlink always works)
- ✅ Better CI coverage without requiring elevated privileges

### 2. Windows-Only Test Dependency

**File:** `Cargo.toml`

Added:
```toml
[target.'cfg(windows)'.dev-dependencies]
junction = "1.3"
```

**Usage:**
```powershell
# Tests automatically use junction fallback on Windows when symlinks fail
cargo test
```

### 3. Documentation Updates


**Files:**
- `docs/junction_crate_analysis.md` - Comprehensive analysis document

**Key points documented:**
- Both symlinks and junctions are resolved transparently
- Junction points can be created without admin privileges
- Test helper available for better coverage

## Production Code Changes


**None.** Our canonicalization already handles junctions correctly through `std::fs` APIs.

The junction crate is only useful for **creating** junctions (test infrastructure), not for **resolving** them (production code).

## Usage Example


```rust
// In any test file (integration)
mod test_helpers;
use crate::test_helpers::symlink_or_junction::create_symlink_or_junction;

#[test]
fn test_symlink_behavior() -> io::Result<()> {
    let tmp = TempDir::new()?;
    let target = tmp.path().join("target");
    let link = tmp.path().join("link");

    fs::create_dir(&target)?;

    match create_symlink_or_junction(&target, &link)? {
        true => {
            let result = soft_canonicalize(&link)?;
            assert!(result.is_absolute());
        }
        false => {
            eprintln!("Skipping: symlink and junction creation not permitted");
            return Ok(());
        }
    }

    Ok(())
}
```

## Migration Path


### For New Tests

Use `create_symlink_or_junction()` instead of direct `symlink_dir()` calls.

### For Existing Tests

**Optional** - Migrate when actively failing or when improving test coverage is needed.

Current pattern (skip on permission error):
```rust
match symlink_dir(&target, &link) {
    Ok(_) => { /* test continues */ }
    Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
        eprintln!("Skipping test - no permission");
        return Ok(()); // Skip entire test
    }
    Err(e) => return Err(e),
}
```

New pattern (fallback to junction with explicit match):
```rust
match create_symlink_or_junction(&target, &link)? {
    true => { /* proceed */ }
    false => return Ok(()),
}
```

## CI Impact


**No changes needed** - junction fallback is automatic on Windows via the test helper.

**Benefits:**
- ✅ More tests run on Windows CI runners (no admin elevation needed)
- ✅ Catches more bugs in symlink/junction handling
- ✅ No impact on Unix CI (junction crate is Windows-only)

## Related Documentation


- **Detailed analysis:** `docs/junction_crate_analysis.md`
- **Security considerations:** `docs/SECURITY.md`
- **Test helper implementation:** `tests/test_helpers/symlink_or_junction.rs`

## Recommendations


### Immediate Actions

1. ✅ Documentation updated (README, analysis doc)
2. ✅ Test helper implemented
3. ✅ Dev-dependency added to Cargo.toml (Windows only)
4. ✅ No CI changes needed - automatic fallback

### Future Considerations

1. Gradually migrate existing tests to use the helper (low priority)
2. Monitor test coverage improvements in CI
3. Consider adding more junction-specific tests if valuable

## Conclusion


**Impact:** Better test coverage on Windows without requiring admin privileges.

**Risk:** Minimal - junction fallback is opt-in via feature flag, no production code changes.

**Recommendation:** Junction fallback is automatic—no feature flags or special CI configuration needed.