diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 95db0ed..36f5e4a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -18,6 +18,8 @@ "postStartCommand": ".devcontainer/post.sh start", "containerEnv": { "GEM_REPO": "https://rubygems.org", - "NPM_CONFIG_REGISTRY": "https://registry.npmjs.org" + "NPM_CONFIG_REGISTRY": "https://registry.npmjs.org", + "NODE_EXTRA_CA_CERTS": "/workspaces/spec/.devcontainer/root.pem" + } } diff --git a/docs/Gemfile b/docs/Gemfile index b10a16e..56bef89 100644 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -1,8 +1,6 @@ source ENV['GEM_REPO'] -gem "faraday", '>= 2.9', '< 2.10' - -gem "github-pages", "~> 228", group: :jekyll_plugins +gem "github-pages", "~> 232", group: :jekyll_plugins gem "webrick", "~> 1.8" diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 5a6c239..068205b 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,16 +1,17 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.1.3.4) + activesupport (7.2.0) base64 bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) base64 (0.2.0) @@ -18,11 +19,12 @@ GEM coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.11.1) + coffee-script-source (1.12.2) colorator (1.1.0) commonmarker (0.23.10) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) + csv (3.3.0) dnsruby (1.72.2) simpleidn (~> 0.2.1) drb (2.2.1) @@ -33,23 +35,24 @@ GEM ffi (>= 1.15.0) eventmachine (1.2.7) execjs (2.9.1) - faraday (2.9.2) + faraday (2.10.1) faraday-net_http (>= 2.0, < 3.2) + logger faraday-net_http (3.1.1) net-http ffi (1.17.0) forwardable-extended (2.6.0) - gemoji (3.0.1) - github-pages (228) - github-pages-health-check (= 1.17.9) - jekyll (= 3.9.3) - jekyll-avatar (= 0.7.0) - jekyll-coffeescript (= 1.1.1) - jekyll-commonmark-ghpages (= 0.4.0) - jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.15.1) + gemoji (4.1.0) + github-pages (232) + github-pages-health-check (= 1.18.2) + jekyll (= 3.10.0) + jekyll-avatar (= 0.8.0) + jekyll-coffeescript (= 1.2.2) + jekyll-commonmark-ghpages (= 0.5.1) + jekyll-default-layout (= 0.1.5) + jekyll-feed (= 0.17.0) jekyll-gist (= 1.5.0) - jekyll-github-metadata (= 2.13.0) + jekyll-github-metadata (= 2.16.1) jekyll-include-cache (= 0.2.1) jekyll-mentions (= 1.6.0) jekyll-optional-front-matter (= 0.3.2) @@ -76,20 +79,21 @@ GEM jekyll-theme-tactile (= 0.2.0) jekyll-theme-time-machine (= 0.2.0) jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.12.0) - kramdown (= 2.3.2) + jemoji (= 0.13.0) + kramdown (= 2.4.0) kramdown-parser-gfm (= 1.1.0) liquid (= 4.0.4) mercenary (~> 0.3) minima (= 2.5.1) - nokogiri (>= 1.13.6, < 2.0) - rouge (= 3.26.0) + nokogiri (>= 1.16.2, < 2.0) + rouge (= 3.30.0) terminal-table (~> 1.4) - github-pages-health-check (1.17.9) + webrick (~> 1.8) + github-pages-health-check (1.18.2) addressable (~> 2.3) dnsruby (~> 1.60) - octokit (~> 4.0) - public_suffix (>= 3.0, < 5.0) + octokit (>= 4, < 8) + public_suffix (>= 3.0, < 6.0) typhoeus (~> 1.3) html-pipeline (2.14.3) activesupport (>= 2) @@ -97,9 +101,10 @@ GEM http_parser.rb (0.8.0) i18n (1.14.5) concurrent-ruby (~> 1.0) - jekyll (3.9.3) + jekyll (3.10.0) addressable (~> 2.4) colorator (~> 1.0) + csv (~> 3.0) em-websocket (~> 0.5) i18n (>= 0.7, < 2) jekyll-sass-converter (~> 1.0) @@ -110,27 +115,28 @@ GEM pathutil (~> 0.9) rouge (>= 1.7, < 4) safe_yaml (~> 1.0) - jekyll-avatar (0.7.0) + webrick (>= 1.0) + jekyll-avatar (0.8.0) jekyll (>= 3.0, < 5.0) - jekyll-coffeescript (1.1.1) + jekyll-coffeescript (1.2.2) coffee-script (~> 2.2) - coffee-script-source (~> 1.11.1) + coffee-script-source (~> 1.12) jekyll-commonmark (1.4.0) commonmarker (~> 0.22) - jekyll-commonmark-ghpages (0.4.0) - commonmarker (~> 0.23.7) - jekyll (~> 3.9.0) + jekyll-commonmark-ghpages (0.5.1) + commonmarker (>= 0.23.7, < 1.1.0) + jekyll (>= 3.9, < 4.0) jekyll-commonmark (~> 1.4.0) rouge (>= 2.0, < 5.0) - jekyll-default-layout (0.1.4) - jekyll (~> 3.0) - jekyll-feed (0.15.1) + jekyll-default-layout (0.1.5) + jekyll (>= 3.0, < 5.0) + jekyll-feed (0.17.0) jekyll (>= 3.7, < 5.0) jekyll-gist (1.5.0) octokit (~> 4.2) - jekyll-github-metadata (2.13.0) + jekyll-github-metadata (2.16.1) jekyll (>= 3.4, < 5.0) - octokit (~> 4.0, != 4.4.0) + octokit (>= 4, < 7, != 4.4.0) jekyll-include-cache (0.2.1) jekyll (>= 3.7, < 5.0) jekyll-mentions (1.6.0) @@ -201,16 +207,16 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - jemoji (0.12.0) - gemoji (~> 3.0) + jemoji (0.13.0) + gemoji (>= 3, < 5) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - just-the-docs (0.8.2) + just-the-docs (0.9.0) jekyll (>= 3.8.5) jekyll-include-cache jekyll-seo-tag (>= 2.0) rake (>= 12.3.1) - kramdown (2.3.2) + kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) @@ -218,13 +224,13 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.0) mercenary (0.3.6) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.24.1) - mutex_m (0.2.0) + minitest (5.25.1) net-http (0.4.1) uri nokogiri (1.16.7-x86_64-linux) @@ -234,15 +240,15 @@ GEM sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (4.0.7) - racc (1.8.0) + public_suffix (5.1.1) + racc (1.8.1) rake (13.2.1) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rexml (3.3.2) + rexml (3.3.5) strscan - rouge (3.26.0) + rouge (3.30.0) rubyzip (2.3.2) safe_yaml (1.0.5) sass (3.7.4) @@ -253,6 +259,7 @@ GEM sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) + securerandom (0.3.1) simpleidn (0.2.3) strscan (3.1.0) terminal-table (1.8.0) @@ -269,8 +276,7 @@ PLATFORMS x86_64-linux DEPENDENCIES - faraday (>= 2.9, < 2.10) - github-pages (~> 228) + github-pages (~> 232) jekyll-redirect-from just-the-docs webrick (~> 1.8) diff --git a/docs/_data/components/parameters/monitoring-set-filter.yaml b/docs/_data/components/parameters/monitoring-set-filter.yaml index 4999b49..929ef56 100644 --- a/docs/_data/components/parameters/monitoring-set-filter.yaml +++ b/docs/_data/components/parameters/monitoring-set-filter.yaml @@ -11,5 +11,5 @@ schema: $ref: ../schemas/generic-identifier.yaml examples: nerc-id: - summary: A NERC id that nominates a `monitoring-set`. + summary: A pre-coordinated id that nominates a `monitoring-set`. value: "X-AMPL" diff --git a/docs/_data/components/schemas/array-max-monitored-elements.yaml b/docs/_data/components/schemas/array-max-monitored-elements.yaml index b42338a..c04df7a 100644 --- a/docs/_data/components/schemas/array-max-monitored-elements.yaml +++ b/docs/_data/components/schemas/array-max-monitored-elements.yaml @@ -7,7 +7,7 @@ forecast-limits-snapshot: limits: &max type: array minItems: 0 - maxItems: &max-facilities 50000 + maxItems: &max-facilities 50000 description: Set of forecast limits items: $ref: 'array-max-forecast-periods.yaml#/forecast-limit-item' @@ -28,12 +28,19 @@ forecast-limits-detailed-snapshot: items: $ref: 'array-max-forecast-periods.yaml#/forecast-limit-item-detailed' -named-power-system-resources: +named-power-system-resources: &psr <<: *max description: Collection of power system resource names items: $ref: ./names.yaml +ordered-named-power-system-resources: + <<: *psr + description: | + + Ordered array of power system resource names. The order of these items + determines the order of the ratings proposals in the `ratings` array. + forecast-proposal: type: object properties: @@ -58,7 +65,7 @@ common-proposal-status: not been met in this forecast window. This number may be larger than the size of `incomplete-facilities`, since the latter has a pre-defined upper bound for performance and application security reasons. - + ⚠️ **The Ratings Provider should check that this value is zero when they believe they have completed their submission process.️** ⚠️ @@ -67,7 +74,7 @@ common-proposal-status: minimum: 0 maximum: *max-facilities - incomplete-obligations: + incomplete-obligations: &incomplete-obligations type: array description: | @@ -96,13 +103,22 @@ common-proposal-status: proposal-validation-errors: type: array - description: The most recent validation errors + description: The most recent validation errors minItems: 0 maxItems: 50 items: type: object additionalProperties: false - description: Validation errors. + description: | + Validation errors. + + Note to implementors, the property `resource-id` intentionally is not `names` + as was used in `incomplete-obligations` to mitigate the + possibility of information disclosure when a Ratings Provider + submits a proposal for a valid resource that they are not + permitted to write to. It should be the same `resource-id` that + the client submitted. + properties: message: type: string @@ -110,12 +126,6 @@ common-proposal-status: maxLength: 500 example: The `resource-forecast-proposal` for `8badf00d` is incomplete. resource-id: - # NOTE to implementors: This intentionally is not `names` - # as was used in `incomplete-obligations` to mitigate the - # possibility of information disclosure when a Ratings Provider - # submits a proposal for a valid resource that they are not - # permitted to write to. It should be the same `resource-id` that - # the client submitted. $ref: ./resource-id.yaml required: @@ -124,13 +134,15 @@ common-proposal-status: - invalid-proposal-count - proposal-validation-errors - forecast-proposal-status: type: object description: | - Status of the rating provider's forecast proposal relative to the current - forecast window. Includes any validation errors encountered while processing proposals. - properties: + + Status of the rating provider's forecast proposal relative to the current + forecast window. Includes any validation errors encountered while + processing proposals. + + properties: <<: *common-proposal-status-props forecast-provider: $ref: ./data-provenance.yaml @@ -143,15 +155,15 @@ forecast-proposal-status: - incomplete-obligation-count - incomplete-obligations - invalid-proposal-count - - proposal-validation-errors + - proposal-validation-errors real-time-proposal-status: type: object description: | - Status of the rating provider's real-time obligations. - Includes any validation errors encountered while processing proposals. + Status of the rating provider's real-time obligations. + Includes any validation errors encountered while processing proposals. properties: - <<: *common-proposal-status-props + <<: *common-proposal-status-props ratings-provider: $ref: ./data-provenance.yaml required: @@ -159,8 +171,7 @@ real-time-proposal-status: - incomplete-obligation-count - incomplete-obligations - invalid-proposal-count - - proposal-validation-errors - + - proposal-validation-errors realtime-limits-snapshot: type: object @@ -197,50 +208,98 @@ realtime-proposal: items: type: object description: > - Real-time ratings data for a segment. + Real-time ratings data for a segment. allOf: - type: object properties: - resource-id: + resource-id: $ref: ./resource-id.yaml - $ref: ./limit-proposal.yaml required: - resource-id - continuous-operating-limit - emergency-operating-limits - + required: - proposal-header - ratings -seasonal-rating-proposal: - description: Seasonal rating proposal - allOf: - - $ref: ./mutable-rating-proposal.yaml - - type: object - properties: - ratings: - <<: *max - items: - $ref: 'array-max-seasons.yaml#/seasonal-proposals' - -seasonal-rating-snapshot: +seasonal-ratings-proposal: type: object - description: A snapshot of the realtime limits for a monitoring set. properties: + proposal-header: + $ref: ./headers.yaml#/seasonal-proposal-header + ratings: + <<: *max + description: Seasonal Ratings proposals + items: + $ref: 'array-max-seasons.yaml#/seasonal-proposals' + required: + - proposal-header + - ratings + +seasonal-ratings-proposal-slim: + type: object + properties: + proposal-header: + $ref: ./headers.yaml#/seasonal-proposal-header-slim + ratings: + <<: *max + description: Seasonal Ratings proposals (slim) + items: + $ref: 'array-max-seasons.yaml#/seasonal-proposals-slim' + required: + - proposal-header + - ratings + +seasonal-ratings-proposal-status: + type: object + description: Seasonal rating proposal status + properties: + <<: *common-proposal-status-props + incomplete-obligations: + <<: *incomplete-obligations + description: | + + Indicates which Seasonal Ratings Obligations have not been fulfilled. + The size of this set is bounded and may be less than the actual count of + unfulfilled Obligations indicated in `incomplete-obligation-count`. + items: + $ref: ./array-max-seasons.yaml#/missing-seasonal-obligation + provider-info: + $ref: ./data-provenance.yaml + required: + - provider-info + - incomplete-obligation-count + - invalid-proposal-count + +seasonal-ratings-snapshot: + type: object + description: A snapshot of the seasonal ratings for a monitoring set. + properties: &seasonal-rating-snapshot-props snapshot-header: $ref: ./headers.yaml#/common-header - limits: + ratings: <<: *max - description: Seasonal rating snapshot items: $ref: ./array-max-seasons.yaml#/seasonal-rating-snapshot-item + +seasonal-ratings-snapshot-detailed: + description: A snapshot of the seasonal ratings for a monitoring set. + properties: + <<: *seasonal-rating-snapshot-props + ratings: + <<: *max + items: + $ref: ./array-max-seasons.yaml#/seasonal-rating-snapshot-item-detailed + temporary-aar-exception-set: type: array minItems: 0 maxItems: *max-facilities items: $ref: ./time-bound-static-ratings.yaml#/temporary-aar-exception + seasonal-override-set: type: array minItems: 0 diff --git a/docs/_data/components/schemas/array-max-seasons.yaml b/docs/_data/components/schemas/array-max-seasons.yaml index ff12131..1277246 100644 --- a/docs/_data/components/schemas/array-max-seasons.yaml +++ b/docs/_data/components/schemas/array-max-seasons.yaml @@ -1,22 +1,89 @@ +season: + type: object + properties: + season-name: + $ref: ./season-name.yaml + begins: + $ref: ./period-start.yaml + required: + - season-name + - begins + +seasonal-schedule: &schedule + description: | + + Defines the seasonal ratings schedule adopted in this proposal. Each season + is given a `season-name` with the beginning of the season starting on + `begins` and ending on the `begins` of the next season chronologically. + + It is required that the seasons are listed chronologically. + + type: array + minItems: 1 + maxItems: 240 # monthly "seasons" for twenty years + items: + $ref: '#/season' + seasonal-proposals: + x-tags: + - Seasonal + title: Per-Resource Seasonal Ratings Schedule type: object additionalProperties: false properties: - resource-id: + resource-id: &id $ref: ./resource-id.yaml - seasons: &max - type: array - maxItems: 20 - minItems: 0 + periods: + <<: *schedule + items: + $ref: ./seasonal-rating-period.yaml#/proposal + +missing-seasonal-obligation: + type: object + additionalProperties: false + properties: + resource-id: *id + obligation-period-begins: # nominates the beginning of the seasonal rating obligation window + $ref: ./period-start.yaml + obligation-period-ends: # nominates the end of seasonal rating obligation window + $ref: ./period-start.yaml + periods: + <<: *schedule items: - $ref: ./seasonal-proposal-season.yaml + $ref: '#/season' + +seasonal-proposals-slim: + <<: *schedule + x-tags: + - Seasonal + title: Per-Resource Seasonal Ratings Schedule (slim) + description: | + + A proposal for the seasonal ratings for a power system object, e.g., a + segment. The proposal's structure is determined by the contents of the + `proposal-header`. In particular, this element should have an entry corresponding + to each season in the `default-seasonal-schedule`. + + items: + $ref: ./seasonal-rating-period.yaml#/proposal-slim + example: [[50, 55, 60, 65], [70, 75, 80, 85], [90, 95, 100, 105],[90, 95, 100, 105]] + seasonal-rating-snapshot-item: type: object additionalProperties: false properties: - resource-id: - $ref: ./resource-id.yaml - seasons: - <<: *max + resource-id: *id + periods: + <<: *schedule + items: + $ref: ./seasonal-rating-period.yaml#/snapshot + +seasonal-rating-snapshot-item-detailed: + type: object + additionalProperties: false + properties: + resource-id: *id + periods: + <<: *schedule items: - $ref: ./seasonal-rating-snapshot-value.yaml + $ref: ./seasonal-rating-period.yaml#/snapshot-detailed diff --git a/docs/_data/components/schemas/conditional-value-set.yaml b/docs/_data/components/schemas/conditional-value-set.yaml deleted file mode 100644 index 121c76d..0000000 --- a/docs/_data/components/schemas/conditional-value-set.yaml +++ /dev/null @@ -1,14 +0,0 @@ -type: array -description: > - List of alternative ratings for rating altering conditions on the segment. -minItems: 1 -maxItems: 100 -items: - type: object - properties: - condition: - $ref: ./network-component-name.yaml - continuous-operating-limit: - $ref: ./limit.yaml - emergency-operating-limits: - $ref: ./array-max-emergency-durations.yaml#/limit-value-set diff --git a/docs/_data/components/schemas/day-night.yaml b/docs/_data/components/schemas/day-night.yaml new file mode 100644 index 0000000..c911f4b --- /dev/null +++ b/docs/_data/components/schemas/day-night.yaml @@ -0,0 +1,10 @@ +description: | + + Optional label to specify if the proposed seasonal ratings schedule is meant + to be used only during the day or only a night. If this field is not provided, + the schedule is assumed to be valid for both day and night. + +type: string +enum: + - DAY + - NIGHT diff --git a/docs/_data/components/schemas/forecast-limit-period.yaml b/docs/_data/components/schemas/forecast-limit-period.yaml index 0454c4a..168e319 100644 --- a/docs/_data/components/schemas/forecast-limit-period.yaml +++ b/docs/_data/components/schemas/forecast-limit-period.yaml @@ -24,7 +24,7 @@ proposal: - $ref: ./limit-proposal.yaml proposal-considered: - type: object + description: Details a proposal that was considered by the Clearinghouse run. allOf: - $ref: '#/proposal' @@ -35,13 +35,13 @@ proposal-considered: proposal-disposition: description: | - Despite a proposal being accepted by TROLIE, the downstream - Clearinghouse logic may still disqualify a proposal. This might - occur if, for example, the upper and lower reasonability limits - are not aligned between TROLIE and the Clearinghouse. To aid - troubleshooting, the specification requires that TROLIE instances - explicitly indicate if the proposal was `Used` in the - determination of the limit or was `Rejected`. + Despite a proposal being accepted by TROLIE, the downstream + Clearinghouse logic may still disqualify a proposal. This might + occur if, for example, the upper and lower reasonability limits are + not aligned between TROLIE and the Clearinghouse. To aid + troubleshooting, the specification requires that TROLIE instances + explicitly indicate if the proposal was `Used` in the determination + of the limit or was `Rejected`. type: string enum: diff --git a/docs/_data/components/schemas/forecast-rating-period-deprecated.yaml b/docs/_data/components/schemas/forecast-rating-period-deprecated.yaml deleted file mode 100644 index ce99475..0000000 --- a/docs/_data/components/schemas/forecast-rating-period-deprecated.yaml +++ /dev/null @@ -1,38 +0,0 @@ -type: object -additionalProperties: false -description: > - Forecast ratings data for a segment and period. Includes status of the - - proposal relative to this data, as well as rating values. - - It also optionally may include a set of "branch-only" ratings. - - While forecast ratings in the "values" fields should be based on - - ambient conditions, they may also be limited by current topology. - - The ratings provider should take this into account when populating the - - values field for the proposal. - - - However, since this is a forecast, the Transmission Provider may run various - - look-ahead functions that change this topology such that it is no longer a - limiting factor. - - To accommodate these scenarios, a "branch-only" rating should be sent that - does not factor in - - topology. -properties: - period-start: - $ref: ./period-start.yaml - status: - $ref: ./proposal-status.yaml - continuous-operating-limit: - $ref: ./limit.yaml - emergency-operating-limits: - $ref: ./array-max-emergency-durations.yaml#/limit-value-set - branch-only-values: - $ref: ./array-max-emergency-durations.yaml#/limit-value-set diff --git a/docs/_data/components/schemas/headers.yaml b/docs/_data/components/schemas/headers.yaml index c123db0..a9a0767 100644 --- a/docs/_data/components/schemas/headers.yaml +++ b/docs/_data/components/schemas/headers.yaml @@ -10,30 +10,29 @@ common-header: &common-header power-system-resources: $ref: ./array-max-monitored-elements.yaml#/named-power-system-resources - required: + required: - source - default-emergency-durations - power-system-resources additionalProperties: false -real-time-proposal-header: &real-time-header +real-time-proposal-header: <<: *common-header description: | - Populated by the Ratings Provider in a request to submit real-time ratings. - The Clearinghouse implementation should record this information, - and the detail limits snapshot should should reflect the + Populated by the Ratings Provider in a request to submit real-time ratings. + The Clearinghouse implementation should record this information, + and the detail limits snapshot should should reflect the appropriate metadata from the Clearinghouse Provider's perspective. - -forecast-proposal-header: &forecast-header +forecast-proposal-header: <<: *common-header description: | - Populated by the Ratings Provider in a request to submit forecast ratings. - The Clearinghouse implementation should record this information, - and the detail limits snapshot should should reflect the + Populated by the Ratings Provider in a request to submit forecast ratings. + The Clearinghouse implementation should record this information, + and the detail limits snapshot should should reflect the appropriate metadata from the Clearinghouse Provider's perspective. @@ -56,8 +55,7 @@ forecast-proposal-header: &forecast-header - begins - source - default-emergency-durations - - power-system-resources - + - power-system-resources forecast-snapshot-header: description: Details about the snapshot provided by the Clearinghouse provider. @@ -83,7 +81,6 @@ forecast-snapshot-header: - snapshot-provenance - power-system-resources - real-time-snapshot-header: description: Details about the snapshot provided by the Clearinghouse provider. properties: @@ -98,4 +95,49 @@ real-time-snapshot-header: required: - last-updated - snapshot-provenance - - power-system-resources + - power-system-resources + +seasonal-proposal-header: + <<: *common-header + description: | + + Describes the contents of this seasonal ratings proposal. + + +seasonal-proposal-header-slim: + <<: *common-header + description: | + + Describes the contents of the seasonal proposal. In particular, the + structure of the `ratings` is determined by the details provided in this + header. + + properties: + <<: *common-header-props + power-system-resources: + $ref: ./array-max-monitored-elements.yaml#/ordered-named-power-system-resources + default-seasonal-schedule: + description: | + + Defines the seasonal schedule that is used in the proposal. Each season + is defined in the `schedule` array and the `ends` property defines the + end of the last season. + + Each individual facility proposal must have + + properties: + schedule: + $ref: ./array-max-seasons.yaml#/seasonal-schedule + ends: + $ref: ./period-start.yaml + day-night: + $ref: ./day-night.yaml + required: + - schedule + - ends + + required: + - source + - default-emergency-durations + - power-system-resources + - default-seasonal-schedule diff --git a/docs/_data/components/schemas/limit-types/active-power.yaml b/docs/_data/components/schemas/limit-types/active-power.yaml index 6037058..4a3bcff 100644 --- a/docs/_data/components/schemas/limit-types/active-power.yaml +++ b/docs/_data/components/schemas/limit-types/active-power.yaml @@ -1,20 +1,19 @@ type: object -title: Active Power and Power Factor -description: | - - Representation of a limit using a combination of active power in MW and an - assumed power factor. N.b. power factor is optional in the spec though it - may be required in a particular exchange. - additionalProperties: false properties: mw: type: number + description: Active Power in megawatts format: float minimum: 1 maximum: 10000 pf: type: number + description: | + Assumed power factor. + + N.b. power factor is optional in the spec though it may be required in a + particular exchange. format: float minimum: 0 maximum: 1 diff --git a/docs/_data/components/schemas/limit-types/apparent-power.yaml b/docs/_data/components/schemas/limit-types/apparent-power.yaml index 641cc5a..31484b0 100644 --- a/docs/_data/components/schemas/limit-types/apparent-power.yaml +++ b/docs/_data/components/schemas/limit-types/apparent-power.yaml @@ -1,12 +1,9 @@ type: object -title: Apparent Power -description: >- - Representation of a limit in megavolt-amperes (MVA). This is the recommended - default for limits in TROLIE additionalProperties: false properties: mva: type: number + description: Representation of a limit in megavolt-amperes (MVA). format: float minimum: 1 maximum: 10000 diff --git a/docs/_data/components/schemas/limit-types/current.yaml b/docs/_data/components/schemas/limit-types/current.yaml index a044d5c..01a7264 100644 --- a/docs/_data/components/schemas/limit-types/current.yaml +++ b/docs/_data/components/schemas/limit-types/current.yaml @@ -1,12 +1,11 @@ type: object -title: Current -description: >- - Representation of a limit in amperes. Assumes that TROLIE has a nominal voltage - in its model. additionalProperties: false properties: amps: type: number + description: >- + Representation of a limit in amperes. Assumes that Clearinghouse Provider + has the nominal voltage in its model. format: float minimum: 1 maximum: 100000 diff --git a/docs/_data/components/schemas/limit-types/reactive-power.yaml b/docs/_data/components/schemas/limit-types/reactive-power.yaml index 0e2a6e3..8c78970 100644 --- a/docs/_data/components/schemas/limit-types/reactive-power.yaml +++ b/docs/_data/components/schemas/limit-types/reactive-power.yaml @@ -1,10 +1,9 @@ type: object -title: Reactive Power -description: Representation of a limit in megavolt-amperes reactive (MVAR). additionalProperties: false properties: mvar: type: number + description: Representation of a limit in megavolt-amperes reactive (MVAR). format: float minimum: -10000 maximum: 10000 diff --git a/docs/_data/components/schemas/limit-types/voltage.yaml b/docs/_data/components/schemas/limit-types/voltage.yaml index d272d7e..c1aea7c 100644 --- a/docs/_data/components/schemas/limit-types/voltage.yaml +++ b/docs/_data/components/schemas/limit-types/voltage.yaml @@ -1,16 +1,18 @@ overvoltage-threshold-pu: type: object - title: Overvoltage Threshold per unit - description: An upper limit to voltage for a transmission facility in per unit. additionalProperties: false properties: voltage-pu-max: &pu type: number + description: > + An upper limit to voltage for a transmission facility in per unit. format: float minimum: 0 maximum: 2 base-kV: &voltage type: number + description: > + The base voltage in kilovolts for the per unit voltage. format: int32 minimum: 0 maximum: 1100 @@ -19,31 +21,32 @@ overvoltage-threshold-pu: overvoltage-threshold: type: object - title: Overvoltage Threshold - description: An upper limit to voltage for a transmission facility in kilovolts. additionalProperties: false properties: - kV-max: *voltage + kV-max: + <<: *voltage + description: > + An upper limit to voltage for a transmission facility in kilovolts. required: - kV-max undervoltage-threshold-pu: type: object - title: Undervoltage Threshold per unit - description: An lower limit to voltage for a transmission facility in per unit. additionalProperties: false properties: - voltage-pu-min: *pu + voltage-pu-min: + <<: *pu + description: An lower limit to voltage for a transmission facility in per unit. base-kV: *voltage required: - voltage-pu-min undervoltage-threshold: type: object - title: Undervoltage Threshold - description: A lower limit to voltage for a transmission facility in kilovolts. additionalProperties: false properties: - kV-min: *voltage + kV-min: + <<: *voltage + description: A lower limit to voltage for a transmission facility in kilovolts. required: - kV-min diff --git a/docs/_data/components/schemas/limit.yaml b/docs/_data/components/schemas/limit.yaml index e38148d..adba318 100644 --- a/docs/_data/components/schemas/limit.yaml +++ b/docs/_data/components/schemas/limit.yaml @@ -1,3 +1,5 @@ +type: object +title: Limit description: | Defines the limit. In practice, most exchanges will only support one kind of diff --git a/docs/_data/components/schemas/mutable-rating-proposal.yaml b/docs/_data/components/schemas/mutable-rating-proposal.yaml index 001eff5..1ebff14 100644 --- a/docs/_data/components/schemas/mutable-rating-proposal.yaml +++ b/docs/_data/components/schemas/mutable-rating-proposal.yaml @@ -1,21 +1,9 @@ type: object description: > - General type for ratings proposal that is mutable over time, such as forecasts - and seasonal ratings. - Like the immutable proposal, it includes general fields created by the - system. + Used as a base type for mutable ratings proposals, i.e., forecast and seasonal + ratings. - Filling in these fields before posting may be ignored, or result in a 400 - error from TROLIE. - - Properties include: - - * The time the proposal was last updated. - - * The ratings provider that owns the proposal. For mutable proposals such as - those for forecasts or seasonal - ratings, the ID of the owning ratings provider is the ID of the proposal itself. properties: last-updated: $ref: ./timestamp.yaml diff --git a/docs/_data/components/schemas/proposal-status.yaml b/docs/_data/components/schemas/proposal-status.yaml deleted file mode 100644 index 75344a6..0000000 --- a/docs/_data/components/schemas/proposal-status.yaml +++ /dev/null @@ -1,24 +0,0 @@ -type: string -description: > - Enumeration of the possible statuses of a proposal, or parts of a proposal. - Note that submissions of proposals do not - - set this value. It is system-generated after submission. The following - values are possible: - - * *pending* indicates that the system has not yet processed this proposal. - - * *accepted* indicates that the proposal has been accepted, and is now the - basis for the associated ratings / limit - snapshot. - * *superseded* indicates that the proposal was superseded to a more - conservative rating. This rating may have - come from another party, as may be the case on jointly owned equipment or tie lines, or it may have come from a - topological condition on the network such that some related equipment is now forcing a more conservative limit. - * *overridden* indicates that the proposal was overridden manually by an - operator for the Transmission Provider. -enum: - - pending - - accepted - - superseded - - overridden diff --git a/docs/_data/components/schemas/season-instance-set.yaml b/docs/_data/components/schemas/season-instance-set.yaml deleted file mode 100644 index 8a7fb56..0000000 --- a/docs/_data/components/schemas/season-instance-set.yaml +++ /dev/null @@ -1,5 +0,0 @@ -type: array -minItems: 0 -maxItems: 100 -items: - $ref: ./season-instance.yaml diff --git a/docs/_data/components/schemas/season-instance.yaml b/docs/_data/components/schemas/season-instance.yaml deleted file mode 100644 index c17a107..0000000 --- a/docs/_data/components/schemas/season-instance.yaml +++ /dev/null @@ -1,15 +0,0 @@ -type: object -additionalProperties: false -properties: - season: - $ref: ./generic-identifier.yaml - id: - $ref: ./generic-identifier.yaml - effective-time: - $ref: ./period-start.yaml - active: - description: Set to true if this season is currently active - type: boolean -required: - - id - - active diff --git a/docs/_data/components/schemas/season-name.yaml b/docs/_data/components/schemas/season-name.yaml new file mode 100644 index 0000000..c258d6b --- /dev/null +++ b/docs/_data/components/schemas/season-name.yaml @@ -0,0 +1,4 @@ +type: string +description: A name for the season +maxLength: 255 +pattern: \w+ \ No newline at end of file diff --git a/docs/_data/components/schemas/seasonal-proposal-season.yaml b/docs/_data/components/schemas/seasonal-proposal-season.yaml deleted file mode 100644 index d39e9f8..0000000 --- a/docs/_data/components/schemas/seasonal-proposal-season.yaml +++ /dev/null @@ -1,19 +0,0 @@ -type: object -description: > - Seasonal ratings data for a segment. Includes status of the proposal relative - to this data, as well as rating values. - - Also includes a set of values for rating altering conditions on the segment, - should they apply. -additionalProperties: false -properties: - season-id: - $ref: ./generic-identifier.yaml - status: - $ref: ./proposal-status.yaml - continuous-operating-limit: - $ref: ./limit.yaml - emergency-operating-limits: - $ref: ./array-max-emergency-durations.yaml#/limit-value-set - conditional-values: - $ref: ./conditional-value-set.yaml diff --git a/docs/_data/components/schemas/seasonal-rating-period.yaml b/docs/_data/components/schemas/seasonal-rating-period.yaml new file mode 100644 index 0000000..5ac9d2b --- /dev/null +++ b/docs/_data/components/schemas/seasonal-rating-period.yaml @@ -0,0 +1,95 @@ +proposal: + type: object + description: Proposes the continuous and emergency ratings for the specified Season. + title: Seasonal Rating Proposal + allOf: + - $ref: 'forecast-limit-period.yaml#/proposal' + - type: object + properties: + season-name: + $ref: ./season-name.yaml + day-night: + $ref: ./day-night.yaml + +proposal-slim: + type: array + title: Seasonal Period Proposal slim + maxItems: 20 # (max continuous + emergency ratings) * max num fields in limit type, e.g. MW and p.f. + minItems: 1 + items: + type: number + title: Continuous and Emergency Ratings values + description: | + + Each number in this array corresponds to a value of the continuous and + emergency ratings for a particular period. The first values correspond to + the continuous (normal) rating and the subsequent values correspond to the + emergency ratings in order of decreasing duration. The durations are + defined in the `proposal-header.default-emergency-durations` field. + + The exact number of values in this array is further determined by the + `limit-type` parameter of the media type. + ```http + Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power + ``` + If the [limit-type](#tag/limit-type) is single valued, like + `apparent-power`, then the array will have a single value for each rating. + For example, if there was only one emergency duration defined, then the + array would have two values, e.g. `[50, 55]`, corresponding to a 50MVA + continuous rating and 55MVA emergency rating, respectively. A + single-valued limit type is anticipated to be the most common case in + practice. + + However, if the [limit-type](#tag/limit-type) is `active-power` and the + Clearinghouse Provider has required both MW and power factor, e.g., + `{"mw":1, "pf":1}`, then the array will have two values for each rating. + If we continue with the example of having only one emergency duration + defined, then the array would have four values. Thus, instead of + `[normal_MVA, emergency_MVA]`, we would have `[normal_MW, normal_pf, + emergency_MW, emergency_pf]`, e.g., `[300, 1.0, 350, 1.0]`. + +snapshot: + type: object + description: Proposes the continuous and emergency ratings for the specified Season. + title: Seasonal Rating Proposal + allOf: + - $ref: 'forecast-limit-period.yaml#/snapshot-slim' + - type: object + properties: + season-name: + $ref: ./season-name.yaml + day-night: + $ref: ./day-night.yaml + +snapshot-detailed: + type: object + description: Proposes the continuous and emergency ratings for the specified Season. + title: Seasonal Rating Proposal + allOf: + - $ref: '#/snapshot' + - type: object + properties: + proposals-considered: + description: | + + The seasonal ratings proposals considered when determining the + seasonal ratings of a power system resource, e.g., a line or + transformer. + + type: array + minItems: 1 + maxItems: 10 + items: + allOf: + - $ref: '#/proposal' + - type: object + properties: + source: + $ref: ./data-provenance.yaml + resource-id: + $ref: ./resource-id.yaml + required: + - source + - resource-id + required: + - proposals-considered \ No newline at end of file diff --git a/docs/_data/components/schemas/seasonal-rating-snapshot-value.yaml b/docs/_data/components/schemas/seasonal-rating-snapshot-value.yaml deleted file mode 100644 index 08760e4..0000000 --- a/docs/_data/components/schemas/seasonal-rating-snapshot-value.yaml +++ /dev/null @@ -1,13 +0,0 @@ -type: object -additionalProperties: false -properties: - season-instance: - $ref: ./generic-identifier.yaml - effective-date: - $ref: ./period-start.yaml - continuous-operating-limit: - $ref: ./limit.yaml - emergency-operating-limits: - $ref: ./array-max-emergency-durations.yaml#/limit-value-set - conditional-values: - $ref: ./conditional-value-set.yaml diff --git a/docs/_data/openapi-split.yaml b/docs/_data/openapi-split.yaml index 5169c5a..fc17c30 100644 --- a/docs/_data/openapi-split.yaml +++ b/docs/_data/openapi-split.yaml @@ -54,44 +54,72 @@ servers: - url: https://trolie.example.com tags: - - name: Forecasting + - name: Real-Time description: | - The operations related to data exchange of forecasted ratings. - - This data exchange specifically includes the 240-hour-ahead forecasted - AAR data exchange between Ratings Providers and Transmission Providers - mandated FERC order 881. It includes the ability to submit rating proposals, - query back in-use limits, and monitor the health and validity of the rating - proposal submissions relative the Rating Provider's obligations. - - name: Real-Time + At the discretion of the TROLIE server owner, Ratings Providers may use + these functions to exchange ratings within the current hour, either as an + alternative or supplement to traditional telemetry protocols such as ICCP. + + These are assumed to be real-time ratings, based on measurements of + ambient conditions as opposed to forecasts. These ratings will be used by + Transmission Providers in real-time grid operations processes, such as + state estimator and real-time markets. The clearinghouse for real-time + ratings may be run more frequently than the one for forecast ratings to + adapt to real-world conditions. + + These ratings may be either AARs or DLRs. + + - name: Forecasting description: | - At the discretion of the TROLIE server owner, Ratings Providers may - use these functions to exchange ratings within the current hour, - either as an alternative or supplement to traditional telemetry protocols - such as ICCP. - - These are assumed to be real-time ratings, based on measurements - of ambient conditions as opposed to forecasts. These ratings will be - used by Transmission Providers in real-time grid operations processes, - such as state estimator and real-time markets. The clearinghouse for real-time ratings - may be run more frequently than the one for forecast ratings to adapt to real-world - conditions. - These ratings may be either AARs or DLRs. + The operations related to data exchange of forecasted ratings. + + This data exchange specifically includes the 240-hour-ahead forecasted AAR + data exchange between Ratings Providers and Transmission Providers + mandated FERC order 881. It includes the ability to submit rating + proposals, query back in-use limits, and monitor the health and validity + of the rating proposal submissions relative the Rating Provider's + obligations. - name: Seasonal - description: > - While not typically used directly in operational decisions, seasonal - ratings are provided for two purposes: + description: | - 1. They are used when applicable forecast ratings are not available. + Seasonal ratings are static ratings associated with extended durations, + typically months. These are used in both planning and operations. + + For Ratings Obligations with an AAR Exemption, the power system resource + will be generally operated to a seasonal rating. For Ratings Obligations + that *are* satisfied with dynamic ratings, a seasonal rating is still + required, because the seasonal rating is typically used as a recourse + rating when a dynamic rating is unavailable for any reason. For example, a + dynamic rating would likely not be available during a communication outage + or when determining a forecast rating for the power system resource beyond + the period for which a forecast has been provided, e.g., beyond the ten + day forecast required by FERC Order 881. - 2. They may be used in future-looking studies that look out (potentially - far) beyond the time - window where forecast ratings are available. A snapshot is provided of the resource ratings configured by the system, - as well as their relationship to upcoming seasons. + as well as their relationship to upcoming seasons. + + - name: Seasonal Overrides + description: | + + A Seasonal Override is an instruction to use a temporary static rating set + in lieu of any concurrent Seasonal Rating for a given segment. + + A typical use case is a so-called "de-rate" due to temporary clearance + issue for a transmission facility that is exempt from providing AARs. + Exempt facilities normally operate against a seasonal rating, yet rather + than provide a seasonal ratings schedule update, the Ratings Provider + could send a Seasonal Override. During the provided duration of the + override, the Transmission Provider would operate to the Seasonal Override + rather than any ratings that would have been used from the seasonal rating + schedule. + + In contrast, for a segment that is *not* exempt from providing AARs, the + Ratings Provider would issue a Temporary AAR Exception to the + Clearinghouse Provider to address a clearance issue or other temporary + operating condition that calls for a static rating. - name: Temporary AAR Exceptions description: > @@ -142,43 +170,49 @@ tags: data feed could be down for some reason. Therefore, this provides a placeholder set of numbers until the AAR data feed is repaired. - - name: Seasonal Overrides - description: > - - A Seasonal Override allows for temporary overrides of the seasonal - rating, due to some unusual condition on the facility. This essentially - overrides the current "recourse" rating used in operations. - - NOTE- this description is likely incomplete, and needs to be added to in - future releases. + - name: limit-type + description: + x-displayName: Limit Type + +x-tagGroups: + - name: Operations + tags: + - Real-Time + - Forecasting + - Seasonal + - Seasonal Overrides + - Temporary AAR Exceptions + - name: Common Schemas + tags: + - limit-type paths: /limits/forecast-snapshot: $ref: paths/limits_forecast-snapshot.yaml + /rating-proposals/realtime: + $ref: paths/rating-proposals_realtime.yaml + /limits/realtime-snapshot: $ref: paths/limits_realtime-snapshot.yaml /rating-proposals/forecast: $ref: paths/rating-proposals_forecasts.yaml - /rating-proposals/realtime: - $ref: paths/rating-proposals_realtime.yaml + + /seasonal-ratings/snapshot: + $ref: paths/seasonal-ratings-snapshot.yaml /rating-proposals/seasonal: $ref: paths/rating-proposals_seasonal.yaml - /rating-proposals/seasonal/{ratings-provider}: - $ref: paths/rating-proposals_seasonal_{ratings-provider}.yaml - /seasonal-ratings/snapshot: - $ref: paths/seasonal-ratings_snapshot.yaml - /seasonal-ratings/season-instances: - $ref: paths/seasonal-ratings_season-instances.yaml - /seasonal-ratings/season-instances/{id}: - $ref: paths/seasonal-ratings_season-instances_{id}.yaml - /temporary-aar-exceptions: - $ref: paths/temporary-aar-exceptions.yaml - /temporary-aar-exceptions/{id}: - $ref: paths/temporary-aar-exceptions_{id}.yaml + /seasonal-overrides: $ref: paths/seasonal-overrides.yaml /seasonal-overrides/{id}: $ref: paths/seasonal-overrides_{id}.yaml + + /temporary-aar-exceptions: + $ref: paths/temporary-aar-exceptions.yaml + /temporary-aar-exceptions/{id}: + $ref: paths/temporary-aar-exceptions_{id}.yaml + + components: responses: @@ -389,12 +423,12 @@ components: read:realtime-proposals: Read real-time rating proposals read:seasonal-proposals: Read seasonal rating proposals read:temporary-aar-exceptions: Read temporary AAR exceptions - read:temporary-seasonal-ratings: Read temporary seasonal ratings + read:seasonal-overrides: Read seasonal overrides write:forecast-proposals: Submit forecasted ratings write:realtime-proposals: Submit realtime ratings write:seasonal-proposals: Submit seasonal ratings write:temporary-aar-exceptions: Write temporary AAR exceptions - write:temporary-seasonal-ratings: Write temporary seasonal ratings + write:seasonal-overrides: Write seasonal overrides read:operating-snapshot: >- Read the ratings and limits snapshots in-use by the transmission provider diff --git a/docs/_data/paths/rating-proposals_seasonal.yaml b/docs/_data/paths/rating-proposals_seasonal.yaml index 9b32e60..c7570ca 100644 --- a/docs/_data/paths/rating-proposals_seasonal.yaml +++ b/docs/_data/paths/rating-proposals_seasonal.yaml @@ -1,29 +1,46 @@ -get: - operationId: getSeasonalRatingProposal +get: &get + operationId: getSeasonalRatingProposalStatus + summary: Obtain seasonal rating proposal status description: | - Obtain the latest Seasonal Ratings the Ratings Provider has submitted. + Used to obtain the status of the Seasonal Ratings proposal. The response is + implicitly restricted to the requesting Ratings Provider's obligation. + Accordingly, the caller can use this endpoint to check the state of their + proposal submission. + + Note that the same status object is returned for each + `patchSeasonalRatingsProposal`, so this endpoint may seem redundant. + However, an anticipated use case for this `GET` endpoint is to support + supervisor processes that are setup by the client to independently ensure + the provider's process for rating submission if functioning properly. For + example, the Rating Provider might have one program responsible for + producing and submitting Seasonal Ratings via + `patchSeasonalRatingsProposal`, while having a separate monitoring job that + checks this endpoint regularly. Clients SHOULD perform Conditional `GET` using the `If-None-Match` header - and the `ETag` of a previous `GET` response. + and the `ETag` of a previous `GET` response to poll this endpoint. Rate + limiting is done on a per Ratings Provider basis, so requests from + independent clients used by the same provider count against the same quota. - summary: Get a Seasonal Rating Proposal - tags: &tags + tags: - Seasonal - parameters: - - $ref: ../components/parameters/monitoring-set-filter.yaml - - $ref: ../components/parameters/segment-filter.yaml responses: '200': description: OK - content: - application/vnd.trolie.seasonal-rating-proposal.v1+json: - schema: &seasonal-rating-proposal - $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-rating-proposal" - example: &get-example - $ref: ../../example-narratives/examples/seasonal-ratings-proposals-get.json - application/json: - schema: *seasonal-rating-proposal + content: &status + application/vnd.trolie.seasonal-ratings-proposal-status.v1+json: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-proposal-status" + examples: + complete: + summary: Status reflects no errors or outstanding obligations + value: + $ref: ../../example-narratives/examples/seasonal-ratings-proposal-status.json + incomplete: + summary: Status reflects outstanding obligations + value: + $ref: ../../example-narratives/examples/seasonal-ratings-proposal-status-incomplete.json headers: $ref: '../openapi-split.yaml#/components/responses/204/headers' @@ -35,12 +52,8 @@ get: $ref: '../openapi-split.yaml#/components/responses/401-empty' '403': &forbidden-empty $ref: '../openapi-split.yaml#/components/responses/403-empty' - '404': ¬-found-empty - $ref: '../openapi-split.yaml#/components/responses/404-empty' '406': ¬-acceptable-empty $ref: '../openapi-split.yaml#/components/responses/406-empty' - '410': - $ref: '../openapi-split.yaml#/components/responses/410-empty' '429': &rate-limit-hit $ref: '../openapi-split.yaml#/components/responses/429-empty' '500': &unexpected-error-empty @@ -52,41 +65,81 @@ get: - read:seasonal-proposals patch: - operationId: patchSeasonalProposal - description: &patch_desc Update this Provider's Rating Proposal - summary: *patch_desc - tags: *tags + <<: *get + operationId: patchSeasonalRatingsProposal + summary: Submit a Seasonal Ratings proposal + description: | + + This operation allows the Ratings Provider to provide a partial or complete + updates of their Seasonal Ratings that will be used by the Clearinghouse + Provider to determine the Seasonal Ratings Schedule. + requestBody: + description: | + + There are two supported media types for a Seasonal Ratings proposals. + + `application/vnd.trolie.seasonal-ratings-proposal.v1+json` allows the + Ratings Provider to combine different limit types, such as + `apparent-power` (MVA) and `current` (MW), in a single proposal. + + `application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json` for + proposals that only require a single limit type, e.g., `apparent-power`. + Clients *MUST* specify that [limit-type](#tag/limit-type) as a media type + parameter. For example, + ```http + PATCH /ratings-proposals/seasonal HTTP/1.1 + Content-Type: application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json; limit-type=apparent-power + ``` + Note that this format is much more concise but requires significant care + in serialization/deserialization. For details, see the schema description + for the [seasonal ratings proposal of an individual + resource](#schema/seasonal-proposals-slim) which is the description for + each element of the `ratings` array. + + required: true content: - application/vnd.trolie.seasonal-rating-proposal.v1+json: - schema: *seasonal-rating-proposal + application/vnd.trolie.seasonal-ratings-proposal.v1+json: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-proposal" example: $ref: ../../example-narratives/examples/seasonal-ratings-proposals-patch.json - application/json: - schema: *seasonal-rating-proposal + application/vnd.trolie.seasonal-ratings-proposal-slim.v1+json: + schema: + $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-proposal-slim" + example: + $ref: ../../example-narratives/examples/seasonal-ratings-proposals-slim-patch.json responses: '202': - description: > - The update was accepted for later processing. Updates to ratings may + description: | + The update was accepted for later processing. Updates to ratings may need to undergo additional validation and propagation to other systems. - content: - application/vnd.trolie.seasonal-proposal.v1+json: - schema: *seasonal-rating-proposal - example: *get-example - application/json: - schema: *seasonal-rating-proposal + content: *status headers: $ref: '../openapi-split.yaml#/components/responses/204/headers' '400': *malformed '401': *unauthorized-empty '403': *forbidden-empty - '404': *not-found-empty '406': *not-acceptable-empty + '409': + description: Conflict with Seasonal Ratings Schedule + content: + application/problem+json: + schema: + $ref: '../openapi-split.yaml#/components/schemas/problem' + # TODO: an example, e.g., all proposed extents are in the past. + headers: + $ref: '../openapi-split.yaml#/components/responses/304/headers' '413': $ref: '../openapi-split.yaml#/components/responses/413-empty' + '415': + $ref: '../openapi-split.yaml#/components/responses/415-problem' '422': $ref: '../openapi-split.yaml#/components/responses/422-problem' + # TODO example of violating a Clearinghouse processing rule + # but still be syntactically valid, e.g., if the CP requires + # seasons to begin on the first of the month '429': *rate-limit-hit '500': *unexpected-error-empty default: *unexpected-error-empty diff --git a/docs/_data/paths/rating-proposals_seasonal_{ratings-provider}.yaml b/docs/_data/paths/rating-proposals_seasonal_{ratings-provider}.yaml deleted file mode 100644 index 69271ac..0000000 --- a/docs/_data/paths/rating-proposals_seasonal_{ratings-provider}.yaml +++ /dev/null @@ -1,92 +0,0 @@ -get: - operationId: getSeasonalProposalForProvider - description: &get_desc Obtain a specific rating proposal by ratings provider - summary: *get_desc - tags: &tags - - Seasonal - parameters: - - $ref: ../components/parameters/ratings-provider.yaml - - $ref: ../components/parameters/monitoring-set-filter.yaml - - $ref: ../components/parameters/segment-filter.yaml - responses: - '200': - description: OK - content: - application/vnd.trolie.seasonal-rating-proposal.v1+json: - schema: &seasonal-rating-proposal - $ref: "../components/schemas/array-max-monitored-elements.yaml#/seasonal-rating-proposal" - example: &get-example - $ref: ../../example-narratives/examples/seasonal-ratings-proposals-get.json - application/json: - schema: *seasonal-rating-proposal - headers: - $ref: '../openapi-split.yaml#/components/responses/204/headers' - - '304': - $ref: '../openapi-split.yaml#/components/responses/304' - '400': &malformed - $ref: '../openapi-split.yaml#/components/responses/400-problem' - '401': &unauthorized-empty - $ref: '../openapi-split.yaml#/components/responses/401-empty' - '403': &forbidden-empty - $ref: '../openapi-split.yaml#/components/responses/403-empty' - '404': ¬-found-empty - $ref: '../openapi-split.yaml#/components/responses/404-empty' - '406': ¬-acceptable-empty - $ref: '../openapi-split.yaml#/components/responses/406-empty' - '410': - $ref: '../openapi-split.yaml#/components/responses/410-empty' - '429': &rate-limit-hit - $ref: '../openapi-split.yaml#/components/responses/429-empty' - '500': &unexpected-error-empty - $ref: '../openapi-split.yaml#/components/responses/500-empty' - default: *unexpected-error-empty - - security: - - oauth2-primary-flow: - - read:seasonal-proposals -patch: - operationId: patchSeasonalProposalByProvider - description: &patch_desc Update a given Provider's Rating Proposal - summary: *patch_desc - tags: *tags - parameters: - - $ref: ../components/parameters/ratings-provider.yaml - requestBody: - content: - application/vnd.trolie.seasonal-rating-proposal.v1+json: - schema: *seasonal-rating-proposal - example: - $ref: ../../example-narratives/examples/seasonal-ratings-proposals-patch.json - application/json: - schema: *seasonal-rating-proposal - responses: - '202': - description: > - The update was accepted for later processing. Updates to ratings may - need to undergo additional validation and propagation to other systems. - content: - application/vnd.trolie.seasonal-proposal.v1+json: - schema: *seasonal-rating-proposal - example: *get-example - application/json: - schema: *seasonal-rating-proposal - headers: - $ref: '../openapi-split.yaml#/components/responses/204/headers' - - '400': *malformed - '401': *unauthorized-empty - '403': *forbidden-empty - '404': *not-found-empty - '406': *not-acceptable-empty - '413': - $ref: '../openapi-split.yaml#/components/responses/413-empty' - '422': - $ref: '../openapi-split.yaml#/components/responses/422-problem' - '429': *rate-limit-hit - '500': *unexpected-error-empty - default: *unexpected-error-empty - - security: - - oauth2-primary-flow: - - write:seasonal-proposals diff --git a/docs/_data/paths/seasonal-ratings_snapshot.yaml b/docs/_data/paths/seasonal-ratings-snapshot.yaml similarity index 77% rename from docs/_data/paths/seasonal-ratings_snapshot.yaml rename to docs/_data/paths/seasonal-ratings-snapshot.yaml index 82e716d..cac0946 100644 --- a/docs/_data/paths/seasonal-ratings_snapshot.yaml +++ b/docs/_data/paths/seasonal-ratings-snapshot.yaml @@ -13,9 +13,14 @@ get: content: application/vnd.trolie.seasonal-rating-snapshot.v1+json: schema: &seasonal-rating-snapshot - $ref: ../components/schemas/array-max-monitored-elements.yaml#/seasonal-rating-snapshot + $ref: ../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-snapshot example: - $ref: '../../example-narratives/examples/seasonal-limits-snapshot.json' + $ref: '../../example-narratives/examples/seasonal-ratings-snapshot.json' + application/vnd.trolie.seasonal-rating-snapshot-detailed.v1+json: + schema: + $ref: ../components/schemas/array-max-monitored-elements.yaml#/seasonal-ratings-snapshot-detailed + example: + $ref: '../../example-narratives/examples/seasonal-ratings-snapshot-detailed.json' application/json: schema: *seasonal-rating-snapshot headers: diff --git a/docs/_data/paths/seasonal-ratings_season-instances.yaml b/docs/_data/paths/seasonal-ratings_season-instances.yaml deleted file mode 100644 index 23ccdeb..0000000 --- a/docs/_data/paths/seasonal-ratings_season-instances.yaml +++ /dev/null @@ -1,47 +0,0 @@ -get: - operationId: getSeasonInstances - description: Seasonal ratings are always bound against season instances, with effective dates. - summary: Get Instances of Seasons - tags: - - Seasonal - responses: - '200': - description: OK - content: - application/vnd.trolie.season-instance-set.v1+json: - schema: - $ref: ../components/schemas/season-instance-set.yaml - example: - - season: fall - id: fall-2023 - effective-time: '2023-09-10T00:00:00-07:00' - active: true - application/json: - schema: - $ref: ../components/schemas/season-instance-set.yaml - headers: - $ref: '../openapi-split.yaml#/components/responses/204/headers' - - '304': - $ref: '../openapi-split.yaml#/components/responses/304' - '400': - $ref: '../openapi-split.yaml#/components/responses/400-problem' - '401': - $ref: '../openapi-split.yaml#/components/responses/401-empty' - '403': - $ref: '../openapi-split.yaml#/components/responses/403-empty' - '404': - $ref: '../openapi-split.yaml#/components/responses/404-empty' - '406': - $ref: '../openapi-split.yaml#/components/responses/406-empty' - '410': - $ref: '../openapi-split.yaml#/components/responses/410-empty' - '429': - $ref: '../openapi-split.yaml#/components/responses/429-empty' - '500': &unexpected-error-empty - $ref: '../openapi-split.yaml#/components/responses/500-empty' - default: *unexpected-error-empty - - security: - - oauth2-primary-flow: - - read:operating-snapshot diff --git a/docs/_data/paths/seasonal-ratings_season-instances_{id}.yaml b/docs/_data/paths/seasonal-ratings_season-instances_{id}.yaml deleted file mode 100644 index f57e371..0000000 --- a/docs/_data/paths/seasonal-ratings_season-instances_{id}.yaml +++ /dev/null @@ -1,49 +0,0 @@ -get: - operationId: getSeasonInstance - description: &get_desc Gets a single season instance. - summary: *get_desc - tags: - - Seasonal - parameters: - - $ref: ../components/parameters/id.yaml - responses: - '200': - description: OK - content: - application/vnd.trolie.season-instance.v1+json: - schema: - $ref: ../components/schemas/season-instance.yaml - example: - season: fall - id: fall-2023 - effective-time: '2023-09-01T00:00:00-07:00' - active: true - application/json: - schema: - $ref: ../components/schemas/season-instance.yaml - headers: - $ref: '../openapi-split.yaml#/components/responses/204/headers' - - '304': - $ref: '../openapi-split.yaml#/components/responses/304' - '400': - $ref: '../openapi-split.yaml#/components/responses/400-problem' - '401': - $ref: '../openapi-split.yaml#/components/responses/401-empty' - '403': - $ref: '../openapi-split.yaml#/components/responses/403-empty' - '404': - $ref: '../openapi-split.yaml#/components/responses/404-empty' - '406': - $ref: '../openapi-split.yaml#/components/responses/406-empty' - '410': - $ref: '../openapi-split.yaml#/components/responses/410-empty' - '429': - $ref: '../openapi-split.yaml#/components/responses/429-empty' - '500': &unexpected-error-empty - $ref: '../openapi-split.yaml#/components/responses/500-empty' - default: *unexpected-error-empty - - security: - - oauth2-primary-flow: - - read:operating-snapshot diff --git a/docs/example-narratives/examples/seasonal-ratings-proposal-status-incomplete.json b/docs/example-narratives/examples/seasonal-ratings-proposal-status-incomplete.json new file mode 100644 index 0000000..9b38a4c --- /dev/null +++ b/docs/example-narratives/examples/seasonal-ratings-proposal-status-incomplete.json @@ -0,0 +1,24 @@ +{ + "provider-info": { + "provider": "UTILITY-A", + "last-updated": "2023-07-12T15:05:43.044267100-07:00", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "incomplete-obligation-count": 1, + "incomplete-obligations": [ + { + + "resource-id": "8badf00d", + "obligation-period-begins": "2024-01-01T00:00:00-05:00", + "obligation-period-ends": "2024-01-01T00:00:00-05:00", + "periods":[ + { + "season-name":"WINTER", + "begins":"2024-01-01T00:00:00-05:00" + } + ] + } + ], + "invalid-proposal-count": 0, + "proposal-validation-errors": [] +} \ No newline at end of file diff --git a/docs/example-narratives/examples/seasonal-ratings-proposal-status.json b/docs/example-narratives/examples/seasonal-ratings-proposal-status.json new file mode 100644 index 0000000..ef67539 --- /dev/null +++ b/docs/example-narratives/examples/seasonal-ratings-proposal-status.json @@ -0,0 +1,11 @@ +{ + "provider-info": { + "provider": "UTILITY-A", + "last-updated": "2023-07-12T15:05:43.044267100-07:00", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "incomplete-obligation-count": 0, + "incomplete-obligations": [], + "invalid-proposal-count": 0, + "proposal-validation-errors": [] +} diff --git a/docs/example-narratives/examples/seasonal-ratings-proposals-get.json b/docs/example-narratives/examples/seasonal-ratings-proposals-get.json deleted file mode 100644 index 989297c..0000000 --- a/docs/example-narratives/examples/seasonal-ratings-proposals-get.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "timestamp": "2023-07-12T15:05:43.044267100-07:00", - "owner": "UTILITY A", - "ratings": [ - { - "resource-id": "segmentX", - "seasons": [ - { - "season-id": "fall", - "status": "accepted", - "continuous-operating-limit": { - "mva": 160 - }, - "emergency-operating-limits": [ - { - "duration-name": "lte", - "limit": { - "mva": 165 - } - }, - { - "duration-name": "ste", - "limit": { - "mva": 170 - } - }, - { - "duration-name": "dal", - "limit": { - "mva": 170 - } - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/docs/example-narratives/examples/seasonal-ratings-proposals-patch.json b/docs/example-narratives/examples/seasonal-ratings-proposals-patch.json index b662cdf..b0a49a5 100644 --- a/docs/example-narratives/examples/seasonal-ratings-proposals-patch.json +++ b/docs/example-narratives/examples/seasonal-ratings-proposals-patch.json @@ -1,10 +1,52 @@ { + "proposal-header": { + "source": { + "last-updated": "2025-10-31T15:05:43.044267100-07:00", + "provider": "UTILITY-A", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "default-emergency-durations": [ + { + "name": "emergency", + "duration-minutes": 240 + } + ], + "power-system-resources": [ + { + "resource-id": "8badf00d", + "alternate-identifiers": [ + { + "name": "segmentX", + "authority": "TO-NERC-ID" + } + ] + } + ] + }, "ratings": [ { - "resource-id": "segmentX", - "seasons": [ + "resource-id": "8badf00d", + "periods": [ { - "season-id": "fall", + "season-name": "WINTER", + "period-start": "2024-11-15T00:00:00-05:00", + "period-end": "2025-03-01T00:00:00-05:00", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "emergency", + "limit": { + "mva": 165 + } + } + ] + }, + { + "season-name": "SPRING", + "period-start": "2025-03-01T00:00:00-05:00", + "period-end": "2025-06-15T00:00:00-05:00", "continuous-operating-limit": { "mva": 160 }, @@ -14,17 +56,37 @@ "limit": { "mva": 165 } - }, + } + ] + }, + { + "season-name": "SUMMER", + "period-start": "2025-06-15T00:00:00-05:00", + "period-end": "2025-09-01T00:00:00-05:00", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ { - "duration-name": "ste", + "duration-name": "lte", "limit": { - "mva": 170 + "mva": 165 } - }, + } + ] + }, + { + "season-name": "FALL", + "period-start": "2025-09-01T00:00:00-05:00", + "period-end": "2025-11-15T00:00:00-05:00", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ { - "duration-name": "dal", + "duration-name": "lte", "limit": { - "mva": 170 + "mva": 165 } } ] diff --git a/docs/example-narratives/examples/seasonal-ratings-proposals-slim-patch.json b/docs/example-narratives/examples/seasonal-ratings-proposals-slim-patch.json new file mode 100644 index 0000000..4a99889 --- /dev/null +++ b/docs/example-narratives/examples/seasonal-ratings-proposals-slim-patch.json @@ -0,0 +1,70 @@ +{ + "proposal-header": { + "source": { + "last-updated": "2024-11-20T15:05:43.044267100-07:00", + "provider": "UTILITY-A", + "origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640" + }, + "default-emergency-durations": [ + { + "name": "emergency", + "duration-minutes": 240 + } + ], + "power-system-resources": [ + { + "resource-id": "8badf00d", + "alternate-identifiers": [ + { + "name": "segmentX", + "authority": "TO-NERC-ID" + } + ] + }, + { + "resource-id": "f34d3d", + "alternate-identifiers": [ + { + "name": "segmentY", + "authority": "TO-NERC-ID" + } + ] + } + ], + "default-seasonal-schedule": { + "schedule": [ + { + "season-name": "WINTER", + "begins": "2024-11-15T00:00:00-05:00" + }, + { + "season-name": "SPRING", + "begins": "2025-03-01T00:00:00-05:00" + }, + { + "season-name": "SUMMER", + "begins": "2025-06-15T00:00:00-05:00" + }, + { + "season-name": "FALL", + "begins": "2025-09-01T00:00:00-05:00" + } + ], + "ends": "2025-11-15T00:00:00-05:00" + } + }, + "ratings": [ + [ + [160, 170], + [155, 160], + [145, 150], + [155, 160] + ], + [ + [161, 171], + [156, 161], + [146, 151], + [156, 161] + ] + ] +} \ No newline at end of file diff --git a/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed.json b/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed.json new file mode 100644 index 0000000..3684ca8 --- /dev/null +++ b/docs/example-narratives/examples/seasonal-ratings-snapshot-detailed.json @@ -0,0 +1,110 @@ +{ + "snapshot-header": { + "source": { + "provider": "X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "default-emergency-durations": [ + { + "name": "lte", + "duration-minutes": 240 + }, + { + "name": "ste", + "duration-minutes": 30 + }, + { + "name": "dal", + "duration-minutes": 15 + } + ], + "power-system-resources": [ + { + "resource-id": "8badf00d", + "alternate-identifiers": [ + { + "name": "segmentX", + "authority": "TO-NERC-ID" + }, + { + "name": "LINE1 SEG-X", + "authority": "RC-NERC-ID", + "mrid": "8badf00d" + } + ] + } + ] + }, + "ratings": [ + { + "resource-id": "LINE1", + "periods": [ + { + "period-start": "2024-04-01T01:00:00Z", + "period-end": "2024-07-01T01:00:00Z", + "season-name": "spring", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ], + "proposals-considered": [ + { + "resource-id": "8badf00d", + "period-start": "2024-04-01T01:00:00Z", + "period-end": "2024-07-01T01:00:00Z", + "source": { + "provider": "X-AMPL", + "last-updated": "2023-07-12T16:00:00-07:00", + "origin-id": "//trolie.example.com/snapshots/2024-08-05T11%3a00%3a00-07%3a00" + }, + "season-name": "spring", + "continuous-operating-limit": { + "mva": 160 + }, + "emergency-operating-limits": [ + { + "duration-name": "lte", + "limit": { + "mva": 165 + } + }, + { + "duration-name": "ste", + "limit": { + "mva": 170 + } + }, + { + "duration-name": "dal", + "limit": { + "mva": 180 + } + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/example-narratives/examples/seasonal-limits-snapshot.json b/docs/example-narratives/examples/seasonal-ratings-snapshot.json similarity index 90% rename from docs/example-narratives/examples/seasonal-limits-snapshot.json rename to docs/example-narratives/examples/seasonal-ratings-snapshot.json index f138737..56dcb06 100644 --- a/docs/example-narratives/examples/seasonal-limits-snapshot.json +++ b/docs/example-narratives/examples/seasonal-ratings-snapshot.json @@ -36,13 +36,14 @@ } ] }, - "limits": [ + "ratings": [ { "resource-id": "segmentX", - "seasons": [ + "periods": [ { - "season-instance": "fall", - "effective-date": "2024-04-04T01:00:00Z", + "period-start": "2024-04-01T01:00:00Z", + "period-end": "2024-07-01T01:00:00Z", + "season-name": "spring", "continuous-operating-limit": { "mva": 160 },