Summary
fillSchemeKind's default branch exists for a type the compiler does not recognise:
it degrades to AuthKindCustom and keeps the unrecognised token in Scheme, which
TestAuth_SchemeDegradations pins. An entry with no type at all falls into the
same branch, where ss.GetType() is "" — so it interns as a custom scheme whose
mechanism is the empty string. A requirement naming it gets a live AuthID, and the IR
states that the API is authenticated by a scheme that names no mechanism at all.
The same branch also drops whatever the entry did declare. in/name are read only
under type: apiKey, flows only under oauth2, and so on, so an entry that wrote them
without a type loses them entirely — no field, no Unmodeled entry, no diagnostic.
That is a silent drop of declared source text, which "lossless by default" forbids.
Reproduction
Verified at 0ed7683.
openapi: 3.1.0
info: {title: T, version: '1'}
security:
- ghost: []
paths: {}
components:
securitySchemes:
ghost: {in: header, name: X-Key} # no `type`
Interned scheme, with in and name gone:
{"id":"auth/openapi/components/securitySchemes/ghost",
"name":{"source":"ghost","canonical":"ghost"},
"kind":"custom","docs":{},
"provenance":{"source":0,"pointer":"/components/securitySchemes/ghost"}}
and the requirement keeps a live reference to it:
[{"schemes":[{"scheme":"auth/openapi/components/securitySchemes/ghost"}]}]
ghost: {} behaves identically. Compare ghost: {type: bananas}, which is the
degradation the branch was written for and does carry "scheme":"bananas".
Why nothing catches it
Every spec that reaches this state carries a validation-required-field error from the
loader, and harness.Check returns at the first error diagnostic — so irverify never
runs on these documents. It would not catch it anyway: irverify has no AuthScheme
rules, so nothing asserts that an interned scheme names a mechanism. The one existing
test over this branch uses type: bananas, which fills Scheme and so cannot
distinguish "unknown type" from "no type".
Expected
Two things, which may want different answers:
Summary
fillSchemeKind'sdefaultbranch exists for atypethe compiler does not recognise:it degrades to
AuthKindCustomand keeps the unrecognised token inScheme, whichTestAuth_SchemeDegradationspins. An entry with notypeat all falls into thesame branch, where
ss.GetType()is""— so it interns as a custom scheme whosemechanism is the empty string. A requirement naming it gets a live
AuthID, and the IRstates that the API is authenticated by a scheme that names no mechanism at all.
The same branch also drops whatever the entry did declare.
in/nameare read onlyunder
type: apiKey,flowsonly underoauth2, and so on, so an entry that wrote themwithout a
typeloses them entirely — no field, noUnmodeledentry, no diagnostic.That is a silent drop of declared source text, which "lossless by default" forbids.
Reproduction
Verified at
0ed7683.Interned scheme, with
inandnamegone:{"id":"auth/openapi/components/securitySchemes/ghost", "name":{"source":"ghost","canonical":"ghost"}, "kind":"custom","docs":{}, "provenance":{"source":0,"pointer":"/components/securitySchemes/ghost"}}and the requirement keeps a live reference to it:
[{"schemes":[{"scheme":"auth/openapi/components/securitySchemes/ghost"}]}]ghost: {}behaves identically. Compareghost: {type: bananas}, which is thedegradation the branch was written for and does carry
"scheme":"bananas".Why nothing catches it
Every spec that reaches this state carries a
validation-required-fielderror from theloader, and
harness.Checkreturns at the first error diagnostic — soirverifyneverruns on these documents. It would not catch it anyway:
irverifyhas noAuthSchemerules, so nothing asserts that an interned scheme names a mechanism. The one existing
test over this branch uses
type: bananas, which fillsSchemeand so cannotdistinguish "unknown type" from "no type".
Expected
Two things, which may want different answers:
in/name/flowsunder amissing or unrecognised
typeshould keep them — underUnmodeledif the lowered kindhas no home for them — rather than vanishing.
the entry, in which case a requirement naming it drops whole under the rule openapi: security requirement naming an undeclared scheme degrades to "explicitly public" #41
established, or give the empty case a spelling distinguishable from a custom scheme
whose token happens to be known. Note the tension with openapi: security requirement naming an undeclared scheme degrades to "explicitly public" #41: an entry that is present
but invalid is not the same as one that resolves to nothing, so reusing that refusal
needs a deliberate decision rather than an assumption.