Apache Ossie - Core Metadata Specification¶
DRAFT version — in development, schema may change before 0.2.0 is released.
Version: 0.2.0.dev0
Goals¶
- Standardization: Establish uniform language and structure for semantic model definitions, ensuring consistency and ease of interpretation across various tools and systems.
- Extensibility: Support domain-specific extensions while maintaining core compatibility.
- Interoperability: Enable exchange and reuse across different AI and BI applications.
Table of Contents¶
Enumerations¶
Standard enumeration values used throughout the specification.
Dialects¶
Dialects in which metric and field expressions can be declared.
| Dialect | Description |
|---|---|
ANSI_SQL |
Standard SQL dialect |
SNOWFLAKE |
Snowflake SQL |
MDX |
Multi-Dimensional Expressions |
TABLEAU |
Tableau calculations |
DATABRICKS |
Databricks SQL |
MAQL |
GoodData MAQL (Multi-Dimensional Analytical Query Language) |
BIGQUERY |
Google BigQuery (GoogleSQL) |
SIGMA |
Sigma Computing's spreadsheet-style formula language |
THOUGHTSPOT |
ThoughtSpot formula language |
DAX |
Data Analysis Expressions (Power BI / Analysis Services) |
HOLISTICS_AQL |
Holistics AQL (Analytical Query Language) |
OSSIE_SQL_2026 |
Ossie's portable SQL expression language, defined in expression_language.md |
OSSIE_SQL_2026 is the only dialect whose semantics this specification defines. The other values
identify vendor or third-party expression languages. Ossie treats expressions in those dialects as
opaque, and implementations MAY ignore them (see
Dialect Extensions). Registering a dialect makes it
valid for declaring a model; it does not mean Ossie supports querying in that dialect (see
Model Declaration vs. Querying).
Data types¶
DataType declares the logical value type of a field or metric independently
of its role and physical representation. The shared names align with the
ontology specification's built-in value types; Time, DateTimeTz, and
Opaque are additional core data types.
| DataType | Description |
|---|---|
String |
Variable-length Unicode character data; length and collation are unspecified. |
Integer |
Exact integral number; width and signedness are unspecified. |
Decimal |
Exact base-10 number; precision and scale are unspecified. |
Float |
Approximate floating-point number. |
Boolean |
Logical two-valued truth type. |
Date |
Calendar date with no time-of-day component. |
Time |
Time-of-day with no date or timezone. |
DateTime |
Local/civil date and time with no timezone or offset. |
DateTimeTz |
Date and time with sufficient offset or timezone context to identify an instant. Preservation of a named timezone identifier is not guaranteed. |
Opaque |
Known type outside the portable vocabulary; use custom_extensions for vendor-specific refinement. Omit datatype when the type is unknown or unspecified. |
Semantic Model¶
Each JSON or YAML document represents exactly one semantic model.
A standalone document must contain version, name, and a non-empty datasets
array. For bulk exchange, use separate model documents. This specification does
not define a bundle format or cross-model references.
Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Apache Ossie specification version (0.2.0.dev0) |
name |
string | Yes | Unique identifier for the semantic model |
description |
string | No | Human-readable description |
ai_context |
string/object | No | Additional context for AI tools (e.g., custom instructions) |
datasets |
array | Yes | Collection of logical datasets (fact and dimension tables) |
relationships |
array | No | Defines how logical datasets are connected |
metrics |
array | No | Quantifiable measures defined as aggregate expressions on fields from logical datasets |
custom_extensions |
array | No | Vendor-specific attributes for extensibility |
Example¶
version: 0.2.0.dev0
name: sales_analytics
description: Sales and customer analytics model
ai_context:
instructions: "Use this model for sales analysis and customer insights"
datasets:
- name: orders
source: sales.public.orders
relationships: []
metrics: []
custom_extensions:
- vendor_name: DBT
data: '{"project_name": "tpcds_analytics", "models_path": "models/semantic"}'
The same document structure in JSON:
{
"version": "0.2.0.dev0",
"name": "sales_analytics",
"datasets": [
{"name": "orders", "source": "sales.public.orders"}
]
}
Migrating earlier document shapes¶
This is a breaking change in the unreleased 0.2.0.dev0 specification. Earlier
releases and earlier development snapshots use a semantic_model array. The
current schema accepts only the flat document shape; it does not accept the array
or an object-valued wrapper.
To migrate a document containing one model, move that model's properties to the
root and remove semantic_model. Use version: 0.2.0.dev0 for the migrated
document. Remove any root-level dialects and vendors declarations; preserve
per-expression dialects and vendor information in custom_extensions. For
multiple models, create one document per model and validate each result. An empty
model array cannot produce a valid model document. Preserve model contents and
custom extensions; never silently select only the first model or overwrite a file
when splitting a document.
For ontology maps, each embedded model must be a complete core document.
Datasets¶
Logical datasets represent business entities or concepts (fact and dimension tables). They contain fields and define the structure of the data.
Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the dataset |
source |
string | Yes | Reference to underlying physical table/view (e.g., database.schema.table) or query |
primary_key |
array | No | Primary key columns that uniquely identify rows (single or composite) |
unique_keys |
array of arrays | No | Array of unique key definitions (each can be single or composite) |
description |
string | No | Human-readable description |
ai_context |
string/object | No | Additional context for AI tools (e.g., synonyms, common terms) |
fields |
array | No | Row-level attributes for grouping, filtering, and metric expressions |
custom_extensions |
array | No | Vendor-specific attributes |
Primary Key Examples¶
# Simple primary key
primary_key: [customer_id]
# Composite primary key
primary_key: [order_id, line_number]
Unique Keys Examples¶
# Multiple unique keys (each can be simple or composite)
unique_keys:
- [email] # Simple unique key
- [first_name, last_name] # Composite unique key
Example¶
datasets:
- name: orders
source: sales.public.orders
primary_key: [order_id]
unique_keys:
- [order_id]
- [order_number]
description: Order transactions
ai_context:
synonyms:
- "purchases"
- "sales"
fields: []
custom_extensions:
- vendor_name: DBT
data: '{"materialized": "table"}'
Relationships¶
Relationships define how logical datasets are connected through foreign key constraints. They support both simple and composite keys.
Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the relationship |
from |
string | Yes | The logical dataset on the many side of the relationship |
to |
string | Yes | The logical dataset on the one side of the relationship |
from_columns |
array | Yes | Array of column names in the "from" dataset (foreign key columns) |
to_columns |
array | Yes | Array of column names in the "to" dataset (primary or unique key columns) |
ai_context |
string/object | No | Additional context for AI tools |
custom_extensions |
array | No | Vendor-specific attributes |
Important Notes¶
- The order of columns in
from_columnsmust correspond to the order into_columns - Both arrays must have the same number of columns
- For simple relationships, use a single column:
[column1] - For composite relationships, use multiple columns:
[column1, column2]
Examples¶
Simple Relationship:
Composite Relationship:
# order_lines.product_id = products.id AND order_lines.variant_id = products.variant_id
- name: order_lines_to_products
from: order_lines
to: products
from_columns: [product_id, variant_id]
to_columns: [id, variant_id]
Fields¶
Fields represent row-level attributes that can be used for grouping, filtering, and in metric expressions. They can be simple column references or computed expressions.
Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the field within the dataset |
expression |
object | Yes | Expression definition with dialect support |
dimension |
object | No | Dimension metadata (e.g., is_time flag) |
label |
string | No | Label for categorization |
description |
string | No | Human-readable description |
datatype |
string (enum) | No | Logical data type for this field. See Data types. |
ai_context |
string/object | No | Additional context for AI tools (e.g., synonyms) |
custom_extensions |
array | No | Vendor-specific attributes |
Expression Object¶
The expression object supports multiple SQL dialects for cross-platform compatibility. Each field can define expressions in different dialects.
Structure:
expression:
dialects:
- dialect: ANSI_SQL # Must be one of the dialects enum values
expression: "customer_id" # Scalar SQL expression
Key Points:
- Use scalar SQL expressions (no aggregations)
- Can be simple column references (e.g.,
customer_id) or computed expressions (e.g.,first_name || ' ' || last_name) - Multiple dialect versions can be provided for the same field
Dimension Object¶
| Field | Type | Description |
|---|---|---|
is_time |
boolean | Temporal-role marker. When true, consumers that distinguish time dimensions (e.g. for time-series analysis or temporal filtering) should treat this field as a time dimension. This is a role flag, independent of the field's data type. See DataType and is_time: type vs. role. |
Examples¶
Simple Column Reference for a Dimension:
- name: customer_id
expression:
dialects:
- dialect: ANSI_SQL
expression: customer_id
description: Customer identifier
dimension:
is_time: false
Computed Field:
- name: full_name
expression:
dialects:
- dialect: ANSI_SQL
expression: first_name || ' ' || last_name
description: Customer full name
ai_context:
synonyms:
- "name"
- "customer name"
Time Dimension:
- name: order_date
expression:
dialects:
- dialect: ANSI_SQL
expression: order_date
datatype: Date
dimension:
is_time: true
description: Date when order was placed
ai_context:
synonyms:
- "purchase date"
- "transaction date"
Multi-Dialect Field:
- name: email_normalized
expression:
dialects:
- dialect: ANSI_SQL
expression: LOWER(email)
- dialect: SNOWFLAKE
expression: LOWER(email)::VARCHAR
- dialect: BIGQUERY
expression: SAFE_CAST(LOWER(email) AS STRING)
description: Normalized email address
DataType and is_time: type vs. role¶
datatype and dimension.is_time are independent properties that answer different questions:
datatypedescribes the data type of the field (e.g.Date,Integer,String,DateTimeTz): what kind of values the field holds.dimension.is_timeis a temporal-role marker: whether the field should be treated as a time dimension for time-series analysis or temporal filtering, regardless of its data type.
Default for is_time. When is_time is not set explicitly, it defaults to true if datatype is one of Date, Time, DateTime, DateTimeTz, and false otherwise. Explicit is_time always wins. Set is_time: false on a temporal-typed column (e.g. an audit created_at you don't want on the time axis) to opt out of the default.
Common combinations:
| Column example | datatype |
is_time |
Effective role | Why |
|---|---|---|---|---|
d_date (calendar date) |
Date |
omitted | time dimension | Temporal datatype; is_time defaults to true. |
order_timestamp |
DateTimeTz |
omitted | time dimension | Same. |
created_at (audit timestamp) |
DateTime |
false |
regular dimension | Explicit opt-out of the temporal default. |
d_year (integer year grain) |
Integer |
true |
time dimension | Non-temporal datatype; is_time: true makes the role explicit. |
d_quarter_name (e.g. "Q1") |
String |
true |
time dimension | String-valued temporal grain. |
customer_id |
Integer |
omitted | regular dimension | Non-temporal datatype; is_time defaults to false. |
Precedent. This type/role separation mirrors Snowflake Semantic Views' YAML authoring form, which has a structural
time_dimensions:collection whose entries can carry anydata_type. The published example annotatesorder_yearwithdata_type: NUMBER. LookML supports a similar split via itsdimension_group, whosedatatypeenum coversdate,datetime,timestamp, plus the integer-encoded formsepochandyyyymmdd.
Consumer guidance.
- For data-type questions (casting, serialization, downstream type inference): prefer
datatypewhen present. If onlyis_time: trueis set, do not infer a specific scalar type from it. - For role questions (classifying time dimensions in a query UI, generating time-series output sections, choosing time-aware aggregations): treat the field as a time dimension when
is_timeresolves totrue, whether explicitly set or defaulted from a temporaldatatype.
Metrics¶
Quantitative measures defined on business data, representing key calculations like sums, averages, ratios, etc. Metrics are defined at the semantic model level and can span multiple datasets.
Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the metric |
expression |
object | Yes | Expression definition with dialect support |
description |
string | No | Human-readable description of what the metric measures |
datatype |
string (enum) | No | Logical data type for this metric. See Data types. |
ai_context |
string/object | No | Additional context for AI tools (e.g., synonyms) |
custom_extensions |
array | No | Vendor-specific attributes |
Expression Object¶
The expression object supports multiple dialects
expression:
dialects:
- dialect: ANSI_SQL # Default
expression: "SUM(order.sales) / COUNT(DISTINCT order.customer_id)"
Examples¶
Simple Aggregation:
- name: total_revenue
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(orders.amount)
description: Total revenue across all orders
datatype: Decimal
ai_context:
synonyms:
- "total sales"
- "revenue"
Cross-Dataset Metric:
- name: avg_orders
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(orders.amount) / COUNT(DISTINCT customers.id)
description: Average orders
datatype: Decimal
ai_context:
synonyms:
- "Order Average by customer"
Custom Extensions¶
Custom extensions allow vendors to add platform-specific metadata without breaking core compatibility. Each extension includes a vendor name and arbitrary JSON data.
Schema¶
custom_extensions:
- vendor_name: string # Free-form string identifying the vendor
data: string # JSON string containing vendor-specific data
Vendor Names¶
The vendor_name field is a free-form string, allowing any vendor or organization to
define custom extensions without requiring changes to the core specification.
The following are well-known examples:
| Vendor | Description |
|---|---|
COMMON |
Common/standard extensions |
SNOWFLAKE |
Snowflake-specific attributes |
SALESFORCE |
Salesforce/Tableau-specific attributes |
DBT |
dbt-specific attributes |
DATABRICKS |
Databricks-specific attributes |
GOODDATA |
GoodData-specific attributes |
HONEYDEW |
Honeydew-specific attributes |
WISDOM |
WisdomAI-specific attributes |
POWER_BI |
Microsoft Power BI-specific attributes |
SIGMA |
Sigma Computing-specific attributes |
THOUGHTSPOT |
ThoughtSpot-specific attributes |
HEX |
Hex-specific attributes |
Examples¶
Snowflake Extension:
- vendor_name: SNOWFLAKE
data: '{
"warehouse": "ANALYTICS_WH",
"database": "PROD",
"schema": "PUBLIC"
}'
Salesforce Extension:
- vendor_name: SALESFORCE
data: '{
"tableau_workbook_id": "sales_dashboard",
"einstein_enabled": true,
"crm_sync": {
"enabled": true,
"sync_frequency": "daily"
}
}'
DBT Extension:
- vendor_name: DBT
data: '{
"project_name": "analytics",
"materialized": "table",
"tags": ["daily", "core"]
}'
Databricks Extension:
Complete Example¶
Here's a complete semantic model example showing all components working together:
version: 0.2.0.dev0
name: ecommerce_analytics
description: E-commerce sales and customer analytics
ai_context:
instructions: "Use this model for analyzing sales trends, customer behavior, and product performance"
datasets:
- name: orders
source: sales.public.orders
primary_key: [order_id]
description: Customer orders
fields:
- name: order_id
expression:
dialects:
- dialect: ANSI_SQL
expression: order_id
description: Order identifier
- name: customer_id
expression:
dialects:
- dialect: ANSI_SQL
expression: customer_id
description: Customer identifier
- name: order_date
expression:
dialects:
- dialect: ANSI_SQL
expression: order_date
datatype: Date
dimension:
is_time: true
description: Order date
- name: amount
expression:
dialects:
- dialect: ANSI_SQL
expression: amount
description: Order amount
- name: customers
source: sales.public.customers
primary_key: [id]
description: Customer information
fields:
- name: id
expression:
dialects:
- dialect: ANSI_SQL
expression: id
description: Customer identifier
- name: email
expression:
dialects:
- dialect: ANSI_SQL
expression: email
description: Customer email
relationships:
- name: orders_to_customers
from: orders
to: customers
from_columns: [customer_id]
to_columns: [id]
metrics:
- name: total_revenue
expression:
dialects:
- dialect: ANSI_SQL
expression: SUM(orders.amount)
description: Total revenue from all orders
ai_context:
synonyms:
- "total sales"
- "revenue"
- name: customer_count
expression:
dialects:
- dialect: ANSI_SQL
expression: COUNT(DISTINCT customers.id)
description: Total number of customers
ai_context:
synonyms:
- "total customers"
- "customer base"
custom_extensions:
- vendor_name: SNOWFLAKE
data: '{"warehouse": "ANALYTICS_WH"}'
AI Context Structure¶
The ai_context field can be either a simple string or a structured object with specific keys:
Simple String:
Structured Object:
ai_context:
instructions: "Use this for sales analysis"
synonyms:
- "orders"
- "purchases"
- "sales"
examples:
- "Show total sales last month"
- "What's the revenue by region?"
Recommended AI Context Fields¶
| Field | Type | Description |
|---|---|---|
instructions |
string | Instructions for AI on how to use this entity |
synonyms |
array | Alternative names and terms |
examples |
array | Sample questions or use cases |
Version History¶
- 0.2.0.dev0 (Unreleased): In-development next minor release. Schema is mutable; do not depend on this version in production.
- Breaking: each standalone document contains one model directly at the root; the
semantic_modelarray is removed. - 0.1.1 (2025-12-11): Initial release
- Core semantic model structure
- Support for datasets, relationships, fields, and metrics
- Multi-dialect metric expressions
- Vendor extensibility framework
- Context for agents
License¶
See LICENSE file for details.