Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 37 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copilot instructions for PSNativeCmdDevKit

## Git workflow

- Never run `git commit`, `git push`, or `git tag`. Leave commits and pushes to the user.
- Stage files only when explicitly asked.
- Summarize changed files and validation results for review with `git diff`.

## Build entrypoint

- Use `./build.ps1` for dependency restore, build, test, packaging, and quality checks.
- Bootstrap with `./build.ps1 -ResolveDependency -Tasks noop`.
- Build with `./build.ps1 -Tasks build`.
- Run focused tests with `./build.ps1 -Tasks test -PesterPath '<path>' -CodeCoverageThreshold 0`.
- Run the default suite with `./build.ps1 -Tasks test`.
- Run quality checks with `./build.ps1 -Tasks hqrmtest`.
- Do not call `Invoke-Pester`, `Build-Module`, or dependency resolvers directly from a fresh shell.
- Do not manually edit `PSModulePath` or copy files into `output\module`.

## Repository constraints

- Keep compatibility with Windows PowerShell 5.1 and PowerShell 7+.
- Keep native-command behavior cross-platform on Windows, Linux, and macOS.
- Treat `source\Public` as the public compatibility surface.
- Keep hand-authored GitHub wiki pages under `source\WikiSource`; generated wiki
content belongs under `output\WikiContent`.
- Keep comment-based help and matching unit tests current for every public function.
- Add an `Unreleased` changelog entry for behavior, security, dependency, or pipeline changes.
- Preserve executable and argument boundaries. Never turn caller-controlled command data into PowerShell source.
- Strings do not retain caller language mode. When executable caller logic is
required, accept and invoke the original caller-created scriptblock; never
stringify or recreate it in trusted module code.

## Instruction files

- Follow `.github\instructions\*.instructions.md`.
- Use `.github\skills\validate-changes\SKILL.md` to choose validation scope.
13 changes: 13 additions & 0 deletions .github/instructions/ai-instruction-authoring.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
applyTo: "{.github/instructions/*.md,.github/prompts/*.md,.github/skills/*.md,**/AGENTS.md,.github/copilot-instructions.md}"
---

# AI instruction authoring

- Write short imperative directives.
- Prefer bullets over prose.
- Remove filler, repetition, and duplicated context.
- Use the narrowest `applyTo` glob possible.
- Keep `applyTo` as a string.
- Add YAML frontmatter to targeted instruction files.
- Use `##` and `###` headings, backticks for identifiers, and fenced blocks for examples.
18 changes: 18 additions & 0 deletions .github/instructions/build-tasks.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
description: 'Build and pipeline instructions'
applyTo: '{build.ps1,build.yaml,RequiredModules.psd1,Resolve-Dependency.ps1,Resolve-Dependency.psd1,azure-pipelines.yml,GitVersion.yml}'
---

# Build and pipeline guidelines

- Use `build.ps1` as the only build entrypoint.
- Keep dependencies under `output\RequiredModules`.
- Keep `Sampler` pinned to the reviewed prerelease in `RequiredModules.psd1`.
- Prefer `PSResourceGet` through `Resolve-Dependency.psd1`.
- Configure workflows and Pester in `build.yaml`; do not embed build logic in Azure Pipelines.
- Keep WikiSource generation in the `docs` workflow and GitHub wiki deployment
in the `publish` workflow.
- Use supported `*-latest` hosted images and pipeline artifacts.
- Test Windows PowerShell 5.1, PowerShell 7 on Windows, Linux, and macOS.
- Run `./build.ps1 -Tasks test` after build or pipeline changes.
- Run `./build.ps1 -Tasks hqrmtest` before release-related changes are considered complete.
15 changes: 15 additions & 0 deletions .github/instructions/public-functions.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
description: 'Public PowerShell function instructions'
applyTo: 'source/Public/**/*.ps1'
---

# Public function guidelines

- Use `[CmdletBinding()]`.
- Use explicit parameter and output types where the contract is stable.
- Preserve Windows PowerShell 5.1 and cross-platform compatibility.
- Include `.SYNOPSIS`, `.DESCRIPTION`, `.PARAMETER`, and `.EXAMPLE` help.
- Keep executables and argument arrays structurally separate.
- Preserve native standard-output and standard-error behavior.
- Update the matching test under `tests\Unit` for every behavior change.
- Update `README.md` and `CHANGELOG.md` for user-visible changes.
23 changes: 23 additions & 0 deletions .github/instructions/test-writing.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
description: 'Pester test instructions'
applyTo: 'tests/**/*.tests.ps1'
---

