The drift report scores whether a required API parameter has a typed parameter on the cmdlet. It does not score whether that parameter is mandatory. Those are different guarantees, and the gap between them is a shape of wire-contract defect the report cannot currently see.
The case that exposed it
Update-PfbLegalHoldEntity → PATCH /legal-holds/held-entities.
In every spec from tools/specs/fb2.17.json through fb2.28.json that operation references #/components/parameters/Legal_holds_release, which resolves to:
name: released
in: query
required: true
The cmdlet declared -Released as an optional [Nullable[bool]] and added the released query key only when the caller explicitly bound it. So this bound cleanly and sent a request the published contract forbids:
Update-PfbLegalHoldEntity -Name 'fs1' -Recursive $true
Reports/PfbApiDriftReport.json carried no gap row for it. The existing -Released parameter satisfied the detector's presence check, so from the report's point of view the endpoint was fully covered. Two of the cmdlet's own .EXAMPLE blocks documented the non-binding shape, and nothing flagged them.
Neither shared helper closes it: Invoke-PfbApiRequest can centrally inject only context_names, and Assert-PfbApiCapability version-checks keys that are already present rather than supplying missing ones.
Why this is not covered by the existing gaps
The report already distinguishes several things well — a missing typed parameter, a missing body property, a dead key sent to an endpoint that does not declare it. What it has no vocabulary for is "the parameter exists, the endpoint requires it, and the cmdlet permits omitting it." That row would be indistinguishable from a healthy one today.
This is also not the same as total_only-style over-exposure, where the cmdlet offers something the endpoint does not accept. Here the direction is reversed: the endpoint demands something the cmdlet treats as optional.
Scope
Evaluate requiredness enforcement separately from typed-parameter presence, so a required-but-optional parameter surfaces as its own gap kind rather than passing as covered.
Two design questions worth settling before implementing:
-
What counts as "enforced"? Mandatory on the ParameterAttribute is the obvious signal, but it is not the only legitimate one. New-PfbObjectStoreAccountExport enforces its required server reference with a throw when neither -ServerName nor -ServerId was supplied, precisely because the requirement is satisfiable two ways and no single parameter can carry Mandatory. A detector keyed only on Mandatory would report that cmdlet as defective when it is the repo's model example. Some AST awareness of the guard-and-throw form is likely needed, or an explicit waiver mechanism.
-
Version-scoped requiredness. max_role on POST /api-clients is required through REST 2.18 and optional-and-deprecated from 2.19. A parameter that must be mandatory on old arrays and must not be on new ones cannot be expressed by Mandatory at all. The detector should say what it expects here rather than picking whichever version happens to be latest.
This is a tooling follow-up. It is not a substitute for fixing the cmdlet — that is being done directly.
Related: #113 (drift report AST scanners miscount coverage two ways) is the nearest existing work on this detector's blind spots, and #124 covers a different one.
Found by the issue #106 Part 2 audit.
The drift report scores whether a required API parameter has a typed parameter on the cmdlet. It does not score whether that parameter is mandatory. Those are different guarantees, and the gap between them is a shape of wire-contract defect the report cannot currently see.
The case that exposed it
Update-PfbLegalHoldEntity→PATCH /legal-holds/held-entities.In every spec from
tools/specs/fb2.17.jsonthroughfb2.28.jsonthat operation references#/components/parameters/Legal_holds_release, which resolves to:The cmdlet declared
-Releasedas an optional[Nullable[bool]]and added thereleasedquery key only when the caller explicitly bound it. So this bound cleanly and sent a request the published contract forbids:Reports/PfbApiDriftReport.jsoncarried no gap row for it. The existing-Releasedparameter satisfied the detector's presence check, so from the report's point of view the endpoint was fully covered. Two of the cmdlet's own.EXAMPLEblocks documented the non-binding shape, and nothing flagged them.Neither shared helper closes it:
Invoke-PfbApiRequestcan centrally inject onlycontext_names, andAssert-PfbApiCapabilityversion-checks keys that are already present rather than supplying missing ones.Why this is not covered by the existing gaps
The report already distinguishes several things well — a missing typed parameter, a missing body property, a dead key sent to an endpoint that does not declare it. What it has no vocabulary for is "the parameter exists, the endpoint requires it, and the cmdlet permits omitting it." That row would be indistinguishable from a healthy one today.
This is also not the same as
total_only-style over-exposure, where the cmdlet offers something the endpoint does not accept. Here the direction is reversed: the endpoint demands something the cmdlet treats as optional.Scope
Evaluate requiredness enforcement separately from typed-parameter presence, so a required-but-optional parameter surfaces as its own gap kind rather than passing as covered.
Two design questions worth settling before implementing:
What counts as "enforced"?
Mandatoryon theParameterAttributeis the obvious signal, but it is not the only legitimate one.New-PfbObjectStoreAccountExportenforces its requiredserverreference with athrowwhen neither-ServerNamenor-ServerIdwas supplied, precisely because the requirement is satisfiable two ways and no single parameter can carryMandatory. A detector keyed only onMandatorywould report that cmdlet as defective when it is the repo's model example. Some AST awareness of the guard-and-throw form is likely needed, or an explicit waiver mechanism.Version-scoped requiredness.
max_roleonPOST /api-clientsis required through REST 2.18 and optional-and-deprecated from 2.19. A parameter that must be mandatory on old arrays and must not be on new ones cannot be expressed byMandatoryat all. The detector should say what it expects here rather than picking whichever version happens to be latest.This is a tooling follow-up. It is not a substitute for fixing the cmdlet — that is being done directly.
Related: #113 (drift report AST scanners miscount coverage two ways) is the nearest existing work on this detector's blind spots, and #124 covers a different one.
Found by the issue #106 Part 2 audit.