diff --git a/crates/registryctl/CHANGELOG.md b/crates/registryctl/CHANGELOG.md index de9aae445..2280dbc1c 100644 --- a/crates/registryctl/CHANGELOG.md +++ b/crates/registryctl/CHANGELOG.md @@ -6,6 +6,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Changed + +- BREAKING: a structured output declares nullability the same way at every + type. Object and array outputs use `type: [object, "null"]` and + `type: ["array", "null"]`, which is what scalar outputs already used, and the + separate `nullable:` key they carried is removed. It shipped on composites + only, in 0.16.0, and never applied to scalars, so one grammar had two ways to + say the same thing depending on the type in hand. Migration: delete + `nullable: true` and pair the declared form with `"null"` in the `type` union; + delete `nullable: false` outright, since a form without `"null"` is already + non-nullable. An authored project that still carries the key is rejected by + `registryctl.authoring.yaml.unknown_field` with the offending pointer and the + union syntax to replace it. The `nullable` field on the compiled Registry + Relay and Registry Notary contracts is a different, internal wire surface and + is unchanged. +- BREAKING: a claim value declares nullability with its `type` union, the same + way scalar outputs, structured outputs, and entity fields already do. Write + `type: [string, "null"]` for a nullable claim value and `type: string` for a + required one, and the separate `nullable:` key is removed. It shipped with + the project authoring workflow in 0.10.0 and was the last place on the + authored surface that spelled nullability a second way. Migration: delete + `nullable: true` and pair the declared type with `"null"` in the `type` + union; delete `nullable: false` outright, since a type without `"null"` is + already non-nullable. An authored project that still carries the key is + rejected by `registryctl.authoring.yaml.unknown_field` with the offending + pointer and the union syntax to replace it. The `nullable` field on the + compiled Registry Relay and Registry Notary contracts is a different, + internal wire surface and is unchanged. + ## [0.16.0] - 2026-08-01 ### Removed diff --git a/crates/registryctl/schemas/project-authoring/documentation-intent.json b/crates/registryctl/schemas/project-authoring/documentation-intent.json index 91b5a2ccf..5d6d21117 100644 --- a/crates/registryctl/schemas/project-authoring/documentation-intent.json +++ b/crates/registryctl/schemas/project-authoring/documentation-intent.json @@ -96,6 +96,10 @@ { "schema": "project", "pointer": "/$defs/consultations/additionalProperties", "path_kind": "map_value" }, { "schema": "project", "pointer": "/$defs/consultations/additionalProperties/properties/input/propertyNames", "path_kind": "map_key" }, { "schema": "project", "pointer": "/$defs/consultations/additionalProperties/properties/input/additionalProperties", "path_kind": "map_value" }, + { "schema": "project", "pointer": "/$defs/claimValueType/oneOf/0", "path_kind": "branch" }, + { "schema": "project", "pointer": "/$defs/claimValueType/oneOf/1", "path_kind": "branch" }, + { "schema": "project", "pointer": "/$defs/claimValueType/oneOf/1/prefixItems/0", "path_kind": "array_item" }, + { "schema": "project", "pointer": "/$defs/claimValueType/oneOf/1/prefixItems/1", "path_kind": "array_item" }, { "schema": "environment", "pointer": "/properties/integrations/propertyNames", "path_kind": "map_key" }, { "schema": "environment", "pointer": "/properties/integrations/additionalProperties", "path_kind": "map_value" }, { "schema": "environment", "pointer": "/properties/entities/propertyNames", "path_kind": "map_key" }, @@ -180,6 +184,14 @@ { "schema": "integration", "pointer": "/$defs/scalarType/oneOf/1", "path_kind": "branch" }, { "schema": "integration", "pointer": "/$defs/scalarType/oneOf/1/prefixItems/0", "path_kind": "array_item" }, { "schema": "integration", "pointer": "/$defs/scalarType/oneOf/1/prefixItems/1", "path_kind": "array_item" }, + { "schema": "integration", "pointer": "/$defs/objectType/oneOf/0", "path_kind": "branch" }, + { "schema": "integration", "pointer": "/$defs/objectType/oneOf/1", "path_kind": "branch" }, + { "schema": "integration", "pointer": "/$defs/objectType/oneOf/1/prefixItems/0", "path_kind": "array_item" }, + { "schema": "integration", "pointer": "/$defs/objectType/oneOf/1/prefixItems/1", "path_kind": "array_item" }, + { "schema": "integration", "pointer": "/$defs/arrayType/oneOf/0", "path_kind": "branch" }, + { "schema": "integration", "pointer": "/$defs/arrayType/oneOf/1", "path_kind": "branch" }, + { "schema": "integration", "pointer": "/$defs/arrayType/oneOf/1/prefixItems/0", "path_kind": "array_item" }, + { "schema": "integration", "pointer": "/$defs/arrayType/oneOf/1/prefixItems/1", "path_kind": "array_item" }, { "schema": "integration", "pointer": "/$defs/versions/anyOf/0", "path_kind": "branch" }, { "schema": "integration", "pointer": "/$defs/versions/anyOf/1", "path_kind": "branch" }, { "schema": "integration", "pointer": "/$defs/versionList/items", "path_kind": "array_item" }, @@ -885,12 +897,7 @@ { "schema": "project", "pointer": "/$defs/claimValue/properties/type", - "purpose": "Declares the boolean, integer, string, or date type of a claim value." - }, - { - "schema": "project", - "pointer": "/$defs/claimValue/properties/nullable", - "purpose": "States whether the claim value may be null." + "purpose": "Declares the boolean, integer, string, or date type of a claim value, paired with null when the claim value may be null." }, { "schema": "project", @@ -1475,12 +1482,7 @@ { "schema": "integration", "pointer": "/$defs/outputObject/properties/type", - "purpose": "Selects the closed object form for a structured integration output." - }, - { - "schema": "integration", - "pointer": "/$defs/outputObject/properties/nullable", - "purpose": "Declares whether the complete structured output object may be null." + "purpose": "Selects the closed object form for a structured integration output, and declares the object nullable by pairing it with null." }, { "schema": "integration", @@ -1495,12 +1497,7 @@ { "schema": "integration", "pointer": "/$defs/outputArray/properties/type", - "purpose": "Selects the array form for a structured integration output." - }, - { - "schema": "integration", - "pointer": "/$defs/outputArray/properties/nullable", - "purpose": "Declares whether the complete structured output array may be null." + "purpose": "Selects the array form for a structured integration output, and declares the array nullable by pairing it with null." }, { "schema": "integration", diff --git a/crates/registryctl/schemas/project-authoring/dto-shape-contract.v1.json b/crates/registryctl/schemas/project-authoring/dto-shape-contract.v1.json index fe8ccb96d..df45ae998 100644 --- a/crates/registryctl/schemas/project-authoring/dto-shape-contract.v1.json +++ b/crates/registryctl/schemas/project-authoring/dto-shape-contract.v1.json @@ -24,6 +24,34 @@ }, "type": "object" }, + "AuthoredNullType": { + "description": "The `\"null\"` member of an authored composite `type` union.", + "enum": [ + "null" + ], + "type": "string" + }, + "AuthoredNullableType": { + "anyOf": [ + { + "$ref": "#/$defs/ClaimValueType" + }, + { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "$ref": "#/$defs/ClaimValueType" + }, + { + "$ref": "#/$defs/AuthoredNullType" + } + ], + "type": "array" + } + ], + "description": "The one authored nullability idiom, shared with `AuthoredSchemaType`.\n\nScalar, object, array, and claim-value declarations all express nullability\nas the JSON-Schema-native `type` union `[