From 8d148a49fa24915dc6bbb5b5acd92bd93e27c2f9 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 4 Nov 2026 13:25:02 +0100 Subject: [PATCH 1/3] State module type conventions in concrete terms --- docs/content/reference/module-types.md | 90 +++++++++++++------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/content/reference/module-types.md b/docs/content/reference/module-types.md index 6de0fa2b..208bbd03 100644 --- a/docs/content/reference/module-types.md +++ b/docs/content/reference/module-types.md @@ -1,27 +1,24 @@ # Module types -Most PSModule modules fall into one of a few archetypes. The general rules in -[PowerShell module standard](powershell-module-standard.md) and [MSX PowerShell Standards](https://msx.no/docs/Coding-Standards/PowerShell/) always apply; this -page adds the conventions that are specific to a module's type so that modules of the same kind feel -the same to use. +Most PSModule modules use one or both of the module types below. The general rules in +[PowerShell module standard](powershell-module-standard.md) and [MSX PowerShell Standards](https://msx.no/docs/Coding-Standards/PowerShell/) +always apply. This page defines additional conventions for each module type. -Two archetypes have enough shared shape to standardize: +The module types are: -- **Integration (API) modules** wrap an external service's REST or GraphQL API. +- **Integration (API) modules** provide PowerShell commands for an external service's REST or GraphQL API. - **Data modules** convert or manage a data format or in-memory structure. -A module can be both (for example, an integration module that also exposes conversion helpers). -Apply each relevant section. +A module can serve both roles. For example, an integration module can also provide conversion helpers. Apply each relevant section. ## Integration (API) modules -Integration modules are the PowerShell face of an external service. `GitHub`, and the -service-client modules such as `Anthropic`, `OpenAI`, `Bluesky`, and `Domeneshop`, are integration -modules. +Integration modules provide PowerShell commands for an external service. `GitHub` and the +service-client modules `Anthropic`, `OpenAI`, `Bluesky`, and `Domeneshop` are integration modules. ### Command naming maps to the resource, not the HTTP method -Name commands after the resource and the intent, using approved verbs. Never name a command after +Name commands after the resource and the intended operation. Use approved verbs. Never name a command after the HTTP method or the endpoint path. Map REST methods to verbs: | REST method | PowerShell verb | Example | @@ -32,55 +29,58 @@ the HTTP method or the endpoint path. Map REST methods to verbs: | `DELETE` | `Remove-` | `Remove-GitHubRepository` | | Non-CRUD action | Approved verb for the intent | `Invoke-`, `Start-`, `Stop-`, `Enable-`, ... | -Prefix the noun with the service's term of art (`GitHubRepository`, not `Repository`). +Prefix the noun with the service-specific term (`GitHubRepository`, not `Repository`). ### Transport abstraction -Lower-level helpers own the concrete `Invoke-RestMethod` / GraphQL / HTTP calls. How you expose -or hide this abstraction is a design choice: +Helper functions make the `Invoke-RestMethod`, GraphQL, or HTTP calls. Choose how to expose the transport and module state: - **Private transport** (common): Keep REST, GraphQL, and HTTP helpers private. Public functions - accept resolved inputs and typed objects. This follows the Dependency Inversion rule from - [Standards](powershell-module-standard.md#solid-applied) applied to the network boundary. -- **Public transport**: Expose REST or GraphQL functions publicly for power users or module + accept resolved inputs and typed objects. This applies the Dependency Inversion rule from + [Standards](powershell-module-standard.md#solid-applied) to network calls. +- **Public transport**: Expose REST or GraphQL functions publicly for advanced users or module composition. -- **Public Context**: Expose the `Context` module as public so users can configure and manage +- **Public Context**: Expose the `Context` module so users can configure and manage module state, secrets, and settings directly. -Choose the strategy that best serves your module's audience. +Choose the strategy for the module's intended users. ### Use Context for user and module settings -Integration modules persist state with the [`Context`](https://github.com/PSModule/Context) module -rather than inventing bespoke storage. Context provides on-disk storage for user data and secrets, -organized by context and environment. Two kinds of state are both standard: +Integration modules use the [`Context`](https://github.com/PSModule/Context) module to store state instead of a separate storage implementation. +Context stores user data and secrets on disk, organized by context and environment. It supports two standard kinds of state: - **User settings and secrets**: accounts, tokens, sessions, and per-user configuration. Store these - in a per-user context. `Context` encrypts secrets at rest (via `Sodium`), so a user can resume work - without reconfiguring or logging in again when the service supports session refresh. + in a per-user context. `Context` encrypts stored secrets with `Sodium`. + If the service supports session refresh, users can resume work without new configuration or another login. - **Module settings**: module-wide defaults, endpoints, and feature flags that are not tied to a single user. Store these in a module-scoped context. -Your module must expose functions and object types so users can target specific contexts and -environments. Users need to be able to read from, write to, and manage contexts programmatically, -selecting which environment or context their functions operate against. Persisting both through -`Context` gives every integration module the same, discoverable settings model and keeps secrets -out of source, logs, and plain files. +Your module must expose functions and object types for specific contexts and environments. +Users must be able to read, write, and manage contexts programmatically. +They must be able to select the environment or context that their functions use. +Use `Context` for both kinds of state to give integration modules the same settings model. +Keep secrets out of source code, logs, and unencrypted files. ## Data modules Data modules convert between representations or manage an in-memory structure. `Hashtable` is the -reference shape; `Base64`, `Json`, `Lua`, `Hcl`, `Sodium`, and `Uri` follow the same pattern. +reference implementation. `Base64`, `Json`, `Lua`, `Hcl`, `Sodium`, and `Uri` follow the same pattern. -### The neutral object is the pivot + -Every conversion goes through the neutral PowerShell object model -(`[PSCustomObject]` / `[hashtable]` / `[PSObject]`). `ConvertFrom-` parses a -format-specific representation into an object; `ConvertTo-` renders an object into the -format. Converting through the object as a common pivot means any format interoperates with any -other, instead of writing a direct converter for every pair. +### Conversions use the neutral object model -Always ship both directions so data can round-trip between the format and the object model. +Every conversion uses the neutral PowerShell object model +(`[PSCustomObject]` / `[hashtable]` / `[PSObject]`) as the intermediate representation. +`ConvertFrom-` parses a format-specific representation into an object. +`ConvertTo-` converts an object into the target format. + +To convert between formats, first convert the source representation to an object. +Then convert the object to the target format. +The common object model removes the need for a separate converter for each pair of formats. + +Always provide both conversion directions so users can convert from a format to an object and back. ### Verb vocabulary @@ -88,19 +88,19 @@ Always ship both directions so data can round-trip between the format and the ob | ------------ | ------- | | `ConvertFrom-` | Format-specific text/representation → `[PSCustomObject]` / `[hashtable]` | | `ConvertTo-` | `[PSCustomObject]` / `[hashtable]` → format-specific text/representation | -| `Import-` | Read from a file or store into objects | -| `Export-` | Write objects to a file or store | -| `Format-` | Produce a normalized or pretty rendering | +| `Import-` | Read objects from a file or data store | +| `Export-` | Write objects to a file or data store | +| `Format-` | Produce a normalized or human-readable representation | | `Merge-` | Combine two structures | -| `Compare-` | Diff two structures | +| `Compare-` | Identify differences between two structures | | `Test-` | Validate a value or structure | -| `Remove-Entry` | Remove elements by criteria | +| `Remove-Entry` | Remove elements that match specified criteria | -The `Hashtable` module demonstrates the full set: `ConvertFrom-Hashtable`, `ConvertTo-Hashtable`, +The `Hashtable` module demonstrates `ConvertFrom-Hashtable`, `ConvertTo-Hashtable`, `Import-Hashtable`, `Export-Hashtable`, `Format-Hashtable`, `Merge-Hashtable`, and `Remove-HashtableEntry`. ## Where this connects - [PowerShell module standard](powershell-module-standard.md): layout, private functions, and the mandatory context parameter. -- [Repository Standard](repository-standard.md): repository files, README shape, and agent onboarding. +- [Repository Standard](repository-standard.md): repository files, README content, and instructions for agents. From b158a5312295ec0271c6d967aca24bd81b3d6772 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 4 Nov 2026 13:26:58 +0100 Subject: [PATCH 2/3] State Pester test rules without vague assurances --- docs/content/reference/test-specification.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/content/reference/test-specification.md b/docs/content/reference/test-specification.md index d08eb9b7..6b532456 100644 --- a/docs/content/reference/test-specification.md +++ b/docs/content/reference/test-specification.md @@ -2,25 +2,25 @@ ## Overview -This document defines the structure and guidelines for writing Pester tests for PowerShell functions. The goal is to ensure consistency and comprehensive test coverage while maintaining clarity. +This specification defines the Pester test hierarchy, input guidance, and coverage requirements for PowerShell functions. ## Test Structure -Each function is tested within a structured Pester `Describe` block that follows this hierarchy: +Organize each function's Pester tests in the following hierarchy: ### 1. Module-Level `Describe` - The outermost `Describe` block corresponds to the module. -- The module name is derived from the prefix of the function name's noun part. +- Use the prefix of the function name's noun part as the module name. ### 2. Function-Level `Describe` -- Each function within the module gets its own `Describe` block. -- Named using the full function name. +- Give each function in the module its own `Describe` block. +- Use the full function name as the block name. ### 3. Use Case `Context` -- Each use case is grouped within a `Context` block. +- Group each use case in a `Context` block. - The context name starts with the function name followed by a descriptive test case identifier. - Example: `Get-Uri - simple usage` - Example: `Get-Uri - Pipeline usage` @@ -28,7 +28,7 @@ Each function is tested within a structured Pester `Describe` block that follows ### 4. Functional `It` Statements -- Each `It` block tests a specific aspect of the function's behavior. +- Each `It` block tests one aspect of the function's behavior. - The name follows the format: `FunctionName - ` - Example: `Get-Uri - gets the URI object when provided a string` - Example: `Get-Uri - returns $null when input is empty` @@ -36,9 +36,9 @@ Each function is tested within a structured Pester `Describe` block that follows ### 5. Test Guidelines -- **No Mocks**: We do not use mocks in tests. +- **No Mocks**: Do not use mocks in tests. - **Real Inputs**: Tests should use actual inputs and expected outputs. -- **Comprehensive Coverage**: All function functionality, including edge cases, must be tested. +- **Comprehensive Coverage**: Tests must cover all function behavior, including edge cases. ## Example Test Structure @@ -62,4 +62,4 @@ Describe 'Uri' { } ``` -This ensures our tests are structured, maintainable, and adhere to best practices. +The example groups `Get-Uri` tests under the `Uri` module and uses separate contexts for direct and pipeline input. From 5ee3e9393c6bd47f78def6b5841cf22ecacad86f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 4 Nov 2026 13:31:50 +0100 Subject: [PATCH 3/3] Clarify test jobs and reference script maintenance --- docs/content/reference/framework-test-ids.md | 22 ++++++++++--------- docs/content/reference/guidance-scripts.md | 10 ++++++--- .../module-development-foundations.md | 10 +++++---- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/docs/content/reference/framework-test-ids.md b/docs/content/reference/framework-test-ids.md index 880c5f3e..26010575 100644 --- a/docs/content/reference/framework-test-ids.md +++ b/docs/content/reference/framework-test-ids.md @@ -5,14 +5,15 @@ description: The PSModule framework tests enforced on module source code and on # Framework test IDs -The PSModule framework runs a fixed set of tests on every module, separate from the module's own Pester tests. Each -source-code test has an ID that can be used to -[skip it for a single file](../guides/skipping-framework-tests.md). +The PSModule framework runs a fixed set of tests on every module. These tests are separate from the module's own Pester tests. +Each source-code test has an ID. Use the ID to +[skip the test for a single file](../guides/skipping-framework-tests.md). ## Source-code tests -Run by the [Test source code](pipeline-stages.md#test-source-code) job against files in `src/`. Implemented in -[PSModule - SourceCode tests](https://github.com/PSModule/Process-PSModule/blob/main/.github/actions/Test-PSModule/src/tests/SourceCode/PSModule/PSModule.Tests.ps1). +The [Test source code](pipeline-stages.md#test-source-code) job runs these tests against files in `src/`. +The [PSModule - SourceCode tests](https://github.com/PSModule/Process-PSModule/blob/main/.github/actions/Test-PSModule/src/tests/SourceCode/PSModule/PSModule.Tests.ps1) +file defines them. | ID | Category | Description | Example skip comment | | ---- | ---------- | ------------- | ---------------------- | @@ -30,17 +31,18 @@ Run by the [Test source code](pipeline-stages.md#test-source-code) job against f ## Module tests -Run by the [Framework test](pipeline-stages.md#framework-test) job against the compiled module in -`.PSModule/module`. Implemented in -[PSModule - Module tests](https://github.com/PSModule/Process-PSModule/blob/main/.github/actions/Test-PSModule/src/tests/Module/PSModule/PSModule.Tests.ps1). +The [Framework test](pipeline-stages.md#framework-test) job runs these tests against the compiled module in +`.PSModule/module`. The +[PSModule - Module tests](https://github.com/PSModule/Process-PSModule/blob/main/.github/actions/Test-PSModule/src/tests/Module/PSModule/PSModule.Tests.ps1) +file defines them. | Name | Description | | ---- | ----------- | | Module Manifest exists | Verifies that a module manifest file is present. | | Module Manifest is valid | Verifies that the module manifest file is valid. | -| Module import validation | Verifies that the built module imports cleanly. | +| Module import validation | Verifies that an import of the built module does not throw an error. | -Module tests typically don't need to be skipped, as they validate the final built module. +In most cases, keep module tests enabled to validate the final built module. ## Related diff --git a/docs/content/reference/guidance-scripts.md b/docs/content/reference/guidance-scripts.md index 7f3d8bd3..16849d60 100644 --- a/docs/content/reference/guidance-scripts.md +++ b/docs/content/reference/guidance-scripts.md @@ -5,9 +5,11 @@ description: Reference PowerShell scripts that demonstrate implementation patter # PowerShell guidance scripts -The [guidance directory](https://github.com/PSModule/Process-PSModule/tree/main/guidance) contains runnable reference scripts for common PowerShell implementation patterns. They are framework learning assets, not Process-PSModule module source, so they are intentionally kept outside `src/` and are not included in a module manifest. +The [guidance directory](https://github.com/PSModule/Process-PSModule/tree/main/guidance) contains runnable reference scripts for common PowerShell implementation patterns. +These scripts are not Process-PSModule module source. The `guidance/` directory is outside `src/`. Module manifests do not include these scripts. -Run an individual script only when its scenario is suitable for the local environment. Several scripts create temporary files, make web requests, or measure execution time. +Before you run a script, make sure that its scenario is suitable for the local environment. +Several scripts create temporary files, make web requests, or measure execution time. | Script | Focus | | --- | --- | @@ -28,4 +30,6 @@ Run an individual script only when its scenario is suitable for the local enviro ## Maintenance -The files are maintained in the [`guidance` directory](https://github.com/PSModule/Process-PSModule/tree/main/guidance). When that published set changes, import the complete current file from its Git blob into this directory and preserve its contents. Keep this index synchronized with the directory so users can discover every available script. +Maintain the reference scripts in the [`guidance` directory](https://github.com/PSModule/Process-PSModule/tree/main/guidance). +When the published script set changes, import the complete file from its Git blob into `guidance/`. +Preserve the file contents. Keep this index synchronized with the directory so it lists every available script. diff --git a/docs/content/reference/module-development-foundations.md b/docs/content/reference/module-development-foundations.md index 566174d5..67cca5ac 100644 --- a/docs/content/reference/module-development-foundations.md +++ b/docs/content/reference/module-development-foundations.md @@ -1,13 +1,15 @@ # Module development foundations -Process-PSModule is the framework for building, testing, versioning, documenting, and publishing PowerShell modules. These foundations define the repository, source, test, and release conventions that the framework supports and validates. +Process-PSModule builds, tests, versions, documents, and publishes PowerShell modules. +These pages define repository, source, test, and release conventions for modules that use the framework. -Start with the [Process-PSModule overview](../index.md) to understand the workflow. Use these pages when creating or maintaining a module that runs through it. +Start with the [Process-PSModule overview](../index.md) for the workflow description. +Use these pages to create or maintain a module that uses Process-PSModule. | Page | Use it for | | --- | --- | -| [Repository Standard](repository-standard.md) | Creating a module repository with the required metadata, files, and framework wiring. | +| [Repository Standard](repository-standard.md) | Creating a module repository with the required metadata, files, and workflow configuration. | | [PowerShell module standard](powershell-module-standard.md) | Structuring source code, designing functions, and applying module-specific conventions. | | [Module types](module-types.md) | Applying conventions for integration (API) and data modules. | -| [Test Specification](test-specification.md) | Writing consistent, comprehensive Pester tests for module functions. | +| [Test Specification](test-specification.md) | Defining the Pester test hierarchy, input guidance, and coverage requirements for module functions. | | [Versioning](versioning.md) | Choosing semantic version changes from the module's public API impact. |