# Pester test guidelines

- Use Pester 5-compatible syntax.
- Start new or modernized `It` descriptions with `Should`.
- Use `BeforeDiscovery` for generated test cases.
- Put setup and mocks in the smallest practical scope.
- Cover success, validation, failure, and platform-specific branches.
- Wrap pipeline results in `@()` before using `.Count` or indexing for Windows PowerShell 5.1 compatibility.
- Prefer the built module for exported behavior. Dot-source source files only
when source-level coverage or isolated language-mode setup requires it.
- Add constrained-language regression tests for code that accepts commands, arguments, expressions, or script blocks.
- Run focused tests through:

```powershell
./build.ps1 -Tasks test -PesterPath 'tests/Unit/<File>.Tests.ps1' -CodeCoverageThreshold 0
```

- Run `./build.ps1 -Tasks test` after focused tests pass.
50 changes: 50 additions & 0 deletions .github/instructions/wdac-language-mode.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
description: 'WDAC and PowerShell language-mode security instructions'
applyTo: '{source/**/*.ps1,source/**/*.psm1,source/**/*.psd1,RequiredModules.psd1,build.yaml}'
---

# WDAC PowerShell language-mode safety

## Prohibited patterns

- Never pass caller-controlled strings to `[scriptblock]::Create()`, `Invoke-Expression`, `AddScript()`, or equivalent dynamic PowerShell evaluation.
- Never concatenate an executable, username, option, or argument into PowerShell source text.
- Never stringify a caller-provided script block and recompile it.
- Never assume input is trusted because the containing module is signed.
- Never sign or redistribute copied PowerShell source without reviewing its exported trust boundary.

## Required implementation patterns

- Invoke native commands with the call operator and splatted argument arrays:

```powershell
& $Executable @Parameters 2>&1
```

- Pass `sudo`, `-u`, usernames, executables, and arguments as separate array elements.
- If script blocks are part of the public API, retain and invoke the original script block object so its language mode is preserved.
- A plain string has no caller language-mode or execution-context metadata.
Trusted code cannot reconstruct the caller's language mode from text.
- `[scriptblock]::Create()` has no public language-mode parameter. Calling it
inside trusted code compiles in the trusted execution context.
- Do not accept a caller-supplied language-mode value as proof of provenance.
- A separately constrained runspace is a new isolation context, not the
caller's original context.
- If executable caller logic is required, accept a caller-created
`[scriptblock]`, retain the exact object, and invoke it directly.
- If an API receives only text, treat it as data, parse it with a deliberately
limited non-PowerShell grammar, or reject it.
- Prefer structured data rules over executable predicates.
- Consider `[ValidateTrustedData()]` when a trusted function must reject values originating from constrained callers.

## Review procedure

1. Search source and built artifacts for `ScriptBlock.Create`, `Invoke-Expression`, `AddScript`, command strings, and call-operator use.
2. Trace every value entering those APIs to determine whether a constrained caller controls it.
3. Inspect nested modules and the final signed package, not only source files.
4. Verify which child manifests can be imported directly and which functions they export.
5. Test from a `ConstrainedLanguage` runspace and assert that caller-provided script blocks remain constrained.
6. Verify that no code path converts a caller scriptblock to text and recreates
it, and that no string parameter is treated as recoverable caller code.
7. Test metacharacters and PowerShell expressions in executable and argument parameters and assert they remain inert data.
8. Re-run the search against the merged `.psm1` under `output\module`.
29 changes: 29 additions & 0 deletions .github/instructions/wiki-publishing.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
description: 'GitHub wiki content and publishing instructions'
applyTo: 'source/WikiSource/**/*.md,build.yaml,azure-pipelines.yml'
---

# GitHub Wiki Publishing Guidelines

## Source of truth

- Keep hand-authored GitHub wiki pages under `source\WikiSource`.
- Treat `source\WikiSource` as canonical; do not edit generated files under
`output\WikiContent`.
- Prefer stable page names so published wiki links do not churn.

## Build wiring

- Keep wiki generation and publishing wired through `build.yaml`.
- Keep `Copy_Source_Wiki_Folder` before `Generate_Wiki_Sidebar`.
- Keep `Package_Wiki_Content` in the `docs` workflow so `WikiContent.zip` is
included in the pipeline artifact.
- Keep `Publish_GitHub_Wiki_Content` in the `publish` workflow. The Azure
Pipelines deployment stage supplies the existing `GitHubToken`.

