diff --git a/.github/ISSUE_TEMPLATE/discussion-topic.yml b/.github/ISSUE_TEMPLATE/discussion-topic.yml
index 04310627b..08d54d674 100644
--- a/.github/ISSUE_TEMPLATE/discussion-topic.yml
+++ b/.github/ISSUE_TEMPLATE/discussion-topic.yml
@@ -2,7 +2,7 @@ name: Discussion Topic
description: Initiate discussion on broad topics within the FOCUS community.
title: "[DISCUSSION]: "
labels: ["discussion topic"]
-assignees: ["mike-finopsorg,udam-f2"]
+assignees: ["shawnalpay"]
body:
- type: textarea
attributes:
diff --git a/.github/ISSUE_TEMPLATE/feedback.yml b/.github/ISSUE_TEMPLATE/feedback.yml
index 1ab51c5c0..656903ca8 100644
--- a/.github/ISSUE_TEMPLATE/feedback.yml
+++ b/.github/ISSUE_TEMPLATE/feedback.yml
@@ -1,14 +1,14 @@
-name: FinOps Use Case Feedback
-description: Provide feedback on FinOps use cases that cannot be performed with the current FOCUS specification.
+name: Feature Request and Use Case Feedback
+description: Provide feedback on unsupported use cases or features in the FOCUS specification, including FinOps scenarios, to help prioritize updates. Avoid sharing proprietary information.
title: "[FEEDBACK]: "
-labels: [""]
-assignees: ["mike-finopsorg,udam-f2"]
+labels: ["use case"]
+assignees: ["shawnalpay, jpradocueva,"]
body:
- type: markdown
attributes:
- value: "The FOCUS working group wants to understand what FinOps use cases cannot be performed today using the current specification so they can be prioritized for upcoming release. Please do not provide any information that may be considered Intellectual Property by any individual or organization."
+ value: "FOCUS working group seeks gaps in the current specification for FinOps and beyond. Share unsupported use cases or features to prioritize updates. Avoid sharing proprietary information."
- - type: input
+ - type: textarea
attributes:
label: Proposed Change
description: Short description of the change and why it is necessary.
@@ -18,8 +18,8 @@ body:
- type: textarea
attributes:
- label: What FinOps use cases cannot be performed without the proposed change?
- description: Describe in detail the current FinOps use cases your organization cannot perform without the proposed change
+ label: What use cases, FinOps or others, can't be performed with the current specification without this change?
+ description: Describe in detail the use cases, whether FinOps-related or otherwise, that your organization cannot perform with the current specification without the proposed change.
validations:
required: true
@@ -51,6 +51,14 @@ body:
validations:
required: true
+ - type: textarea
+ attributes:
+ label: Key Metrics and KPIs
+ description: List the metrics and KPIs that will measure the success of this use case (e.g., cost per service, spend reduction percentage).
+ placeholder: e.g., cost per service, spend reduction percentage, etc.
+ validations:
+ required: false
+
- type: textarea
attributes:
label: Context / Supporting information
@@ -66,4 +74,3 @@ body:
placeholder: Attach sample data or data extracts here. Ensure compliance with data privacy guidelines.
validations:
required: false
-
diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml
index 3a39989ce..daae0715e 100644
--- a/.github/ISSUE_TEMPLATE/maintenance.yml
+++ b/.github/ISSUE_TEMPLATE/maintenance.yml
@@ -2,7 +2,7 @@ name: Maintenance Task
description: Create tasks related to work on the GitHub Repository or GitHub Actions.
title: "[MAINTENANCE]: "
labels: ["repo maintenance"]
-assignees: ["mike-finopsorg,udam-f2"]
+assignees: ["shawnalpay"]
body:
- type: textarea
attributes:
diff --git a/.github/ISSUE_TEMPLATE/spec-change.yml b/.github/ISSUE_TEMPLATE/spec-change.yml
index 344bdcc8c..aa4104c63 100644
--- a/.github/ISSUE_TEMPLATE/spec-change.yml
+++ b/.github/ISSUE_TEMPLATE/spec-change.yml
@@ -2,7 +2,7 @@ name: Spec Change
description: Submit changes or updates to the current specification.
title: "[SPEC CHANGE]: "
labels: ["discussion topic"]
-assignees: ["mike-finopsorg,udam-f2"]
+assignees: ["shawnalpay"]
body:
- type: dropdown
attributes:
diff --git a/.github/ISSUE_TEMPLATE/work-item.md b/.github/ISSUE_TEMPLATE/work-item.md
new file mode 100644
index 000000000..e8c3b7d2b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/work-item.md
@@ -0,0 +1,53 @@
+# Work Item Issue Template
+description:
+title: "[Work_Item]"
+labels: ["work item"]
+assignees: [shawnalpay, jpradocueva]
+
+### **Template Usage Notes**:
+1. All fields marked as **mandatory** [*] must be filled before submission. While some datapoints are optional for the initial creation of the work item, all datapoints must be provided in order to be considered for spec development.
+2. If you have suggestions for the specification but cannot fill out all fields in this issue template, please fill out a [Feedback] or [Discussion] issue template instead.
+3. For **Supporting Documentation**, ensure that linked files are accessible to relevant stakeholders.
+
+---
+
+## 1. **Problem Statement** *
+Describe the problem, issue, use case, or opportunity that this work item addresses.
+Include practitioner quotes illustrating real examples a) of questions being asked by practitioners and b) value unlocked by answering these questions, if available.
+- **What is the problem?**: Explain the context and why it needs resolution.
+- **Impact**: Describe how the problem affects users, systems, or the project.
+
+Your input ...
+
+## 2. **Objective** *
+State the objective of this work item. What outcome is expected?
+- **Success Criteria**: Define how success will be measured (e.g. metrics and KPIs).
+
+Your input ...
+
+## 3. **Supporting Documentation** *
+Include links to supporting documents such as:
+- Data Examples: [Link to data or relevant files; DO NOT share proprietary information]
+- Related Use Cases or Discussion Documents: [Link to discussion]
+- PRs or Other References: [Link to relevant references]
+
+Your input ...
+
+## 4. **Proposed Solution / Approach**
+Outline any proposed solutions, approaches, or potential paths forward. Do not submit detailed solutions; please keep suggestions high-level.
+- **Initial Ideas**: Describe potential solution paths, tools, or technologies.
+- **Considerations**: Include any constraints, dependencies, or risks.
+- **Feasibility**: Include any information that helps quantify feasibility, such as perceived level of effort to augment the spec, or existing fields in current data generator exports.
+- **Benchmarks**: Are there established best practices for solving this problem available to practitioners today (e.g. mappings from existing CSP exports that are widely used)?
+
+Your input ...
+
+## 5. **Epic or Theme Association**
+> This section will be completed by the Maintainers.
+> - **Epic**: [Epic Name]
+> - **Theme**: [Theme Name, if applicable]
+
+## 6. **Stakeholders** *
+List the main stakeholders for this issue.
+- **Primary Stakeholders**: [Name/Role]
+- **Other Involved Parties**: [Names/Roles]
diff --git a/.github/ISSUE_TEMPLATE/work-item.yml b/.github/ISSUE_TEMPLATE/work-item.yml
new file mode 100644
index 000000000..bc422b790
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/work-item.yml
@@ -0,0 +1,121 @@
+name: "Work Item Issue Template"
+description: "Template for creating new work item issues"
+title: "[Work_Item]"
+labels:
+ - "work item"
+assignees:
+ - "shawnalpay"
+ - "jpradocueva"
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ---
+ ### **Template Usage Notes**:
+ 1. All fields marked as **mandatory** [*] must be filled before submission. While some datapoints are optional for the initial creation of the work item, all datapoints must be provided in order to be considered for spec development.
+ 2. If you have suggestions for the specification but cannot fill out all fields in this issue template, please fill out a [Feedback] or [Discussion] issue template instead.
+ 3. For **Supporting Documentation**, ensure that linked files are accessible to relevant stakeholders.
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 1. **Problem Statement**
+ Describe the problem, issue, use case, or opportunity that this work item addresses.
+ Include practitioner quotes illustrating real examples a) of questions being asked by practitioners and b) value unlocked by answering these questions, if available.
+ - **What is the problem?**: Explain the context and why it needs resolution.
+ - **Impact**: Describe how the problem affects users, systems, or the project.
+
+ - type: textarea
+ id: problem_statement
+ attributes:
+ label: "Problem Statement"
+ description: "Provide a detailed explanation of the problem or issue."
+ placeholder: "Your input here..."
+ value: "Provide details of the problem statement here."
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 2. **Objective**
+ State the objective of this work item. What outcome is expected?
+ - **Success Criteria**: Define how success will be measured (e.g. metrics and KPIs).
+
+ - type: textarea
+ id: objective
+ attributes:
+ label: "Objective"
+ description: "Describe the expected outcome and success criteria."
+ placeholder: "Your input here..."
+ value: "Outline the expected outcome and success criteria."
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 3. **Supporting Documentation**
+ - Data Examples: [Link to data or relevant files; DO NOT share proprietary information]
+ - Related Use Cases or Discussion Documents: [Link to discussion]
+ - PRs or Other References: [Link to relevant references]
+
+ - type: textarea
+ id: supporting_documentation
+ attributes:
+ label: "Supporting Documentation"
+ description: "Provide links to data examples, use cases, PRs, or other relevant documents."
+ placeholder: "Your input here..."
+ value: "Include links to supporting documentation, if applicable."
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 4. **Proposed Solution / Approach**
+ Outline any proposed solutions, approaches, or potential paths forward. Do not submit detailed solutions; please keep suggestions high-level.
+ - **Initial Ideas**: Describe potential solution paths, tools, or technologies.
+ - **Considerations**: Include any constraints, dependencies, or risks.
+ - **Feasibility**: Include any information that helps quantify feasibility, such as perceived level of effort to augment the spec, or existing fields in current data generator exports.
+ - **Benchmarks**: Are there established best practices for solving this problem available to practitioners today (e.g. mappings from existing CSP exports that are widely used)?
+
+ - type: textarea
+ id: proposed_solution
+ attributes:
+ label: "Proposed Solution / Approach"
+ description: "Outline potential solutions or approaches."
+ placeholder: "Your input here..."
+ value: "Summarize the proposed solution or approach."
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 5. **Epic or Theme Association**
+ > This section will be completed by the Maintainers.
+ > - **Epic**: [Epic Name]
+ > - **Theme**: [Theme Name, if applicable]
+
+ - type: textarea
+ id: epic_theme
+ attributes:
+ label: "Epic or Theme Association"
+ description: "Provide potential epics or themes"
+ placeholder: "Your input here..."
+ value: "Provide the rational for the Epic or Theme."
+
+ - type: markdown
+ attributes:
+ value: |
+ ## 6. **Stakeholders**
+ List the main stakeholders for this issue.
+ - **Primary Stakeholder**: [Name/Role]
+ - **Other Involved Parties**: [Names/Roles]
+
+ - type: textarea
+ id: stakeholders
+ attributes:
+ label: "Stakeholders"
+ description: "List the main stakeholders for this work item."
+ placeholder: "Your input here..."
+ value: "Provide names and roles of key stakeholders."
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96131dca2..90c970c37 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,13 +5,60 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## v1.1
+
+Announced November 2024
+
+**Added:**
+
+- `CapacityReservationId` column
+- `CapacityReservationStatus` column
+- `CommitmentDiscountQuantity` column
+- `CommitmentDiscountUnit` column
+- `ServiceSubcategory` column
+- `SkuMeter` column
+- `SkuPriceDetails` column
+- `ProviderVersion` metadata schema property
+
+**Changed:**
+
+- `CommitmentDiscountId` column updates:
+ - Must be globally unique within the provider.
+ - Should be a fully-qualified identifier.
+- `ConsumedQuantity` column updates:
+ - Must be null when `CommitmentDiscountStatus` is "Unused".
+- `ConsumedUnit` column updates:
+ - Must be null when `ChargeClass` is not "Correction" and `ChargeCategory` is not "Usage".
+ - Must be null when `ChargeClass` is not "Correction" and `ChargeCategory` is "Usage" and `CommitmentDiscountStatus` is "Unused".
+ - May be null when `ChargeCategory` is "Usage" and `ChargeClass` is "Correction".
+- `EffectiveCost` column updates:
+ - When `CommitmentDiscountStatus` is "Unused", must be the difference between the used commitment discount amount and the portion of the total commitment discount purchase applicable for the charge period.
+- `PricingCategory` column updates:
+ - Must not be "Committed" when the charge is for a commitment discount purchase.
+- `SkuPriceId` column updates:
+ - `SkuId` can be used if the provider does not have a `SkuPriceId` but other requirements must be met.
+- Metadata updates:
+ - Must be provided in the defined metadata schema.
+ - Must be an object.
+ - Must not be null.
+ - Must include a reference to the schema of the data.
+ - Schema reference must not be in the FOCUS dataset itself.
+ - Must be an accurate and complete representation of the provided FOCUS dataset.
+ - Metadata implementation should be publicly documented.
+- `SchemaId` metadata schema property updates:
+ - Recommended to be a globally unique identifier (GUID) instead of a universally unique identifier (UUID) or SemVer version.
+
+[All 1.1 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0...v1.1-cr)
+
+
+
## v1.0
Announced June 20, 2024
@@ -25,6 +72,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- `ContractedUnitPrice` column
- `RegionId` column
- `RegionName` column
+- `DataGenerator` metadata property
+- `CreationDate` metadata schema property
+- `FocusVersion` metadata schema property
+- `SchemaId` metadata schema property
+- `ColumnName` metadata column definition property
+- `DataType` metadata column definition property
+- `NumberScale` metadata column definition property
+- `NumberPrecision` metadata column definition property
+- `ProviderTagPrefix` metadata column definition property
+- `StringEncoding` metadata column definition property
+- `StringMaxLength` metadata column definition property
**Changed:**
@@ -104,7 +162,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- `ChargeSubcategory` column - See `ChargeCategory` and `ChargeClass` columns
-[All 1.0 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview-cr...1.0-cr)
+[All 1.0 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview...v1.0)
@@ -147,14 +205,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- `AmortizedCost` column renamed to `EffectiveCost`
- `ChargeType` column renamed to `ChargeCategory`
-[All 1.0-preview changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v0.5-cr...v1.0-preview-cr)
+[All 1.0-preview changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v0.5...v1.0-preview)
## v0.5
+
Announced June 24, 2023
**Added:**
+
- `Column naming convention` attribute
- `Currency code format` attribute
- `Date/time format` attribute
@@ -181,7 +241,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- `SubAccountId` column
- `SubAccountName` column
-[All 0.5 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/7106bbe...v0.5-cr)
+[All 0.5 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/7106bbe...v0.5)
@@ -199,6 +259,8 @@ This table maps the evolution of the specification, showcasing column introducti
| BillingCurrency | 0.5 | |
| BillingPeriodEnd | 0.5 | |
| BillingPeriodStart | 0.5 | |
+| CapacityReservationId | 1.1 | |
+| CapacityReservationStatus | 1.1 | |
| ChargeType | 0.5 | Renamed to ChargeCategory in v1.0-preview |
| ChargeCategory | 1.0-preview | Renamed from ChargeType in v1.0-preview |
| ChargeClass | 1.0 | |
@@ -212,6 +274,8 @@ This table maps the evolution of the specification, showcasing column introducti
| CommitmentDiscountName | 1.0-preview | |
| CommitmentDiscountStatus | 1.0 | |
| CommitmentDiscountType | 1.0-preview | |
+| CommitmentDiscountQuantity | 1.1 | |
+| CommitmentDiscountUnit | 1.1 | |
| ConsumedQuantity | 1.0 | Renamed from UsageQuantity in v1.0 |
| ConsumedUnit | 1.0 | Renamed from UsageUnit in v1.0 |
| ContractedCost | 1.0 | |
@@ -233,7 +297,10 @@ This table maps the evolution of the specification, showcasing column introducti
| ResourceType | 1.0-preview | |
| ServiceCategory | 0.5 | |
| ServiceName | 0.5 | |
+| ServiceSubcategory | 1.1 | |
| SkuId | 1.0-preview | |
+| SkuMeter | 1.1 | |
+| SkuPriceDetails | 1.1 | |
| SkuPriceId | 1.0-preview | |
| SubAccountId | 0.5 | |
| SubAccountName | 0.5 | |
diff --git a/EDITORIAL_GUIDELINES.md b/EDITORIAL_GUIDELINES.md
new file mode 100644
index 000000000..29e7cbab1
--- /dev/null
+++ b/EDITORIAL_GUIDELINES.md
@@ -0,0 +1,251 @@
+## Editorial Style Guidelines
+The "Editorial Style Guidelines" section ensures consistency and clarity across all documentation. Adhering to these guidelines is crucial for maintaining a unified style, which enhances readability and reduces misinterpretation. By following the specified standards—whether in formatting, linking, or structuring information—we ensure that all documents are professional, clear, and aligned with our editorial principles. Consistent application of these guidelines contributes to high-quality, user-friendly documentation.
+
+These guidelines can be modified through a Pull Request (PR), which the members must review and agree upon. This process ensures that any changes are thoughtfully considered and maintains the overall integrity of our editorial standards.
+
+
+
+ Component |
+ Display (PDF, HTML) |
+ Markdown (examples) |
+ Editorial Guidelines |
+
+
+ Column & Attribute Names: |
+
+ Column Names:
+ - Pricing Quantity
+ - Pricing Unit
+ - Provider
+ Attribute Names:
+ - Currency Code Format
+ - Date/Time Format
+ |
+
+ Column Names:
+ Pricing Quantity
+ Pricing Unit
+ Provider
+ Attribute Names:
+ Currency Code Format
+ Date/Time Format
+ |
+
+ - Use the display name in the non-normative section.
+ - The first occurrence in a section is linked to the section.
+ |
+
+
+ Column & Attribute IDs: |
+
+ Columns IDs:
+ - PricingQuantity
+ - PricingUnit
+ - ProviderName
+ Attributes IDs:
+ - CurrencyCodeFormat
+ - DateTimeFormat
+ |
+
+ Columns IDs:
+ PricingQuantity
+ PricingUnit
+ ProviderName
+ Attributes IDs:
+ CurrencyCodeFormat
+ DateTimeFormat
+ |
+
+ - Use PascalCamel case (the first letter of every word, is capitalized)
+ - Normal text without bold or italics.
+ - The first occurrence in a section is linked to the section.
+ |
+
+
+ Column Values: |
+
+ - "Usage"
+ - "Tax"
+ - "TB"
+ |
+
+ This column:
+ * MUST be null when ChargeCategory is "Tax" ...
+ |
+
+ - Enclosed in double quotation marks
+ - Normal text without bold or italics
+ |
+
+
+ Normative Keywords & Statements |
+
+ MUST, MAY, MUST NOT and normative statements
+ |
+
+ This column:
+ * MUST NOT be null when ChargeClass is ...
+ * MUST be null when ChargeCategory is ...
+ * MAY be null for all other combinations of ...
+ |
+
+ - All uppercase, without bold.
+ - Bullet list format.
+ |
+
+
+ Glossary |
+
+ SKU, resource, service
+ |
+
+ [*SKU*](#glossary:sku)
+ [*resource*](#glossary:resource)
+ [*service*](#glossary:service)
+ |
+
+ - Blue font + italic
+ - The first occurrence in a section is linked to the glossary.
+ |
+
+
+ Important Text |
+ ![image](https://github.com/user-attachments/assets/c6f60ff9-1503-43a3-8229-004595b334d2) |
+ > Important Consideration |
+ - It is added as a note. |
+
+
+ Key-Value Format |
+ JSON Script |
+
+
+**Example**:
+```json
+{
+ "key1": "value1",
+ "key2": true,
+ "key3": 123
+}
+```
+
+ |
+ - Monospace font |
+
+
+ Tables |
+ ![image](https://github.com/user-attachments/assets/5185cbf9-306d-4663-a1c7-c8b7ab5c5bb8) |
+ ![image](https://github.com/user-attachments/assets/83d0977f-a731-4def-93e3-b3e5f5dedb72) |
+ - Tables: Simple tables can be created using markdown, but for more complex tables, it is RECOMMENDED to use HTML elements. See the example below. |
+
+
+
+**Editorial Notes**
+* **Linking Only the First Time**: To prevent excessive linking within sections, Column Name, Column ID, Attributes Names, Attributes IDs, and Glossary will only be linked to their corresponding section or glossary the first time they appear in a section.
+
+* **Normative Requirements as a Bullet List**: Normative statements (those using Normative Keywords) should be written as bullet points instead of lengthy sentences.
+
+* **Column IDs:** They SHOULD be used in normative text sections, such as when specifying mandatory rules, schema definitions, or other implementation-related content. These Column IDs should be formatted without spaces and should match the exact naming conventions used in the schema (e.g., CommitmentDiscountID).
+
+* **Display Names:** They SHOULD be used in introductory or explanatory sections where natural language context is more appropriate. In these sections, display names should follow normal text conventions, including spaces between words (e.g., Commitment Discount ID).
+
+
+### Example
+
+> **2.28. Pricing Quantity**
+>
+> The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption.
+>
+> * The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
+> * This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements
+> * The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction".
+>
+> This column:
+> * MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase",
+> * MUST be null when ChargeCategory is "Tax", and
+> * MAY be null for all other combinations of ChargeClass and ChargeCategory.
+> * When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
+>
+> **2.28.1. Column ID**
+>
+> PricingQuantity
+>
+> **2.28.2. Display Name**
+>
+> Pricing Quantity
+>
+> **2.28.3. Description**
+>
+> The volume of a given SKU associated with a *resource* or *service* used or purchased, based on the Pricing Unit.
+>
+> **2.28.4. Content Constraints Constraint**
+>
+>
+>
+> **2.28.5. Introduced (version)**
+>
+> 1.0-preview
+
+### Example HTML Table
+This is an example of a complex table with merged rows and columns, along with an additional header row.
+
+
+
+ Heading 1 |
+ Heading 2 |
+ Heading 3 |
+
+
+ Cell 1,1 and Cell 1,2 Merged |
+ Cell 1,3 |
+ Cell 1,4 |
+
+
+ Heading 4 |
+ Heading 5 |
+ Heading 6 |
+ Heading 7 |
+
+
+ Cell 2,1 & Cell 2,2 |
+ Cell 3,3 & Cell 4,3 |
+ Cell 3,4 |
+
+
+ Cell 4,1 |
+ Cell 4,2 |
+ Cell 4,4 |
+
+
+
+This is how it is written in HTML:
+```html
+
+
+ Heading 1 |
+ Heading 2 |
+ Heading 3 |
+
+
+ Cell 1,1 and Cell 1,2 Merged |
+ Cell 1,3 |
+ Cell 1,4 |
+
+
+ Heading 4 |
+ Heading 5 |
+ Heading 6 |
+ Heading 7 |
+
+
+ Cell 2,1 & Cell 2,2 |
+ Cell 3,3 & Cell 4,3 |
+ Cell 3,4 |
+
+
+ Cell 4,1 |
+ Cell 4,2 |
+ Cell 4,4 |
+
+
+
+```
diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md
index 34b21361f..043128d06 100644
--- a/RELEASE-PLANNING.md
+++ b/RELEASE-PLANNING.md
@@ -22,6 +22,10 @@ This section outlines the planned release schedule and key milestones for the FO
Move beyond the highest-level service categorization to a sub-categorization for services while adding flexibility for providers to share their native categorizations within FOCUS.
+ Commitment Discount Visibility
+
+ - Provide deeper visibility into how various commitment discount purchases are amortized across eligible resources.
+
Capacity Reservation
- Ability to represent on-demand capacity reservations within FOCUS datasets.
@@ -54,6 +58,71 @@ This section outlines the planned release schedule and key milestones for the FO
+### Estimated Timeline for v1.2
+This table displays key milestones and dates related to the development of FOCUS Release v1.2 Specifications.
+
+
+ Date |
+ Milestone |
+ Comment |
+
+
+ 8-Oct-24 |
+ Start Work Item Preparation |
+ For Release v1.2, the group will implement a new process for creating Work Items. |
+
+
+ 8-Oct-24 to 21-Nov-24 |
+ Work Item Creation |
+ Six weeks (6) to develop the FOCUS Release (Rel) v1.2 scope. |
+
+
+ 21-Nov-24 to 3-Apr-25 |
+ Development Phase |
+ Nineteen weeks (19) to develop FOCUS Rel v1.2 specifications. |
+
+
+ 23-Jan-25 to 6-Feb-25 |
+ Interim Consistency Review |
+ Two weeks (2) for the Interim Consistency Review of FOCUS Rel v1.2. |
+
+
+ 3-Apr-25 |
+ End Development Phase |
+ End of FOCUS Rel v1.2 development. |
+
+
+ 3-17-Apr-25 |
+ Consistency Review |
+ Two weeks (2) for the Final Consistency Review of FOCUS Rel v1.2. |
+
+
+ 17-24-Apr-25 |
+ Preparing baseline for IPR Review |
+ One week (1) of preparation to start the IPR Review. |
+
+
+ 24-April-25 to 24-May-25 |
+ Start / End IPR Review v1.2 |
+ During this 30-day period, members may exclude essential claims from their licensing commitments. Contact the FOCUS Executive Director. |
+
+
+ 29-May-25 |
+ WG Approval v1.2 |
+ FOCUS Release Candidate v1.2 approved by the FOCUS members. |
+
+
+ 29-May-25 |
+ SC Ratification v1.2 |
+ FOCUS Steering Committee ratifies Rel v1.2. |
+
+
+ 3-Jun-25 |
+ FinOpsX Announcement |
+ FOCUS Rel v1.2 must be ready for announcement sometime in June. |
+
+
+
### Estimated Timeline for v1.1
This table displays key milestones and dates related to the development of FOCUS Release v1.1.
@@ -81,7 +150,7 @@ This table displays key milestones and dates related to the development of FOCUS
CANCELED Two weeks Interim Consistency Review FOCUS Rel v1.1 |
- 19-Sep-24 to 03-Oct-24 |
+ 19-Sep-24 to 08-Oct-24 |
Start / End of the FOCUS Rel v1.1 Final Consistency Review |
Two weeks Final Consistency Review FOCUS Rel v1.1 |
diff --git a/specification/Makefile b/specification/Makefile
index 0465221a0..253b32424 100644
--- a/specification/Makefile
+++ b/specification/Makefile
@@ -25,7 +25,13 @@ else
endif
./validate_includes.py columns
./validate_includes.py attributes
+ ./validate_includes.py metadata
+ ./validate_includes.py metadata/data_generator
+ ./validate_includes.py metadata/schema
+ ./validate_includes.py metadata/schema/column_definition
./validate_includes.py appendix
+ ./validate_includes.py appendix/examples
+ ./validate_includes.py appendix/examples/metadata_examples
PYTHONPATH=../vendored/ $(MARKDOWNPP) spec.mdpp -o $@
$(PYMARKDOWNLNT) --config markdownlnt.cfg scan $(SPEC_SOURCE_MDFILES)
$(PYMARKDOWNLNT) --config markdownlnt.cfg scan $@
diff --git a/specification/appendix/appendix.mdpp b/specification/appendix/appendix.mdpp
index 9ee6066aa..c184f8c3c 100644
--- a/specification/appendix/appendix.mdpp
+++ b/specification/appendix/appendix.mdpp
@@ -6,3 +6,4 @@
!INCLUDE "commitment_discounts/size_flexibility.md",1
!INCLUDE "grouping_constructs_for_resources_and_or_services.md",1
!INCLUDE "origination_of_cost_data.md",1
+!INCLUDE "examples/examples.mdpp",1
diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md
new file mode 100644
index 000000000..243502a74
--- /dev/null
+++ b/specification/appendix/commitment_discounts.md
@@ -0,0 +1,278 @@
+# Commitment Discounts
+
+A [*commitment discount*](#glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](#glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets.
+
+Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](#glossary:commitment-discount-flexibility) which may expand the types of [*resources*](#glossary:resource) that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the [CommitmentDiscountUnit](#commitmentdiscountunit) should reflect this difference.
+
+Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](#glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the CommitmentDiscountUnit chosen is "USD", or the [*billing currency*](#glossary:billing-currency).
+
+## Purchasing
+
+While customers are bound to the *term* of a *commitment discounts*, providers offer some or all of the following payment options before and/or during the *term*:
+
+* *All Upfront* - The *commitment discounts* is paid in full before the *term* begins.
+* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](#glossary:billing-period) of the *term*.
+* *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*.
+
+For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals:
+
+1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`)
+2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`)
+
+## Usage
+
+Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](#glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](#glossary:charge-period) of the *term*.
+
+For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste.
+
+## Commitment Discounts in FOCUS
+
+Within the FOCUS specification, the following examples demonstrate how a *commitment discount* appears across various payment and usage scenarios.
+
+### Purchase *Rows*
+
+All *commitment discount* purchases appear with a positive [BilledCost](#billedcost), [PricingCategory](#pricingcategory) as "Standard", and with the *commitment discount's* id populating both the [ResourceId](#resourceid) and [CommitmentDiscountId](#commitmentdiscountid) value. One-time purchases appear as a single record with [ChargeCategory](#chargecategory) as "Purchase", [ChargeFrequency](#chargefrequency) as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as [CommitmentDiscountQuantity](#commitmentdiscountquantity) and CommitmentDiscountUnit, respectively.
+
+Recurring purchases are allocated across all corresponding *charge periods* of the *term* when ChargeCategory is "Purchase", ChargeFrequency is "Recurring", and CommitmentDiscountQuantity and CommitmentDiscountUnit are reflected only for that *charge period*.
+
+Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available:
+
+#### Scenario #1: All Upfront
+
+The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`).
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2024-01-01T00:00:00Z",
+ "ChargeCategory": "Purchase",
+ "ChargeFrequency": "One-Time",
+ "PricingCategory": "Standard",
+ "ResourceId": "",
+ "BilledCost": 8760.00,
+ "EffectiveCost": 0.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 8760.00,
+ "CommitmentDiscountUnit": "USD"
+ }
+]
+```
+
+#### Scenario #2: No Upfront
+
+The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Purchase",
+ "ChargeFrequency": "Recurring",
+ "PricingCategory": "Standard",
+ "ResourceId": "",
+ "BilledCost": 1.00,
+ "EffectiveCost": 0.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 1.00,
+ "CommitmentDiscountUnit": "USD"
+ },
+
+ /* ... 8,759 more recurring purchase records for the *term* ... */
+]
+```
+
+#### Scenario #3: Partial Upfront
+
+With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2024-01-01T00:00:00Z",
+ "ChargeCategory": "Purchase",
+ "ChargeFrequency": "One-Time",
+ "PricingCategory": "Standard",
+ "ResourceId": "",
+ "BilledCost": 4380.00,
+ "EffectiveCost": 0.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 4380.00,
+ "CommitmentDiscountUnit": "USD"
+ },
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Purchase",
+ "ChargeFrequency": "Recurring",
+ "PricingCategory": "Standard",
+ "ResourceId": "",
+ "BilledCost": 0.50,
+ "EffectiveCost": 0.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 0.50,
+ "CommitmentDiscountUnit": "USD"
+ },
+
+ /* ... 8,759 more recurring purchase records for the *term* ... */
+]
+```
+
+### Usage *Rows*
+
+*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*:
+
+* Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization)
+* Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization)
+* Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization)
+* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage)
+
+#### Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization)
+
+In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Committed",
+ "ResourceId": "",
+ "ConsumedQuantity": 1,
+ "ConsumedUnit": "Hour",
+ "BilledCost": 0.00,
+ "EffectiveCost": 1.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 1.00,
+ "CommitmentDiscountStatus": "Used",
+ "CommitmentDiscountUnit": "USD"
+ }
+]
+```
+
+#### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization)
+
+In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while CommitmentDiscountQuantity is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so [ConsumedQuantity](#consumedquantity) and [ConsumedUnit](#consumedunit) are null.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Committed",
+ "ResourceId": "",
+ "ConsumedQuantity": null,
+ "ConsumedUnit": null,
+ "BilledCost": 0.00,
+ "EffectiveCost": 1.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 1.00,
+ "CommitmentDiscountStatus": "Unused",
+ "CommitmentDiscountUnit": "USD"
+ }
+]
+```
+
+#### Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization)
+
+In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Committed",
+ "ResourceId": "",
+ "ConsumedQuantity": 1,
+ "ConsumedUnit": "Hour",
+ "BilledCost": 0.00,
+ "EffectiveCost": 0.75,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 0.75,
+ "CommitmentDiscountStatus": "Used",
+ "CommitmentDiscountUnit": "USD"
+ },
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Committed",
+ "ResourceId": "",
+ "ConsumedQuantity": null,
+ "ConsumedUnit": null,
+ "BilledCost": 0.00,
+ "EffectiveCost": 0.25,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 0.25,
+ "CommitmentDiscountStatus": "Unused",
+ "CommitmentDiscountUnit": "USD"
+ }
+]
+```
+
+#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage)
+
+In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend.
+
+```json
+[
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Committed",
+ "ResourceId": "",
+ "ConsumedQuantity": 1,
+ "ConsumedUnit": "Hour",
+ "BilledCost": 0.00,
+ "EffectiveCost": 1.00,
+ "CommitmentDiscountId": "",
+ "CommitmentDiscountQuantity": 1.00,
+ "CommitmentDiscountStatus": "Used",
+ "CommitmentDiscountUnit": "USD"
+ },
+ {
+ "BillingPeriodStartDate": "2023-01-01T00:00:00Z",
+ "BillingPeriodEndDate": "2023-02-01T00:00:00Z",
+ "ChargePeriodStartDate": "2023-01-01T00:00:00Z",
+ "ChargePeriodEndDate": "2023-01-01T01:00:00Z",
+ "ChargeCategory": "Usage",
+ "ChargeFrequency": "Usage-Based",
+ "PricingCategory": "Standard",
+ "ResourceId": "",
+ "ConsumedQuantity": 1,
+ "ConsumedUnit": "Hour",
+ "BilledCost": 0.50,
+ "EffectiveCost": 0.00
+ }
+]
+```
diff --git a/specification/appendix/examples/examples.mdpp b/specification/appendix/examples/examples.mdpp
new file mode 100644
index 000000000..1d217f201
--- /dev/null
+++ b/specification/appendix/examples/examples.mdpp
@@ -0,0 +1,5 @@
+# Examples
+
+*This section is non-normative.*
+
+!INCLUDE "metadata_examples/metadata_examples.mdpp",1
diff --git a/specification/appendix/examples/metadata_examples/adding_new_columns_example.md b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md
new file mode 100644
index 000000000..fb3111dec
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md
@@ -0,0 +1,76 @@
+# Adding New Columns
+
+## Scenario
+
+ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, this schema object has a unique [SchemaId](#schemaid). The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "23456-abcde-23456-abcde-23456",
+ "FocusVersion": "1.0",
+ "CreationDate": "2024-02-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["awecorp", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "x_awesome_column3",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md
new file mode 100644
index 000000000..7e2bb1687
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md
@@ -0,0 +1,70 @@
+# Changing Column Metadata
+
+## Scenario
+
+ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new [Schema](#schema) object with the modification to x_awesome_column2.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "67891-abcde-67891-abcde-67891",
+ "FocusVersion": "1.0",
+ "CreationDate": "2024-06-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md
new file mode 100644
index 000000000..1248e7c24
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md
@@ -0,0 +1,71 @@
+# Provider Metadata Error Correction
+
+## Scenario
+
+ACME has discovered that while their export includes the column x_awesome_column3, the [Schema](#schema) metadata does not include this column. In this case, the provider fixes the metadata in the existing schema object and does not need to create a new schema object. Reference metadata remains the same.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "34567-abcde-34567-abcde-34567",
+ "FocusVersion": "1.0",
+ "CreationDate": "2024-03-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ }
+ ]
+}
+```
+
diff --git a/specification/appendix/examples/metadata_examples/data_generator_example.md b/specification/appendix/examples/metadata_examples/data_generator_example.md
new file mode 100644
index 000000000..62f03e9e3
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/data_generator_example.md
@@ -0,0 +1,18 @@
+# Data Generator Metadata
+
+## Scenario
+
+Acme provides metadata about the data generator as a part of their FOCUS data export. They provide the relevant data via the [Data Generator](#datagenerator) schema object.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/data_generator.json`.
+
+The updated data generator related metadata could look like this:
+
+```json
+{
+ "DataGenerator": "Acme"
+}
+```
+
diff --git a/specification/appendix/examples/metadata_examples/focus_version_changed_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md
new file mode 100644
index 000000000..d684e31e6
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md
@@ -0,0 +1,70 @@
+# FOCUS Version Changed
+
+## Scenario
+
+ACME's previous exports used FOCUS version 1.0. They are now going to adopt FOCUS version 1.1. It is required that they create a new schema metadata object which specifies the new FOCUS version via the [FOCUS Version](#focusversion) property - regardless of schema changes. In this example, the new FOCUS version adoption doesn't include columns changes. This is to illustrate that FOCUS version changes are independent of column changes, however, this scenario is unlikely.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "45678-abcde-45678-abcde-45678",
+ "FocusVersion": "1.1",
+ "CreationDate": "2024-04-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md
new file mode 100644
index 000000000..536a4a1b0
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md
@@ -0,0 +1,134 @@
+# FOCUS Version Changed by Provider Using Provider Version
+
+## Scenario
+
+ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. Their provider version 2.2 supported FOCUS version 1.0. They are now going to adopt FOCUS Version 1.1 which requires that they update their Provider Version when updating the FOCUS Version. They create a new schema object designating that both properties have changed. In this example, the adoption of the new FOCUS version doesn't include additional columns. This is to illustrate that Provider Version can change independent of column changes; however, this scenario is unlikely.
+
+The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "45678-abcde-45678-abcde-45678",
+ "FocusVersion": "1.1",
+ "ProviderVersion": "2.3",
+ "name": "New Columns",
+ "CreationDate": "2024-04-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For reference, the prior schema object looked like this:
+
+```json
+ {
+ "SchemaId": "34567-abcde-34567-abcde-34567",
+ "FocusVersion": "1.0",
+ "ProviderVersion": "2.2",
+ "CreationDate": "2024-04-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp
new file mode 100644
index 000000000..971e1df8b
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp
@@ -0,0 +1,24 @@
+# Metadata Examples
+
+The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the [*FOCUS dataset*](#glossary:FOCUS-dataset) and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example.
+
+In this example, the provider supports delivery of FOCUS data via file export to a data storage system. It uses JSON as the format for providing the metadata. The provider delivers data every 12 hours into a path structure described below:
+
+| Type of data | Path |
+|:--------------------|:------------------|
+| Export location | `/FOCUS` |
+| Metadata location | `/FOCUS/metadata` |
+| Cost data location | `/FOCUS/data` |
+
+Here are some metadata examples for various scenarios:
+
+!INCLUDE "data_generator_example.md",1
+!INCLUDE "schema_metadata_example.md",1
+!INCLUDE "schema_metadata_reference_example.md",1
+!INCLUDE "adding_new_columns_example.md",1
+!INCLUDE "removing_columns_example.md",1
+!INCLUDE "changing_column_metadata_example.md",1
+!INCLUDE "correcting_schema_errors_example.md",1
+!INCLUDE "focus_version_changed_example.md",1
+!INCLUDE "focus_version_changed_with_provider_version_used_example.md",1
+!INCLUDE "provider_version_changed_example.md",1
diff --git a/specification/appendix/examples/metadata_examples/provider_version_changed_example.md b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md
new file mode 100644
index 000000000..3284c5eed
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md
@@ -0,0 +1,73 @@
+# Data Changed by Provider Using Provider Version
+
+## Scenario
+
+ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the [*FOCUS dataset*](#glossary:FOCUS-dataset) they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes.
+
+The provider creates a new schema object to represent the new schema. The provider includes both the FOCUS Version and Provider Version in the schema object.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "56789-abcde-56789-abcde-56789",
+ "FocusVersion": "1.1",
+ "ProviderVersion": "2.4",
+ "CreationDate": "2024-05-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/removing_columns_example.md b/specification/appendix/examples/metadata_examples/removing_columns_example.md
new file mode 100644
index 000000000..0b44141cd
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/removing_columns_example.md
@@ -0,0 +1,70 @@
+# Removing Columns
+
+## Scenario
+
+ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, with a unique [SchemaId](#schemaid).
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+ {
+ "SchemaId": "34567-abcde-34567-abcde-34567",
+ "FocusVersion": "1.0",
+ "CreationDate": "2024-03-02T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ },
+ {
+ "ColumnName": "x_awesome_column1",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "x_awesome_column2",
+ "DataType": "DATETIME"
+ }
+ ]
+}
+```
+
+For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference)
diff --git a/specification/appendix/examples/metadata_examples/schema_metadata_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_example.md
new file mode 100644
index 000000000..8ec30f88e
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/schema_metadata_example.md
@@ -0,0 +1,59 @@
+# Schema Metadata
+
+## Scenario
+
+ACME has only provided one [Schema](#schema) for their FOCUS data export. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json`.
+
+The updated schema related metadata could look like this:
+
+```json
+{
+ "SchemaId": "1234-abcde-12345-abcde-12345",
+ "FocusVersion": "1.0",
+ "CreationDate": "2024-01-01T12:01:03.083z",
+ "ColumnDefinition": [
+ {
+ "ColumnName": "BillingAccountId",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "BillingAccountName",
+ "DataType": "STRING",
+ "StringMaxLength": 64,
+ "StringEncoding": "UTF-8"
+ },
+ {
+ "ColumnName": "ChargePeriodStart",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "ChargePeriodEnd",
+ "DataType": "DATETIME"
+ },
+ {
+ "ColumnName": "BilledCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "EffectiveCost",
+ "DataType": "DECIMAL",
+ "NumericPrecision": 20,
+ "NumberScale": 10
+ },
+ {
+ "ColumnName": "Tags",
+ "DataType": "JSON",
+ "ProviderTagPrefixes": ["acme", "ac"]
+ }
+ ]
+}
+```
+
diff --git a/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md
new file mode 100644
index 000000000..d2ac2aa3b
--- /dev/null
+++ b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md
@@ -0,0 +1,74 @@
+# Schema Metadata to FOCUS Data Reference
+
+## Scenario
+
+ACME makes a change to the [Schema](#schema) of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided in each export, Acme has elected to include a metadata file in each export folder that includes the FOCUS schema reference that applies to the data export files within that folder. When the schema changes, they include the new [Schema ID](#schemaid) in their export metadata file of the new folder.
+
+## Supplied Metadata
+
+Metadata can be provided at a location such as `/FOCUS/data/export1-metadata.json`
+
+The export metadata could look like this:
+
+```json
+{
+ "SchemaId":"1234-abcde-12345-abcde-12345",
+ "data_location":
+ [
+ {
+ "filepath": "/FOCUS/data/export1/export1-part1.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export1/export1-part2.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export1/export1-part3.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export1/export1-part4.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ }
+ ]
+}
+```
+
+New metadata can be provided at a location such as `/FOCUS/data/export2-metadata.json`.
+
+The new export metadata could look like this:
+
+```json
+{
+ "SchemaId":"23456-abcde-23456-abcde-23456",
+ "data_location":
+ [
+ {
+ "filepath": "/FOCUS/data/export2/export2-part1.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export2/export2-part2.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export2/export2-part3.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ },
+ {
+ "filepath": "/FOCUS/data/export2/export2-part4.csv",
+ "total_bytes": 9010387,
+ "total_rows": 4450
+ }
+ ]
+}
+```
+
diff --git a/specification/appendix/grouping_constructs_for_resources_and_or_services.md b/specification/appendix/grouping_constructs_for_resources_and_or_services.md
index 76bb5b994..3fb69f94f 100644
--- a/specification/appendix/grouping_constructs_for_resources_and_or_services.md
+++ b/specification/appendix/grouping_constructs_for_resources_and_or_services.md
@@ -1,11 +1,11 @@
# Grouping constructs for resources or services
-Providers natively support various constructs for grouping resources or services. These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements.
+Providers natively support various constructs for grouping [*resources*](#glossary:resource) or [*services*](#glossary:service). These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements.
Providers may support multiple levels of resource or service grouping mechanisms. FOCUS supports two distinct levels of groupings that are commonly needed for FinOps capabilities like chargeback, invoice reconciliation and cost allocation.
-* Billing account: A mandatory container for resources or services that are billed together in an invoice. Billing accounts are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies.
-* Sub account: An optional provider-supported construct for organizing resources and services connected to a billing account. Sub accounts are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. Sub accounts must be associated with a billing account as they do not receive invoices.
+* [*Billing account*](#glossary:billing-account): A mandatory container for *resources* or *services* that are billed together in an invoice. *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies.
+* [Sub account](#glossary:sub-account): An optional provider-supported construct for organizing *resources* and *services* connected to a *billing account*. *Sub accounts* are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. *Sub accounts* must be associated with a *billing account* as they do not receive invoices.
The table below highlights key properties of the two grouping constructs supported by FOCUS.
diff --git a/specification/appendix/origination_of_cost_data.md b/specification/appendix/origination_of_cost_data.md
index 55ed959ba..4d5ffe239 100644
--- a/specification/appendix/origination_of_cost_data.md
+++ b/specification/appendix/origination_of_cost_data.md
@@ -2,11 +2,11 @@
Cost data presented in the billing datasets originates from various sources depending on the purchasing mechanism. There are at least 3 different pieces of information that are important for understanding where cost originated from.
-* Provider: The entity that made the resources or services available for purchase.
-* Publisher: The entity that produced the resources or services that were purchased.
-* Invoice Issuer: The entity responsible for invoicing for the resources or services consumed.
+* [Provider](#provider): The entity that made the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase.
+* [Publisher](#publisher): The entity that produced the *resources* or *services* that were purchased.
+* [Invoice Issuer](#invoiceissuer): The entity responsible for invoicing for the *resources* or *services* consumed.
-The value for each of these may be different depending on the various purchasing scenarios for resources or services. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario.
+The value for each of these may be different depending on the various purchasing scenarios for *resources* or *services*. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario.
| # | Scenario | Provider | Publisher | Invoice Issuer |
|:----|:----------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------|
diff --git a/specification/attributes/attributes.mdpp b/specification/attributes/attributes.mdpp
index 36fe447e9..595ceebba 100644
--- a/specification/attributes/attributes.mdpp
+++ b/specification/attributes/attributes.mdpp
@@ -1,6 +1,6 @@
# Attributes
-Attributes are requirements that apply across a FOCUS dataset instead of an individual column level. Requirements on data content can include naming
+Attributes are requirements that apply across a [*FOCUS dataset*](#glossary:FOCUS-dataset) instead of an individual column level. Requirements on data content can include naming
conventions, data types, formatting standardizations, etc. Attributes may introduce high-level requirements
for data granularity, recency, frequency, etc. Requirements defined in attributes are necessary for servicing
[FinOps capabilities][FODOFC] accurately using a standard set of instructions regardless of the origin of the data.
diff --git a/specification/attributes/column_naming_and_ordering.md b/specification/attributes/column_naming_and_ordering.md
index 1b279efb1..410c61894 100644
--- a/specification/attributes/column_naming_and_ordering.md
+++ b/specification/attributes/column_naming_and_ordering.md
@@ -14,14 +14,14 @@ Column Naming and Ordering
## Description
-Naming and ordering convention for columns appearing in a FOCUS dataset.
+Naming and ordering convention for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Requirements
### Column Names
* All columns defined by FOCUS MUST follow the following rules:
- * Column IDs MUST use [Pascal case](https://techterms.com/definition/pascalcase).
+ * Column IDs MUST use [Pascal case](#glossary:pascalcase).
* Column IDs MUST NOT use abbreviations.
* Column IDs MUST be alphanumeric with no special characters.
* Columns that have an ID and a Name MUST have the `Id` or `Name` suffix in the Column ID. Display Name for a Column MAY avoid the Name suffix if there are no other columns with the same name prefix.
diff --git a/specification/attributes/currency_code_format.md b/specification/attributes/currency_code_format.md
index 68c5b2a68..a0f53f449 100644
--- a/specification/attributes/currency_code_format.md
+++ b/specification/attributes/currency_code_format.md
@@ -14,7 +14,7 @@ Currency Code Format
## Description
-Formatting for currency columns appearing in a FOCUS dataset.
+Formatting for currency columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Requirements
diff --git a/specification/attributes/datetime_format.md b/specification/attributes/datetime_format.md
index d04b6e032..b6b013df7 100644
--- a/specification/attributes/datetime_format.md
+++ b/specification/attributes/datetime_format.md
@@ -14,7 +14,7 @@ Date/Time Format
## Description
-Rules and formatting requirements for date/time-related columns appearing in a FOCUS dataset.
+Rules and formatting requirements for date/time-related columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Requirements
diff --git a/specification/attributes/discount_handling.md b/specification/attributes/discount_handling.md
index be585c284..d301e51cf 100644
--- a/specification/attributes/discount_handling.md
+++ b/specification/attributes/discount_handling.md
@@ -1,10 +1,10 @@
# Discount Handling
-A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially negotiated discounts, commitment discounts when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings.
+A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially [*negotiated discounts*](#glossary:negotiated-discount), [*commitment discounts*](#glossary:commitment-discount) when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings.
-Some discount offers can be purchased from a provider to get reduced prices. The most common example is a commitment discount, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. In order to show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount the be amortized over the term the discount is applied to (e.g., 1 year) with each charge period split and applied to each row that received the discount.
+Some discount offers can be purchased from a provider to get reduced prices. The most common example is a *commitment discount*, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. To show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount to be amortized over the [*term*](#glossary:term) the discount is applied to (e.g., 1 year) with each [*charge period*](#glossary:chargeperiod) split and applied to each row that received the discount.
-Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount.
+Amortization is a process used to break down and spread purchase costs over a period of time or *term* of use. When a purchase is applicable to resources, like *commitment discounts*, the amortized cost of a resource takes the initial payment and *term* into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount.
While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Category. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend.
@@ -29,15 +29,15 @@ Indicates how to include and apply discounts to usage charges or rows in a FOCUS
* Multiple discounts MAY apply to a row, but they MUST apply to the entire charge covered by that row.
* If a discount only applies to a portion of a charge, then the discounted portion of the charge MUST be split into a separate row.
* Each discount MUST be identifiable using existing FOCUS columns.
- * Rows with a commitment discount applied to them MUST include a CommitmentDiscountId.
+ * Rows with a *commitment discount* applied to them MUST include a CommitmentDiscountId.
* If a provider applies a discount that cannot be represented by a FOCUS column, they SHOULD include additional columns to identify the source of the discount.
-* Purchased discounts (e.g., commitment discounts) MUST be amortized.
+* Purchased discounts (e.g., *commitment discounts*) MUST be amortized.
* The BilledCost MUST be 0 for any row where the commitment covers the entire cost for the charge period.
* The EffectiveCost MUST include the portion of the amortized purchase cost that applies to this row.
- * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the commitment discount.
- * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the commitment discount. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a commitment discount.
+ * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the *commitment discount*.
+ * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the *commitment discount*. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a *commitment discount*.
* CommitmentDiscountStatus MUST be "Used" for ChargeCategory "Usage" rows that received a reduced price from a commitment. CommitmentDiscountId MUST be set to the ID assigned to the discount. ResourceId MUST be set to the ID of the resource that received the discount.
- * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that charge period. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the commitment discount.
+ * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that *charge period*. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the *commitment discount*.
* Credits that are applied after the fact MUST use a ChargeCategory of "Credit".
## Exceptions
diff --git a/specification/attributes/key_value_format.md b/specification/attributes/key_value_format.md
index 136d81447..9ae056915 100644
--- a/specification/attributes/key_value_format.md
+++ b/specification/attributes/key_value_format.md
@@ -14,7 +14,7 @@ Key-Value Format
## Description
-Rules and formatting requirements for columns appearing in a FOCUS dataset that convey data as key-value pairs.
+Rules and formatting requirements for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset) that convey data as key-value pairs.
## Requirements
diff --git a/specification/attributes/numeric_format.md b/specification/attributes/numeric_format.md
index 992a60c56..cf9980562 100644
--- a/specification/attributes/numeric_format.md
+++ b/specification/attributes/numeric_format.md
@@ -14,7 +14,7 @@ Numeric Format
## Description
-Rules and formatting requirements for numeric columns appearing in a FOCUS dataset.
+Rules and formatting requirements for numeric columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Requirements
diff --git a/specification/attributes/string_handling.md b/specification/attributes/string_handling.md
index 108fb8f08..7beb1e014 100644
--- a/specification/attributes/string_handling.md
+++ b/specification/attributes/string_handling.md
@@ -14,7 +14,7 @@ String Handling
## Description
-Requirements for string-capturing columns appearing in a FOCUS dataset.
+Requirements for string-capturing columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Requirements
diff --git a/specification/attributes/unit_format.md b/specification/attributes/unit_format.md
index 7fa10a32c..929dc9cbb 100644
--- a/specification/attributes/unit_format.md
+++ b/specification/attributes/unit_format.md
@@ -1,6 +1,6 @@
# Unit Format
-Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a FOCUS dataset.
+Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
All columns defined in FOCUS specifying Unit Format as a value format MUST follow the requirements listed below.
@@ -14,7 +14,7 @@ Unit Format
## Description
-Indicates standards for expressing measurement units in columns appearing in a FOCUS dataset.
+Indicates standards for expressing measurement units in columns appearing in a *FOCUS dataset*.
## Requirements
diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md
index da70e1d38..eb54c5ec3 100644
--- a/specification/columns/billedcost.md
+++ b/specification/columns/billedcost.md
@@ -2,7 +2,7 @@
The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation.
-The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
+The BilledCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
## Column ID
diff --git a/specification/columns/billingaccountid.md b/specification/columns/billingaccountid.md
index e2b3a1a74..b66ccd0e0 100644
--- a/specification/columns/billingaccountid.md
+++ b/specification/columns/billingaccountid.md
@@ -2,7 +2,7 @@
A Billing Account ID is a provider-assigned identifier for a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies.
-The BillingAccountId column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider.
+The BillingAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider.
See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS.
diff --git a/specification/columns/billingaccountname.md b/specification/columns/billingaccountname.md
index b5ced23e6..cdfb8fe9b 100644
--- a/specification/columns/billingaccountname.md
+++ b/specification/columns/billingaccountname.md
@@ -2,7 +2,7 @@
A Billing Account Name is a display name assigned to a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies.
-The BillingAccountName column MUST be present in a FOCUS dataset and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*.
+The BillingAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*.
See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS.
diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md
index 86ac91fa0..8dfd03818 100644
--- a/specification/columns/billingcurrency.md
+++ b/specification/columns/billingcurrency.md
@@ -2,7 +2,7 @@
[*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated.
-The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements.
+The BillingCurrency column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements.
## Column ID
diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md
index 9cd030e6d..f0303f384 100644
--- a/specification/columns/billingperiodend.md
+++ b/specification/columns/billingperiodend.md
@@ -2,7 +2,7 @@
Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*.
-The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
+The BillingPeriodEnd column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
## Column ID
diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md
index bc54163c5..9289a10ea 100644
--- a/specification/columns/billingperiodstart.md
+++ b/specification/columns/billingperiodstart.md
@@ -2,7 +2,7 @@
Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound).
-The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
+The BillingPeriodStart column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account).
## Column ID
diff --git a/specification/columns/capacityreservationid.md b/specification/columns/capacityreservationid.md
new file mode 100644
index 000000000..bd87afd80
--- /dev/null
+++ b/specification/columns/capacityreservationid.md
@@ -0,0 +1,37 @@
+# Capacity Reservation ID
+
+A Capacity Reservation ID is the identifier assigned to a [*capacity reservation*](#glossary:capacity-reservation) by the provider. Capacity Reservation ID is commonly used for scenarios to allocate charges for capacity reservation usage.
+
+The CapacityReservationId column adheres to the following requirements:
+
+* CapacityReservationId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String.
+* CapacityReservationId SHOULD NOT be null when a charge is related to a capacity reservation.
+* CapacityReservationId MUST NOT be null when a charge represents the unused portion of a *capacity reservation*.
+* CapacityReservationId MUST be null when a charge is not related to a *capacity reservation*.
+* CapacityReservationId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier.
+
+## Column ID
+
+CapacityReservationId
+
+## Display Name
+
+Capacity Reservation ID
+
+## Description
+
+The identifier assigned to a *capacity reservation* by the provider.
+
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Column type | Dimension |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | String |
+| Value format | \ |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/capacityreservationstatus.md b/specification/columns/capacityreservationstatus.md
new file mode 100644
index 000000000..afc139b2e
--- /dev/null
+++ b/specification/columns/capacityreservationstatus.md
@@ -0,0 +1,44 @@
+# Capacity Reservation Status
+
+Capacity Reservation Status indicates whether the charge represents either the consumption of the [*capacity reservation*](#glossary:capacity-reservation) identified in the CapacityReservationId column or when the *capacity reservation* is unused.
+
+The CapacityReservationStatus column adheres to the following requirements:
+
+* CapacityReservationStatus MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String.
+* CapacityReservationStatus MUST be null when CapacityReservationId is null.
+* CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage".
+* CapacityReservationStatus MUST be one of the allowed values.
+* CapacityReservationStatus MUST label all unused *capacity reservation* charges and MUST label used *capacity reservation* charges if the provider supports it.
+
+## Column ID
+
+CapacityReservationStatus
+
+## Display Name
+
+Capacity Reservation Status
+
+## Description
+
+Indicates whether the charge represents either the consumption of a *capacity reservation* or when a *capacity reservation* is unused.
+
+## Content constraints
+
+| Constraint | Value |
+| :-------------- | :------------- |
+| Column type | Dimension |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | String |
+| Value format | Allowed Values |
+
+Allowed values:
+
+| Value | Description |
+| :----- | :-------------------------------------------------------------------------- |
+| Used | Charges that utilized a specific amount of a capacity reservation. |
+| Unused | Charges that represent the unused portion of a capacity reservation. |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/chargecategory.md b/specification/columns/chargecategory.md
index 41f183c26..e3e672ad9 100644
--- a/specification/columns/chargecategory.md
+++ b/specification/columns/chargecategory.md
@@ -2,7 +2,7 @@
Charge Category represents the highest-level classification of a charge based on the nature of how it is billed. Charge Category is commonly used to identify and distinguish between types of charges that may require different handling.
-The ChargeCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values.
+The ChargeCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values.
## Column ID
diff --git a/specification/columns/chargeclass.md b/specification/columns/chargeclass.md
index 41866810e..85569d6aa 100644
--- a/specification/columns/chargeclass.md
+++ b/specification/columns/chargeclass.md
@@ -2,7 +2,7 @@
Charge Class indicates whether the row represents a correction to a previously invoiced [*billing period*](#glossary:billing-period). Charge Class is commonly used to differentiate corrections from regularly incurred charges.
-The ChargeClass column MUST be present in the FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*.
+The ChargeClass column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*.
## Column ID
diff --git a/specification/columns/chargedescription.md b/specification/columns/chargedescription.md
index 0f875c6e4..e0b280f2e 100644
--- a/specification/columns/chargedescription.md
+++ b/specification/columns/chargedescription.md
@@ -2,7 +2,7 @@
A Charge Description provides a high-level context of a [*row*](#glossary:row) without requiring additional discovery. This column is a self-contained summary of the charge's purpose and price. It typically covers a select group of corresponding details across a billing dataset or provides information not otherwise available.
-The ChargeDescription column MUST be present in a FOCUS dataset, MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation.
+The ChargeDescription column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation.
## Column ID
diff --git a/specification/columns/chargefrequency.md b/specification/columns/chargefrequency.md
index 45d94183c..3f5c1d825 100644
--- a/specification/columns/chargefrequency.md
+++ b/specification/columns/chargefrequency.md
@@ -2,7 +2,7 @@
Charge Frequency indicates how often a charge will occur. Along with the [charge period](#glossary:chargeperiod) related columns, the Charge Frequency is commonly used to understand recurrence periods (e.g., monthly, yearly), forecast upcoming charges, and differentiate between one-time and recurring fees for purchases.
-The ChargeFrequency column is RECOMMENDED be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based".
+The ChargeFrequency column is RECOMMENDED be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based".
## Column ID
diff --git a/specification/columns/chargeperiodend.md b/specification/columns/chargeperiodend.md
index c7e5060e8..d0eccd134 100644
--- a/specification/columns/chargeperiodend.md
+++ b/specification/columns/chargeperiodend.md
@@ -2,7 +2,7 @@
Charge Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*charge period*](#glossary:chargeperiod). For example, a time period where [ChargePeriodStart](#chargeperiodstart) is '2024-01-01T00:00:00Z' and ChargePeriodEnd is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for January 2 since ChargePeriodEnd is *exclusive*.
-ChargePeriodEnd MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge.
+ChargePeriodEnd MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge.
## Column ID
diff --git a/specification/columns/chargeperiodstart.md b/specification/columns/chargeperiodstart.md
index fe701b161..2d4d4700a 100644
--- a/specification/columns/chargeperiodstart.md
+++ b/specification/columns/chargeperiodstart.md
@@ -2,7 +2,7 @@
Charge Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time within a [*charge period*](#glossary:chargeperiod). For example, a time period where ChargePeriodStart is '2024-01-01T00:00:00Z' and [ChargePeriodEnd](#chargeperiodend) is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is *inclusive*, but does not include charges for January 2 since ChargePeriodEnd is [*exclusive*](#glossary:exclusivebound).
-ChargePeriodStart MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge.
+ChargePeriodStart MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge.
## Column ID
diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp
index f1d027b95..48cbb79f4 100644
--- a/specification/columns/columns.mdpp
+++ b/specification/columns/columns.mdpp
@@ -9,6 +9,8 @@ The FOCUS specification defines a group of columns that provide qualitative valu
!INCLUDE "billingcurrency.md",1
!INCLUDE "billingperiodend.md",1
!INCLUDE "billingperiodstart.md",1
+!INCLUDE "capacityreservationid.md",1
+!INCLUDE "capacityreservationstatus.md",1
!INCLUDE "chargecategory.md",1
!INCLUDE "chargeclass.md",1
!INCLUDE "chargedescription.md",1
@@ -18,8 +20,10 @@ The FOCUS specification defines a group of columns that provide qualitative valu
!INCLUDE "commitmentdiscountcategory.md",1
!INCLUDE "commitmentdiscountid.md",1
!INCLUDE "commitmentdiscountname.md",1
+!INCLUDE "commitmentdiscountquantity.md",1
!INCLUDE "commitmentdiscountstatus.md",1
!INCLUDE "commitmentdiscounttype.md",1
+!INCLUDE "commitmentdiscountunit.md",1
!INCLUDE "consumedquantity.md",1
!INCLUDE "consumedunit.md",1
!INCLUDE "contractedcost.md",1
@@ -40,7 +44,10 @@ The FOCUS specification defines a group of columns that provide qualitative valu
!INCLUDE "resourcetype.md",1
!INCLUDE "servicecategory.md",1
!INCLUDE "servicename.md",1
+!INCLUDE "servicesubcategory.md",1
!INCLUDE "skuid.md",1
+!INCLUDE "skumeter.md",1
+!INCLUDE "skupricedetails.md",1
!INCLUDE "skupriceid.md",1
!INCLUDE "subaccountid.md",1
!INCLUDE "subaccountname.md",1
diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md
index 70c08b180..44c111b02 100644
--- a/specification/columns/commitmentdiscountcategory.md
+++ b/specification/columns/commitmentdiscountcategory.md
@@ -1,8 +1,8 @@
# Commitment Discount Category
-Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend").
+Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
-The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values.
+The CommitmentDiscountCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values.
## Column ID
diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md
index 30e99853f..958b13744 100644
--- a/specification/columns/commitmentdiscountid.md
+++ b/specification/columns/commitmentdiscountid.md
@@ -1,8 +1,8 @@
# Commitment Discount ID
-A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*.
+A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. The CommitmentDiscountId column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
-The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider.
+The CommitmentDiscountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier.
## Column ID
diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md
index 97abc352d..72d2907ec 100644
--- a/specification/columns/commitmentdiscountname.md
+++ b/specification/columns/commitmentdiscountname.md
@@ -1,8 +1,8 @@
# Commitment Discount Name
-A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount).
+A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountName column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
-The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*.
+The CommitmentDiscountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*.
## Column ID
diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md
new file mode 100644
index 000000000..650e2f50d
--- /dev/null
+++ b/specification/columns/commitmentdiscountquantity.md
@@ -0,0 +1,54 @@
+# Commitment Discount Quantity
+
+Commitment Discount Quantity is the amount of a [*commitment discount*](#glossary:commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [Commitment Discount Units](#commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total Commitment Discount Units acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of Commitment Discount Units consumed by a *row* that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount).
+
+When [CommitmentDiscountCategory](#commitmentdiscountcategory) is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](#glossary:commitment-discount-flexibility) is applicable, this value may be further transformed based on additional, provider-specific requirements. When CommitmentDiscountCategory is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed.
+
+The CommitmentDiscountQuantity column adheres to the following requirements:
+
+* CommitmentDiscountQuantity MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*.
+* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements.
+* CommitmentDiscountQuantity MAY be null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction".
+
+In cases where the ChargeCategory is "Purchase", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies:
+
+* When [ChargeFrequency](#chargefrequency) is "One-Time", and CommitmentDiscountId is not null, CommitmentDiscountQuantity MUST be the positive quantity of CommitmentDiscountUnits, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*.
+* When ChargeFrequency is "Recurring", and CommitmentDiscountId is not null, CommitmentDiscountQuantity MUST be the positive quantity of CommitmentDiscountUnits that is eligible for consumption for each *charge period* that corresponds with the purchase.
+
+In cases where the ChargeCategory is "Usage", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies:
+
+* When [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of CommitmentDiscountUnits that is consumed over the *row's* *charge period*.
+* When CommitmentDiscountStatus is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of CommitmentDiscountUnits for the *row's* *charge period*.
+
+CommitmentDiscountQuantity MUST be null in all other cases.
+
+## Column ID
+
+CommitmentDiscountQuantity
+
+## Display Name
+
+Commitment Discount Quantity
+
+## Description
+
+The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in Commitment Discount Units.
+
+## Usability Constraints
+
+**Aggregation:** When aggregating Commitment Discount Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when ChargeCategory is "Purchase") that are paid to cover future eligible charges (e.g., *commitment discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when ChargeCategory is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation.
+
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Column type | Metric |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | Decimal |
+| Value format | [Numeric Format](#numericformat) |
+| Number range | Any valid decimal value |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md
index 8353d0284..2c5facecb 100644
--- a/specification/columns/commitmentdiscountstatus.md
+++ b/specification/columns/commitmentdiscountstatus.md
@@ -1,8 +1,8 @@
# Commitment Discount Status
-Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount.
+Commitment Discount Status indicates whether the charge corresponds with the consumption of a [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. The CommitmetnDiscountStatus column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
-The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values.
+The CommitmentDiscountStatus column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". CommitmentDiscountStatus MUST be one of the allowed values.
## Column ID
diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md
index 48e61926e..a88f1cf96 100644
--- a/specification/columns/commitmentdiscounttype.md
+++ b/specification/columns/commitmentdiscounttype.md
@@ -1,8 +1,8 @@
# Commitment Discount Type
-Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row).
+Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). The CommitmentDiscountType column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
-The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null.
+The CommitmentDiscountType column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null.
## Column ID
diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md
new file mode 100644
index 000000000..596f4df77
--- /dev/null
+++ b/specification/columns/commitmentdiscountunit.md
@@ -0,0 +1,43 @@
+# Commitment Discount Unit
+
+Commitment Discount Unit represents the provider-specified measurement unit indicating how a provider measures the [Commitment Discount Quantity](#commitmentdiscountquantity) of a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountUnit column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).
+
+The CommitmentDiscountUnit column adheres to the following requirements:
+
+* CommitmentDiscountUnit MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports [*commitment discounts*](#glossary:commitment-discount).
+* CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute.
+* The CommitmentDiscountUnit MUST be the same across all *rows* where CommitmentDiscountQuantity has the same [CommitmentDiscountId](#commitmentdiscountid).
+* CommitmentDiscountUnit MAY be null if CommitmentDiscountId is not null and [ChargeClass](#chargeclass) is "Correction".
+* CommitmentDiscountUnit MUST NOT be null when CommitmentDiscountId is not null and ChargeClass is not "Correction".
+* CommitmentDiscountUnit MUST be null in all other cases.
+
+In cases where the CommitmentDiscountUnit is not null, the following applies:
+
+* The CommitmentDiscountUnit MUST represent the unit used to measure the *commitment discount*.
+* When accounting for [*commitment discount flexibility*](#glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration.
+
+## Column ID
+
+CommitmentDiscountUnit
+
+## Display Name
+
+Commitment Discount Unit
+
+## Description
+
+The provider-specified measurement unit indicating how a provider measures the Commitment Discount Quantity of a *commitment discount*.
+
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Column type | Dimension |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | String |
+| Value format | [Unit Format](#unitformat)|
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md
index faab3c0fa..234f63b7e 100644
--- a/specification/columns/consumedquantity.md
+++ b/specification/columns/consumedquantity.md
@@ -1,8 +1,14 @@
# Consumed Quantity
-The Consumed Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost.
+The Consumed Quantity represents the volume of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost.
-ConsumedQuantity column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction".
+The ConsumedQuantity column adheres to the following requirements:
+
+* ConsumedQuantity MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage.
+* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements.
+* ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction".
+* ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction".
+* ConsumedQuantity MUST be null in all other cases.
## Column ID
@@ -14,7 +20,7 @@ Consumed Quantity
## Description
-The volume of a given SKU associated with a *resource* or *service* used, based on the Consumed Unit.
+The volume of a metered SKU associated with a *resource* or *service* used, based on the Consumed Unit.
## Content constraints
diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md
index cb36de660..a9f7b78bc 100644
--- a/specification/columns/consumedunit.md
+++ b/specification/columns/consumedunit.md
@@ -1,8 +1,14 @@
# Consumed Unit
-The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost.
+The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost.
-The ConsumedUnit column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST be of type String. ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. Units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The ConsumedUnit column MUST NOT be used to determine values related to any pricing or cost metrics.
+The ConsumedUnit column adheres to the following requirements:
+
+* ConsumedUnit MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage.
+* ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute.
+* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction".
+* ConsumedUnit MAY be null if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction".
+* ConsumedUnit MUST be null in all other cases.
## Column ID
@@ -14,7 +20,7 @@ Consumed Unit
## Description
-Provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a *resource* or *service*.
+Provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a *resource* or *service*.
## Content constraints
diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md
index 12912f761..96a678312 100644
--- a/specification/columns/contractedcost.md
+++ b/specification/columns/contractedcost.md
@@ -1,10 +1,8 @@
# Contracted Cost
-Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If negotiated discounts are not applicable, the Contracted Cost defaults to the List Cost.
+Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost.
-**Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0.
-
-The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently.
+The ContractedCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently.
In cases where the ContractedUnitPrice is present and null, the following applies:
@@ -23,6 +21,10 @@ Contracted Cost
Cost calculated by multiplying *contracted unit price* and the corresponding Pricing Quantity.
+## Usability Constraints
+
+**Aggregation:** When aggregating Contracted Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0.
+
## Content Constraints
| Constraint | Value |
diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md
index faf177d32..36d21392b 100644
--- a/specification/columns/contractedunitprice.md
+++ b/specification/columns/contractedunitprice.md
@@ -1,8 +1,8 @@
# Contracted Unit Price
-The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice).
+The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice).
-The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concept. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
+The ContractedUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
## Column ID
@@ -16,6 +16,10 @@ Contracted Unit Price
The agreed-upon unit price for a single Pricing Unit of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts.
+## Usability Constraints
+
+**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total.
+
## Content Constraints
| Constraint | Value |
diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md
index eb5b28887..f54dec19d 100644
--- a/specification/columns/effectivecost.md
+++ b/specification/columns/effectivecost.md
@@ -7,12 +7,13 @@ This column resolves two challenges that are faced by practitioners:
1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)).
2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*.
-The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*.
+The EffectiveCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*.
In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies:
* The EffectiveCost MUST be calculated based on the EffectiveCost of the related charges if the charge is calculated based on other charges (e.g. [ChargeCategory](#chargecategory) is "Tax").
* The EffectiveCost MUST match the [BilledCost](#billedcost) if the charge is unrelated to other charges (e.g. [ChargeCategory](#chargecategory) is "Credit").
+* When CommitmentDiscountStatus is "Unused", the EffectiveCost MUST be the total committed cost consumed for the given charge period minus related usage charges.
## Column ID
diff --git a/specification/columns/invoiceissuer.md b/specification/columns/invoiceissuer.md
index 7a1b76edf..dfe03ed11 100644
--- a/specification/columns/invoiceissuer.md
+++ b/specification/columns/invoiceissuer.md
@@ -3,7 +3,7 @@
An Invoice Issuer is an entity responsible for invoicing for the [*resources*](#glossary:resource) or [*services*](#glossary:service) consumed. It is commonly
used for cost analysis and reporting scenarios.
-The InvoiceIssuer column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values.
+The InvoiceIssuer column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values.
See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), [Publisher](#publisher) and
Invoice Issuer values that can be used for various purchasing scenarios.
diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md
index de5fabc87..c2e6d3dd9 100644
--- a/specification/columns/listcost.md
+++ b/specification/columns/listcost.md
@@ -2,9 +2,7 @@
List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost).
-**Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0.
-
-The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently.
+The ListCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently.
In cases where the ListUnitPrice is present and is null, the following applies:
@@ -23,6 +21,10 @@ List Cost
Cost calculated by multiplying List Unit Price and the corresponding Pricing Quantity.
+## Usability Constraints
+
+**Aggregation:** When aggregating List Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0.
+
## Content Constraints
| Constraint | Value |
diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md
index 531bd716c..d35d73b32 100644
--- a/specification/columns/listunitprice.md
+++ b/specification/columns/listunitprice.md
@@ -2,7 +2,7 @@
The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities.
-The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
+The ListUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
## Column ID
@@ -16,6 +16,10 @@ List Unit Price
The suggested provider-published unit price for a single Pricing Unit of the associated SKU, exclusive of any discounts.
+## Usability Constraints
+
+**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total.
+
## Content Constraints
| Constraint | Value |
diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md
index 7f881fa46..504c807e9 100644
--- a/specification/columns/pricingcategory.md
+++ b/specification/columns/pricingcategory.md
@@ -1,14 +1,14 @@
# Pricing Category
-Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [commitment discount](#glossary:commitment-discount) coverage.
+Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [*commitment discount*](#glossary:commitment-discount) coverage.
The PricingCategory column adheres to the following requirements:
-* PricingCategory MUST be present in a FOCUS dataset when the provider supports more than one pricing category across all SKUs and MUST be of type String.
+* PricingCategory MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports more than one pricing category across all SKUs and MUST be of type String.
* PricingCategory MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory.
* PricingCategory MUST be one of the allowed values.
* PricingCategory MUST be "Standard" when pricing is predetermined at the agreed upon rate for the [billing account](#glossary:billing-account).
-* PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null.
+* PricingCategory MUST be "Committed" when the charge is subject to an existing *commitment discount* and is not the purchase of the *commitment discount*.
* PricingCategory MUST be "Dynamic" when pricing is determined by the provider and may change over time, regardless of predetermined agreement pricing.
* PricingCategory MUST be "Other" when there is a pricing model but none of the allowed values apply.
@@ -38,9 +38,9 @@ Allowed values:
| Value | Description |
| :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Standard | Charges priced at the agreed upon rate for the billing account, including negotiated discounts. This includes any flat rate and volume/tiered pricing but does not include dynamic or commitment discount pricing. |
+| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This pricing includes any flat rate and volume/tiered pricing but does not include dynamic pricing or reduced pricing due to the application of a *commitment discount*. This does include the purchase of a commitment discount at agreed upon rates. |
| Dynamic | Charges priced at a variable rate determined by the provider. This includes any product or service with a unit price the provider can change without notice, like interruptible or low priority resources. |
-| Committed | Charges with reduced prices due to a commitment discount specified by the Commitment Discount ID. |
+| Committed | Charges with reduced pricing due to the application of the *commitment discount* specified by the Commitment Discount ID. |
| Other | Charges priced in a way not covered by another pricing category. |
## Introduced (version)
diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md
index b811cd71b..2a10fb652 100644
--- a/specification/columns/pricingquantity.md
+++ b/specification/columns/pricingquantity.md
@@ -2,7 +2,7 @@
The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption.
-The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
+The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently.
## Column ID
@@ -16,7 +16,11 @@ Pricing Quantity
The volume of a given SKU associated with a *resource* or *service* used or purchased, based on the Pricing Unit.
-## Content constraints
+## Usability Constraints
+
+**Aggregation:** When aggregating Pricing Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation.
+
+## Content Constraints
| Constraint | Value |
|:----------------|:--------------------------|
diff --git a/specification/columns/pricingunit.md b/specification/columns/pricingunit.md
index 73e38c943..dccea8655 100644
--- a/specification/columns/pricingunit.md
+++ b/specification/columns/pricingunit.md
@@ -1,8 +1,8 @@
# Pricing Unit
-The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#Consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity.
+The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity.
-The PricingUnit column MUST be present in a FOCUS dataset. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute.
+The PricingUnit column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute.
The PricingUnit value MUST be semantically equal to the corresponding pricing measurement unit value provided in:
diff --git a/specification/columns/provider.md b/specification/columns/provider.md
index e17f43e90..a88b07b69 100644
--- a/specification/columns/provider.md
+++ b/specification/columns/provider.md
@@ -2,7 +2,7 @@
A Provider is an entity that makes the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. It is commonly used for cost analysis and reporting scenarios.
-The Provider column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values.
+The Provider column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values.
See [Appendix: Origination of cost data](#originationofcostdata) section for examples of Provider, Publisher and
Invoice Issuer values that can be used for various purchasing scenarios.
diff --git a/specification/columns/publisher.md b/specification/columns/publisher.md
index a9f5fd16c..14a407167 100644
--- a/specification/columns/publisher.md
+++ b/specification/columns/publisher.md
@@ -2,7 +2,7 @@
A Publisher is an entity that produces the [*resources*](#glossary:resource) or [*services*](#glossary:service) that were purchased. It is commonly used for cost analysis and reporting scenarios.
-The Publisher column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values.
+The Publisher column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values.
See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), Publisher and
[Invoice Issuer](#invoiceissuer) values that can be used for various purchasing scenarios.
diff --git a/specification/columns/regionid.md b/specification/columns/regionid.md
index 873d036df..b1cada0e4 100644
--- a/specification/columns/regionid.md
+++ b/specification/columns/regionid.md
@@ -2,7 +2,7 @@
A Region ID is a provider-assigned identifier for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. The region is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed.
-The RegionId column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area.
+The RegionId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area.
## Column ID
diff --git a/specification/columns/regionname.md b/specification/columns/regionname.md
index 934ca0b91..ee3092e51 100644
--- a/specification/columns/regionname.md
+++ b/specification/columns/regionname.md
@@ -2,7 +2,7 @@
Region Name is a provider-assigned display name for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. Region Name is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed.
-The RegionName column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area.
+The RegionName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area.
## Column ID
diff --git a/specification/columns/resourceid.md b/specification/columns/resourceid.md
index e48d24d08..f494aa480 100644
--- a/specification/columns/resourceid.md
+++ b/specification/columns/resourceid.md
@@ -2,7 +2,7 @@
A Resource ID is an identifier assigned to a [*resource*](#glossary:resource) by the provider. The Resource ID is commonly used for cost reporting, analysis, and allocation scenarios.
-The ResourceId column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider.
+The ResourceId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider.
## Column ID
diff --git a/specification/columns/resourcename.md b/specification/columns/resourcename.md
index 524311b0c..71fa7a938 100644
--- a/specification/columns/resourcename.md
+++ b/specification/columns/resourcename.md
@@ -2,7 +2,7 @@
The Resource Name is a display name assigned to a [*resource*](#glossary:resource). It is commonly used for cost analysis, reporting, and allocation scenarios.
-The ResourceName column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName.
+The ResourceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName.
## Column ID
diff --git a/specification/columns/resourcetype.md b/specification/columns/resourcetype.md
index 96480f78a..d05622c87 100644
--- a/specification/columns/resourcetype.md
+++ b/specification/columns/resourcetype.md
@@ -2,7 +2,7 @@
Resource Type describes the kind of [*resource*](#glossary:resource) the charge applies to. A Resource Type is commonly used for scenarios like identifying cost changes in groups of similar *resources* and may include values like Virtual Machine, Data Warehouse, and Load Balancer.
-The ResourceType column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null.
+The ResourceType column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null.
## Column ID
diff --git a/specification/columns/servicecategory.md b/specification/columns/servicecategory.md
index c8d474fbb..77a83c41e 100644
--- a/specification/columns/servicecategory.md
+++ b/specification/columns/servicecategory.md
@@ -2,7 +2,7 @@
The Service Category is the highest-level classification of a [*service*](#glossary:service) based on the core function of the *service*. Each *service* should have one and only one category that best aligns with its primary purpose. The Service Category is commonly used for scenarios like analyzing costs across providers and tracking the migration of workloads across fundamentally different architectures.
-The ServiceCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values.
+The ServiceCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values.
## Column ID
diff --git a/specification/columns/servicename.md b/specification/columns/servicename.md
index db1fc0cda..a5086cba1 100644
--- a/specification/columns/servicename.md
+++ b/specification/columns/servicename.md
@@ -4,7 +4,7 @@ A [*service*](#glossary:service) represents an offering that can be purchased fr
The Service Name is a display name for the offering that was purchased. The Service Name is commonly used for scenarios like analyzing aggregate cost trends over time and filtering data to investigate anomalies.
-The ServiceName column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values.
+The ServiceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values.
## Column ID
diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md
new file mode 100644
index 000000000..8452e588b
--- /dev/null
+++ b/specification/columns/servicesubcategory.md
@@ -0,0 +1,123 @@
+# Service Subcategory
+
+The Service Subcategory is a secondary classification of the [Service Category](#servicecategory) for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures.
+
+The ServiceSubcategory column adheres to the following requirements:
+
+* ServiceSubcategory is RECOMMENDED to be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null.
+* ServiceSubcategory is of type String and MUST be one of the allowed values.
+* Each ServiceSubcategory value MUST have one and only one parent ServiceCategory as specified in the allowed values below.
+* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one ServiceSubcategory that best aligns with its primary purpose.
+
+## Column ID
+
+ServiceSubcategory
+
+## Display Name
+
+Service Subcategory
+
+## Description
+
+Secondary classification of the Service Category for a *service* based on its core function.
+
+## Content Constraints
+
+| Constraint | Value |
+| :-------------- | :------------- |
+| Column type | Dimension |
+| Feature level | Recommended |
+| Allows nulls | False |
+| Data type | String |
+| Value format | Allowed Values |
+
+Allowed values:
+
+| Service Category | Service Subcategory | Service Subcategory Description |
+| ------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
+| AI and Machine Learning | AI Platforms | Unified solution that combines artificial intelligence and machine learning technologies. |
+| AI and Machine Learning | Bots | Automated performance of tasks such as customer service, data collection, and content moderation. |
+| AI and Machine Learning | Generative AI | Creation of content like text, images, and music by learning patterns from existing data. |
+| AI and Machine Learning | Machine Learning | Creation, training, and deployment of statistical algorithms that learn from and perform tasks based on data. |
+| AI and Machine Learning | Natural Language Processing | Generation of human language, handling tasks like translation, sentiment analysis, and text summarization. |
+| AI and Machine Learning | Other (AI and Machine Learning) | AI and Machine Learning services that do not fall into one of the defined subcategories. |
+| Analytics | Analytics Platforms | Unified solution that combines technologies across the entire analytics lifecycle. |
+| Analytics | Business Intelligence | Semantic models, dashboards, reports, and data visualizations to track performance and identify trends. |
+| Analytics | Data Processing | Integration and transformation tasks to prepare data for analysis. |
+| Analytics | Search | Discovery of information by indexing and retrieving data from various sources. |
+| Analytics | Streaming Analytics | Real-time data stream processes to detect patterns, trends, and anomalies as they occur. |
+| Analytics | Other (Analytics) | Analytics services that do not fall into one of the defined subcategories. |
+| Business Applications | Productivity and Collaboration | Tools that facilitate individuals managing tasks and working together. |
+| Business Applications | Other (Business Applications) | Business Applications services that do not fall into one of the defined subcategories. |
+| Compute | Containers | Management and orchestration of containerized compute platforms. |
+| Compute | End User Computing | Virtualized desktop infrastructure and device / endpoint management. |
+| Compute | Quantum Compute | Resources and simulators that leverage the principles of quantum mechanics. |
+| Compute | Serverless Compute | Enablement of compute capabilities without provisioning or managing servers. |
+| Compute | Virtual Machines | Computing environments ranging from hosts with abstracted operating systems to bare-metal servers. |
+| Compute | Other (Compute) | Compute services that do not fall into one of the defined subcategories. |
+| Databases | Caching | Low-latency and high-throughput access to frequently accessed data. |
+| Databases | Data Warehouses | Big data storage and querying capabilities. |
+| Databases | Ledger Databases | Immutable and transparent databases to record tamper-proof and cryptographically secure transactions. |
+| Databases | NoSQL Databases | Unstructured or semi-structured data storage and querying capabilities. |
+| Databases | Relational Databases | Structured data storage and querying capabilities. |
+| Databases | Time Series Databases | Time-stamped data storage and querying capabilities. |
+| Databases | Other (Databases) | Database services that do not fall into one of the defined subcategories. |
+| Developer Tools | Developer Platforms | Unified solution that combines technologies across multiple areas of the software development lifecycle. |
+| Developer Tools | Continuous Integration and Deployment | CI/CD tools and services that support building and deploying code for software and systems. |
+| Developer Tools | Development Environments | Tools and services that support authoring code for software and systems. |
+| Developer Tools | Source Code Management | Tools and services that support version control of code for software and systems. |
+| Developer Tools | Quality Assurance | Tools and services that support testing code for software and systems. |
+| Developer Tools | Other (Developer Tools) | Developer Tools services that do not fall into one of the defined subcategories. |
+| Identity | Identity and Access Management | Technologies that ensure users have appropriate access to resources. |
+| Identity | Other (Identity) | Identity services that do not fall into one of the defined subcategories. |
+| Integration | API Management | Creation, publishing, and management of application programming interfaces. |
+| Integration | Messaging | Asynchronous communication between distributed applications. |
+| Integration | Workflow Orchestration | Design, execution, and management of business processes and workflows. |
+| Integration | Other (Integration) | Integration services that do not fall into one of the defined subcategories. |
+| Internet of Things | IoT Analytics | Examination of data collected from IoT devices. |
+| Internet of Things | IoT Platforms | Unified solution that combines IoT data collection, processing, visualization, and device management. |
+| Internet of Things | Other (Internet of Things) | Internet of Things (IoT) services that do not fall into one of the defined subcategories. |
+| Management and Governance | Architecture | Planning, design, and construction of software systems. |
+| Management and Governance | Compliance | Adherance to regulatory standards and industry best practices. |
+| Management and Governance | Cost Management | Monitoring and controlling expenses of systems and services. |
+| Management and Governance | Data Governance | Management of the availability, usability, integrity, and security of data. |
+| Management and Governance | Disaster Recovery | Plans and procedures that ensure systems and services can recover from disruptions. |
+| Management and Governance | Endpoint Management | Tools that configure and secure access to devices. |
+| Management and Governance | Observability | Monitoring, logging, and tracing of data to track the performance and health of systems. |
+| Management and Governance | Support | Assistance and expertise supplied by providers. |
+| Management and Governance | Other (Management and Governance) | Management and governance services that do not fall into one of the defined subcategories. |
+| Media | Content Creation | Production of media content. |
+| Media | Gaming | Development and delivery of gaming services. |
+| Media | Media Streaming | Multimedia delivered and rendered in real-time on devices. |
+| Media | Mixed Reality | Technologies that blend real-world and computer-generated environments. |
+| Media | Other (Media) | Media services that do not fall into one of the defined subcategories. |
+| Migration | Data Migration | Movement of stored data from one location to another. |
+| Migration | Resource Migration | Movement of resources from one location to another. |
+| Migration | Other (Migration) | Migration services that do not fall into one of the defined subcategories. |
+| Mobile | Other (Mobile) | All Mobile services. |
+| Multicloud | Multicloud Integration | Environments that facilitate consumption of services from multiple cloud providers. |
+| Multicloud | Other (Multicloud) | Multicloud services that do not fall into one of the defined subcategories. |
+| Networking | Application Networking | Distribution of incoming network traffic across application-based workloads. |
+| Networking | Content Delivery | Distribution of digital content using a network of servers (CDNs). |
+| Networking | Network Connectivity | Facilitates communication between networks or network segments. |
+| Networking | Network Infrastructure | Configuration, monitoring, and troubleshooting of network devices. |
+| Networking | Network Routing | Services that select paths for traffic within or across networks. |
+| Networking | Network Security | Protection from unauthorized network access and cyber threats using firewalls and anti-malware tools. |
+| Networking | Other (Networking) | Networking services that do not fall into one of the defined subcategories. |
+| Security | Secret Management | Information used to authenticate users and systems, including secrets, certificates, tokens, and other keys. |
+| Security | Security Posture Management | Tools that help organizations configure, monitor, and improve system security. |
+| Security | Threat Detection and Response | Collect and analyze security data to identify and respond to potential security threats and vulnerabilities. |
+| Security | Other (Security) | Security services that do not fall into one of the defined subcategories. |
+| Storage | Backup Storage | Secondary storage to protect against data loss. |
+| Storage | Block Storage | High performance, low latency storage that provides random access. |
+| Storage | File Storage | Scalable, sharable storage for file-based data. |
+| Storage | Object Storage | Highly available, durable storage for unstructured data. |
+| Storage | Storage Platforms | Unified solution that supports multiple storage types. |
+| Storage | Other (Storage) | Storage services that do not fall into one of the defined subcategories. |
+| Web | Application Platforms | Integrated environments that run web applications. |
+| Web | Other (Web) | Web services that do not fall into one of the defined subcategories. |
+| Other | Other (Other) | Services that do not fall into one of the defined categories. |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/skuid.md b/specification/columns/skuid.md
index 7ab6ce38d..584a54416 100644
--- a/specification/columns/skuid.md
+++ b/specification/columns/skuid.md
@@ -2,7 +2,7 @@
A SKU ID is a unique identifier that defines a provider-supported construct for organizing properties that are common across one or more [*SKU Prices*](#glossary:sku-price). SKU ID can be referenced on a catalog or [*price list*](#glossary:price-list) published by a provider to look up detailed information about the SKU. The composition of the properties associated with the SKU ID may differ across providers. Some providers may not support the [*SKU*](#glossary:sku) construct and instead associate all such properties directly with the *SKU Price*. SKU ID is commonly used for analyzing cost based on *SKU*-related properties above the pricing constructs.
-The SkuId column MUST be present in a FOCUS dataset when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct.
+The SkuId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct.
## Column ID
diff --git a/specification/columns/skumeter.md b/specification/columns/skumeter.md
new file mode 100644
index 000000000..bdd892b9a
--- /dev/null
+++ b/specification/columns/skumeter.md
@@ -0,0 +1,43 @@
+# SKU Meter
+
+The SKU Meter describes the functionality being metered or measured by a particular SKU in a charge.
+
+Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a [*FOCUS dataset*](#glossary:FOCUS-dataset).
+
+The SkuMeter column adheres to the following requirements:
+
+* SkuMeter MUST be present in a *FOCUS dataset* when when the provider includes a [SkuId](#skuid).
+* SkuMeter MUST be of type String.
+* SkuMeter MUST be null when SkuId is null.
+* SkuMeter SHOULD NOT be null when SkuId is not null.
+* SkuMeter SHOULD remain consistent over time for a given SkuId.
+
+## Examples
+
+Compute Usage, Block Volume Usage, Data Transfer, API Requests
+
+## Column ID
+
+SkuMeter
+
+## Display Name
+
+SKU Meter
+
+## Description
+
+Describes the functionality being metered or measured by a particular SKU in a charge.
+
+## Content Constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Column type | Dimension |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | String |
+| Value format | \ |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/skupricedetails.md b/specification/columns/skupricedetails.md
new file mode 100644
index 000000000..a8f8381c3
--- /dev/null
+++ b/specification/columns/skupricedetails.md
@@ -0,0 +1,56 @@
+# SKU Price Details
+
+The SKU Price Details column represents a list of relevant properties shared by all charges with the same [SKU Price ID](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a SKU Price ID. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a SKU Price ID and differentiate it other SKU Price IDs.
+
+The SkuPriceDetails column adheres to the following requirements:
+
+* The SkuPriceDetails column MUST be in [KeyValueFormat](#key-valueformat).
+* The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase).
+* The properties (both keys and values) contained in the SkuPriceDetails column MUST be shared across all charges having the same SkuPriceId, subject to the below provisions.
+ * Additional properties (key-value pairs) MAY be added to SkuPriceDetails going forward for a given SkuPriceId.
+ * Properties SHOULD NOT be removed from SkuPriceDetails for a given SkuPriceId, once they have been included.
+ * Individual properties (key-value pairs) SHOULD NOT be modified for a given SkuPriceId and SHOULD remain consistent over time.
+* The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format.
+* The SkuPriceDetails column MUST NOT contain properties which are not applicable to the corresponding SkuPriceId.
+* The SkuPriceDetails column MAY contain properties which are already captured in other dedicated columns.
+* If a property has a numeric value, it MUST represent the value for a single [PricingUnit](#pricingunit).
+* The SkuPriceDetails column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider includes a SkuPriceId.
+ * The SkuPriceDetails column MAY be null when SkuPriceId is not null.
+ * The SkuPriceDetails column MUST be null when SkuPriceId is null.
+
+## Examples
+
+```json
+{
+ "OperationClass": "A",
+ "PricingTier": 2,
+ "CoreHours": 4,
+ "PreimumProcessing": true,
+}
+```
+
+## Column ID
+
+SkuPriceDetails
+
+## Display Name
+
+SKU Price Details
+
+## Description
+
+A set of properties of a SKU Price ID which are meaningful and common to all instances of that SKU Price ID.
+
+## Content Constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Column type | Dimension |
+| Feature level | Conditional |
+| Allows nulls | True |
+| Data type | JSON |
+| Value format | [Key-Value Format](#key-valueformat) |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md
index 2dad50bc1..69bf70a87 100644
--- a/specification/columns/skupriceid.md
+++ b/specification/columns/skupriceid.md
@@ -2,7 +2,14 @@
A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers.
-The SkuPriceId column MUST be present in a FOCUS dataset when the provider publishes a SKU price list. This column MUST be of type String. SkuPriceId MUST define a single unit price used for calculating the charge. The [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published *price list*. This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of commitment discount flexibility.
+The SkuPriceId column adheres to the following requirements:
+
+* SkuPriceId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU price list and MUST be of type String.
+* SkuPriceId MUST define a single unit price used for calculating the charge.
+* [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published price list.
+* SkuPriceId MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory.
+* A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of [commitment discount flexibility](#glossary:commitment-discount-flexibility).
+* If a provider does not have a SkuPriceId and wants to include information in columns linked to SkuPriceId such as ListUnitPrice or [SkuPriceDetails](#skupricedetails), the SkuId MAY be used in the SkuPriceId column as long as it adheres to the above conditions.
## Column ID
diff --git a/specification/columns/subaccountid.md b/specification/columns/subaccountid.md
index f0bfd2a4a..7ca7ccd62 100644
--- a/specification/columns/subaccountid.md
+++ b/specification/columns/subaccountid.md
@@ -2,7 +2,7 @@
A Sub Account ID is a provider-assigned identifier assigned to a [*sub account*](#glossary:sub-account). Sub Account ID is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies.
-The SubAccountId column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null.
+The SubAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null.
See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS.
diff --git a/specification/columns/subaccountname.md b/specification/columns/subaccountname.md
index 0f837ecec..b64f56fd6 100644
--- a/specification/columns/subaccountname.md
+++ b/specification/columns/subaccountname.md
@@ -2,7 +2,7 @@
A Sub Account Name is a display name assigned to a [*sub account*](#glossary:sub-account). Sub account Name is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies.
-The SubAccountName column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null.
+The SubAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null.
See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS.
diff --git a/specification/columns/tags.md b/specification/columns/tags.md
index f97b75d92..d273fa195 100644
--- a/specification/columns/tags.md
+++ b/specification/columns/tags.md
@@ -6,10 +6,10 @@ A tag becomes [*finalized*](#glossary:finalized-tag) when a single value is sele
The Tags column adheres to the following requirements:
-* The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags.
+* The Tags column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports setting user or provider-defined tags.
* The Tags column MUST contain user-defined and provider-defined tags.
* The Tags column MUST only contain finalized tags.
-* The Tags column MUST be in [Key-Value Format](#key-valueformat).
+* The Tags column MUST be in [KeyValueFormat](#key-valueformat).
* A Tag key with a non-null value for a given resource SHOULD be included in the tags column.
* A Tag key with a null value for a given resource MAY be included in the tags column depending on the provider's tag finalization process.
* A Tag key that does *not* support a corresponding value, MUST have a corresponding true (boolean) value set.
diff --git a/specification/contributors.md b/specification/contributors.md
index 2674fe1e6..8ecc94997 100644
--- a/specification/contributors.md
+++ b/specification/contributors.md
@@ -2,80 +2,39 @@
### Maintainers
-Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS specification.
+Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS Release **v1.1** specification.
+* Alex Hullah (Goldman Sachs)
* Christopher Harris (Datadog)
-* Dennis Park-Rodriguez (Amazon Web Services)
-* Erik Peterson (CloudZero)
* Irena Jurica (Neos)
* Joaquin Prado (FinOps Foundation)
* Karl Kraft (Walmart)
* Larry Advey (Twilio)
* Michael Flanakin (Microsoft)
-* Mike Fuller (FinOps Foundation)
* Riley Jenkins (Domo)
-* Rupa Patel (Google)
+* Shawn Alpay (Envisor / FinOps Foundation)
* Udam Dewaraja (FinOps Foundation)
+* Zach Erdman (Amazon Web Services)
### Contributors
-Thanks to the following FOCUS members for their contributions to the FOCUS specification.
+Thanks to the following FOCUS members for their contributions to the FOCUS Release **v1.1** specification.
* Adam Schwartz (Ernst & Young)
-* Alex Hullah (Goldman Sachs)
-* Amit Wadhwa (Google)
-* Anand Tripathi (Amazon Web Services)
-* Anderson Oliveira (Farfetch.com)
* Andrew Qu (Everest)
-* Anne Johnston (Capital One)
* Arun Ramakrishnan (Oracle)
-* Ben Shy (Microsoft)
-* Ben Swoboda (NetApp)
-* Ben Zhou (Apptio)
-* Casey Doran (Apptio)
-* Chandra Devarajan (CloudTrakr)
-* Chew Esmero (Alphaus Inc.)
-* Colin Jack (Snow Software)
-* Deeja Cruz (Datadog)
-* Eleni Rundle (Google)
+* Erik Peterson (CloudZero)
* George Parker (Salesforce)
* Graham Murphy (Australian Retirement Trust)
-* Harish Kumar Munagapat (Kyndryl)
-* Hrishikesh Sardar (Kyndryl)
-* Ilia Semenov (CloudThread)
-* Jacky Liu (Google Cloud)
-* Jacqui Wilson (Old Mutual South Africa)
* Janine Pickard-Green (MagicOrange Group Limited)
-* Jason Kelly (Anglepoint Group Inc)
-* Joe Ferrero (DB Gurus Inc)
* John Grubb (Platform.sh)
-* Joshua Kwan (Ternary)
-* Letian Wang (Atlassian)
-* Luna Bernal (Twilio)
+* Joseph John (Microsoft)
* Marc Perreaut (Amadeus)
-* Marcin Walkow (Nordcloud)
-* Mark Krawczeniuk (NetApp)
-* Matt Ray (Kubecost)
-* Michael Arkoosh (Vega)
-* Mike Polson (VMWare)
-* Nick Kotze (Surveil)
-* Nicolas Fonrose (Teevity)
-* Peter Marton (OpenMeter.io)
-* Ray Ding (Accenture)
-* Ricardo Triana (Accenture)
-* Rodney Joyce (CloudMonitor)
+* Rob Martin (FinOps Foundation)
+* Rupa Patel (Google)
* Sanjna Srivatsa (VMWare)
-* Shawn Alpay (Envisor)
-* Sireesha Oram (Kyndryl)
* Sonal Garg (Kyndryl)
-* Sumaira Nazir (Platform.sh)
-* Tatiana Dubovchenko (Flexera)
-* Tim O'Brien (Walmart)
-* Trey Morgan (Microsoft)
-* Trig Ghosh (Accenture)
-* Webb Brown (Kubecost)
-* Yuriy Prykhodko (Amazon Web Services)
-* Zach Erdman (Amazon Web Services)
+* Tim Wright (Google)
## Steering Committee Members
diff --git a/specification/glossary.md b/specification/glossary.md
index dae733a37..443971a6a 100644
--- a/specification/glossary.md
+++ b/specification/glossary.md
@@ -30,7 +30,11 @@ The time window that an organization receives an invoice for, inclusive of the s
Block Pricing
- A pricing approach where the cost of a particular resource or service is determined based on predefined quantities or tiers of usage. In these scenarios, the Pricing Unit and the corresponding Pricing Quantity can be different from the Consumed Unit and Consumed Quantity.
+A pricing approach where the cost of a particular resource or service is determined based on predefined quantities or tiers of usage. In these scenarios, the Pricing Unit and the corresponding Pricing Quantity can be different from the Consumed Unit and Consumed Quantity.
+
+Capacity Reservation
+
+A capacity reservation is an agreement that secures a dedicated amount of resources or services for a specified period. This ensures the reserved capacity is always available and accessible, even if it's not fully utilized. Customers are typically charged for the reserved capacity, regardless of actual consumption.
Charge
@@ -40,17 +44,21 @@ A row in a FOCUS-compatible cost and usage dataset.
The time window for which a charge is effective, inclusive of the start date and exclusive of the end date. The charge period for continuous usage should match the time granularity of the dataset (e.g., 1 hour for hourly, 1 day for daily). The charge period for a non-usage charge with time boundaries should match the duration of eligibility.
+Cloud Service Provider (CSP)
+
+A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee.
+
Commitment
A customer's agreement to consume a specific quantity of a service or resource over a defined period, usually also creating a financial commitment throughout the entirety of the commitment period. Some commitments also hold Providers to certain assurance levels of resource availability.
Commitment Discount
-Also known as Commitment Discount, this is a commitment for an amount of usage or spend throughout a specified term, in exchange for discounted unit pricing on that amount. The commitment may be based on quantities of resource units or monetary value, with various payment options and time frames.
+A billing discount model that offers reduced rates on preselected SKUs in exchange for an obligated usage or spend amount over a predefined term. Commitment discount purchases, made upfront and/or with recurring monthly payments are amortized evenly across predefined charge periods (i.e. hourly), and unused amounts cannot be carried over to subsequent charge periods. Commitment discounts are publicly available to customers without special contract arrangements.
-Cloud Service Provider (CSP)
+Commitment Discount Flexibility
-A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee.
+A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermined amount of usage purchased or consumed based on additional, provider-specific requirements.
Contracted Unit Price
@@ -92,34 +100,42 @@ A category of compute resources that can be paused or terminated by the CSP with
The suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated [SKU](#glossary:sku), exclusive of any discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency).
+Managed Service Provider (MSP)
+
+A company or organization that provides outsourced management and support of a range of IT services, such as network infrastructure, cybersecurity, cloud computing, and more.
+
Metric
A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations.
-Managed Service Provider (MSP)
+Negotiated Discount
-A company or organization that provides outsourced management and support of a range of IT services, such as network infrastructure, cybersecurity, cloud computing, and more.
+A contractual agreement where a customer commits to specific spend or usage goals over a [*term*](#glossary:term) in exchange for discounted rates across varying SKUs. Unlike [*commitment discounts*](#glossary:commitment-discount), negotiated discounts are typically more customized to customer's accounts, can be utilized at varying frequencies, and may overlap with *commitment discounts*.
On-Demand
A term that describes a service that is available and provided immediately or as needed, without requiring a pre-scheduled appointment or prior arrangement. In cloud computing, virtual machines can be created and terminated as needed, i.e. on demand.
-Practitioner
+Pascal Case
-An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services.
+Pascal Case (PascalCase, also known as UpperCamelCase) is a format for identifiers which contain one or more words meaning the words are concatenated together with no delimiter and the first letter of each word is capitalized.
Potato
A long and often painful conversation had by the FOCUS contributors. Sometimes the name of a thing that we could not yet name. No starchy root vegetables were harmed during the production of this specification. We thank potato for its contribution in the creation of this specification.
-Provider
+Practitioner
-An entity that made internal or 3rd party resources and/or services available for purchase.
+An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services.
Price List
A comprehensive list of prices offered by a provider.
+Provider
+
+An entity that made internal or 3rd party resources and/or services available for purchase.
+
Resource
A unique component that incurs a charge.
@@ -151,3 +167,7 @@ A metadata label assigned to a resource to provide information about it or to ca
Tag Source
A Resource or Provider-defined construct for grouping resources and/or other Provider-defined construct that a Tag can be assigned to.
+
+Term
+
+A duration of a contractual agreement like with a [*commitment discount*](#glossary:commitment-discount) or [*negotiated discount*](#glossary:negotiated-discount).
diff --git a/specification/metadata/data_generator/data_generator.mdpp b/specification/metadata/data_generator/data_generator.mdpp
index 80b36aa5c..f6381353c 100644
--- a/specification/metadata/data_generator/data_generator.mdpp
+++ b/specification/metadata/data_generator/data_generator.mdpp
@@ -2,4 +2,12 @@
The FOCUS metadata about the generator of the FOCUS data.
+## Requirements
+
+The FOCUS Data Generator metadata MUST be provided. This metadata MUST be of type Object and MUST NOT contain null values.
+
+## Schema Example
+
+For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#datageneratormetadata)
+
!INCLUDE "datagenerator.md",1
diff --git a/specification/metadata/data_generator/datagenerator.md b/specification/metadata/data_generator/datagenerator.md
index a731c5999..64ed31dca 100644
--- a/specification/metadata/data_generator/datagenerator.md
+++ b/specification/metadata/data_generator/datagenerator.md
@@ -1,8 +1,8 @@
# Data Generator
-Human readable name of the entity that is generating the data.
+Human-readable name of the entity that is generating the data.
-The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT contain null values. The DataGenerator SHOULD be easily associated with the provider who generated the FOCUS dataset.
+The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Metadata ID
@@ -12,6 +12,15 @@ DataGenerator
Data Generator
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | String |
+| Value format | \ |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/metadata.mdpp b/specification/metadata/metadata.mdpp
index 4b1b22fe0..128078fe5 100644
--- a/specification/metadata/metadata.mdpp
+++ b/specification/metadata/metadata.mdpp
@@ -1,6 +1,8 @@
# Metadata
-The FOCUS specification defines a metadata structure that is to be supplied by data providers to facilitate practitioners use of FOCUS data. This meta data includes general information about the data generator and the schema of the FOCUS dataset. FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as: a file, website, api, table.
+The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the [*FOCUS dataset*](#glossary:FOCUS-dataset).
+
+FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as a file, website, API, or table. Providers SHOULD provide documentation on their implementation of the FOCUS metadata.
!INCLUDE "data_generator/data_generator.mdpp",1
-!INCLUDE "schema/schema.mdpp",1
+!INCLUDE "schema/schema.mdpp",1
\ No newline at end of file
diff --git a/specification/metadata/schema/column_definition/column_definition.mdpp b/specification/metadata/schema/column_definition/column_definition.mdpp
index 75971504e..71ef1132e 100644
--- a/specification/metadata/schema/column_definition/column_definition.mdpp
+++ b/specification/metadata/schema/column_definition/column_definition.mdpp
@@ -1,6 +1,10 @@
# Column Definition
-The FOCUS metadata schema column definition provides a list of the columns present in the FOCUS dataset along with metadata about the columns.
+The FOCUS metadata schema column definition provides a list of the columns present in the [*FOCUS dataset*](#glossary:FOCUS-dataset) along with metadata about the columns.
+
+## Requirements
+
+This metadata MUST be present in the FOCUS metadata schema. This metadata MUST be of type Object and MUST NOT contain null values.
!INCLUDE "columnname.md",1
!INCLUDE "datatype.md",1
diff --git a/specification/metadata/schema/column_definition/columnname.md b/specification/metadata/schema/column_definition/columnname.md
index cc9ff728b..0762433e9 100644
--- a/specification/metadata/schema/column_definition/columnname.md
+++ b/specification/metadata/schema/column_definition/columnname.md
@@ -1,6 +1,6 @@
# Column Name
-The name of the column provided in the FOCUS dataset.
+The name of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset).
The ColumnName MUST be provided in the FOCUS Metadata schema. ColumnName MUST be of type String and MUST NOT contain null values.
@@ -12,6 +12,15 @@ ColumnName
Column Name
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | String |
+| Value format | \ |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/column_definition/datatype.md b/specification/metadata/schema/column_definition/datatype.md
index bd099443d..bbd6b2eea 100644
--- a/specification/metadata/schema/column_definition/datatype.md
+++ b/specification/metadata/schema/column_definition/datatype.md
@@ -1,6 +1,6 @@
# Data Type
-The data type of the column provided in the FOCUS dataset.
+The data type of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset).
The DataType MUST be provided in the FOCUS Metadata schema. DataType MUST be of type String and MUST NOT contain null values.
@@ -12,6 +12,15 @@ DataType
Data Type
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | String |
+| Value format | \ |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/column_definition/numberscale.md b/specification/metadata/schema/column_definition/numberscale.md
index 4602e7058..e45bdbd1b 100644
--- a/specification/metadata/schema/column_definition/numberscale.md
+++ b/specification/metadata/schema/column_definition/numberscale.md
@@ -12,6 +12,15 @@ NumberScale
Number Scale
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:---------------------------------|
+| Feature level | Conditional |
+| Allows nulls | False |
+| Data type | Integer |
+| Value format | [Numeric Format](#numericformat) |
+
## Introduced (version)
1.0
\ No newline at end of file
diff --git a/specification/metadata/schema/column_definition/numericprecision.md b/specification/metadata/schema/column_definition/numericprecision.md
index 1ac35d95c..999c73c46 100644
--- a/specification/metadata/schema/column_definition/numericprecision.md
+++ b/specification/metadata/schema/column_definition/numericprecision.md
@@ -12,6 +12,15 @@ NumericPrecision
Numeric Precision
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:---------------------------------|
+| Feature level | Conditional |
+| Allows nulls | False |
+| Data type | Integer |
+| Value format | [Numeric Format](#numericformat) |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/column_definition/providertagprefixes.md b/specification/metadata/schema/column_definition/providertagprefixes.md
index d6267ffae..5fdfc278b 100644
--- a/specification/metadata/schema/column_definition/providertagprefixes.md
+++ b/specification/metadata/schema/column_definition/providertagprefixes.md
@@ -2,7 +2,7 @@
The Provider Tag Prefixes defines the list of prefixes used in the tag name of provider-defined [tags](#tags). This metadata is useful for the consumer to identify which tags are provider-defined vs user-defined.
-The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the FOCUS dataset.
+The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset).
## Metadata ID
@@ -12,6 +12,15 @@ ProviderTagPrefixes
Provider Tag Prefixes
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:------------------------------------|
+| Feature level | Conditional |
+| Allows nulls | False |
+| Data type | Array |
+| Value format | STRING datatype values in the array |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/column_definition/stringencoding.md b/specification/metadata/schema/column_definition/stringencoding.md
index cb9f870a1..ae790dee1 100644
--- a/specification/metadata/schema/column_definition/stringencoding.md
+++ b/specification/metadata/schema/column_definition/stringencoding.md
@@ -1,6 +1,6 @@
# String Encoding
-The string encoding scheme of the column provided in the FOCUS dataset.
+The string encoding scheme of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset).
StringEncoding SHOULD be provided in the FOCUS Metadata schema when it is required to know this information in order to successfully read the data. StringEncoding MUST be of type String and MUST NOT contain null values.
@@ -12,6 +12,15 @@ StringEncoding
StringEncoding
+## Content constraints
+
+| Constraint | Value |
+|:----------------|:-----------------|
+| Feature level | Conditional |
+| Allows nulls | False |
+| Data type | String |
+| Value format | \ |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/column_definition/stringmaxlength.md b/specification/metadata/schema/column_definition/stringmaxlength.md
index 69a74e3e0..4a0299995 100644
--- a/specification/metadata/schema/column_definition/stringmaxlength.md
+++ b/specification/metadata/schema/column_definition/stringmaxlength.md
@@ -12,6 +12,15 @@ StringMaxLength
String Max Length
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:---------------------------------|
+| Feature level | Conditional |
+| Allows nulls | False |
+| Data type | Integer |
+| Value format | [Numeric Format](#numericformat) |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/creationdate.md b/specification/metadata/schema/creationdate.md
index 6c5ed6bc1..2a1afc2bb 100644
--- a/specification/metadata/schema/creationdate.md
+++ b/specification/metadata/schema/creationdate.md
@@ -2,7 +2,7 @@
Date the schema was created.
-The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [Date/Time Format](#date/timeformat).
+The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [DateTimeFormat](#date/timeformat).
## Metadata ID
@@ -12,6 +12,15 @@ CreationDate
Creation Date
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:------------------------------------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | Date/Time |
+| Value format | [Date/Time Format](#date/timeformat) |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/focusversion.md b/specification/metadata/schema/focusversion.md
index c650665bd..0950e42a5 100644
--- a/specification/metadata/schema/focusversion.md
+++ b/specification/metadata/schema/focusversion.md
@@ -2,7 +2,7 @@
The version of FOCUS utilized for building the dataset.
-The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FOCUSVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the FOCUS dataset conforms to.
+The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the [*FOCUS dataset*](#glossary:FOCUS-dataset) conforms to.
## Metadata ID
@@ -12,6 +12,15 @@ FocusVersion
FOCUS Version
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:-----------------------------------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | STRING |
+| Value format | Must align with a published FocusVersion |
+
## Introduced (version)
1.0
diff --git a/specification/metadata/schema/providerversion.md b/specification/metadata/schema/providerversion.md
new file mode 100644
index 000000000..0b0c8450c
--- /dev/null
+++ b/specification/metadata/schema/providerversion.md
@@ -0,0 +1,26 @@
+# Provider Version
+
+The ProviderVersion MAY be supplied to declare the version of logic by which the [*FOCUS dataset*](#glossary:FOCUS-dataset) was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version.
+
+ProviderVersion MUST be of type String and MUST NOT contain null values. If FocusVersion is changed a new ProviderVersion MUST be also changed. The provider MUST document what changes are present in the ProviderVersion.
+
+## Metadata ID
+
+ProviderVersion
+
+## Metadata Name
+
+Provider Version
+
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:-----------------|
+| Feature level | Optional |
+| Allows nulls | False |
+| Data type | STRING |
+| Value format | \ |
+
+## Introduced (version)
+
+1.1
diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp
index b27448e13..8f40cc61b 100644
--- a/specification/metadata/schema/schema.mdpp
+++ b/specification/metadata/schema/schema.mdpp
@@ -1,8 +1,37 @@
# Schema
-Each FOCUS dataset must have a metadata about the schema associated with it. The schema metadata provides information about the structure of the data provided.
+The schema metadata object and its contents provides information about the structure of the data provided.
+
+## Requirements
+
+### Reference to FOCUS Data
+
+FOCUS data artifacts, whether they are data files, data streams, or data tables, MUST provide a clear reference to the schema of the data. This reference MUST be retrievable without inspection of the contents of the FOCUS data within the data artifact. For some delivery mechanisms such as database tables, the provider may rely on the schema functionality of the providing system.
+
+It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the [*FOCUS datasets*](#glossary:FOCUS-dataset) occurs.
+
+### Schema Metadata Creation
+
+Should the provider change the structure of the supplied FOCUS data artifact, a new schema metadata object MUST be supplied.
+These scenarios include, but are not limited to:
+
+* [Adding a new column](#addingnewcolumns)
+* [Removing a column](#removingcolumns)
+* [Changing column metadata](#changingcolumnmetadata)
+* [FOCUS Version has changed](#focusversionchanged)
+* [Provider Version has changed](#schemametadatatofocusdatareference)
+* [Correcting schema metadata errors](#providermetadataerrorcorrection)
+
+### Schema Metadata Updates
+
+Should there be an error where the schema metadata object does not match the schema of the FOCUS data artifact, the provider MUST update the schema metadata object to match the schema of the FOCUS data artifact. This is to ensure that the schema metadata object is always accurate.
+
+## Schema Example
+
+For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schemametadata)
!INCLUDE "schemaid.md",1
!INCLUDE "creationdate.md",1
!INCLUDE "focusversion.md",1
+!INCLUDE "providerversion.md",1
!INCLUDE "column_definition/column_definition.mdpp",1
diff --git a/specification/metadata/schema/schemaid.md b/specification/metadata/schema/schemaid.md
index d55872250..c1cf64388 100644
--- a/specification/metadata/schema/schemaid.md
+++ b/specification/metadata/schema/schemaid.md
@@ -2,7 +2,7 @@
The Schema ID provides the reference item to associate which Schema was used for the generation of a FOCUS Dataset.
-The SchemaId MUST be present in the metadata. The SchemaId MUST be of String. It is RECOMMENDED for SchemaId to be a Universally Unique Identifier (UUID) or [SemVer](https://semver.org) version.
+The SchemaId MUST be present in the metadata. The SchemaId MUST be of String. It is RECOMMENDED for SchemaId to be a Globally Unique Identifier (GUID).
## Metadata ID
@@ -12,6 +12,15 @@ SchemaId
Schema ID
+## Content constraints
+
+| Constraint | Value |
+|:--------------|:----------------------|
+| Feature level | Mandatory |
+| Allows nulls | False |
+| Data type | STRING |
+| Value format | Recommend GUID String |
+
## Introduced (version)
1.0
diff --git a/specification/use_case_library.md b/specification/use_case_library.md
index b8b5da96c..23069b781 100644
--- a/specification/use_case_library.md
+++ b/specification/use_case_library.md
@@ -1,46 +1,3 @@
# Use Case Library
-The following table contains a set of commonly performed FinOps scenarios that were used as a basis for developing this specification. These use cases were developed by FinOps practitioners.
-
-| Persona | Capability | Use Case | FOCUS Columns |
-|:--|:--|:--|:--|
-| Business / Product Owner | Budget Management | As a Business/Product Owner, I need to compare actual usage costs incurred within a time period to the amount forecasted. | BilledCost
BillingAccountId
BillingAccountName
ChargePeriodStart
ChargePeriodEnd
ChargeCategory
Provider |
-| Engineering & Operations | Budget Management | As an Engineering Manager who wants to reduce their billed cost for Compute for a specific provider, I want to understand what is my current rate of commitment discount (without negotiated discounts) per type of commitment, so that I can strategize further purchases | BillingPeriodStart
CommitmentDiscountType
EffectiveCost
ProviderName
ServiceName
SubAccountId
SubAccountName |
-| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components that belong to an application | ChargeDescription
ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
ResourceType
ServiceCategory
ServiceName
SkuId
Tags |
-| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components for a specific resource | ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
SkuId |
-| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of all components and resources within a subaccount | ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
SkuId
SubAccountId |
-| Engineering & Operations | Data Analysis and Showback | As an Engineering & Operations person I would like to analyze the usage of serverless requests on a weekly basis to identity potential optimization candidates | BilledCost
ProviderName
ChargePeriodStart
ChargePeriodEnd
SkuId
ConsumedQuantity
Tags
ConsumedUnit |
-| Engineering & Operations | Data Analysis and Showback | As an Engineer, I need to extract a ranked list of the top 10 service cost drivers within a sub account from a time period | ChargePeriodStart
EffectiveCost
SubAccountId
SubAccountName
ServiceName |
-| Engineering & Operations | Workload Management & Automation | As an Engineer I need to ensure my costs within a region are distributed across the different availability zones in an expected manner. | ProviderName
AvailabilityZone
RegionId
RegionName
BillingPeriodStart
EffectiveCost |
-| Engineering & Operations | Workload Management & Automation | As an Engineering manager, I need to see the cost of each compute resource in a production SubAccount I'm responsible for. | ResourceId
ResourceName
ChargePeriodStart
ChargePeriodEnd
ServiceName
ServiceCategory
PricingQuantity
EffectiveCost |
-| Finance | Budget Management | As a person in Finance, I need to update cloud budget with actual cost details within a billing period | BilledCost
BillingPeriodStart
BillingPeriodEnd
ProviderName |
-| Finance | Budget Management | As a person in Finance, I need to update budget, by application, with actual cost details within a billed time period | BilledCost
BillingPeriodStart
BillingPeriodEnd
ProviderName
Tags |
-| Finance | Budget Management | As a person in Finance, I need to track tax costs month over month. | BillingPeriodStart
BilledCost
ChargeCategory
ProviderName |
-| Finance | Budget Management | As a Financial Analyst or member of the company's treasury, I would like to understand what volume of commitment discount charges are going to reoccur in the coming financial year | ChargeFrequency
BillingPeriodStart
BilledCost |
-| Finance | Data Analysis and Showback | As a Finance person of a company that sells SaaS services, I need to determine the resource quantity and type used by a customer so that a monthly invoice can be issued to the customer. | ProviderName
BillingPeriodStart
SkuId
PricingQuantity
ConsumedQuantity
ConsumedUnit
Tags |
-| Finance | Data Analysis and Showback | As a person in Finance, I need a report of all cost associated with a product from all geographic locations for a given month. | BilledCost
BillingCurrency
BillingAccountId
BillingAccountName
BillingPeriodEnd
ProviderName
Tags |
-| Finance | FinOps & Intersecting Frameworks | As a person in Finance, I need a report of service-level cost within a specific Sub Account as a part of a private pricing negotiation. | BillingPeriodStart
EffectiveCost
ProviderName
ServiceName
SubAccountId
SubAccountName |
-| Finance | Forecasting | As a person in Finance, I need to forecast amortized costs on a month over month basis, based on historical trends | BillingPeriodStart
ChargeCategory
EffectiveCost
PricingUnit
ProviderName
ServiceName
ServiceCategory |
-| Finance | Forecasting | As a person in Finance, I need to forecast cashflow on a month over month basis, based on historical trends | BillingPeriodStart
ChargeCategory
ChargeDescription
BilledCost
BillingCurrency
ProviderName
ServiceName
ServiceCategory |
-| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs month over month, over a time period | EffectiveCost
BillingPeriodStart
ProviderName
ServiceName |
-| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs, by region, over a time period | EffectiveCost
BillingPeriodStart
ProviderName
RegionId
RegionName
ServiceName |
-| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze Compute Engine service costs month over month for a period of time to identify accounts spending the most money on Compute Engine | BilledCost
BillingPeriodStart
ProviderName
ResourceId
ResourceName
ServiceName
SubAccountId
SubAccountName |
-| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I want to monitor how much we are spending on a specific SaaS product purchased via the cloud service provider's marketplace. | ChargePeriodStart
ChargePeriodEnd
EffectiveCost
InvoiceIssuer
ProviderName
Publisher |
-| FinOps Practitioner | Data Analysis and Showback | As a FinOps Practitioner, I need to understand what we are spending across providers, billing periods, and service categories | ProviderName
BillingPeriodStart
BilledCost
BillingCurrency
ServiceCategory |
-| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices | ProviderName
BillingAccountId
BillingAccountName
BillingPeriodStart
BilledCost
BillingCurrency |
-| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices and the underlying services | ProviderName
BillingAccountId
BillingAccountName
BillingPeriodStart
BilledCost
BillingCurrency
ServiceName |
-| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to reconcile discounts on the cloud service provider invoices and the underlying services | ProviderName
BillingAccountId
BillingAccountName
BillingPeriodStart
BilledCost
BillingCurrency
EffectiveCost
ListCost
ServiceName |
-| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to analyze usage data of resources | ChargePeriodStart
ChargeCategory
EffectiveCost
ProviderName
PricingQuantity
ConsumedQuantity
ResourceId
ServiceName
SkuId
ConsumedUnit |
-| FinOps Practitioner | Forecasting | As a FinOps Practitioner, I need to forecast costs, based on historical usage trends and rates | BillingPeriodStart
ChargeCategory
ChargeDescription
EffectiveCost
ProviderName
PricingQuantity
ConsumedQuantity
RegionId
ServiceCategory
ServiceName
SkuId
ConsumedUnit |
-| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, and sub accounts | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
ProviderName
EffectiveCost |
-| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and region | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
EffectiveCost
ProviderName
RegionId
RegionName |
-| FinOps Practitioner | Managing Anomalies | As a FinOps practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and service | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
EffectiveCost
ProviderName
ServiceName |
-| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track all commitment discounts purchased for a time period | ProviderName
BillingAccountId
CommitmentDiscountId
CommitmentDiscountType
BilledCost
ChargePeriodStart
ChargeCategory |
-| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track unused commitment charges in any given time period so that I consider them in my future commitment planning or remedy them | CommitmentDiscountStatus (filter)
CommitmentDiscountId
BilledCost
ChargePeriodStart |
-| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture. | ChargeCategory
ChargeDescription
ChargePeriodStart
ProviderName
ResourceType
SubAccountId
ServiceName |
-| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture within a specific service | ChargeCategory
ChargeDescription
ChargePeriodStart
ProviderName
ResourceType
SubAccountId
ServiceName |
-| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify total refunds within a billing period. | ProviderName
BillingAccountId
ServiceCategory
BilledCost
BillingPeriodStart
ChargeCategory
ChargeClass |
-| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify refunds across sub accounts within a billing period. | ProviderName
BillingAccountId
ServiceCategory
BilledCost
BillingPeriodStart
ChargeCategory
ChargeClass
SubAccountId |
-| FinOps Practitioner | Workload Management & Automation | As a FinOps Practitioner, I need to do an analysis on compliance to data residency requirements across all regions | ChargePeriodStart
ProviderName
RegionId
RegionName
SubAccountId |
-| Procurement | Data Analysis and Showback | As a person in Procurement, I need to understand what we are spending, across billing periods, across service categories to focus negotiations toward highest costing items | ProviderName
BillingAccountId
BillingAccountName
BillingCurrency
BilledCost
BillingPeriodStart
ServiceCategory
ServiceName |
-| Procurement, Finance, FinOps Practitioner | FinOps & Intersecting Frameworks | Multiple personas in an organization need to know the top SKU Codes based on spend, so that they can achieve multiple goals such as contract negotiation, SKU based forecasting, or high unit cost cleanup activities. | ChargePeriodStart
ChargePeriodEnd
ListCost
PricingUnit
ListUnitPrice
PricingQuantity
SkuId
SkuPriceId
ProviderName |
+This specification is based on a set of common FinOps use cases, which are publicly available at [https://focus.finops.org/use-cases/](https://focus.finops.org/use-cases/). Developed by FinOps practitioners, these use cases are organized by persona and capability, making it easy to find relevant scenarios. Each use case includes sample SQL queries to help you get started with implementation.
diff --git a/supporting_content/columns/commitmentdiscountquantity.md b/supporting_content/columns/commitmentdiscountquantity.md
new file mode 100644
index 000000000..78c9fbb38
--- /dev/null
+++ b/supporting_content/columns/commitmentdiscountquantity.md
@@ -0,0 +1,25 @@
+# Column: CommitmentDiscountQuantity
+
+## Example provider mappings
+
+Current column mappings found in available data sets:
+
+| Provider | Data set | Column |
+|----------|----------|--------|
+| AWS | CUR | reservation/UnusedQuantity (inverse), reservation/TotalReservedUnits, savingsPlan/UsedCommitment, savingsPlan/TotalCommitmentToDate |
+| Google Cloud | BigQuery Billing Export | Not available |
+| Microsoft | Cost Details | Not available |
+
+## Example usage scenarios
+
+Current values observed in billing data for various scenarios:
+
+AWS Reservation Utilization Rate: (1 - (reservation/UnusedQuantity / reservation/TotalReservedUnits)) * 100
+AWS Savings Plan Utilization Rate: savingsPlan/UsedCommitment / savingsPlan/TotalCommitmentToDate * 100
+
+## Documentation
+- AWS
+ - Reservation details - https://docs.aws.amazon.com/cur/latest/userguide/reservation-columns.html
+ - Savings Plans details - https://docs.aws.amazon.com/cur/latest/userguide/savingsplans-columns.html
+
+
diff --git a/supporting_content/columns/commitmentdiscountunit.md b/supporting_content/columns/commitmentdiscountunit.md
new file mode 100644
index 000000000..180d2919e
--- /dev/null
+++ b/supporting_content/columns/commitmentdiscountunit.md
@@ -0,0 +1,23 @@
+# Column: CommitmentDiscountUnit
+
+## Example provider mappings
+
+Current column mappings found in available data sets:
+
+| Provider | Data set | Column |
+|----------|----------|--------|
+| AWS | CUR | Not available |
+| Google Cloud | BigQuery Billing Export | Not available |
+| Microsoft | Cost Details | Usage commitments: UnitOfMeasure
Spend commitments: BillingCurrency |
+
+## Example usage scenarios
+
+Current values observed in billing data for various scenarios:
+
+AWS Reservation Utilization Rate: (1 - (reservation/UnusedQuantity / reservation/TotalReservedUnits)) * 100
+AWS Savings Plan Utilization Rate: savingsPlan/UsedCommitment / savingsPlan/TotalCommitmentToDate * 100
+
+## Documentation
+- AWS
+ - Reservation details - https://docs.aws.amazon.com/cur/latest/userguide/reservation-columns.html
+ - Savings Plans details - https://docs.aws.amazon.com/cur/latest/userguide/savingsplans-columns.html
diff --git a/supporting_content/columns/effectivecost.md b/supporting_content/columns/effectivecost.md
index 0364fe0e0..248eb57a4 100644
--- a/supporting_content/columns/effectivecost.md
+++ b/supporting_content/columns/effectivecost.md
@@ -42,7 +42,7 @@ ___
| Jan 4 2023 - Jan 5 2023 | Jan 1 2023 - Jan 31 2023 | OD Usage | 1 | 0 | 2.542465753 |
| Jan 4 2023 - Jan 5 2023 | Jan 1 2023 - Jan 31 2023 | Unused RI Usage | 2 | 0 | 1.271232877 |
-*Note: For the Reserved Instance Usage the Billed cost is zero as this RI is full upfront. It is especially important to note that the usage units must be normalized for this formula to be applicable in cases of size flexibility (e.g. c7g.large normalized units is 4, c7g.medium is 2). Effective cost is the same as amortization because the upfront fee covers all of the compute usage expense for this row.*
+*Note: For the Reserved Instance Usage the Billed cost is zero as this RI is full upfront. It is especially important to note that the usage units must be normalized for this formula to be applicable in cases of commitment discount flexibility (e.g. c7g.large normalized units is 4, c7g.medium is 2). Effective cost is the same as amortization because the upfront fee covers all of the compute usage expense for this row.*
### Example usage scenarios
diff --git a/supporting_content/columns/servicesubcategory.md b/supporting_content/columns/servicesubcategory.md
new file mode 100644
index 000000000..5834fef2a
--- /dev/null
+++ b/supporting_content/columns/servicesubcategory.md
@@ -0,0 +1,210 @@
+# Column: ServiceSubcategory
+
+## Example provider mappings
+
+Current column mappings found in available data sets:
+
+| Provider | Data set | Column |
+| --------- | ------------------------ | ------------------------------------------ |
+| AWS | FOCUS; CUR | None |
+| GCP | FOCUS; Big Query Billing Export | None |
+| Microsoft | FOCUS; Cost details | None |
+| OCI | FOCUS; Cost reports | None |
+
+The creation of this publicly-available column shall be net-new for the cloud service providers, though they may already maintain their own proprietary Subcategories. For example, AWS describes their Database Subcategories [here](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/database.html).
+
+## Discussion / Scratch space
+
+### Principles
+
+In addition to the principles as defined during the creation of Service Categories in FOCUS 0.5, the following principles shall also be followed when constructing Service Subcategories:
+
+- Undercategorize rather than overcategorize where there is not broad consensus and/or materiality.
+ - Allow the community to advocate for new Subcategories (and Categories) in future releases, and leave Services uncategorized and/or unsubcategorized in the meantime.
+- Assign each Service to the one (and only one) Subcategory that describes its primary function.
+ - The Service hierarchy is meant to serve as a relatively high-level set of groupings that primarily address the needs of the Executive persona. A given Service can fulfill multiple functions across and within organizations, and so the assignment of a Service to one and only one Category and Subcategory may be inaccurate from org to the next. However, this hierarchy will then give the Practitioner a solid place to start, and they can make a few tweaks to its composition to meet their org's needs rather than create a hierarchy from scratch. Ultimately, the creation and maintenance of the Service hierarchy requires us to embrace the imperfect and somewhat subjective nature of assigining a given Service to a single Category / Subcategory.
+ - The (forthcoming) SKU hierarchy will be an opportunity to get very specific on the categorizations of cost and usage activity. For example, GCP maintains a seven-level taxonomy for every SKU, and this will hopefully more concretely address the lower-level reporting needs of the Engineering persona.
+ - Use the "Platforms" suffix whenever a subcategory is needed to cover products and services that span multiple other subcategories.
+ - Avoid a "Platforms" subcategory if the service category does not have other subcategories.
+
+### Sample provider mappings
+Here are sample subcategorizations of various services across the AWS, Azure, and GCP landscape.
+
+To be clear, this list is neither exhaustive nor prescriptive nor suggestive; it shall be up to the providers to decide where to assign their services, and FOCUS shall merely provide the list of available Subcategories. This list was generated merely for illustrative purposes when constructing the subcategories.
+
+| Service Category | Service Subcategory | AWS | Azure | GCP |
+| ------------------------- | ------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
+| AI and Machine Learning | AI Platforms | | AI Services, Video Indexer, Autonomous Systems, Syntex, Intelligent Recommendations | |
+| AI and Machine Learning | Bots | Lex, Robomaker | Bot Service, Health Bot | |
+| AI and Machine Learning | Generative AI | Bedrock, Q | | Gemini, Vertex AI |
+| AI and Machine Learning | Machine Learning | Sagemaker, Sagemaker Savings Plan, Lookout, Personalize | Machine Learning | |
+| AI and Machine Learning | Natural Language Processing | Polly, Transcribe, Translate, Lex | | natural language AI, text-to-speech, Speech-to-text, Document AI |
+| AI and Machine Learning | Other (AI and Machine Learning) | Capacity Blocks, Rekognition | | |
+| Analytics | Analytics Platforms | Athena | Fabric, Synapse, Data Explorer, Modeling and Simulation Workbench, Data Manager for Energy, Health Data Services | |
+| Analytics | Business Intelligence | QuickSight | Power BI, Analysis Services, Grafana | Looker |
+| Analytics | Data Processing | EMR, Batch, Glue, Data Pipeline | Databricks, HDInsight, Data Lake Analytics, Analysis Services, Data Catalog, Genomics | Cloud Composer, Dataflow, Dataproc |
+| Analytics | Search | Cognitive Search, CloudSearch, Elasticsearch, Kendra | Azure AI Search | Vertex AI Search |
+| Analytics | Streaming Analytics | Kinesis | Stream Analytics | |
+| Analytics | Other (Analytics) | Clean Rooms | | |
+| Business Applications | Productivity and Collaboration | WorkDocs, WorkLink, WorkMail, Chime | Microsoft 365, Teams, Power Platform | Workspace |
+| Business Applications | Other (Business Applications) | Supply Chain, Connect | Dynamics 365, Community Training | |
+| Compute | Containers | EKS, ECS | AKS, Container Apps, Container Instances, Container Registry, Container Service, Service Fabric | GKE, Cloud Run |
+| Compute | End User Computing | AppStream | Virtual Desktop, Lab Services, Citrix | |
+| Compute | Quantum Compute | Braket | Quantum | |
+| Compute | Serverless Compute | Lambda | Cloud Services, Batch | Cloud Functions, Cloud Run |
+| Compute | Virtual Machines | EC2 | BareMetal Infrastructure, Dedicated Host, VMware Solution, SAP on Azure, Virtual Machine Scale Sets, Virtual Machines | Compute Engine |
+| Compute | Other (Compute) | Compute Savings Plan | Savings Plan for Compute | Flex CUDs |
+| Databases | Caching | ElastiCache, MemoryDB | Cache for Redis | Memorystore |
+| Databases | Data Warehouses | Redshift | (none) | BigQuery |
+| Databases | Ledger Databases | QLDB, Managed Blockchain | Confidential Ledger | Blockchain Node Engine |
+| Databases | NoSQL Databases | DynamoDB, Neptune, Cassandra, SimpleDB, AppSync | Cosmos DB | Datastore, Bigtable, Firestore |
+| Databases | Relational Databases | RDS, Aurora | MariaDB, MySQL, PostgreSQL, SQL Database | Cloud SQL, AlloyDB, Spanner |
+| Databases | Time Series Databases | Timestream | (none) | |
+| Databases | Other (Databases) | Cloud Directory | (none) | |
+| Developer Tools | Developer Platforms | CodeCatalyst | DevOps, GitHub, App Center | |
+| Developer Tools | Continuous Integration and Deployment | CodeDeploy, CodePipeline, CodeBuild, CodeArtifact | | Cloud Build, Cloud Deploy |
+| Developer Tools | Development Environments | | Trusted Signing, Dev Box, Managed DevOps Pools | Cloud Code |
+| Developer Tools | Source Code Management | CodeCommit | | |
+| Developer Tools | Quality Assurance | CodeGuru | Playwright Testing, Load Testing, Test Base for M365 | |
+| Developer Tools | Other (Developer Tools) | re:Post Private | | |
+| Identity | Identity and Access Management | IAM | Entra ID, External Identities, Domain Services | Cloud Identity, IAM |
+| Identity | Other (Identity) | | | |
+| Integration | API Management | API Gateway | API Center, API Management, Microsoft Graph | |
+| Integration | Messaging | SQS, SNS, EventBridge, Pinpoint | Service Bus, Relay, Event Grid, Communcation Services, Notification Hubs | Cloud Pub/Sub, Firebase |
+| Integration | Workflow Orchestration | Managed Workflows, Entity Resolution | Apache Airflow, Data Factory, Logic Apps, Automation | |
+| Integration | Other (Integration) | | | |
+| Internet of Things | IoT Analytics | | Digital Twins, Time Series Insights, FarmBeats | |
+| Internet of Things | IoT Platforms | IoT Core, Greengrass | IoT Central, IoT Hub, Windows for IoT, Defender for IoT | |
+| Internet of Things | Other (Internet of Things) | | | |
+| Management and Governance | Architecture | Well-Architected Tool, Config, Trusted Advisor | (none) | |
+| Management and Governance | Compliance | Compliance | Policy | |
+| Management and Governance | Cost Management | Cost Explorer, Billing Conductor | Reservations | Invoice |
+| Management and Governance | Data Governance | DataZone | Purview | Dataplex |
+| Management and Governance | Disaster Recovery | DRS (Disaster Recovery Service) | Chaos Studio, Site Recovery | |
+| Management and Governance | Endpoint Management | | Intune, Universal Print, Defender for Endpoint | |
+| Management and Governance | Observability | CloudWatch, CloudTrail, X-Ray, Grafana | Monitor | Cloud Monitoring, Cloud Logging, Cloud Trace |
+| Management and Governance | Support | AWS Support | Support | Customer Care ([Support](https://cloud.google.com/support/?hl=en)) |
+| Management and Governance | Other (Management and Governance) | | | |
+| Media | Content Creation | Deadline | | |
+| Media | Gaming | | PlayFab | |
+| Media | Media Streaming | | Media Services | |
+| Media | Mixed Reality | | Spatial Anchors, Object Anchors, Remote Rendering | |
+| Media | Other (Media) | Deadline | | |
+| Migration | Data Migration | Database Migration, Snowball, Import/Export | Database Migration Service, Data Box, Import/Export, Data Share, File Sync | |
+| Migration | Resource Migration | App Migration | Migrate | |
+| Migration | Other (Migration) | | | |
+| Mobile | Other (Mobile) | | | |
+| Multicloud | Multicloud Integration | | Arc, Stack Edge, Stack HCI | |
+| Multicloud | Other (Multicloud) | Outposts | | Anthos, AlloyDB Omni |
+| Networking | Application Networking | ELB, Application Load Balancer | Load Balancer, Application Gateway, Traffic Manager | |
+| Networking | Content Delivery | CloudFront | Front Door, CDN | |
+| Networking | Network Connectivity | Ground Station, VPN Gateway, PrivateLink, Network Connect | Peering, 5G Core, Orbital, VPN Gateway, NAT Gateway, PrivateLink, Virtual WAN | Cloud VPN, Cloud Interconnect |
+| Networking | Network Infrastructure | VPC, VPC Flow Logs | Virtual Network, Network Watcher, Network Function Manager | Shared VPC (XPN) |
+| Networking | Network Routing | Route 53 | ExpressRoute, DNS | |
+| Networking | Network Security | Web Application Firewall | Firewall, DDoS Protection, Bastion | |
+| Networking | Other (Networking) | | | Networking |
+| Security | Secret Management | Secrets Manager, Certificate Manager, KMS, CloudHSM, Payment Cryptography | Key Vault, Dedicated HSM | Secret Manager, Certificate Authority, KMS |
+| Security | Security Posture Management | Security Hub, Macie | Defender for Cloud, Copilot for Security | |
+| Security | Threat Detection and Response | GuardDuty, Inspector, Detective, Shield, Security Lake | Dynamics 365 Fraud Protection | |
+| Security | Other (Security) | | | |
+| Storage | Backup Storage | Backup | Backup | |
+| Storage | Block Storage | EBS | Managed disk, ElasticSAN | Persistent Disks, Local SSDs |
+| Storage | File Storage | EFS | NetApp Files | Hyperdisk |
+| Storage | Object Storage | S3, Glacier | ADLS | Cloud Storage |
+| Storage | Storage Platforms | | Storage Accounts, HPC Cache, StoreSimple | |
+| Storage | Other (Storage) | | | |
+| Web | Application Platforms | Elastic Beanstalk | App Service, Spring Apps | App Engine |
+| Web | Other (Web) | Lightsail | App Configuration, Maps, SignalR Service, Fluid Relay | Maps {Directions API, Distance Matrix API, Geolocation API, etc.} |
+| Other | Other (Other) | | |
+
+### Discussion Outcomes
+
+A series of open questions were discussed over the course of July and August 2024, both in the [draft spreadsheet](https://docs.google.com/spreadsheets/d/1aYq79sWp8TK4zbcSKUb-gRIBei3fERVwAgDJ5ezZf1w/edit?usp=sharing) and in Task Force (TF) and Member calls. This section attempts to describe the largest topics and outcomes of those discussions.
+
+#### Shall the Category composition change from FOCUS 1.0?
+
+With Subcategories now in scope for FOCUS 1.1, there was then the potential of changing Categories. For example:
+
+- `Identity` could become a child Subcategory of `Security`.
+- `Web` and `Mobile` could be grouped together into a net-new category (proposed `Front-end` or `Application Tools`).
+- Activity that is truly cross-categorical could be placed in a net-new category (proposed `Crossfunctional`) separate from `Other`, which is more of an uncategorized placeholder.
+- `Integration` could be rescoped and renamed `Data Management` to be more inclusive of Service Subcategories such as Data Processing and API Management.
+- `Multicloud` could be rescoped and renamed `Hybrid and Multicloud` to be more inclusive of on-premises Services.
+
+After much discussion, particularly on the Aug 6 TF1 call, it became clear that the "burden of proof" for changing existing Categories is higher, given that some of the group feels this to constitute a "breaking change". Some of the group felt that the Service hierarchy should be considered more of a "living document" that is revisited from one FOCUS release to another, in order to stay more tightly aligned with the slowly-changing nature of Service categorizations; others felt that would be prohibitively disruptive for FOCUS consumers who have constructed various downstream artifacts and depend on a certain Category and Subcategory composition.
+
+_Outcome_: leave the Category composition in place for FOCUS 1.1 and narrow scope of this release to only add Subcategories underneath them, leaving the door open to alter the Category composition in a future release (either major or not, pending a larger decision around what constitutes a "breaking change").
+
+#### Shall the Subcategory (and Category) assignment describe the activity's _use case_?
+
+Consider the example of [AWS Inf2 VM instances](https://aws.amazon.com/ec2/instance-types/inf2/). These instance types are purpose-built to be used for AI and ML use cases, and so any related cost and usage activity belongs in the Category of `AI and Machine Learning`, right?
+
+Not so fast. While the _intended purpose_ of this VM is for AI use cases, it's still a VM that technically could be used for anything. Ultimately, we cannot attempt to categorize the _SKU_ with our Service Subcategory; we can only categorize the Service, which in this case is still EC2, which therefore falls into `Compute > Virtual Machines`. When FOCUS implements a SKU taxonomy / hierarchy, we would be able to get more specific about the use of Inf2 vs, say, T2 instances. Any reporting that attempted to better convey the use case would either need to leverage that future hierarchy or an appropriate tag of the involved Resources that conveys purpose.
+
+This was discussed at the Jul 30 TF1 call, and the strong majority, if not consensus, opinion was that examples such as these should remain in their Service's assignment, regardless of use case. However, it does not dismiss the fair point that a Service Category of AI & Machine Learning will exclude Services that can be used for AI and ML purposes. That is an issue that goes beyond the scope of these columns and must be solved with other mechanisms.
+
+_Outcome_: Service Category and Subcategory shall describe the Service's primary function -- not the use case of the usage or SKU.
+
+#### Where do Commitment Discounts belong?
+
+Commitment Discounts have various models that could belong in various places of a Service category hierarchy. For example:
+
+- An Azure reservation for D8as v5 can be both Categorized (i.e. `Compute`) and Subcategorized (i.e. `Virtual Machines`).
+- An AWS Compute savings plan can be Categorized (i.e. `Compute`) but not Subcategorized (e.g. it can be applied to both `Virtual Machines` and `Serverless Compute`).
+- An OCI Credit can neither be Categorized nor Subcategorized (e.g. it can be applied to a wide variety of usage).
+
+Based on that, there was a robust discussion, particularly on the Jul 23 TF1 and Aug 8 Member calls, as to where Commitment Discounts belong. Do they deserve their own Subcategories (e.g. `Commitments (Compute)`, `Commitments (Databases)`) underneath each Category? Do they also deserve their own Category (e.g. `Commitments` or `Crossfunctional`)?
+
+_Outcome_: given the decision not to change the Category composition, and given the principle of undercategorizing rather than overcategorizing:
+
+- Commitment Discounts with a natural Category / Subcategory shall be placed therein.
+- Commitment Discounts with a natural Category but no Subcategory shall be placed in `Other ()`.
+- Commitment Discounts with no natural Category or Subcategory shall be placed in `Other (Other)`.
+
+#### Shall certain technologies be given their own Categories?
+
+The group discussed the possibility of "graduating" Services to their own net-new categories, such as `Blockchain`, `Containers`, and `Mixed Reality`. These are technologies for which some or all of the three major cloud service providers have created their own Categories, and there is certainly a use case for being able to easily build reports to show those (and only those) Services.
+
+Given the decision not to change the Category composition on the Aug 6 TF1 call, this became a moot discussion. However, the group did discuss some specific examples, particularly on the Jul 23 TF1 and Jul 25 Member calls:
+
+- `Blockchain` belongs under `Databases > Ledger`.
+- `Containers` belongs under `Compute > Containers`.
+- `Support` belongs under `Management and Governance`.
+- `Mixed Reality` does not deserve its own Category.
+- `Industry Specific` does not deserve its own Category.
+- `Marketplace` Services shall be placed into the Category and Subcategory aligned with their purpose, rather than placed into a `Marketplace` Category.
+
+_Outcome_: No Category additions or changes at this time.
+
+#### What shall we call the "unsubcategorized" Subcategory?
+
+Each Category carries an "Other" Subcategory to allow the providers to provide a Category without a Subcategory. A vote was issued via Slack on Aug 13 with the following options:
+
+:one: `Uncategorized ()`
+:two: `Other ()`
+:three: `Uncategorized`
+:four: `Other`
+
+The following considerations were included:
+
+- Brevity, simplicity, and consistency of Subcategory names (e.g. “Uncategorized (Management and Governance)” is pretty long).
+- Delineation of Category values from Subcategory values (e.g. use of Subcategory “Other” underneath all Categories “Compute”, “Databases” and “Other” could be confusing).
+- Analytical utility of Subcategory without Category context (e.g. uncategorized Compute from uncategorized Databases are automatically separated in a bar chart).
+
+_Outcome_: Option :two: was chosen.
+
+#### Why do some of the Categories lack Subcategories beyond "Other"?
+
+Per the principles and some of the outcomes described above, we have leaned towards subcategorizing only those Categories on which we had broad consensus and/or could target significant usage. Several of the existing Categories do not have sufficient Service counts and/or activity to allow designating Subcategories at a high degree of confidence, and future FOCUS versions can add such groupings if and when requested by the community.
+
+#### Shall this column be mandatory or optional?
+
+There was some discussion around this at the 8/15 Member call. Some felt that Service Subcategory should be mandatory because Service Category is mandatory, and together they form a hierarchy. Others felt that provider adoption would be easier if the column were not required. Still others felt that making the column mandatory, even populated completely with Other, would entice FOCUS consumers to petition their provider(s) to populate the column with actual Subcategories.
+
+Ultimately, it seemed that the majority leaned towards making it optional.
+
+_Outcome_: Optional.
+
+
+
+
diff --git a/supporting_content/columns/skumeter.md b/supporting_content/columns/skumeter.md
new file mode 100644
index 000000000..4806f91d9
--- /dev/null
+++ b/supporting_content/columns/skumeter.md
@@ -0,0 +1,44 @@
+# Column: SkuMeter
+
+## Example provider mappings
+
+Current column mappings found in available data sets:
+
+| Provider | Data set | Column |
+|-----------|--------------------------|------------------------------------|
+| AWS | CUR | line_item_usage_type |
+| GCP | Big Query Billing Export | service.description |
+| Microsoft | Cost details | MeterName |
+| OCI | Cost reports | TBD |
+
+## Background
+
+Cloud Services, such as managed databases, virtual machines for compute, and object storage, have billing models in which the usage of that service is metered and then charged based on multiple parameters. For example, Amazon S3 charges customers for Storage, API requests, Data transfer, Encryption, Object management, Replication, and custom API requests, and ALL of these functionalities are metered and billed under the service name “Amazon S3”.
+
+Cloud providers use different SKUs to differentiate between these different types of usage of a given service, but the SKU is a GUID that does not have any semantic meaning to a FinOps practitioner. This is problematic because as a FinOps practitioner, I want to be able to understand what the breakdown is of how I am being charged for a particular service so that I can use this information to report what the primary cost drivers are for a particular service and so that I can make optimization decisions. For example, I might want to understand what my data transfer costs within all of my Amazon S3 charges so that I can recommend my development team to change their storage access patterns in order to achieve cost savings.
+
+Research across cloud providers suggests that there are 4 main categories of attributes that contribute to a SKU. They are:
+Product: What is the public name of the thing (eg the resource or service) being sold?
+Region: Where is the thing being sold?
+Function: What is the functionality being measured and sold?
+Size: How big is the thing (eg the resource or service) being sold (if applicable)?
+
+This column addresses the "Function" attribute of a SKU by making it a first class part of the FOCUS schema.
+
+## Problem
+
+Today, FOCUS does not have any columns that enable FinOps practitioners to understand the meaning of different SKUs that appear and group them (such as with SQL GROUP BY) in order to better understand the main contributors to the cost of a given service.
+
+As a practitioner, I want to be able to write a SQL query that easily breaks down my charges for a given service so that I can understand how each kind of "Function" is contributing to the overall cost of a service.
+
+## Solution Discussion
+
+**Short term (V1.1):**
+Given that these data may not be readily available immediately from providers, we are starting with a single column which providers can populate with as much useful data as they can that helps meet this need.
+
+We believe it will be OK for providers to decide how to populate this column with the data they have available today. This means the data within this column may cover more than just the "Function" attribute described above. When populating this column, Providers should keep in mind that it will be painful for practitioners if the provider decides to change it in the future.
+
+**Longer term (timeframe TBD):**
+In the future we would like to move to separate columns, one for each of Product, Region, Function, Size, and have each of these columns be populated with only this data.
+
+There may be an opportunity for some of these values to be normalized, or at least the format standardized, but some values will need to be provider-specific. This is similar to how the Unit Attribute works today where the most common units are normalized across providers (such as Hours), while other units are provider specific.
\ No newline at end of file
diff --git a/supporting_content/columns/subaccountid.md b/supporting_content/columns/subaccountid.md
index dd3a6f74f..6c470a27c 100644
--- a/supporting_content/columns/subaccountid.md
+++ b/supporting_content/columns/subaccountid.md
@@ -32,8 +32,8 @@ Current values observed in billing data for various scenarios:
FOCUS plans to include Level 1, Level 3 in the specification. Level 5 (resource name, resource id) are already in the specification.
| Provider | Level 1 | Level 2 | Level 3 | Level 4 | Level 5 | |
-| | Billing Account | Sub Account Group (optional) | Sub Account | | | |
|----------|---------|---------|---------|---------|---------|---------|
+| | Billing Account | Sub Account Group (optional) | Sub Account | | | |
| AWS | Management Account | Org | Account | Resource Group (optional) | Resource | |
| GCP | Billing Account | Folder | Project | | | |
| MS EA | Billing Account (Invoice Scope) | Department | Enrollment Account | Subscription | Resource Group | Resource |
diff --git a/supporting_content/metadata/schema_creation_scenarios.md b/supporting_content/metadata/schema_creation_scenarios.md
new file mode 100644
index 000000000..bbe6a39de
--- /dev/null
+++ b/supporting_content/metadata/schema_creation_scenarios.md
@@ -0,0 +1,13 @@
+# Scheme Creation Scenarios
+
+## The following is a list of scenarios and their schema update requirements
+
+
+| Scenario | Requires New Schema object | Requires Change in Provider Version | Requires Change FOCUS Version |
+|:---------------------------------------------------------------------------------------------------------|:----------------------------|:------------------------------------|:-------------------------------|
+| Provider uses a new focus version when they supply a provider version | Y | | Y |N |
+| Provider is changing the way they generate the data that doesn't affect the focus version or the columns | Y | Y | N |
+| Addition of Column | Y | N | N |
+| Removal of Columns | Y | N | N |
+| Change of Focus Version | Y | Y| Y|
+| Correction of schema metadata that is not correct | N | N | N |
\ No newline at end of file