Summary
Private/Test-PfbContextMultiValueCapable.ps1 shipped in #73, but the code that produces its -ContextComponent input did not. The predicate is loaded into the module and cannot be fed from inside it.
Demonstrated against main at 191b7a9:
Import-Module .\PureStorageFlashBladePowerShell.psd1 -Force
Test-PfbContextMultiValueCapable exported: False internal: True
Get-PfbContextParameterFact internal: False
The .psm1 dot-sources only Private/ and Public/; tools/ is never loaded and the manifest has no FileList reaching it. So the three-step component-resolution contract — override key-present-but-null, override key-absent, then the top-level default — is currently reachable only from the maintainer toolchain.
Why it matters
This is a silent failure mode, not a loud one. Nothing is broken today: the predicate is simply inert, with no runtime callers. But the next piece of work is the Fusion context_names injection path, and that path needs resolved component names to call the predicate at all. Built in the obvious order, it will not error — it will quietly reimplement the resolution inside Private/, giving the codebase two copies of a rule whose entire design premise is that it has exactly one declared home.
The key-present-but-null vs key-absent distinction is the part most likely to be reimplemented subtly wrong, because both look like "no value" to a casual reading and only one of them means "this endpoint's parameter has no component."
What needs to happen
Split the resolution step out of Get-PfbContextParameterFact (tools/lib/PfbContextRuleTools.ps1) into Private/, then have both sides consume it:
tools/lib/PfbContextRuleTools.ps1 — for the maintainer drift check, unchanged in behaviour.
- The Fusion injection path — to produce
-ContextComponent for Test-PfbContextMultiValueCapable.
Only the resolution belongs in Private/. Get-PfbContextParameterFact currently also does record-shaping and HTTP 207 merging, and both of those are maintainer-toolchain concerns that should stay in tools/. Untangling those three responsibilities is the actual work; the move itself is small.
Note that tools/ can freely depend on Private/, but not the reverse — which is what fixes the direction of the dependency rather than just relocating it.
Where this is specified
Design doc docs/design/fusion-context-injection.md, section 5, implementation prerequisite 3 — currently in flight as #72 (stacked on #22), which revises the doc to rev 3.
Relationship to the open PRs
Verification
Whoever does it: after the move, Get-PfbContextParameterFact must still be internal-only to tools/, the resolver must be reachable inside the module, and Tests/PfbContextRuleTools.Tests.ps1 (54 tests) plus Tests/Build-PfbApiDriftReport.Tests.ps1 (60 tests) must both stay green — the latter includes the check that the committed Reports/ artifacts still reproduce byte-for-byte.
Summary
Private/Test-PfbContextMultiValueCapable.ps1shipped in #73, but the code that produces its-ContextComponentinput did not. The predicate is loaded into the module and cannot be fed from inside it.Demonstrated against
mainat191b7a9:The
.psm1dot-sources onlyPrivate/andPublic/;tools/is never loaded and the manifest has noFileListreaching it. So the three-step component-resolution contract — override key-present-but-null, override key-absent, then the top-level default — is currently reachable only from the maintainer toolchain.Why it matters
This is a silent failure mode, not a loud one. Nothing is broken today: the predicate is simply inert, with no runtime callers. But the next piece of work is the Fusion
context_namesinjection path, and that path needs resolved component names to call the predicate at all. Built in the obvious order, it will not error — it will quietly reimplement the resolution insidePrivate/, giving the codebase two copies of a rule whose entire design premise is that it has exactly one declared home.The key-present-but-null vs key-absent distinction is the part most likely to be reimplemented subtly wrong, because both look like "no value" to a casual reading and only one of them means "this endpoint's parameter has no component."
What needs to happen
Split the resolution step out of
Get-PfbContextParameterFact(tools/lib/PfbContextRuleTools.ps1) intoPrivate/, then have both sides consume it:tools/lib/PfbContextRuleTools.ps1— for the maintainer drift check, unchanged in behaviour.-ContextComponentforTest-PfbContextMultiValueCapable.Only the resolution belongs in
Private/.Get-PfbContextParameterFactcurrently also does record-shaping and HTTP 207 merging, and both of those are maintainer-toolchain concerns that should stay intools/. Untangling those three responsibilities is the actual work; the move itself is small.Note that
tools/can freely depend onPrivate/, but not the reverse — which is what fixes the direction of the dependency rather than just relocating it.Where this is specified
Design doc
docs/design/fusion-context-injection.md, section 5, implementation prerequisite 3 — currently in flight as #72 (stacked on #22), which revises the doc to rev 3.Relationship to the open PRs
Verification
Whoever does it: after the move,
Get-PfbContextParameterFactmust still be internal-only totools/, the resolver must be reachable inside the module, andTests/PfbContextRuleTools.Tests.ps1(54 tests) plusTests/Build-PfbApiDriftReport.Tests.ps1(60 tests) must both stay green — the latter includes the check that the committedReports/artifacts still reproduce byte-for-byte.