DSC icon indicating copy to clipboard operation
DSC copied to clipboard

Meta Issue: Define extended JSON schema vocabulary for DSC itself and for DSC resource instance schemas

Open michaeltlombardi opened this issue 10 months ago • 0 comments

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 format keyword with non-standard formats like uint8 - 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 _keys property, or defining a keyword like x-keyProperty (for per-property annotation) or x-keyProperties (for per-resource annotation).

  • We currently require resource authors to define their canonical properties in their manifests with the $ref keyword, 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-ensurable or x-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/description in the standard vocabulary and the (undocumented) *markdownDescription keywords that VS Code recognizes.

  • We could define annotation keywords that indicate other useful information not defineable in the standard vocabulary, like x-availability to indicate when a property was added or deprecated with a short message - you can use deprecated: true to indicate that a property is now deprecated, but not why, which usually means adding a message to the description and hoping it gets read.

  • We could support custom formats like filePath or glob, 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.

michaeltlombardi avatar Feb 18 '25 18:02 michaeltlombardi