Meta Issue: Define extended JSON schema vocabulary for DSC itself and for DSC resource instance schemas
Summary of the new feature / enhancement
As a contributor to DSC, an integrating developer, and a DSC Resource author, I want to be able to use consistent non-standard keywords to simplify and clarify the schemas I author and consume for DSC.
For example, we currently have a few concepts that aren't represented in the standard vocabularies for JSON Schema.
-
Our numeric types use the
formatkeyword with non-standard formats likeuint8- useful for consumers and integrating developers, but only an annotation for most consuming libraries. -
We have the concept of key properties, but no equivalent in JSON Schema. We have two proposals for managing this - defining a canonical
_keysproperty, or defining a keyword likex-keyProperty(for per-property annotation) orx-keyProperties(for per-resource annotation). -
We currently require resource authors to define their canonical properties in their manifests with the
$refkeyword, like:"_exist": { "$ref": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/resource/properties/exist.json" }However, it would be useful for authors to be able to indicate this with a keyword like
x-ensurableorx-canonicalProperties:title: My resource type: object x-ensurable: true properties: path: { type: string }title: My resource type: object x-canonicalProperties: [_exist] properties: path: { type: string } -
We could provide a way to indicate whether a schema is case insensitive with
x-caseInsensitive:title: My resource type: object x-caseInsensitive: false # default properties: path: { type: string } options: type: array items: type: string enum: [foo, bar, baz]title: My resource type: object x-caseInsensitive: true # all property names and values properties: path: { type: string } options: type: array items: type: string enum: [foo, bar, baz]title: My resource type: object properties: path: { type: string } options: type: array items: type: string enum: [foo, bar, baz] x-caseInsensitive: true # Just these values -
We could define annotation keywords for documentation purposes beyond
title/descriptionin the standard vocabulary and the (undocumented)*markdownDescriptionkeywords that VS Code recognizes. -
We could define annotation keywords that indicate other useful information not defineable in the standard vocabulary, like
x-availabilityto indicate when a property was added or deprecated with a short message - you can usedeprecated: trueto indicate that a property is now deprecated, but not why, which usually means adding a message to thedescriptionand hoping it gets read. -
We could support custom formats like
filePathorglob, clarifying expectations (and potentially providing validation) -
We could provide an annotation or validation keyword indicating that a resource requires elevation:
# instance schema for a resource that requires elevation for any operation, even get type: object x-dsc-requiredSecurityContext: elevated# requires elevation only for set and delete type: object x-dsc-requiredSecurityContext: elevated: { operations: [set, delete] }# - requires elevation only for set and delete when condition is met # - shows alternate keyword specifically for requiring elevation type: object allOf: if: properties: { settingsScope: { const: machine } } then: x-dsc-operationsRequireElevation: [set, delete]
We will probably find other useful cases for an extended vocabulary, and can progressively enhance the DevX for resource authors as we do - addressing per-language concerns in that language's resource development kit implementation, but certainly there's value in the annotation keywords (which don't change how a schema is validated or expanded).
Proposed technical implementation details (optional)
I think the most coherent option is to create a separate crate, like dsc_jsonschema, which is concerned primarily[^1] with defining any custom keywords, validation options, etc that we can then consume in dsc_lib and the eventual rust RDK.
This would also make the vocabulary and any other conveniences available more broadly, especially if published to a public repository.
While I proposed a few use cases above, I believe that any cases we decide to tackle should be extracted into sub-issues where the design discussion can be more appropriately contained.
[^1]: Out of scope in this issue, this would also give us a place to coherently place custom transforms / etc for schemars generating schemas to simplify/improve how schemas generate, like creating an enum subschema instead of a oneOf subschema for string enumerations with documentation.