diff --git a/.bestpractices.json b/.bestpractices.json index 2d5bc1b..4dd7fe5 100644 --- a/.bestpractices.json +++ b/.bestpractices.json @@ -16,12 +16,12 @@ "interact_justification": "README.md provides Install (clone + dot-source), Usage (CLI invocation + hotkeys), and Tests sections covering download, use, and contribution paths. Issue tracker at https://github.com/RandomCodeSpace/snipIT/issues is linked from the GitHub repo header.", "contribution_status": "Met", - "contribution_justification": "shared/runbooks/engineering-standards.md is the contribution-process document — it codifies branch/commit/PR rules (§3), testing tiers (§4), code style (§2), and quality gates (§1) that contributors must satisfy. SECURITY.md covers the vulnerability-report contribution path. README.md links to engineering-standards from §Engineering standards.", - "contribution_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/shared/runbooks/engineering-standards.md", + "contribution_justification": "CONTRIBUTING.md at repo root is the contribution-process entry point: reporting (GitHub Issues for bugs, SECURITY.md for vulnerabilities), development workflow (fork → topic branch → Conventional Commits → signed commits via scripts/setup-git-signed.sh → PR → auto-merge on green CI), CI gate matrix with local commands, coding standards, reviewer expectations, documentation expectations. CONTRIBUTING.md delegates the full quality bar to shared/runbooks/engineering-standards.md (PowerShell variant of the company-canonical runbook).", + "contribution_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/CONTRIBUTING.md", "contribution_requirements_status": "Met", - "contribution_requirements_justification": "Contribution requirements (signed commits via scripts/setup-git-signed.sh, squash-merge only, all CI gates green, PSScriptAnalyzer Error-severity zero, Trivy/Semgrep/Gitleaks/jscpd zero findings, Test-SnipIT.ps1 passing on Linux + Windows runners) are codified in shared/runbooks/engineering-standards.md §1 (Quality gates) and §3 (Branch, commit, PR rules). No standalone CONTRIBUTING.md — engineering-standards.md is the canonical contribution-requirements document.", - "contribution_requirements_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/shared/runbooks/engineering-standards.md", + "contribution_requirements_justification": "CONTRIBUTING.md at repo root documents acceptable contributions: §What every PR must pass tabulates the 8 CI gates (headless tests, Windows AST parse, PSScriptAnalyzer Error-severity 0, Trivy HIGH/CRITICAL 0, Semgrep ERROR 0, Gitleaks 0, jscpd <3%, SBOM artifact) with the local commands to run each. §Coding standards covers the load-bearing rules (PowerShell 7.5+ only, Verb-Noun PascalCase, [CmdletBinding()] + param() for >1-arg functions, pure-logic functions in Core region for headless coverage, named-closure event-handler pattern, single-file deliverable invariant). The full quality bar — branch / commit / PR rules, security tooling, performance targets — is the contents of shared/runbooks/engineering-standards.md, which CONTRIBUTING.md links as the SSoT.", + "contribution_requirements_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/CONTRIBUTING.md", "floss_license_status": "Met", "floss_license_justification": "MIT license — see /LICENSE at repo root. MIT is OSI-approved and FSF-recognized FLOSS; permits use, modification, and redistribution including commercial. Copyright holder: Amit Kumar.", @@ -34,8 +34,8 @@ "license_location_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/LICENSE", "documentation_basics_status": "Met", - "documentation_basics_justification": "Documentation basics cover three surfaces: (1) README.md at repo root — install (clone + run), usage, hotkeys (global + preview-window), output paths, system integration, architecture overview. (2) docs/README.md — a docs/ index pointing to long-form material (current entry: docs/mockups/preview-redesign.html design mock; plus links back to README, CLAUDE, SECURITY, the engineering-standards runbook, CHANGELOG, and .bestpractices.json). (3) CLAUDE.md — agent/developer brief with build/test/run commands, conventions, gotchas, and the OpenSSF Scorecard baseline + target. Conventional discoverability path (root README → docs/ → docs/README.md) is satisfied.", - "documentation_basics_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/docs/README.md", + "documentation_basics_justification": "README.md at repo root IS the basic documentation for the software: §Features (capture, preview window, annotations, output, system integration), §Hotkeys (global + preview window), §Install (3-step clone + run, no admin, what first-launch does), §Usage (annotation flow, zoom, copy/save, new snip), §Architecture (single-file region layout + 10 pure Core functions + preview-window internals), §Tests (84 headless + 42 interactive), §Project files. Long-form material (design mocks, ADR-style notes) lives under docs/ with docs/README.md as the index pointing back to README/CLAUDE/SECURITY/engineering-standards/CHANGELOG. CLAUDE.md provides the agent/developer brief with build/test/run, conventions, gotchas, and the OpenSSF Scorecard baseline + target.", + "documentation_basics_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/README.md", "documentation_interface_status": "Met", "documentation_interface_justification": "snipIT's interface is the global hotkeys, system-tray widget, and preview-window editor — all documented under README.md §Hotkeys (Global + Preview window) and §Usage. There is no programmatic API surface; the .ps1 is invoked directly.", @@ -83,8 +83,8 @@ "release_notes_vulns_justification": "CHANGELOG.md reserves a dedicated `### Security` subsection inside every release entry (and the `[Unreleased]` working set) for non-trivial security fixes. The header text states explicitly: 'Each release MUST list any non-trivial security fixes under a dedicated Security subsection so downstream consumers can decide whether to upgrade.' Zero fixes to date — the current `[Unreleased]` Security subsection is honestly marked 'No security-relevant fixes shipped yet under this release line.' When a fix ships, the entry will reference the GHSA advisory + CVE per SECURITY.md §What you can expect.", "report_process_status": "Met", - "report_process_justification": "Bug-reporting process documented in README.md and the GitHub Issues tracker (https://github.com/RandomCodeSpace/snipIT/issues). Vulnerability-reporting process documented in SECURITY.md §Reporting a vulnerability (private GHSA advisory + email).", - "report_process_url": "https://github.com/RandomCodeSpace/snipIT/issues", + "report_process_justification": "SECURITY.md §Reporting a vulnerability documents the private channel for security issues (GitHub private vulnerability report at /security/advisories/new, or `ak.nitrr13@gmail.com` with `[snipIT security]` subject; 72-hour ack SLA, 7-day triage, 90-day coordinated disclosure). CONTRIBUTING.md §Reporting documents the public channel for functional bugs and feature requests — GitHub Issues at https://github.com/RandomCodeSpace/snipIT/issues. Both channels are linked from README.md.", + "report_process_url": "https://github.com/RandomCodeSpace/snipIT/blob/main/SECURITY.md", "report_tracker_status": "Met", "report_tracker_justification": "GitHub Issues at https://github.com/RandomCodeSpace/snipIT/issues serves as the public, threaded, searchable issue tracker for bug reports and enhancement requests.", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6723b0d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing to snipIT + +Thanks for considering a contribution. snipIT is a single-script PowerShell 7.5+ tool on .NET 9 — the deliverable is `SnipIT.ps1`. There is no compile step; `git clone` + `pwsh -Sta -File .\SnipIT.ps1` is the install path. + +## Reporting + +- **Functional bugs and feature requests** — open a [GitHub Issue](https://github.com/RandomCodeSpace/snipIT/issues). Include your Windows + PowerShell + .NET versions and the shortest repro you can produce. +- **Security vulnerabilities** — do **not** open a public issue. Use the private channel documented in [`SECURITY.md`](SECURITY.md): a [GitHub private vulnerability report](https://github.com/RandomCodeSpace/snipIT/security/advisories/new) or `ak.nitrr13@gmail.com` with `[snipIT security]` in the subject. Disclosure SLA + scope are listed there. + +## Development workflow + +1. Fork and create a topic branch off `main` (e.g. `feat/window-shadow` or `fix/dpi-on-mixed-displays`). +2. Make focused, atomic commits in [Conventional Commits](https://www.conventionalcommits.org/) style (`feat:`, `fix:`, `refactor:`, `chore:`, `docs:`, `test:`, `ci:`, `perf:`). +3. Sign every commit. Run `scripts/setup-git-signed.sh` once per worktree to apply repo-local signing config (SSH / OpenPGP / x509). Branch protection on `main` rejects unsigned commits. +4. Open a PR against `main`. Auto-merge fires when CI is green; no human merge button on the happy path. + +`main` is the only protected branch. Direct pushes are blocked; squash-merge is the only allowed merge style; linear history is required. + +## What every PR must pass + +CI gates every PR on the following — please run them locally before requesting review. Each gate has zero tolerance: + +| Gate | Local command | Where it lives | +|---|---|---| +| Headless tests | `pwsh -NoProfile -File ./Test-SnipIT.ps1` (84/84 must pass) | `.github/workflows/test.yml` | +| Windows AST parse | `pwsh -NoProfile -Command "[System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path ./SnipIT.ps1), [ref]\$null, [ref]\$errors)"` | `.github/workflows/test.yml` | +| **PSScriptAnalyzer** (PowerShell lint) | `pwsh -c "Invoke-ScriptAnalyzer -Path ./SnipIT.ps1 -Severity Error"` (0 errors) | `.github/workflows/security.yml` | +| Trivy filesystem scan | (CI only) | `.github/workflows/security.yml` | +| Semgrep SAST (`p/security-audit`, `p/owasp-top-ten`) | (CI only) | `.github/workflows/security.yml` | +| Gitleaks (full git history) | (CI only) | `.github/workflows/security.yml` | +| jscpd duplication < 3% (powershell, `--min-tokens 100`) | (CI only) | `.github/workflows/security.yml` | +| SBOM (SPDX + CycloneDX) | (CI only — surface only) | `.github/workflows/security.yml` | + +## Coding standards (acceptable contributions) + +The full quality bar — quality gates, code style, branch/commit/PR rules, security tooling, performance targets — is codified in [`shared/runbooks/engineering-standards.md`](shared/runbooks/engineering-standards.md), the PowerShell variant of the company-canonical runbook. Treat that file as the single source of truth for what is acceptable in this repo. The most load-bearing rules: + +- **PowerShell 7.5+ only.** No PS5.1 fallbacks, no `Add-Type` shims that only compile on Windows PowerShell. +- **Functions: `Verb-Noun` PascalCase**, [approved verbs](https://learn.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands), `[CmdletBinding()]` + `param()` for any function with > 1 parameter. +- **Pure-logic functions go in the `Core` region** of `SnipIT.ps1` so the headless test suite picks them up via `-CoreOnly`. +- **Preview-window event handlers are one-line wrappers** around named closures captured at window-creation time (e.g. `$beginPan`, `$pickColor`, `$handleMouseDown`) — keeps the test harness able to drive every code path through the closures via `-TestAction`. +- **Tests are zero-dependency** (no Pester). Follow the assertion pattern in `Test-SnipIT.ps1`. +- **Single-file deliverable is a headline product feature.** Do not propose splitting `SnipIT.ps1` into modules without an explicit board reversal. + +## What you'll need + +- Windows 11 + PowerShell 7.5+ for full interactive testing (`Test-SnipIT-Interactive.ps1`). +- Any pwsh 7.5+ host (Linux / macOS work) for headless tests. +- A signed-commit setup. `scripts/setup-git-signed.sh` does the repo-local config; the script auto-detects ssh / openpgp / x509 from your global git config. + +## Reviewing + +A PR lands when: + +1. All CI gates above are green (the protection rule on `main` enforces eight required check contexts). +2. Codex / TechLead review pass shows no HIGH-severity findings. +3. The squash commit is signed (GitHub web-flow signing handles this automatically on merge). + +For larger changes (new region in `SnipIT.ps1`, new top-level function group, new workflow file), open a brief proposal as a GitHub Issue first so we can align on shape before you sink hours into the PR. + +## Documentation + +- Update [`CHANGELOG.md`](CHANGELOG.md) `[Unreleased]` section with an entry under **Added** / **Changed** / **Fixed** / **Security** as appropriate. +- If your PR changes how to build/test/run, conventions, gotchas, or introduces a new dependency, also update [`CLAUDE.md`](CLAUDE.md). It is the agent / contributor brief read at session start. +- Long-form docs go under [`docs/`](docs/README.md). + +Thanks again — the project is small, the test suite is fast, and your PR will get a reply quickly.