diff --git a/.github/instructions/code-review.instructions.md b/.github/instructions/code-review.instructions.md new file mode 100644 index 000000000..c159bebbf --- /dev/null +++ b/.github/instructions/code-review.instructions.md @@ -0,0 +1,67 @@ +--- +applyTo: '**/*.rs,**/*.ps1,**/*.psm1,**/*.tests.ps1,**/*.json' +description: 'Repository-specific code review guidance for DSC (Rust, PowerShell/Pester, JSON)' +--- + +# Code Review Instructions for DSC Repository + +These instructions guide Copilot when performing code reviews on pull requests in this repository. +Focus on high-confidence, actionable findings. Do not comment on style, formatting, or trivial issues. + +Detailed review guidance is split by contribution area in `.github/instructions/code-review/`. +Use the path-based mapping below to determine which area instructions apply to the files under review. + +## Area Routing + +| Area | Paths | Instruction File | +|------|-------|------------------| +| Engine | `lib/dsc-lib/src/configure/`, `lib/dsc-lib/src/discovery/`, `lib/dsc-lib/src/dscresources/`, `lib/dsc-lib/src/functions/`, `lib/dsc-lib/src/settings/` | `code-review/engine.instructions.md` | +| Resources | `resources/` | `code-review/resource.instructions.md` | +| Adapters | `adapters/` | `code-review/adapter.instructions.md` | +| Extensions | `extensions/`, `lib/dsc-lib/src/extensions/` | `code-review/extension.instructions.md` | +| CLI | `dsc/src/` | `code-review/cli.instructions.md` | +| Tests | `**/*.tests.ps1`, `**/tests/`, `**/test/`, `**/Tests/` | `code-review/tests.instructions.md` | +| Libraries | `lib/` | `code-review/library.instructions.md` | +| Security | `lib/dsc-lib/src/util.rs`, `lib/dsc-lib-security_context/`, `lib/dsc-lib-registry/`, `resources/registry/`, `resources/windows_firewall/`, `resources/windows_service/`, `resources/dism_dsc/` | `code-review/security.instructions.md` | +| Performance | Any `*.rs` file in hot paths | `code-review/performance.instructions.md` | +| Windows | `resources/windows_*`, `resources/dism_dsc/`, `resources/registry/`, `lib/dsc-lib-registry/`, `lib/dsc-lib-pal/` | `code-review/windows.instructions.md` | +| Linux/macOS | `resources/apt/`, `resources/sshdconfig/`, `resources/brew/`, `lib/dsc-lib-pal/` | `code-review/linux.instructions.md` | + +Multiple areas may apply to a single file. For example, `resources/windows_firewall/` triggers +both the Resource, Windows, and Security instructions. + +## General Principles (False-Positive Avoidance) + +These apply to ALL areas: + +- **Do not claim code will not compile unless you can cite a specific rule violation**: Avoid speculative "this won't compile" claims about Rust ownership/borrowing. Only flag compile errors when you can point to a concrete language rule being violated. +- **Test resources are not production code**: Code in `tools/dsctest/` is for testing only and is never user-facing. Do not require production-grade error handling in test harnesses unless panics would hide regressions. +- **Automatically-generated files**: Files like `lib/dsc-lib-jsonschema/.versions.json` are updated by build automation. Do not flag version bumps as unintentional. +- **Do not demand large abstractions in small PRs**: Suggest extracting a helper function. Do not block a focused PR by requesting trait/framework redesigns -- that is follow-up work. +- **Table output is not a stable API**: JSON/YAML are canonical machine-readable outputs. Table layout changes are not breaking. +- **Separate input/output structs can be intentional**: Resources often distinguish desired state from observed state. Do not assume duplicate structs are accidental. +- **Intentional design decisions**: When maintainers explicitly label behavior as "intentional", do not re-flag. +- **Extract repetitive code into helper functions**: When the same logic appears in multiple places, flag it and suggest extracting a shared helper function to reduce duplication and improve maintainability. + +## Documentation and Logging (All Areas) + +- **Accurate comments**: If code behavior changes, update comments to match. +- **Log level appropriateness**: Full `PATH` contents at `trace!`, not `debug!`. Never log secrets. +- **Doc comments matching implementation**: Update when described behavior doesn't match reality. +- **Remove debug print statements**: Do not use `println!` for debugging -- use `debug!`/`trace!` macros. Note that `println!` is acceptable for intentional CLI user-facing output. +- **Prefer scan-friendly wording**: Log/error strings should be concise for readability in diagnostics. + +## Internationalization (All Rust Code) + +- **Use `rust-i18n` with the `t!` macro**: All user-facing strings in Rust code must use the `t!` macro from the `rust-i18n` crate. Do not hard-code English strings in source files. +- **Strings go in `en-us.toml`**: Localized text must be defined in the `en-us.toml` locale file, not inline in Rust source. +- **Locale key accuracy**: Verify key names match the keyword/function they describe. +- **No dead locale strings**: Do not add i18n keys that are never referenced in code. + +## CI/CD (All Areas) + +- **Fork permission limitations**: Steps posting PR comments should gate on same-repo PRs or use `continue-on-error: true`. +- **Conditional tool installation**: Install expensive tools only after determining the PR needs them. +- **Check control flow, not just syntax**: Verify `if: always()`, `continue-on-error`, and `needs`/stage dependencies match stated failure behavior. +- **Preserve downstream artifact contracts**: Flag changes to artifact names/paths when downstream jobs expect the old layout. +- **PowerShell conventions**: Singular function names (`Test-RustProject`). Build failures should throw. diff --git a/.github/instructions/code-review/adapter.instructions.md b/.github/instructions/code-review/adapter.instructions.md new file mode 100644 index 000000000..7de30c845 --- /dev/null +++ b/.github/instructions/code-review/adapter.instructions.md @@ -0,0 +1,69 @@ +--- +applyTo: 'adapters/**' +description: 'Code review guidance for DSC adapters (PowerShell, WMI, etc.)' +--- + +# Adapter Code Review + +Adapters bridge DSC to external resource ecosystems (PowerShell DSC v1/v2 resources, WMI providers, +etc.). An adapter is a single-mode executable that receives the path or content to the adapted +resource along with the type name and version information. + +## General Adapter Design + +- **Single-mode operation**: Adapters operate in a single mode -- they receive input describing + which adapted resource to invoke and pass through the operation. Do not add multi-mode dispatch + logic inside an adapter; each invocation handles exactly one resource call. +- **Input contract**: Adapters receive the resource type name, version information, and either a + path to or the content of the adapted resource definition. Verify the adapter correctly parses + and forwards all of these. +- **`validate` is deprecated**: The `validate` operation must NOT be implemented by adapters. + Validation is handled by JSONSchema. Flag any new code that adds a `validate` operation or + processes validate requests. +- **Schema-based validation**: Adapted resources should provide JSONSchema for input validation. + The adapter should not re-implement validation logic that the schema already covers. +- **Exit codes**: Adapters must exit 0 on success and non-zero on failure. Ensure all error paths + produce a non-zero exit code with structured error output on stderr. +- **Structured I/O**: Adapters communicate via JSON on stdin/stdout. Verify JSON serialization + round-trips correctly, especially for nested objects, null values, and arrays. +- **Resource enumeration**: When listing available resources, adapters must accurately report + type names, versions, and capabilities. Do not advertise capabilities the adapted resource + does not support. + +## Secrets and Security (All Adapters) + +- **Prevent command injection**: Flag code that embeds user-controlled values (secrets, vault + names, paths) into command strings. Prefer passing arguments or structured data. +- **Never leak secrets into logs**: Verify redaction is applied when logging resource output + that may contain secure values. + +## PowerShell Adapter Specifics + +The PowerShell adapter runs PowerShell runspaces to invoke DSC v1/v2/v3 resources. These +patterns apply specifically to PowerShell-based adapter code. + +### Module Import Safety + +- **Module import can return arrays**: `Get-Module` can return multiple `PSModuleInfo` objects + when multiple versions are loaded. Always select a single module (highest version) before + calling methods. +- **Error handling around module imports**: Wrap import probes in try/catch so one failing module + doesn't abort entire resource enumeration during cache refresh. +- **`$using:` in parallel blocks**: Variables from parent scope are not available inside + `ForEach-Object -Parallel`. Use `$using:variableName`. + +### Error Handling + +- **Distinguish terminating vs non-terminating errors**: Non-terminating errors in `$ps.HadErrors` + should not produce non-zero exit. Only terminating errors (exceptions) should cause adapter failure. +- **Use `$_` in catch blocks, not `$error`**: `$error` is the global error collection. Use `$_` + (the caught exception) for condition checks. +- **Flush trace queues before exit on all paths**: If a catch/finally path exits the script, drain + the trace queue first to avoid losing diagnostic messages. + +### Concurrency and Event Handling + +- **`ConcurrentQueue` draining**: Do not loop on `.IsEmpty` followed by `TryDequeue`. Use + `while queue.TryDequeue(...)` as the single loop condition -- `IsEmpty` is only an approximation. +- **Event subscriber cleanup**: Filter by `-SourceIdentifier`, not blanket + `Get-EventSubscriber | Unregister-Event`. diff --git a/.github/instructions/code-review/cli.instructions.md b/.github/instructions/code-review/cli.instructions.md new file mode 100644 index 000000000..e5ebc92da --- /dev/null +++ b/.github/instructions/code-review/cli.instructions.md @@ -0,0 +1,33 @@ +--- +applyTo: 'dsc/src/**' +description: 'Code review guidance for DSC CLI (command-line interface, subcommands, server mode)' +--- + +# CLI Code Review + +The `dsc` crate is the main CLI binary. It handles argument parsing, subcommand dispatch, +output formatting (JSON/YAML/table), and the MCP server mode. + +## Output Formatting + +- **Deterministic output**: JSON format (compact vs pretty) must be consistent regardless of internal state. +- **Table output is not a stable API**: JSON/YAML are canonical. Table changes are not breaking. +- **Extract shared formatting logic**: When table/list formatting appears in multiple subcommands, extract a helper rather than duplicating. + +## Error Handling + +- **Prefer `Result` over panics**: Avoid `unwrap()`/`expect()` on user input or parsed data. Return clear error messages and exit codes. +- **Names must match semantics**: Flag singular/plural mismatches, stale help text, and deprecated options still visibly advertised. + +## Server Mode (JSONRPC) + +- **CLI additions must be reflected in server mode**: Any new CLI subcommand or capability must + also be exposed as a corresponding JSONRPC API in server mode. Flag PRs that add CLI + functionality without a matching server-mode implementation or a tracking issue for follow-up. +- **Schema/typing for tool parameters**: Prefer typed parameters over generic `serde_json::Value` with runtime validation. This gives clients correct schemas. +- **Tool name accuracy**: Ensure locale strings and schema descriptions reference the correct tool name (e.g., `list_dsc_functions` not `list_dsc_function`). + +## Backward Compatibility + +- **CLI flag changes are compatibility events**: Renaming, removing, or changing the semantics of CLI flags requires consideration of existing users and scripts. +- **Breaking test expectations**: If existing tests must change due to CLI behavior changes, that signals a potential breaking change needing discussion. diff --git a/.github/instructions/code-review/engine.instructions.md b/.github/instructions/code-review/engine.instructions.md new file mode 100644 index 000000000..69a0dccc4 --- /dev/null +++ b/.github/instructions/code-review/engine.instructions.md @@ -0,0 +1,43 @@ +--- +applyTo: 'lib/dsc-lib/src/configure/**,lib/dsc-lib/src/discovery/**,lib/dsc-lib/src/dscresources/**,lib/dsc-lib/src/functions/**,lib/dsc-lib/src/settings/**' +description: 'Code review guidance for DSC engine (configure, discovery, resource dispatch, functions, settings)' +--- + +# Engine Code Review + +The engine is the core of DSC: configuration processing, resource discovery, function evaluation, +schema caching, and settings resolution. Changes here have broad impact. + +## Caching + +- **Cache key correctness**: Cache keys must account for all dimensions affecting the cached value. For adapter resources with `target_resource`, cache by target identity, not just adapter type/version. +- **Centralize cache logic**: Flag duplicate cache writes or wrapper layers that both cache the same result. A single cache owner reduces redundant work and prevents divergent keying. +- **Avoid JSON serialize/parse roundtrips**: If you already have a `serde_json::Value`, cache or return it directly rather than stringifying and re-parsing. + +## Settings Precedence + +- **Full precedence chain**: Policy > CommandLine > Environment > Workspace > User > Install. Missing scopes allow bypasses. +- **Resolved fields vs containers**: Each leaf setting should be individually resolvable with source scope tracked. +- **`allow_override` enforcement**: When false (policy-scoped), must prevent override from both env vars and CLI args. + +## Discovery + +- **Short-circuit redundant work**: Flag loops that keep scanning after all matches are found, or `contains_key` + `insert` patterns where entry APIs would do one pass. +- **Error promotion risk**: Converting previously-ignored errors into hard errors (e.g., `join_paths` failure) can break existing environments. Prefer warnings or graceful degradation unless truly unrecoverable. + +## Resource Dispatch Consistency + +- **Behavior must be consistent across get/set/test/export**: If a validation, parameter, or output shape applies to one operation, verify it applies to all siblings. +- **Deterministic output**: JSON format (compact vs pretty) must be consistent regardless of cache state. +- **Resource filtering logic**: (1) if resource supports filtering, let it handle it; (2) if not, use engine filtering with INFO message. + +## What-If / Dry-Run + +- **No side effects during what-if**: Verify no code path before the what-if gate can mutate state. Functions like `ensure_config_exists()` that create/copy files must be gated. +- **Consistent platform enforcement**: If an operation is platform-restricted, what-if mode must enforce the same restriction. + +## API Surface + +- **Default to private/`pub(crate)`**: New modules, helpers, globals, and cache types should be private or `pub(crate)`. Require a clear external use case before exposing `pub`. +- **Breaking changes to public APIs**: Adding required parameters to public functions is a breaking change. Consider backward-compatible wrappers. +- **Public signature changes are compatibility events**: Adding parameters, changing flags, or exposing new modules should trigger compatibility review. diff --git a/.github/instructions/code-review/extension.instructions.md b/.github/instructions/code-review/extension.instructions.md new file mode 100644 index 000000000..6ded06e21 --- /dev/null +++ b/.github/instructions/code-review/extension.instructions.md @@ -0,0 +1,24 @@ +--- +applyTo: 'extensions/**,lib/dsc-lib/src/extensions/**' +description: 'Code review guidance for DSC extensions (discovery, lifecycle)' +--- + +# Extension Code Review + +Extensions extend DSC's discovery and resource capabilities. They have their own discovery +protocol and manifest format. + +## Discovery Protocol + +- **Manifest content handling**: When deserializing discovered manifests, ensure the expected shape (`ImportedManifest` enum with `Resource`/`Extension` variants) matches what extensions actually emit. +- **Unused variables after refactoring**: When switching from reused helpers (e.g., `process_get_args`) to dedicated ones (e.g., `process_discover_args`), remove intermediate variables and imports that are no longer needed. +- **Doc comments must match parameter semantics**: If a doc comment says "file path" but the parameter actually receives an argument name or extension list, update the comment. + +## Schema Updates + +- **Update JSON schemas when adding protocol fields**: New fields in extension stdout or args (e.g., `manifestContent`, `extensionsArg`) must be reflected in the checked-in JSON schemas under `schemas/`. + +## PowerShell Extensions + +- **`$using:` in parallel blocks**: Variables from parent scope are not available inside `ForEach-Object -Parallel`. Use `$using:variableName`. +- **Error isolation**: One extension failing discovery should not abort the entire extension enumeration. diff --git a/.github/instructions/code-review/library.instructions.md b/.github/instructions/code-review/library.instructions.md new file mode 100644 index 000000000..0e47c8e44 --- /dev/null +++ b/.github/instructions/code-review/library.instructions.md @@ -0,0 +1,34 @@ +--- +applyTo: 'lib/**' +description: 'Code review guidance for DSC libraries (dsc-lib, jsonschema, osinfo, pal, registry, security_context)' +--- + +# Library Code Review + +Libraries under `lib/` provide shared functionality consumed by the engine, CLI, and resources. +They define the public API surface of the DSC codebase. + +## API Surface and Visibility + +- **Default to private/`pub(crate)`**: New modules, helpers, globals, and cache types should be private or `pub(crate)`. Require a clear external use case before `pub`. +- **Breaking changes**: Adding required parameters to public functions is breaking. Consider wrappers or new function names. +- **Remove dead code immediately**: Unused imports, variables, and enums should be deleted -- Rust warnings become CI failures. +- **Extract shared logic into helpers**: Deduplicate common patterns, but don't demand full trait redesigns in focused PRs. + +## Error Handling + +- **Prefer `Result` over panics for user input**: Return clear `Result` or stable exit codes. +- **Return `Option` for fallible lookups**: Rather than empty strings that resolve to `.`. +- **`unwrap_or_default()` on serialization is a bug**: Surface the error and exit non-zero. + +## Serde and Schema + +- **Be precise with serde**: Review `rename_all`, `deny_unknown_fields`, `Option` vs default, and wire-format names. +- **Names must match semantics**: Singular/plural, stale doc comments, misleading function names. +- **Schema version catalogs**: `lib/dsc-lib-jsonschema/.versions.json` is auto-generated by build. Do not flag version entries as unintentional. + +## Performance + +- **Reduce allocations only when semantics stay intact**: Good: repeated `to_lowercase()`, cloning data that can be borrowed. Bad: clone removal that changes ownership semantics. +- **Avoid serialize/parse roundtrips**: If you have a `Value`, don't stringify and re-parse. +- **Short-circuit redundant work**: Use entry APIs instead of `contains_key` + `insert`. diff --git a/.github/instructions/code-review/linux.instructions.md b/.github/instructions/code-review/linux.instructions.md new file mode 100644 index 000000000..da320a7ce --- /dev/null +++ b/.github/instructions/code-review/linux.instructions.md @@ -0,0 +1,30 @@ +--- +applyTo: 'resources/apt/**,resources/sshdconfig/**,lib/dsc-lib-pal/**,resources/brew/**' +description: 'Code review guidance for Linux/macOS-specific code (SSH, apt, platform abstraction)' +--- + +# Linux/macOS Code Review + +Linux and macOS resources manage SSH configuration, package managers, and platform-specific state. +Cross-platform correctness is a recurring theme since the same test suite runs on all platforms. + +## Cross-Platform Path Handling + +- **Never hard-code path separators**: Use platform-appropriate path joining. Rust's `PathBuf`/`Path::join` handles this automatically. +- **Platform-conditional logic**: Gate Linux-specific behavior (like `/etc/dsc` permissions) on the correct platform check. Don't assume "not Windows" means "Linux" -- it could be macOS. + +## SSH Config Resource + +- **Quoting preservation**: Understand what the parser actually preserves vs strips. Comments claiming "retains quoting" when code strips quotes are misleading. +- **Match block handling**: Ensure match/criteria blocks are included in export results and not accidentally filtered out. +- **Repeatable keywords with operators**: Keywords with `+`/`-`/`^` operators have specific semantics about repetition. Operators on non-repeatable keywords are invalid. + +## Permission Checks (Linux) + +- **Fail closed on stat failures**: If `fs::metadata` fails for `/etc/dsc`, do not proceed as if the folder is trusted. +- **Correct permission checks**: Use PowerShell's `Get-Item` or explicit `$IsLinux` gating rather than GNU-specific `stat -c` (which fails on macOS). + +## Package Managers + +- **Idempotent operations**: Package install/remove operations should be safe to run repeatedly without error. +- **Version comparison**: OS and package versions don't follow semver. Don't assume semver parsing applies. diff --git a/.github/instructions/code-review/performance.instructions.md b/.github/instructions/code-review/performance.instructions.md new file mode 100644 index 000000000..ae0ba8179 --- /dev/null +++ b/.github/instructions/code-review/performance.instructions.md @@ -0,0 +1,31 @@ +--- +applyTo: '**/*.rs' +description: 'Code review guidance for performance (Rust allocations, caching, serialization)' +--- + +# Performance Code Review + +These patterns apply to all Rust code but are most critical in engine hot paths: resource +discovery (many manifests), schema caching, and configuration processing. + +## Caching + +- **Cache key correctness**: Keys must include all dimensions that affect the value. Adapter schemas vary by `target_resource`. +- **Centralize cache writes**: Duplicate cache mutations lead to inconsistent keying and redundant work. +- **Avoid serialize/parse roundtrips**: Don't stringify a `Value` just to re-parse it. +- **Deterministic output**: Cache hits and misses must produce identical format (compact vs pretty). + +## Allocations + +- **Reduce allocations only when semantics stay intact**: Flag repeated `to_lowercase()` or cloning owned data that can be borrowed. Do NOT flag clone removal that changes ownership or breaks compilation. +- **Short-circuit redundant work**: Use entry APIs instead of `contains_key` + `insert`. Exit loops early when all matches are found. +- **Avoid cloning before parsing**: Parse first, then return the original owned value. + +## Native Interop + +- **Resource cleanup as performance issue**: Missing `Drop`/RAII cleanup for handles, DLLs, or `VARIANT`s is both correctness and long-run efficiency problem. Especially in loops (firewall enumeration, registry key iteration). + +## False Positives to Avoid + +- **Do not flag performance when call order makes it moot**: If `get` always runs before `set`/`test`, redundant validation in later operations doesn't affect real-world performance. +- **Compact vs pretty JSON**: Maintainers have noted "doesn't matter here" for format differences in non-user-facing internal paths. Only flag when the difference is externally observable. diff --git a/.github/instructions/code-review/resource.instructions.md b/.github/instructions/code-review/resource.instructions.md new file mode 100644 index 000000000..d0537b95e --- /dev/null +++ b/.github/instructions/code-review/resource.instructions.md @@ -0,0 +1,38 @@ +--- +applyTo: 'resources/**' +description: 'Code review guidance for DSC resources (individual resource implementations)' +--- + +# Resource Code Review + +Resources are individual components that manage specific system state (registry, services, +firewall, SSH config, DISM features, etc.). They run as separate executables invoked by the engine. + +## Manifest and Schema Coherence + +- **Schema must match implementation**: Required properties in schema must be enforced in code and vice versa. +- **Behavior must match manifest metadata**: Versions, `requireSecurityContext`, adapter args, and defaults must reflect what the resource actually does. +- **Schema/manifest version consistency**: When bumping a version in `Cargo.toml`, ensure the corresponding `.dsc.resource.json` manifest is also updated. +- **`noFiltering` semantics**: Export input should be treated as empty when `noFiltering` is declared. +- **Canonical property naming**: Leading underscore (`_`) is only for cross-resource canonical properties. Resource-specific properties use descriptive names (e.g., `sshd_config_filepath`). + +## Operation Consistency + +- **All operations must validate consistently**: If a parameter is validated in `get`, it should also be validated in `set`, `test`, and `export`. +- **What-if must not mutate state**: Verify no code path before the what-if gate can create files, modify config, or change system state. +- **Consistent platform enforcement in what-if**: Platform-restricted operations must enforce restrictions even in what-if mode. + +## Error Handling + +- **Prefer `Result` over panics**: Avoid `unwrap()`/`expect()` on user input or manifest data. Return clear error messages and stable exit codes. +- **`unwrap_or_default()` on serialization is a bug**: `serde_json::to_string(...).unwrap_or_default()` silently emits empty string on failure. Surface the error and exit non-zero. +- **Return `Option` for fallible lookups**: Return `Option` rather than empty string (which resolves to `.`). + +## Destructive Operations + +- **Watch for unresolvable system objects**: In list-reconciling resources (firewall, services), flag logic that disables/removes system-created entries (AppX/UWP rules) that users cannot reliably reference in their declared state. +- **Semantic versioning**: Resources below 1.0 are not design-stable. Breaking changes to input/output shapes require a minor version bump. + +## Regex and Wildcard Handling + +- **Escape all metacharacters**: When converting wildcards to regex, escape `[`, `(`, `+`, `^`, `$`, `|`, `\` -- not just `.`. Unescaped metacharacters cause panics or unexpected matching. diff --git a/.github/instructions/code-review/security.instructions.md b/.github/instructions/code-review/security.instructions.md new file mode 100644 index 000000000..42de16d5c --- /dev/null +++ b/.github/instructions/code-review/security.instructions.md @@ -0,0 +1,42 @@ +--- +applyTo: 'lib/dsc-lib/src/util.rs,lib/dsc-lib-security_context/**,lib/dsc-lib-registry/**,resources/registry/**,resources/windows_firewall/**,resources/windows_service/**,resources/dism_dsc/**' +description: 'Code review guidance for security-sensitive code (ACLs, policy, credentials, elevated resources)' +--- + +# Security Code Review + +This repo manages system configuration. Many resources run elevated and modify security-sensitive +state (ACLs, registry, services, firewall rules, policy files). Security review is critical. + +## Fail Closed + +- **All security checks must fail closed**: If reading a security descriptor, enumerating ACEs, or calling stat fails, return the restrictive/denied result -- never fail open. +- **NULL DACL detection**: A NULL DACL means full access to everyone. Treat `p_dacl.is_null()` as insecure. +- **Do not cache or trust failed verifications**: Trust caches (Authenticode, ACL checks) should only be updated on successful validation. + +## ACL and Permission Checks + +- **Complete write-access checks**: Cover `GENERIC_WRITE` and `GENERIC_ALL` in addition to specific write flags. +- **Inherit-only ACEs**: ACEs with `INHERIT_ONLY_ACE` flag don't apply to the object itself -- don't treat them as granting access to the folder. +- **Non-standard ACE variants**: Callback ACEs and object ACEs can still grant write access. Don't skip them. + +## Policy Bypass Prevention + +- **User inputs must not bypass policy**: CLI flags, env vars, or config changes must not override policy-enforced settings. Policy sources remain authoritative. +- **Enforce declared security context**: If manifests declare `requireSecurityContext`, verify runtime enforcement for every operation. + +## DLL and Native Code Safety + +- **DLL loading security**: Use `LoadLibraryExW` with `LOAD_LIBRARY_SEARCH_SYSTEM32` instead of `LoadLibraryW` to prevent DLL hijacking. Critical for elevated resources. +- **Resource cleanup with `Drop`**: COM objects, `VARIANT`s, and library handles must be cleaned up on all paths including error paths. +- **Check HRESULT returns**: Don't silently ignore Windows API return codes. + +## Secrets + +- **Never leak secrets into logs or output**: Verify redaction when logging output that may contain secure values. +- **Prevent command injection**: Don't embed user-controlled values into PowerShell command strings. Pass arguments/JSON instead. + +## Destructive Operations + +- **Unresolvable system objects**: In list-reconciling resources (firewall, services), skip system-created entries (AppX/UWP rules) that users cannot reliably reference. +- **Service credential changes**: Flag service-configuration code that switches accounts without secure credential handling. diff --git a/.github/instructions/code-review/tests.instructions.md b/.github/instructions/code-review/tests.instructions.md new file mode 100644 index 000000000..ceabe713d --- /dev/null +++ b/.github/instructions/code-review/tests.instructions.md @@ -0,0 +1,47 @@ +--- +applyTo: '**/*.tests.ps1,**/tests/**,**/test/**,**/Tests/**' +description: 'Code review guidance for DSC tests (Pester and Rust integration tests)' +--- + +# Test Code Review + +Tests use Pester 5 for end-to-end CLI testing and Rust's built-in test framework for unit tests. +Tests run cross-platform (Windows, Linux, macOS) in CI. + +## Cross-Platform Correctness + +- **Path separators**: Never use hard-coded `\` in path construction. Always use `Join-Path`. Tests with hard-coded backslashes will fail on Linux/macOS. +- **Platform-specific commands**: `stat -c` is GNU/Linux-specific. Gate on `$IsLinux` explicitly or use PowerShell equivalents. +- **OS gating**: A Context that only checks `!$IsWindows` also runs on macOS. Be explicit with `$IsLinux` or `$IsMacOS`. +- **Use realistic cross-platform fixtures**: Test data should use correct path separators and plausible file locations for the target OS. + +## Test Isolation and Cleanup + +- **Preserve and restore environment variables**: Capture the original value in `BeforeAll` and restore in `AfterAll`. Never set to `$null` unconditionally. +- **Conflicting environment variables**: Tests for lower-priority env vars (e.g., `DSC_RESOURCE_PATH`) must explicitly clear higher-priority ones (`DSC_RESTRICTED_PATH`). +- **ACL and permission restoration**: Capture full original state and restore completely. Do not rely on partial undo or hard-coded permission values. +- **Recursive ACL changes**: If `icacls /T` is used, `AfterAll` must restore children too. +- **Event subscriber cleanup**: Filter by `-SourceIdentifier`, not blanket unregister. +- **Use `-ErrorAction Ignore` over `SilentlyContinue`**: When leftover error records could pollute later assertions. + +## Assertions + +- **Test name must match assertions**: If named "X happens only once," assertions must verify the constraint. +- **Assert `$LASTEXITCODE`**: Always check exit code in addition to output content for CLI tests. +- **Prove the intended failure mode**: Negative tests must fail for the exact reason under test, not a broader fallback. +- **Cover both branches**: Test both "present" and "absent" cases explicitly. +- **Array comparisons**: Normalize arrays through JSON conversion before comparing with `Should -Be`. +- **Avoid duplicate reads**: Read file content once into a variable, not multiple times per assertion. +- **Skip guards for cmdlet availability**: Check cmdlet availability in `-Skip`, not just elevation. +- **Ordering assumptions**: `dsc resource list` returns alphabetical order. Sort before position-based assertions. +- **Manifest file naming**: Discovery only loads `.dsc.resource.(json|yaml|yml)` files. Tests with other extensions won't exercise discovery. +- **Prefer `Should -BeExactly`**: Use exact comparisons when full expected result is known. + +## Structure + +- **Use Context blocks for shared setup**: Group found/not-found scenarios with shared `BeforeEach`. +- **Helpers belong near their usage**: Only promote to `build.helpers.psm1` if used across multiple scripts. +- **Test both adapters**: If `PowerShellScript` and `WindowsPowerShellScript` share code, parameterize tests. +- **Distinguish "failed" from "succeeded with errors"**: Separate terminating errors, non-terminating errors, and successful runs with warnings. +- **Add edge-case and malformed-input coverage**: Test boundary conditions whenever only the happy path is covered. +- **Test behavior end-to-end**: Favor tests demonstrating user-visible paths. diff --git a/.github/instructions/code-review/windows.instructions.md b/.github/instructions/code-review/windows.instructions.md new file mode 100644 index 000000000..2a6d5e545 --- /dev/null +++ b/.github/instructions/code-review/windows.instructions.md @@ -0,0 +1,35 @@ +--- +applyTo: 'resources/windows_firewall/**,resources/windows_service/**,resources/WindowsUpdate/**,resources/windows_personalization/**,resources/dism_dsc/**,resources/registry/**,lib/dsc-lib-registry/**,lib/dsc-lib-pal/**' +description: 'Code review guidance for Windows-specific code (FFI, COM, registry, DISM, services)' +--- + +# Windows Code Review + +Windows-specific code uses Win32 APIs, COM interfaces, registry access, DISM, and Windows +service management. These resources typically run elevated. + +## FFI Safety + +- **DLL loading security**: Use `LoadLibraryExW` with `LOAD_LIBRARY_SEARCH_SYSTEM32` to prevent DLL hijacking. +- **Resource cleanup with `Drop`**: COM objects, `VARIANT`s, and `HMODULE` handles must be cleaned up on all paths. Implement `Drop` for wrapper types. +- **Check HRESULT returns**: Don't silently ignore Windows API error codes. +- **Iterative handle operations**: When creating nested structures (registry keys), use previous call's result as parent handle, not always root. + +## ACL and Permissions + +- **Fail closed**: Security descriptor read failures must return "not secure." +- **NULL DACL = full access**: Always treat as insecure. +- **Complete write mask**: Check `GENERIC_WRITE`, `GENERIC_ALL`, and all relevant specific flags. +- **Inherit-only ACEs**: Don't treat `INHERIT_ONLY_ACE` as applying to the folder itself. +- **Callback/object ACEs**: Non-standard ACE types can still grant access. Don't skip them. + +## Service and Firewall Resources + +- **Unresolvable system objects**: AppX/UWP firewall rules with names like "ms-resource://" cannot be referenced by users. Skip them in destructive reconciliation. +- **Service credential handling**: Flag logon identity changes without secure credential supply. +- **Protocol normalization**: Handle `Option` protocol correctly -- protocol may be required for the operation even if optional in the input struct. + +## COM Enumeration + +- **`VariantClear` on all paths**: Clear variants even when `.cast()` or other operations fail early via `?`. +- **Single-item vs collection**: COM enumerations may return collections. Handle both cases.