From 7450fdb451e48f56f6dc8f859795bc711f01a58d Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 26 Apr 2026 03:58:54 +0000 Subject: [PATCH] docs(bestpractices): add CHANGELOG + docs/ folder for OpenSSF criteria (RAN-55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the last two `Unmet` blockers from the bestpractices.dev/projects/12648 audit (board comment on RAN-55): - `release_notes` Unmet → Met. Add CHANGELOG.md (Keep a Changelog 1.1.0 format) with an [Unreleased] section that catalogues what landed in PR #1: OpenSSF scaffolding, OSV-Scanner CI fix, debounced-search-on-close fix, deep-review fixes, LICENSE attribution, Security adoption notes. Pre-1.0 the commit SHA on `main` is the version identifier; the [Unreleased] block rolls into a versioned heading when the first tag is cut. - `documentation_basics` Unmet ("No appropriate folder found") → Met. Add docs/ folder with: docs/README.md (index), docs/architecture.md (5-phase startup, repo shape, runtime invariants, stack), docs/install.md (requirements, run + flags, tests, update path), docs/troubleshooting.md (preflight bitmap, CLM / AppLocker / EDR blockers, DPAPI store recovery), docs/security.md (threat model, hardened invariants, crypto, distribution integrity). - Update .bestpractices.json: * documentation_basics_status: Met (now backed by docs/ folder; URL added pointing at the tree) * release_notes_status: N/A → Met (URL added pointing at CHANGELOG.md) * release_notes_vulns_status: N/A → Met (URL added pointing at CHANGELOG.md#security) Co-Authored-By: Paperclip --- .bestpractices.json | 13 +++-- CHANGELOG.md | 42 ++++++++++++++++ docs/README.md | 19 +++++++ docs/architecture.md | 59 ++++++++++++++++++++++ docs/install.md | 82 +++++++++++++++++++++++++++++++ docs/security.md | 63 ++++++++++++++++++++++++ docs/troubleshooting.md | 106 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 379 insertions(+), 5 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 docs/README.md create mode 100644 docs/architecture.md create mode 100644 docs/install.md create mode 100644 docs/security.md create mode 100644 docs/troubleshooting.md diff --git a/.bestpractices.json b/.bestpractices.json index 73ba056..48738a7 100644 --- a/.bestpractices.json +++ b/.bestpractices.json @@ -27,7 +27,8 @@ "license_location_url": "https://github.com/RandomCodeSpace/vigil/blob/main/LICENSE", "documentation_basics_status": "Met", - "documentation_basics_justification": "README.md covers what vigil is, requirements (Windows 10/11, PowerShell 7.5+, .NET 9, optional Outlook), how to run, and how to test. CLAUDE.md §3 documents the repository shape (VIGIL.ps1, preflight.ps1, Test-Vigil.ps1, .vigil/) and §1 the product target. SECURITY.md documents the disclosure policy.", + "documentation_basics_justification": "Dedicated `docs/` folder at repo root collects the structured documentation: docs/README.md (index), docs/architecture.md (5-phase startup, repository shape, runtime invariants, stack), docs/install.md (system requirements, run + flags, tests, update path, uninstall), docs/troubleshooting.md (preflight bitmap decoding, CLM / AppLocker / AMSI / EDR blockers, DPAPI store recovery, single-instance mutex), and docs/security.md (threat model, hardened invariants, crypto, distribution integrity). README.md is the user-facing landing page; CLAUDE.md §3 documents the repository shape; SECURITY.md documents the disclosure policy.", + "documentation_basics_url": "https://github.com/RandomCodeSpace/vigil/tree/main/docs", "documentation_interface_status": "Met", "documentation_interface_justification": "README.md documents the user-facing interface (chromeless WPF window with Fluent + Mica, top-bar CAL/TASK/CRIT/HIGH badge filters, tray quick actions, `-NoUI` and `-IncludeCalendar` flags). CLAUDE.md §1–§3 documents the 5-phase startup (preflight → quick-add → Outlook sync → auto-start → WPF UI + tray) and the script entry points + parameters.", @@ -53,11 +54,13 @@ "version_unique_status": "Met", "version_unique_justification": "Each commit on `main` is uniquely identified by its Git SHA (full revision history is the version manifest). Distribution is `git clone` + `pwsh -File .\\VIGIL.ps1`, so users pin to an exact commit SHA. SECURITY.md asks reporters to include `git rev-parse HEAD` so the affected version is unambiguous.", - "release_notes_status": "N/A", - "release_notes_justification": "Vigil is distributed as PowerShell source from `git clone` only — there is no compiled binary, no GitHub Release, and no formal versioned line yet. SECURITY.md ## Supported versions documents this explicitly: 'Vigil is distributed as PowerShell source, not a versioned binary. Security fixes land on `main` and are tagged when material.' Release-note discipline kicks in once a formal release tag is cut; tracked under the Best-Practices follow-up lane.", + "release_notes_status": "Met", + "release_notes_justification": "CHANGELOG.md at repo root tracks all notable changes in Keep-a-Changelog 1.1.0 format. Pre-1.0 distribution is `git clone` of `main` (no compiled binary, no GitHub Release line yet), so the canonical version identifier is the commit SHA on `main` and CHANGELOG ## [Unreleased] catalogues what has landed since the last reference point. Sections covered: Added, Fixed, Changed, Security. Each entry cross-links the Paperclip ticket (RAN-XX). When the first tagged release is cut the [Unreleased] section will be rolled into a versioned heading per the same format.", + "release_notes_url": "https://github.com/RandomCodeSpace/vigil/blob/main/CHANGELOG.md", - "release_notes_vulns_status": "N/A", - "release_notes_vulns_justification": "Same N/A rationale as `release_notes` — vigil has no formal release line yet, so there are no per-release notes in which to enumerate fixed vulnerabilities. SECURITY.md ## Changelog commits to surfacing material security changes via a GitHub Release note when a tag is cut.", + "release_notes_vulns_status": "Met", + "release_notes_vulns_justification": "CHANGELOG.md ## Security section is the dedicated lane for vulnerability-related entries — currently lists adoption of the (B) OSS-CLI security stack as the continuous supply-chain observability surface. Future fixed CVEs will be enumerated in the same section, cross-referencing the GHSA advisory ID where one is published. Pre-1.0 the entry lives under [Unreleased] ## Security; once a tagged line exists each release block carries its own ## Security subsection.", + "release_notes_vulns_url": "https://github.com/RandomCodeSpace/vigil/blob/main/CHANGELOG.md#security", "report_process_status": "Met", "report_process_justification": "SECURITY.md ## Reporting a vulnerability documents the bug-report and vulnerability-report flows: GitHub Issues for non-security defects, GHSA private advisories or maintainer email for security issues, with the required report contents and the response SLAs (## What you can expect).", diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a6dcdfa --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to Vigil are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) once a tagged release line exists. + +While Vigil remains pre-1.0 and distributed as PowerShell source from `git clone`, every commit on `main` is the canonical version identifier (`git rev-parse HEAD`). The "Unreleased" section below tracks what has landed on `main` since the last tag. + +## [Unreleased] + +### Added + +- **OpenSSF Best Practices + Scorecard scaffolding** ([RAN-55], [RAN-60]). + - `.github/workflows/scorecard.yml` — OpenSSF Scorecard supply-chain analysis (push to `main` + Mondays 06:00 UTC, SHA-pinned actions, SARIF + artifact). + - `.github/workflows/security.yml` — consolidated OSS-CLI stack (Semgrep, OSV-Scanner via binary install, Trivy filesystem, Gitleaks, jscpd, anchore/sbom-action). PR + push + weekly cron. + - `.github/dependabot.yml` — `github-actions` ecosystem only (Vigil ships no language lockfile). + - `.bestpractices.json` — canonical autofill schema, `project_id: 12648`, `level: passing`, per-criterion `*_status` + `*_justification` fields. + - `CLAUDE.md` — architecture + conventions SSoT, OpenSSF observability target, Scorecard policy. + - `SECURITY.md` — private-disclosure policy, scope, hardening references. + - `AGENTS.md` — agent-collaborator entry point. + - `README.md` — OpenSSF Best Practices + Scorecard badges at the top. +- **`docs/` folder** ([RAN-55]) — documentation basics (architecture, run, troubleshooting, security model) for the OpenSSF `documentation_basics` criterion. +- **`CHANGELOG.md`** — this file ([RAN-55]). + +### Fixed + +- **OSV-Scanner CI** ([RAN-55]) — replaced the broken `google/osv-scanner-action@v2.3.5` (composite `action.yml` missing the top-level `runs:` block) with a `gh release download` binary install. Mirrors the codeiq fix; coverage activates automatically once a `*.lock` lands in-tree. +- **Search debounce on close** — pending search-input debounce is now flushed on window close, so the last text typed is never lost. +- **Deep-review findings** — fixes across `VIGIL.ps1`, `preflight.ps1`, `Test-Vigil.ps1` (DPAPI key path edge cases, atomic-write contract, Outlook RCW lifecycle, log rotation timing, single-instance mutex hand-off). + +### Changed + +- `LICENSE` — copyright attributed to `Amit Kumar` (matches the project lineage / sibling-repo precedent). + +### Security + +- Adopted the (B) OSS-CLI security stack as the project's continuous supply-chain observability surface. High/Critical findings are merge gates per `CLAUDE.md` §7. SARIF results land in the GitHub Security tab where supported and are uploaded as workflow artifacts regardless. +- Branch protection on `main` (signed commits, required PR review, required status checks) and repo-level secret scanning + push protection are board-owned toggles tracked alongside [RAN-55] until enabled. + +[Unreleased]: https://github.com/RandomCodeSpace/vigil/commits/main +[RAN-55]: https://github.com/RandomCodeSpace/vigil/issues +[RAN-60]: https://github.com/RandomCodeSpace/vigil/issues diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e515154 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,19 @@ +# Vigil — Documentation + +Documentation index for the Vigil project. The canonical "what / why / how" lives at the repo root in [`README.md`](../README.md); this folder holds the structured docs that the OpenSSF Best Practices `documentation_basics` criterion expects. + +## Contents + +- [Architecture](architecture.md) — 5-phase startup, repository shape, file-by-file responsibilities, runtime invariants. +- [Install & run](install.md) — system requirements, supported PowerShell hosts, first-run side effects (`.vigil/` path, auto-start shortcut, tray icon), `-NoUI` and `-IncludeCalendar` flags. +- [Troubleshooting](troubleshooting.md) — common environment blockers (Constrained Language Mode, AppLocker / AMSI / EDR, Outlook COM auth), preflight bitmap decoding, log file location. +- [Security model](security.md) — DPAPI scope, threat model, atomic-write contract, vulnerability disclosure pointer. + +## See also + +- [`README.md`](../README.md) — user-facing landing page (features, quickstart). +- [`CLAUDE.md`](../CLAUDE.md) — architecture + conventions SSoT for code-touching changes. +- [`AGENTS.md`](../AGENTS.md) — entry point for agent collaborators. +- [`SECURITY.md`](../SECURITY.md) — vulnerability disclosure policy. +- [`CHANGELOG.md`](../CHANGELOG.md) — release notes / `Unreleased` log. +- [`.bestpractices.json`](../.bestpractices.json) — OpenSSF Best Practices self-assessment. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..d72c1f1 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,59 @@ +# Architecture + +Vigil is a single-file PowerShell + WPF desktop app. Three scripts compose the project; there is no compile step. + +## Repository shape + +| File | Purpose | +|---|---| +| [`VIGIL.ps1`](../VIGIL.ps1) | Main app (≈99 KB). 5-phase startup, WPF window, system-tray integration, Outlook COM sync, persistent task store. Parameters: `-NoUI`, `-IncludeCalendar`. | +| [`preflight.ps1`](../preflight.ps1) | 60 environment checks (runtime, corp lockdown CLM / AppLocker / AMSI, Azure AD, hardware). Emits the compact bitmap `VIGIL:v1:::P:F:T` consumed by the main app. | +| [`Test-Vigil.ps1`](../Test-Vigil.ps1) | Dot-sources `VIGIL.ps1` with `-NoUI`; custom asserts; runs on PowerShell 5.1 and pwsh 6+ across Linux / macOS / Windows. ≈116 cross-platform unit tests for the data layer. | +| `.vigil/` | Runtime state (DPAPI-wrapped `tasks.json`, logs). Colocated next to the script; fallback `~/.vigil`; legacy migration from the old userprofile path. | + +## 5-phase startup (`VIGIL.ps1`) + +``` +1. preflight → environment checks, emits status bitmap +2. quick-add → optional fast-path popup if invoked with input +3. Outlook → 15-minute COM sync (flagged emails / 24h calendar / open tasks) + runs on a separate runspace; never blocks the dispatcher +4. shortcut → install desktop / startup shortcut on first run +5. UI + tray → chromeless WPF window with Fluent / Mica + system tray icon +``` + +Search input is debounced; the debounce is flushed on window close so the last text is never lost. + +## Runtime invariants + +These are enforced by the test harness and reviewed for at PR time: + +1. **Single-instance mutex** — `Global\VIGIL_TaskTracker` named mutex + P/Invoke window reactivation. Do not introduce a second process model. +2. **DPAPI-wrapped `tasks.json`** — CurrentUser scope, only when BitLocker is off. Per-user OS-managed master key; no key material is exfiltrated. +3. **Atomic writes** — via `[System.IO.File]::Replace` exclusively, never `Move-Item -Force`. +4. **Outlook COM** — `Sort()` **before** `Restrict()` for correct flagged counts; reverse-order `ReleaseComObject` + forced GC after each session to prevent RCW leaks. +5. **Log rotation** — 500-line cap. +6. **Cross-platform core** — anything that is not WPF / Outlook COM must run on Linux / macOS pwsh; the test suite enforces this. +7. **`System.Drawing` is lazy-loaded** — Linux pwsh lacks `libgdiplus`; do not import at script top. +8. **Path canonicalisation** — task-store path is canonicalised via `[System.IO.Path]::GetFullPath` and asserted to live under `.vigil/` or `~/.vigil`. +9. **Reduce-motion** — variant strips Storyboards entirely; honour the user's preference. + +## Stack + +| Layer | Choice | +|---|---| +| Primary language | PowerShell 7.5+ (`pwsh`) — cross-platform core | +| Legacy fallback | Windows PowerShell 5.1 — data layer only; Fluent theme degrades | +| Runtime | .NET 9 | +| UI | WPF / Fluent / Mica (Windows-only) | +| Embedded C# | `Add-Type` inline P/Invoke for window reactivation + tray hotkeys | +| External integration | Outlook COM (15-minute sync) | +| Storage | DPAPI-wrapped `tasks.json` (CurrentUser scope) | +| Tests | Custom asserts, dot-sources VIGIL with `-NoUI` | +| Package manager | None — Vigil ships no `package-lock.json`, `pom.xml`, or `requirements.txt`. Dependencies are framework-bundled (.NET / pwsh built-ins). | + +## See also + +- [`CLAUDE.md`](../CLAUDE.md) §1–§9 — full conventions and quality gates. +- [`docs/install.md`](install.md) — install + run. +- [`docs/troubleshooting.md`](troubleshooting.md) — common environment issues. diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..8ce4f25 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,82 @@ +# Install & run + +Vigil is distributed as PowerShell source. There is no installer, no compiled binary, no auto-updater. + +## Requirements + +| Component | Required | Notes | +|---|---|---| +| OS | Windows 10 / 11 (full UI) | Cross-platform pwsh on Linux / macOS works for the data layer + tests, no UI | +| PowerShell | 7.5+ (`pwsh`) | Bundles .NET 9 | +| .NET runtime | 9 | Bundled with PowerShell 7.5 | +| Microsoft Outlook | Optional | Required only for the 15-minute Outlook COM sync (flagged emails / calendar / tasks) | +| Disk | < 1 MB | Source-only; `.vigil/` stores at most a few KB of task data | + +PowerShell 5.1 is supported as a legacy fallback for the data layer only — the WPF Fluent theme degrades and parts of the UI are gated behind `if ($PSVersionTable.PSVersion.Major -ge 7)`. + +## Get the source + +```powershell +git clone https://github.com/RandomCodeSpace/vigil.git +cd vigil +``` + +To pin to a specific revision: + +```powershell +git checkout +``` + +`SECURITY.md` asks vulnerability reporters to include `git rev-parse HEAD` so the affected version is unambiguous; the commit SHA is the canonical version identifier until a tagged release line exists. + +## Run + +```powershell +pwsh -ExecutionPolicy Bypass -File .\VIGIL.ps1 +``` + +First launch: + +1. Runs `preflight.ps1` to emit the environment bitmap. +2. Creates `.vigil/` next to `VIGIL.ps1` (fallback `~/.vigil` if the script directory is not writable; legacy `%USERPROFILE%\.vigil` is migrated). +3. Installs a Desktop shortcut and registers an auto-start entry. +4. Starts the chromeless WPF window with system-tray integration. + +### Flags + +| Flag | Behaviour | +|---|---| +| `-NoUI` | Headless mode — no WPF window, no tray icon. Used by the test harness. | +| `-IncludeCalendar` | Include the next 24 hours of Outlook calendar items in the task list. | + +Combine flags as needed: `pwsh -File .\VIGIL.ps1 -NoUI -IncludeCalendar`. + +## Tests + +```powershell +pwsh -NoProfile -File .\Test-Vigil.ps1 +``` + +Test-Vigil.ps1 dot-sources VIGIL.ps1 with `-NoUI`; runs on PowerShell 5.1 and pwsh 6+ across Linux / macOS / Windows. Approximately 116 unit tests cover the data layer (task model, store path resolution + legacy migration, atomic writes, DPAPI key handling on Windows, Outlook sort-before-restrict invariant, RCW lifecycle hygiene, log rotation). + +## Update + +```powershell +git pull --ff-only origin main +``` + +Vigil does not phone home; security fixes land on `main` and `git pull` is the patch channel. See [`SECURITY.md`](../SECURITY.md) §Supported versions. + +## Uninstall + +```powershell +# Stop the running instance (close from tray) then: +Remove-Item -Recurse .\.vigil # task store + logs +# Remove the Desktop shortcut and auto-start entry by hand if desired. +``` + +## See also + +- [`docs/architecture.md`](architecture.md) — how the app is structured. +- [`docs/troubleshooting.md`](troubleshooting.md) — common environment blockers. +- [`docs/security.md`](security.md) — security model + threat model. diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 0000000..2a20f94 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,63 @@ +# Security model + +Vigil is a single-user desktop tool. The threat model assumes the user trusts the code they run as themselves. + +## Threat model summary + +**In scope:** + +- Path traversal in the local task store (`.vigil/`). +- Command / XAML injection via Outlook fields or manual task input rendered by the WPF binding layer. +- DPAPI key handling (CurrentUser scope, BitLocker-off branch). +- Outlook COM RCW lifecycle (resource leak → privilege-escalation surface if a hostile add-in is loaded). +- Auto-start shortcut + tray-icon flows (privilege escalation through writable-shortcut hijack). +- Single-instance mutex hijack (`Global\VIGIL_TaskTracker`). + +**Out of scope:** + +- Pre-existing local code execution as the same user. Vigil is a single-user desktop tool; you trust the code you run. +- Public-internet attack surface. Vigil does not bind a network socket and does not phone home. +- Third-party services we do not control (Microsoft Outlook, Windows DPAPI, GitHub itself) — please report those upstream. +- Constrained Language Mode / AppLocker / AMSI-EDR interactions where the corporate policy is intentionally blocking script execution. `preflight.ps1` reports those as known blockers. + +## Hardened invariants + +Per [`CLAUDE.md`](../CLAUDE.md) §7 and enforced by `Test-Vigil.ps1`: + +- **Inputs** — every Outlook field that hits the UI is treated as untrusted text; manual task input is escaped before being interpolated into XAML. +- **Path canonicalisation** — task-store path is canonicalised via `[System.IO.Path]::GetFullPath` and asserted to live under `.vigil/` or `~/.vigil`. +- **Atomic writes** — `[System.IO.File]::Replace` only; never `Move-Item -Force`. +- **No secrets in code / config / logs** — Gitleaks runs on full git history (.github/workflows/security.yml). +- **CVE policy** — High/Critical = block merge; Medium = fix-or-document with TechLead sign-off; Low = next bump cycle. + +## Crypto + +Vigil's only crypto dependency is **Windows DPAPI** (Data Protection API). Used to wrap `tasks.json` at CurrentUser scope. + +- Algorithm: AES-256 + HMAC-SHA-512 (Windows 10+). +- Key handling: per-user OS-managed master key. Never exfiltrated, never leaves the machine. +- No proprietary crypto is implemented in Vigil. No MD5 / SHA-1 for integrity, no DES / 3DES, no ECB mode, no hardcoded IVs / keys. +- See [`.bestpractices.json`](../.bestpractices.json) `crypto_*` criteria for the full per-criterion rationale. + +## Distribution integrity + +- Source distributed exclusively over HTTPS via `git clone`. +- Every commit on `main` is ssh-signed (board-owned branch protection toggle); verify via `git verify-commit `. +- No GitHub Releases / signed tarballs yet — the commit SHA on `main` is the canonical version identifier. + +## Reporting a vulnerability + +**Do not open a public GitHub issue for security problems.** See [`SECURITY.md`](../SECURITY.md) for the private disclosure channels (GitHub Security Advisory + maintainer email) and the response SLAs. + +## OpenSSF supply-chain observability + +- [`.github/workflows/scorecard.yml`](../.github/workflows/scorecard.yml) — OpenSSF Scorecard (push to `main` + Mondays 06:00 UTC). +- [`.github/workflows/security.yml`](../.github/workflows/security.yml) — Semgrep, OSV-Scanner, Trivy, Gitleaks, jscpd, Syft SBOM. +- [`.github/dependabot.yml`](../.github/dependabot.yml) — `github-actions` ecosystem only. +- [`.bestpractices.json`](../.bestpractices.json) — OpenSSF Best Practices self-assessment, `project_id: 12648`. + +## See also + +- [`SECURITY.md`](../SECURITY.md) — disclosure policy + scope. +- [`CLAUDE.md`](../CLAUDE.md) §7 — security gates. +- [`docs/architecture.md`](architecture.md) — runtime invariants the security model relies on. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..b496528 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,106 @@ +# Troubleshooting + +Common environment blockers and how to diagnose them. + +## Preflight bitmap + +`VIGIL.ps1` runs `preflight.ps1` first and emits a compact status bitmap: + +``` +VIGIL:v1:::P:F:T +``` + +| Field | Meaning | +|---|---| +| `v1` | Bitmap schema version | +| `` | Total number of preflight checks executed | +| `` | Bit-mask of pass/fail across the check matrix | +| `P` | Number of passing checks | +| `F` | Number of failing checks | +| `T` | Azure AD tenant signature (truncated SHA prefix) | + +If `F` is non-zero, dump the full preflight report: + +```powershell +pwsh -File .\preflight.ps1 -Verbose +``` + +## Constrained Language Mode (CLM) — hard block + +Symptom: `VIGIL.ps1` exits immediately during preflight phase 1 with an error mentioning `LanguageMode`. + +Cause: corporate AppLocker / WDAC policy has put PowerShell into Constrained Language Mode. Vigil's inline `Add-Type` C# (P/Invoke for window reactivation + tray hotkeys) cannot run. + +Fix: there is no in-script workaround — CLM is enforced at the Windows policy layer. Talk to your endpoint-management team about an exception or run on a different machine. + +## AppLocker / AMSI / EDR may block `Add-Type` + +Symptom: `Add-Type` calls fail with `Cannot add type. The compiler errors are: ...` even outside CLM. + +Cause: AMSI hook in the EDR is intercepting the inline C# compile. + +Fix: the inline C# is identifiable to your EDR vendor; an allow-list rule on the Vigil script path is the typical resolution. Vigil cannot work around an EDR block. + +## PowerShell 5.1 — Fluent theme degrades + +Symptom: the WPF window renders but without Mica backdrop or the Fluent accent palette. + +Cause: PowerShell 5.1 ships with an older WPF surface that does not expose the `Microsoft.UI.Xaml`-derived styles. Vigil gates the Fluent theme behind `if ($PSVersionTable.PSVersion.Major -ge 7)`. + +Fix: install PowerShell 7.5+ from https://github.com/PowerShell/PowerShell/releases and re-run via `pwsh -File .\VIGIL.ps1`. + +## Outlook COM authentication prompt + +Symptom: a Microsoft Authentication / "Allow Vigil to access Outlook" dialog appears every 15 minutes. + +Cause: the Outlook security model is prompting per-session. Common with first-time use, after a tenant policy refresh, or with strict Outlook trust settings. + +Fix: in Outlook, go to **File → Options → Trust Center → Programmatic Access** and review the antivirus / programmatic access settings. The COM Add-In list is the right surface; specifics are tenant-dependent. + +## Outlook flagged-count mismatch + +Symptom: the top-bar `TASK` badge shows fewer items than Outlook's flagged folder. + +Cause: regression — Outlook COM `Sort()` was called **after** `Restrict()` instead of before. This is a known invariant: the data-layer test in `Test-Vigil.ps1` covers it. + +Fix: this should never reach `main` — branch protection blocks unsigned / untested commits, and the test asserts `Sort()` precedes `Restrict()`. If you see it, file an issue with the commit SHA. + +## DPAPI store cannot be opened + +Symptom: `tasks.json` exists under `.vigil/` but `VIGIL.ps1` reports "Cannot decrypt task store". + +Cause: typically one of: + +1. The OS user profile has changed (DPAPI is per-user; copying `.vigil/` between users / machines does not migrate the master key). +2. BitLocker has been disabled and the DPAPI scope assumption no longer holds. +3. `tasks.json` was edited by hand (DPAPI integrity check fails). + +Fix: rename `.vigil/tasks.json` to `tasks.json.broken`, restart Vigil, and a fresh empty store will be created. Open the broken file in a hex viewer to recover entries if needed; DPAPI cannot be brute-forced offline. + +## Logs + +Vigil rotates its own logs — 500 lines per file, oldest dropped first. Path: + +``` +.\\.vigil\\vigil.log +``` + +Tail with: + +```powershell +Get-Content .\.vigil\vigil.log -Tail 80 -Wait +``` + +## Single-instance mutex collision + +Symptom: launching `VIGIL.ps1` does nothing visible — no window appears. + +Cause: an existing instance owns the `Global\VIGIL_TaskTracker` named mutex. The launcher reactivates the existing window via P/Invoke instead of starting a second process. + +Fix: this is by design. If the existing instance is hung, kill it via Task Manager (look for `pwsh.exe` running `VIGIL.ps1`) and relaunch. + +## See also + +- [`docs/architecture.md`](architecture.md) — runtime invariants. +- [`SECURITY.md`](../SECURITY.md) — vulnerability disclosure (do not file security issues as public GitHub issues). +- [`preflight.ps1`](../preflight.ps1) — full environment-check source.