## Validation

- Validate generated content with `./build.ps1 -Tasks docs`.
- Validate release packaging with `./build.ps1 -Tasks pack`.
- Do not invoke the publishing task locally unless deployment was explicitly
requested and an appropriate token is available.
38 changes: 38 additions & 0 deletions .github/skills/validate-changes/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: validate-changes
description: Run focused PSNativeCmdDevKit validation first, then widen for source, build, or security changes.
argument-hint: Which files changed and what validation depth is required?
---

# Validate changes

## Mandatory rule

Run every validation command through `./build.ps1`.

```powershell
./build.ps1 -ResolveDependency -Tasks noop
./build.ps1 -Tasks build
./build.ps1 -Tasks test
./build.ps1 -Tasks hqrmtest
```

## Decision flow

1. For one function or test file, run:

```powershell
./build.ps1 -Tasks test -PesterPath 'tests/Unit/<File>.Tests.ps1' -CodeCoverageThreshold 0
```

2. For public source changes, run the focused test and then the default test workflow.
3. For `build.ps1`, `build.yaml`, dependency, or pipeline changes, restore dependencies and run build plus the default test workflow.
4. For command invocation, script-block, signing, or nested-module changes, also run the constrained-language regression tests and inspect the built `.psm1` for dynamic evaluation APIs.
5. Before release, run `./build.ps1 -Tasks hqrmtest`.

## Completion checks

- The selected workflows pass through `build.ps1`.
- Coverage meets the configured threshold.
- The built module contains no caller-controlled dynamic PowerShell compilation.
- Documentation and `CHANGELOG.md` describe user-visible changes.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- GitVersion yaml configuration.
- Copilot repository guidance, targeted WDAC language-mode review rules, and a
validation skill.
- Sampler WikiSource generation, packaging, and GitHub wiki deployment.
- Unit coverage for native command invocation, output parsing, sudo rule
lifecycle, and constrained-language behavior.

### Security

- Removed dynamic PowerShell source generation from `Invoke-NativeCommand`.
- Stopped recompiling sudo preference filter strings and require filters to be
script blocks or the `*` wildcard.

### Fixed

- Updated the Sampler bootstrap and pinned `Sampler` to
`0.121.0-preview0001`.
- Replaced retired Azure Pipelines images and artifact tasks with supported
hosted images and pipeline artifacts.
- Corrected sudo preference output so `Invoke-NativeCommand` receives `Sudo`
and `SudoAs`.
- Corrected replacement of the first sudo rule and removal of multiple matches.
- Prevented continuation lines for discarded properties from accessing a
missing extra-properties collection.

### Changed

- Migrated the test configuration to Pester 5-style settings with an 80 percent
coverage target and a Windows PowerShell/PowerShell 7 cross-platform matrix.
- Updated contributor and user documentation for the Sampler workflow and WDAC
trust boundary.

## [v0.1.0] - 2020-07-12

Expand Down
31 changes: 29 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@

Please check out common DSC Community [contributing guidelines](https://dsccommunity.org/guidelines/contributing).

## Running the Tests
## Development workflow

If want to know how to run this module's tests you can look at the [Testing Guidelines](https://dsccommunity.org/guidelines/testing-guidelines/#running-tests)
Use `build.ps1` for dependency restore, builds, tests, and quality checks:

```powershell
./build.ps1 -ResolveDependency -Tasks noop
./build.ps1 -Tasks build
./build.ps1 -Tasks test
./build.ps1 -Tasks hqrmtest
```

Run a focused Pester file through Sampler:

```powershell
./build.ps1 -Tasks test `
-PesterPath 'tests/Unit/Invoke-NativeCommand.Tests.ps1' `
-CodeCoverageThreshold 0
```

The module supports Windows PowerShell 5.1 and PowerShell 7 on Windows, Linux,
and macOS. Keep tests portable unless the behavior is explicitly
platform-specific.

## Security-sensitive changes

Native executable names and arguments must remain separate values. Do not
construct PowerShell source from caller-controlled strings or recompile
caller-provided script blocks. Review
`.github/instructions/wdac-language-mode.instructions.md` before changing
command invocation, sudo rules, module exports, nested modules, or signing.
1 change: 1 addition & 0 deletions GitVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ assembly-informational-format: '{NuGetVersionV2}+Sha.{Sha}.Date.{CommitDate}'
branches:
master:
tag: preview
regex: ^master$
pull-request:
tag: PR
feature:
Expand Down
Loading