fix: Test-InforcerConnection returns a boolean - #44
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved help-text, test-coverage, versioning, and changelog issues remain.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Fixes Test-InforcerConnection to return a Boolean predicate and report failures as warnings.
Changes:
- Implements
$true/$falseresults and updates failure handling. - Adds tests and updates documentation and migration guidance.
- Updates module metadata and changelog.
File summaries
| File | Findings |
|---|---|
Tests/Consistency.Tests.ps1 |
Moderate (2 votes): Add mocked success and API-failure coverage, including strict error-preference behavior. |
README.md |
No findings. |
module/Public/Test-InforcerConnection.ps1 |
Critical (2 votes): Correct inaccurate “Progress” help text at lines 18, 46, and 50. Moderate (1 vote): Add tests for successful and failed requests, including strict preference behavior. |
module/InforcerCommunity.psd1 |
Moderate (1 vote): Breaking contract changes require a minor version bump rather than 0.7.3. |
docs/CMDLET-REFERENCE.md |
Nit (3 votes): Remove or update the stale statement that no-session calls write an error. |
CHANGELOG.md |
Moderate (1 vote): Classify the breaking changes under a Breaking Changes heading and publish as 0.8.0. |
Review details
Suppressed comments (5)
CHANGELOG.md:13
- These bullets explicitly describe consumer-visible breaking changes: the cmdlet now emits a pipeline value, switches from
-ErrorVariableto-WarningVariable, and no longer throws underStop. The repository's versioning policy requires pre-1.0 breaking changes to use a MINOR version under aBreaking Changesheading, so0.7.3underBug Fixesis inconsistent; publish this as0.8.0and classify it accordingly.
- **`Test-InforcerConnection` now returns `$true` / `$false`.** It previously wrote to the host and returned nothing at all, so `if (Test-InforcerConnection) { ... }` was always false — the `Test-*` verb promised a predicate the cmdlet never delivered. It now returns a boolean; the host output is unchanged.
- **Failures are warnings, not errors.** "Not connected" and a failed API call used to call `Write-Error`. That cannot coexist with a predicate: under `$ErrorActionPreference = 'Stop'` a WriteError throws instead of returning `$false`, so the fix would have been useless in exactly the strict scripts most likely to check a connection first. Both paths now use `Write-Warning`.
- **Migration.** Anything reading `-ErrorVariable` from this cmdlet should read `-WarningVariable` instead. The sharper edge: a script running under `Stop` that called `Test-InforcerConnection` bare, relying on the throw to abort, now continues past it — check the return value instead, e.g. `if (-not (Test-InforcerConnection)) { throw 'no connection' }`. Nothing inside the module calls this cmdlet and neither does the MCP server, so the blast radius is your own scripts.
module/InforcerCommunity.psd1:3
- This changes the public contract in two breaking ways: it adds a pipeline boolean and moves failure reporting from the error stream to warnings; the changelog explicitly calls out scripts using
-ErrorVariableor relying on-ErrorAction Stopas affected. The versioning policy inCHANGELOG.md:5requires pre-1.0 breaking changes to bump the minor version, so0.7.3(and the matching changelog heading) should be a minor-version release.
ModuleVersion = '0.7.3'
module/Public/Test-InforcerConnection.ps1:46
return $trueis reached after anInvoke-RestMethodcall that does not set-ErrorAction Stop. HTTP failures from this cmdlet can be non-terminating under the default preference, so thecatchmay be skipped and a failed or unauthorized probe can still return$true. Make the probe terminating so this predicate reliably returns$falseon request failure.
return $true
module/Public/Test-InforcerConnection.ps1:51
- Every HTTP exception is converted to
$false, butConnect-Inforcerintentionally establishes sessions for valid narrow-scope keys after an app-envelope 403 on this same/beta/baselinesprobe (seeConnect-Inforcer.ps1:219-225and the existing narrow-scope tests). A Reports.Read-only session therefore returns false here, so the new documented reconnect pattern treats a live session as dead; preserve/inspect the response envelope or use a scope-neutral probe before returning false.
Write-Warning "Inforcer connection test failed: $($_.Exception.Message)"
return $false
module/Public/Test-InforcerConnection.ps1:46
- The added tests cover only the no-session branch; the new
$truereturn and the API-failure warning/$falsepath are untested. This suite already uses Pester module mocks, so add a valid synthetic session with mockedInvoke-RestMethodfor both success and a thrown request (including$ErrorActionPreference = 'Stop') to keep the core predicate contract regression-tested.
return $true
- Files reviewed: 6/6 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
It wrote to the host and returned nothing, so `if (Test-InforcerConnection)` was always false — the Test-* verb promised a predicate that was never there. Both failure paths moved from Write-Error to Write-Warning. An error record is the wrong shape for a predicate answering "no", and it throws under `-ErrorAction Stop` or a global $ErrorActionPreference, which would leave the predicate unusable exactly when the connection is broken. A *script-scope* $ErrorActionPreference does not reach a module cmdlet, so that case was never affected — an earlier version of this commit message claimed otherwise. That distinction matters for tests too: the first Stop test asserted on a caller-scope preference and therefore passed whether the cmdlet used Write-Error or Write-Warning. Mutation-testing the success/failure cases caught it. Both Stop assertions now use explicit -ErrorAction Stop, and four of the five tests fail if Write-Error is reintroduced. Blast radius checked before changing: no callers inside the module, none in the InforcerCommunity-MCP server. Only user scripts are affected — those reading -ErrorVariable, passing -ErrorAction Stop, or calling this as a check inside a wrapper function, where False now leaks into that function's output. Migration for all three is in CHANGELOG. Verified against the live API: valid session -> True, no session -> False + warning, bad key -> False without throwing. Closes audit item A9. 471/0/2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3f2fdae to
4a526d1
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Resolve the help/output mismatch and update the breaking-change version and changelog heading.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
module/Public/Test-InforcerConnection.ps1:51
- Returning
$falsefor everyInvoke-RestMethodexception makes a valid narrow-scope session look disconnected. This probe calls/beta/baselines, andConnect-Inforcerdeliberately treats the Inforcer 403 envelope from that endpoint as proof that the key is valid but lacksBaselines.Read(seemodule/Public/Connect-Inforcer.ps1:210-225andTests/Consistency.Tests.ps1:1905-1953). With the documented reconnect pattern, such users will getFalseand repeatedly reconnect; preserve that status/envelope distinction or use a scope-independent probe before mapping the result to a predicate.
Write-Warning "Inforcer connection test failed: $($_.Exception.Message)"
return $false
- Files reviewed: 6/6 changed files
- Comments generated: 2
- Review effort level: Lite
| .OUTPUTS | ||
| None. Writes success or failure to the host. | ||
| System.Boolean. $true when the API responded, $false when it did not or there is no session. | ||
| Status messages go to the host; failures to the warning stream and details to verbose. |
| ## [0.7.3] - 2026-09-14 | ||
|
|
||
| ### Bug Fixes |
It wrote to the host and returned nothing, so
if (Test-InforcerConnection)was always false — the Test-* verb promised a predicate that was never there.Returning a boolean alone would not have fixed it. Verified live: with Write-Error left in place, $ErrorActionPreference = 'Stop' makes the call throw instead of answering, so the predicate stays broken in exactly the strict scripts most likely to check a connection first. Both failure paths moved to Write-Warning; the guardian's error-handling rule gained a Test-* exception.
Blast radius checked before changing: no callers inside the module, none in the InforcerCommunity-MCP server. Only user scripts are affected — those reading -ErrorVariable, or relying on the throw under Stop to abort. One more worth knowing: a wrapper function that calls this as a check now emits False into its own output, so
@(Get-MyWrapper)returns 2 objects where it returned 1. Migration for all three is in CHANGELOG.Verified against the live API: valid session -> True, no session -> False + warning, bad key under Stop -> False without throwing.
Closes audit item A9. 468/0/2.
Summary of changes
Brief description of what this PR does.
Related issue
Fixes #(issue number) — or "None".
Checklist
Invoke-Pester ./Tests/Consistency.Tests.ps1)