@prefix owl: . @prefix rdf: . @prefix rdfs: . @prefix xsd: . @prefix dcterms: . @prefix prov: . @prefix pr: . ################################################################# # PERNOD RICARD DATA META MODEL - T-Box v1.0 # Owner: Bastien Gourdon - Data Governance Office # # WHAT CHANGED vs v0.9.2 # ---------------------- # 1. TERM NAMESPACE IS NOW VERSION-INDEPENDENT. # Terms live at .../metamodel/ (no version segment). # The VERSION lives in owl:versionIRI only. # Rationale: in v0.9 the version was baked into every term IRI, so every # minor release invalidated the whole A-Box. W3C-recommended pattern is to # freeze the term namespace and version the ontology document. # MIGRATION: sed -i 's|/metamodel/0.9/|/metamodel/|g' instances/*.ttl # # 2. NEW ORTHOGONAL AXIS: CuratedObject vs ObservedObject. # LAYER says WHAT an object is. PROVENANCE says HOW IT GOT HERE. # - CuratedObject : asserted by governance, edited via pull request, # subject to the full ownership shape. # - ObservedObject: harvested from a running system, rebuilt every night, # NEVER hand-edited, NOT required to carry owningDomain. # Without this split, the SHACL ownership shape would demand an owning Data # Domain and a named owner on every one of the ~50 000 Snowflake columns. # # 3. PHYSICAL LAYER ACTUALLY MODELLED (was declared, never instantiable). # System / Database / Schema / PhysicalRelation / Field / KeyConstraint / # Transformation, plus column-level lineage (derivedFrom). # # 4. NEW CONSUMPTION LAYER (Tableau + Looker). # BIWorkspace / BIDataSource / BIField / BIReport, plus realizesMetric, # which closes the loop between a certified Metric and its actual # implementations in the BI estate. # # 5. BRIDGE TO CONCEPTUAL ONTOLOGIES: denotes / denotesProperty / # denotesActivity. Declared now, left empty. Annotation properties, not # object properties, to stay in OWL 2 DL without punning. # # 6. FIXES: composedOf/describes false inverse; hasField/livesIn inverse # declared; string-typed source system and grain replaced by real # references; deprecations recorded rather than deleted (LC-002). ################################################################# a owl:Ontology ; owl:versionIRI ; owl:priorVersion ; dcterms:title "Pernod Ricard Data Meta Model" ; dcterms:creator "Bastien Gourdon" ; dcterms:modified "2026-07-25"^^xsd:date ; owl:versionInfo "1.0.0-draft-2026-07-25" ; rdfs:comment """OWL T-Box. Five layers (Ownership, Business, Logical, Physical, Consumption) crossed with a provenance axis (Curated vs Observed). Curated objects are asserted by governance and reviewed; Observed objects are harvested from Snowflake, Tableau and Looker and are rebuilt, never edited. Bridge annotation properties are declared for future alignment with domain ontologies.""" . ################################################################# # ANNOTATION PROPERTIES ################################################################# # ---- Bridge to conceptual (domain) ontologies ----------------- # A meta model instance is a DOCUMENTATION RECORD about a concept. # A domain ontology holds the CONCEPT ITSELF, axiomatised. # "Customer Invoice" is an INSTANCE of pr:BusinessObject here, # and a CLASS (fin:Invoice) there. These three properties join the two. # Annotation properties (not object properties) so that pointing an # individual at a class stays inside OWL 2 DL without punning. pr:denotes a owl:AnnotationProperty ; rdfs:label "denotes" ; rdfs:comment "Links a documentation record (Business Object, Business Concept, Data Object) to the CLASS it describes in a domain ontology. Example: ex:BO_16_03_001 pr:denotes fin:Invoice ." . pr:denotesProperty a owl:AnnotationProperty ; rdfs:label "denotes property" ; rdfs:comment "Links a Data Element or Business Concept to the PROPERTY it describes in a domain ontology. Example: ex:DE_16_03_0001 pr:denotesProperty fin:netAmount ." . pr:denotesActivity a owl:AnnotationProperty ; rdfs:label "denotes activity" ; rdfs:comment "Links a Metric or Business Object to the PROCESS or EVENT it describes, typically a prov:Activity subclass. Example: ex:M_16_03_001 pr:denotesActivity fin:InvoiceIssuance ." . # ---- Operational documentation -------------------------------- pr:harvestSource a owl:AnnotationProperty ; rdfs:label "harvest source" ; rdfs:comment "For Observed terms: the system view or API that populates this term. Documents the contract between the meta model and the harvester." . pr:curationMode a owl:AnnotationProperty ; rdfs:label "curation mode" ; rdfs:comment "ASSERTED (governance writes it), HARVESTED (a job writes it) or PROPOSED_CONFIRMED (a job proposes, a steward confirms)." . ################################################################# # ROOTS - layer axis x provenance axis ################################################################# pr:MetaModelObject a owl:Class ; rdfs:label "Meta Model Object" ; rdfs:comment "Anything the meta model describes. Actors are deliberately NOT Meta Model Objects." . pr:CuratedObject a owl:Class ; rdfs:subClassOf pr:MetaModelObject ; rdfs:label "Curated Object" ; pr:curationMode "ASSERTED" ; rdfs:comment "Asserted by governance, edited through pull request on the domain TTL file, subject to the full ownership and lifecycle shape (identifier, name, owner, owning Data Domain, status, version)." . pr:ObservedObject a owl:Class ; rdfs:subClassOf pr:MetaModelObject ; rdfs:label "Observed Object" ; pr:curationMode "HARVESTED" ; rdfs:comment "Harvested from a running system and rebuilt on every run. Never hand-edited. Carries sourceIdentifier, fullyQualifiedName and harvestedOn instead of curated ownership: attribution is INFERRED through the Data Element it is mapped to, not asserted on the node." . pr:OwnershipLayerObject a owl:Class ; rdfs:subClassOf pr:CuratedObject ; rdfs:label "Ownership & Categorization Layer Object" . pr:BusinessLayerObject a owl:Class ; rdfs:subClassOf pr:CuratedObject ; rdfs:label "Business Layer Object" . pr:LogicalLayerObject a owl:Class ; rdfs:subClassOf pr:CuratedObject ; rdfs:label "Logical Layer Object" . pr:PhysicalLayerObject a owl:Class ; rdfs:subClassOf pr:ObservedObject ; rdfs:label "Physical Layer Object" . pr:ConsumptionLayerObject a owl:Class ; rdfs:subClassOf pr:ObservedObject ; rdfs:label "Consumption Layer Object" ; rdfs:comment "The BI estate. Separate from Physical because BI assets have their own lifecycle and their own owner: a dashboard belongs to its author, not to the Data Domain that owns the underlying data." . ################################################################# # LAYER 1 - OWNERSHIP & CATEGORIZATION (curated) ################################################################# pr:DataDomain a owl:Class ; rdfs:subClassOf pr:OwnershipLayerObject ; rdfs:label "Data Domain" . pr:SubDomain a owl:Class ; rdfs:subClassOf pr:OwnershipLayerObject ; rdfs:label "Sub-Domain" . pr:BusinessObject a owl:Class ; rdfs:subClassOf pr:OwnershipLayerObject ; rdfs:label "Business Object" ; rdfs:comment "The unit of ownership attribution. Sits in the Ownership layer rather than the Business layer on purpose: a Business Object is what a Data Domain is accountable for, and what a Data Object implements. Its business meaning is carried by the Business Concepts it groups." . ################################################################# # LAYER 2 - BUSINESS (curated) ################################################################# pr:BusinessConcept a owl:Class ; rdfs:subClassOf pr:BusinessLayerObject ; rdfs:label "Business Concept" ; rdfs:comment "A shared business notion WITHOUT a formula. The presence of a formula is the sole discriminator against Metric (rule BR-003)." . pr:Metric a owl:Class ; rdfs:subClassOf pr:BusinessLayerObject ; rdfs:label "Metric" ; rdfs:comment "A quantifiable measurement WITH a formula, a unit and a grain. Under BR-013 a Metric carries the harmonised CALCULATION RULE; variants that differ only by analysis context are Data Elements linked back via computedBy." . pr:KPI a owl:Class ; rdfs:subClassOf pr:Metric ; rdfs:label "Key Performance Indicator" ; rdfs:comment "An elevated Metric. Use this class rather than the deprecated isKPI flag." . ################################################################# # LAYER 3 - LOGICAL (curated) ################################################################# pr:DataObject a owl:Class ; rdfs:subClassOf pr:LogicalLayerObject ; rdfs:label "Data Object" ; rdfs:comment "The pivot: implements exactly one Business Object, is composed of Data Elements, and is materialized as one or more Physical Relations. The single junction between governance and technology." . pr:DataElement a owl:Class ; rdfs:subClassOf pr:LogicalLayerObject ; rdfs:label "Data Element" ; pr:curationMode "PROPOSED_CONFIRMED" ; rdfs:comment "The finest curated unit. Its mapping to a physical Field is the ONLY place where the curated graph and the observed graph meet: proposed automatically by name and type matching, confirmed by a Data Steward." . pr:DataAsset a owl:Class ; rdfs:subClassOf pr:LogicalLayerObject ; rdfs:label "Data Asset" ; rdfs:comment "Directly consumable by a business user. A reusable building block is a Data Object, not a Data Asset (rule BR-009)." . pr:DataProduct a owl:Class ; rdfs:subClassOf pr:LogicalLayerObject ; rdfs:label "Data Product" ; rdfs:comment "The unit of delivery: packages Data Assets and is governed by a Data Contract. Candidate alignment: dcat:Dataset / DPROD." . pr:DataContract a owl:Class ; rdfs:subClassOf pr:LogicalLayerObject ; rdfs:label "Data Contract" ; rdfs:comment "The service commitment attached to a Data Product: schema, freshness, quality thresholds, support. Candidate alignment: ODCS (Bitol)." . ################################################################# # LAYER 4 - PHYSICAL (observed) ################################################################# pr:System a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "System" ; pr:harvestSource "Manually seeded once, then referenced. Replaces the free-text hasSourceSystem." ; rdfs:comment "A real system: Snowflake, MDM Product, MDM Customer, a panel provider feed, Tableau Server, Looker. Making this a node rather than a string is what makes 'what depends on MDM Product?' answerable." . pr:Database a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "Database" ; pr:harvestSource "SNOWFLAKE.INFORMATION_SCHEMA.DATABASES" . pr:Schema a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "Schema" ; pr:harvestSource "SNOWFLAKE.INFORMATION_SCHEMA.SCHEMATA" . pr:PhysicalRelation a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "Physical Relation" ; pr:harvestSource "SNOWFLAKE.INFORMATION_SCHEMA.TABLES" ; rdfs:comment "Abstract parent of everything with columns. Specialised because impact traversal differs by kind: a View propagates impact to whatever it reads." . pr:BaseTable a owl:Class ; rdfs:subClassOf pr:PhysicalRelation ; rdfs:label "Base Table" . pr:View a owl:Class ; rdfs:subClassOf pr:PhysicalRelation ; rdfs:label "View" ; rdfs:comment "Depends on other relations through dependsOn, so impact is transitive." . pr:MaterializedView a owl:Class ; rdfs:subClassOf pr:PhysicalRelation ; rdfs:label "Materialized View" . pr:ExternalTable a owl:Class ; rdfs:subClassOf pr:PhysicalRelation ; rdfs:label "External Table" ; rdfs:comment "Backed by files outside the warehouse. Marks the boundary where lineage leaves Snowflake." . pr:Table a owl:Class ; rdfs:subClassOf pr:PhysicalRelation ; rdfs:label "Table (deprecated)" ; owl:deprecated true ; dcterms:isReplacedBy pr:BaseTable ; rdfs:comment "v0.9 term. Kept so that existing assertions still classify. Use BaseTable." . pr:Field a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "Field" ; pr:harvestSource "SNOWFLAKE.INFORMATION_SCHEMA.COLUMNS" ; rdfs:comment "A physical column. The anchor of impact analysis: everything upstream reaches a Field, everything downstream starts from one." . pr:KeyConstraint a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject ; rdfs:label "Key Constraint" ; pr:harvestSource "SNOWFLAKE.INFORMATION_SCHEMA.TABLE_CONSTRAINTS + KEY_COLUMN_USAGE" ; rdfs:comment "Gives foreign keys a home. Rule OW-006 says an FK is not a Data Element - true, but it still needs somewhere to live, and it lets the asserted DataObject-references-DataObject edge be checked against reality." . pr:PrimaryKey a owl:Class ; rdfs:subClassOf pr:KeyConstraint ; rdfs:label "Primary Key" . pr:ForeignKeyConstraint a owl:Class ; rdfs:subClassOf pr:KeyConstraint ; rdfs:label "Foreign Key Constraint" . pr:Transformation a owl:Class ; rdfs:subClassOf pr:PhysicalLayerObject , prov:Activity ; rdfs:label "Transformation" ; pr:harvestSource "dbt manifest.json, Snowflake TASKS, Azure Data Factory pipelines" ; rdfs:comment "The code that turns inputs into outputs: a dbt model, a Snowflake task, an ADF pipeline. Subclass of prov:Activity so that lineage is expressed in a standard vocabulary rather than a private one." . ################################################################# # LAYER 5 - CONSUMPTION (observed) ################################################################# pr:BIWorkspace a owl:Class ; rdfs:subClassOf pr:ConsumptionLayerObject ; rdfs:label "BI Workspace" ; pr:harvestSource "Tableau Metadata API (Project/Site) ; Looker API (Model)" . pr:BIDataSource a owl:Class ; rdfs:subClassOf pr:ConsumptionLayerObject ; rdfs:label "BI Data Source" ; pr:harvestSource "Tableau Published Datasource ; Looker Explore" ; rdfs:comment "The semantic surface a report is built on. This is where BI meets the warehouse." . pr:BIField a owl:Class ; rdfs:subClassOf pr:ConsumptionLayerObject ; rdfs:label "BI Field" ; pr:harvestSource "Tableau calculated fields ; LookML measures and dimensions" ; rdfs:comment "A field as a business user sees it. realizesMetric is what turns a certified Metric from a definition on paper into something measurable against the real BI estate." . pr:BIReport a owl:Class ; rdfs:subClassOf pr:ConsumptionLayerObject ; rdfs:label "BI Report" ; pr:harvestSource "Tableau Workbook/Sheet ; Looker Look/Dashboard" ; rdfs:comment "What a Data Governance Lead actually cares about in an impact analysis: not that a column changed, but which reports break and who to warn." . ################################################################# # ACTORS (outside MetaModelObject on purpose) ################################################################# pr:Actor a owl:Class ; rdfs:label "Actor" ; rdfs:comment "A person or a team. Deliberately NOT a MetaModelObject: people are not subject to ownership and lifecycle rules." . pr:DataDomainOwner a owl:Class ; rdfs:subClassOf pr:Actor ; rdfs:label "Data Domain Owner" . pr:DataGovernanceLead a owl:Class ; rdfs:subClassOf pr:Actor ; rdfs:label "Data Governance Lead (DGL)" . pr:DataSteward a owl:Class ; rdfs:subClassOf pr:Actor ; rdfs:label "Data Steward" . ################################################################# # CONTROLLED VOCABULARIES ################################################################# pr:ActivationStatus a owl:Class ; rdfs:label "Activation Status" . pr:NotActivated a pr:ActivationStatus ; rdfs:label "Not Activated" . pr:LightActivation a pr:ActivationStatus ; rdfs:label "Light Activation" . pr:FullActivation a pr:ActivationStatus ; rdfs:label "Full Activation" . pr:Environment a owl:Class ; rdfs:label "Environment" ; rdfs:comment "Same logical object, several physical incarnations. Kept as a vocabulary rather than folded into the name so that DEV drift never pollutes PROD lineage." . pr:Development a pr:Environment ; rdfs:label "Development" . pr:UserAcceptance a pr:Environment ; rdfs:label "User Acceptance" . pr:Production a pr:Environment ; rdfs:label "Production" . pr:SystemType a owl:Class ; rdfs:label "System Type" . pr:SourceApplication a pr:SystemType ; rdfs:label "Source Application" . pr:MasterDataSystem a pr:SystemType ; rdfs:label "Master Data System" . pr:DataPlatform a pr:SystemType ; rdfs:label "Data Platform" . pr:BITool a pr:SystemType ; rdfs:label "BI Tool" . pr:ExternalProvider a pr:SystemType ; rdfs:label "External Provider" . ################################################################# # OBJECT PROPERTIES - Ownership & Business ################################################################# pr:belongsToDomain a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "belongs to domain" ; rdfs:domain pr:SubDomain ; rdfs:range pr:DataDomain . pr:belongsToSubDomain a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "belongs to sub-domain" ; rdfs:domain pr:BusinessObject ; rdfs:range pr:SubDomain . pr:composedOf a owl:ObjectProperty ; rdfs:label "composed of" ; rdfs:domain pr:BusinessObject ; rdfs:range pr:BusinessConcept ; owl:inverseOf pr:isComponentOf ; rdfs:comment "Part-whole. In v0.9 this was declared owl:inverseOf pr:describes, which was semantically wrong: composition and aboutness are different relations, and a reasoner would infer that every Concept describing an Object is also a component of it." . pr:isComponentOf a owl:ObjectProperty ; rdfs:label "is component of" ; rdfs:domain pr:BusinessConcept ; rdfs:range pr:BusinessObject . pr:describes a owl:ObjectProperty ; rdfs:label "describes (deprecated)" ; owl:deprecated true ; dcterms:isReplacedBy pr:isComponentOf ; rdfs:comment "Removed as a genuine relation. Its only use was as a false inverse of composedOf." . pr:hasMetric a owl:ObjectProperty ; rdfs:label "has metric" ; rdfs:domain pr:BusinessObject ; rdfs:range pr:Metric . pr:measures a owl:ObjectProperty ; rdfs:label "measures" ; rdfs:domain pr:Metric ; rdfs:range pr:BusinessConcept . pr:hasGrainDimension a owl:ObjectProperty ; rdfs:label "has grain dimension" ; rdfs:domain pr:Metric ; rdfs:range pr:DataObject ; rdfs:comment "The dimensional Data Objects that define the Metric's grain. Replaces reading grain out of the free-text hasGranularity string: only a real reference lets you detect that two Metrics cannot be aggregated together." . pr:computedBy a owl:ObjectProperty ; rdfs:subPropertyOf prov:wasDerivedFrom ; rdfs:label "computed by" ; rdfs:domain pr:Metric ; rdfs:range pr:DataElement ; rdfs:comment "BR-013. Links a mother Metric to the granular Data Elements that implement it in a given analysis context (period, promo status, scope, unit, currency)." . ################################################################# # OBJECT PROPERTIES - Logical ################################################################# pr:implements a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "implements" ; rdfs:domain pr:DataObject ; rdfs:range pr:BusinessObject ; rdfs:comment "The pivot. Exactly one, enforced by SHACL (BR-006)." . pr:hasElement a owl:ObjectProperty ; rdfs:label "has element" ; rdfs:domain pr:DataObject ; rdfs:range pr:DataElement . pr:references a owl:ObjectProperty ; rdfs:label "references" ; rdfs:domain pr:DataObject ; rdfs:range pr:DataObject ; rdfs:comment "Foreign-key reference between Data Objects. NOT ownership. Now checkable against the harvested ForeignKeyConstraint objects." . pr:usesDataObject a owl:ObjectProperty ; rdfs:label "uses Data Object" ; rdfs:domain pr:DataAsset ; rdfs:range pr:DataObject . pr:packages a owl:ObjectProperty ; rdfs:label "packages" ; rdfs:domain pr:DataProduct ; rdfs:range pr:DataAsset . pr:governedBy a owl:ObjectProperty ; rdfs:label "governed by" ; rdfs:domain pr:DataProduct ; rdfs:range pr:DataContract . ################################################################# # OBJECT PROPERTIES - the curated / observed seam # These two are the ONLY edges crossing from asserted to harvested. # Everything else is either pure governance or pure machine. ################################################################# pr:materializedAs a owl:ObjectProperty ; rdfs:label "materialized as" ; rdfs:domain pr:DataObject ; rdfs:range pr:PhysicalRelation ; pr:curationMode "PROPOSED_CONFIRMED" ; rdfs:comment "Data Object to physical relation. Not functional: the same Data Object exists in DEV, UAT and PROD, and sometimes across several tables." . pr:physicalizedIn a owl:ObjectProperty ; rdfs:label "physicalized in" ; rdfs:domain pr:DataElement ; rdfs:range pr:Field ; pr:curationMode "PROPOSED_CONFIRMED" ; rdfs:comment "Data Element to physical column, 1..n. Proposed by the reconciliation job on fullyQualifiedName and type, confirmed by a Data Steward. This single edge is what makes end-to-end impact analysis possible." . ################################################################# # OBJECT PROPERTIES - Physical ################################################################# pr:sourcedFrom a owl:ObjectProperty ; rdfs:label "sourced from" ; rdfs:range pr:System ; rdfs:comment "Replaces the free-text hasSourceSystem. Domain deliberately omitted: applies to Data Elements, Physical Relations and BI Data Sources alike." . pr:hasSystemType a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "has system type" ; rdfs:domain pr:System ; rdfs:range pr:SystemType . pr:hostedOn a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "hosted on" ; rdfs:domain pr:Database ; rdfs:range pr:System . pr:inDatabase a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "in database" ; rdfs:domain pr:Schema ; rdfs:range pr:Database . pr:inSchema a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "in schema" ; rdfs:domain pr:PhysicalRelation ; rdfs:range pr:Schema . pr:hasField a owl:ObjectProperty ; rdfs:label "has field" ; rdfs:domain pr:PhysicalRelation ; rdfs:range pr:Field ; owl:inverseOf pr:livesIn ; rdfs:comment "Domain widened from Table to PhysicalRelation so that views and external tables carry columns too. Inverse now declared - in v0.9 hasField and livesIn were inverses in fact but not in the model, so they were free to diverge." . pr:livesIn a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "lives in" ; rdfs:domain pr:Field ; rdfs:range pr:PhysicalRelation . pr:deployedIn a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "deployed in" ; rdfs:domain pr:ObservedObject ; rdfs:range pr:Environment . pr:constrainsRelation a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "constrains relation" ; rdfs:domain pr:KeyConstraint ; rdfs:range pr:PhysicalRelation . pr:constrainsField a owl:ObjectProperty ; rdfs:label "constrains field" ; rdfs:domain pr:KeyConstraint ; rdfs:range pr:Field ; rdfs:comment "Several fields for a composite key." . pr:fromField a owl:ObjectProperty ; rdfs:label "from field" ; rdfs:domain pr:ForeignKeyConstraint ; rdfs:range pr:Field . pr:toField a owl:ObjectProperty ; rdfs:label "to field" ; rdfs:domain pr:ForeignKeyConstraint ; rdfs:range pr:Field . pr:consumes a owl:ObjectProperty ; rdfs:subPropertyOf prov:used ; rdfs:label "consumes" ; rdfs:domain pr:Transformation ; rdfs:range pr:PhysicalRelation . pr:produces a owl:ObjectProperty ; rdfs:label "produces" ; rdfs:domain pr:Transformation ; rdfs:range pr:PhysicalRelation . pr:dependsOn a owl:ObjectProperty , owl:TransitiveProperty ; rdfs:label "depends on" ; rdfs:domain pr:PhysicalRelation ; rdfs:range pr:PhysicalRelation ; pr:harvestSource "SNOWFLAKE.ACCOUNT_USAGE.OBJECT_DEPENDENCIES" ; rdfs:comment "Relation-level dependency, view to table. Transitive by nature; in practice compute the closure at query time in Snowflake rather than materialising it with a reasoner." . pr:derivedFrom a owl:ObjectProperty , owl:TransitiveProperty ; rdfs:subPropertyOf prov:wasDerivedFrom ; rdfs:label "derived from" ; rdfs:domain pr:Field ; rdfs:range pr:Field ; pr:harvestSource "SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY (column lineage) ; dbt manifest" ; rdfs:comment "Column-to-column lineage. The single highest-value edge in the model, and largely free: Snowflake already computes it." . ################################################################# # OBJECT PROPERTIES - Consumption ################################################################# pr:inWorkspace a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "in workspace" ; rdfs:domain pr:ConsumptionLayerObject ; rdfs:range pr:BIWorkspace . pr:biConsumes a owl:ObjectProperty ; rdfs:label "BI consumes" ; rdfs:domain pr:BIDataSource ; rdfs:range pr:PhysicalRelation ; pr:harvestSource "Tableau Metadata API (GraphQL) ; Looker Explore SQL" . pr:hasBIField a owl:ObjectProperty ; rdfs:label "has BI field" ; rdfs:domain pr:BIDataSource ; rdfs:range pr:BIField ; owl:inverseOf pr:inBIDataSource . pr:inBIDataSource a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "in BI data source" ; rdfs:domain pr:BIField ; rdfs:range pr:BIDataSource . pr:biDerivedFrom a owl:ObjectProperty ; rdfs:subPropertyOf prov:wasDerivedFrom ; rdfs:label "BI derived from" ; rdfs:domain pr:BIField ; rdfs:range pr:Field ; rdfs:comment "Closes the last gap in the impact chain: from a dashboard field back to the warehouse column." . pr:realizesMetric a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "realizes metric" ; rdfs:domain pr:BIField ; rdfs:range pr:Metric ; pr:curationMode "PROPOSED_CONFIRMED" ; rdfs:comment "The harmonisation proof. Counting distinct BI Fields realizing one certified Metric, and comparing their expressions, turns 'we harmonised the definitions' from a claim into a measurement over the real BI estate." . pr:usesBIDataSource a owl:ObjectProperty ; rdfs:label "uses BI data source" ; rdfs:domain pr:BIReport ; rdfs:range pr:BIDataSource . pr:hasBIOwner a owl:ObjectProperty ; rdfs:label "has BI owner" ; rdfs:domain pr:ConsumptionLayerObject ; rdfs:range pr:Actor ; rdfs:comment "The author or publisher. This is who gets notified by an impact analysis, and it is NOT the Data Domain owner." . ################################################################# # OBJECT PROPERTIES - Ownership (universal: domain omitted on purpose) ################################################################# pr:ownedBy a owl:ObjectProperty ; rdfs:label "owned by" ; rdfs:range pr:Actor . pr:owningDomain a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "owning Data Domain" ; rdfs:range pr:DataDomain ; rdfs:comment "The single Data Domain with authority to define the object's rule. Required on Curated Objects, absent on Observed Objects: a Snowflake column is attributed through the Data Element mapped to it, never asserted directly." . pr:hasSteward a owl:ObjectProperty ; rdfs:label "has Data Steward" ; rdfs:range pr:DataSteward . pr:hasDGL a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "has DGL" ; rdfs:domain pr:DataDomain ; rdfs:range pr:DataGovernanceLead . pr:hasActivationStatus a owl:ObjectProperty , owl:FunctionalProperty ; rdfs:label "activation status" ; rdfs:domain pr:DataDomain ; rdfs:range pr:ActivationStatus . ################################################################# # DATATYPE PROPERTIES - identity & lifecycle (domain omitted) ################################################################# pr:hasIdentifier a owl:DatatypeProperty , owl:FunctionalProperty ; rdfs:label "identifier" ; rdfs:range xsd:string . pr:hasName a owl:DatatypeProperty , owl:FunctionalProperty ; rdfs:label "canonical name" ; rdfs:range xsd:string . pr:hasStatus a owl:DatatypeProperty ; rdfs:label "status" ; rdfs:range xsd:string . pr:hasVersion a owl:DatatypeProperty ; rdfs:label "version" ; rdfs:range xsd:string . pr:createdOn a owl:DatatypeProperty ; rdfs:label "created on" ; rdfs:range xsd:date . pr:lastReviewedOn a owl:DatatypeProperty ; rdfs:label "last reviewed on" ; rdfs:range xsd:date . pr:hasSource a owl:DatatypeProperty ; rdfs:label "back-doc source" ; rdfs:range xsd:string . pr:arbitrationStatus a owl:DatatypeProperty ; rdfs:label "arbitration status" ; rdfs:range xsd:string ; rdfs:comment "TO_ARBITRATE blocks publication (OW-007). Use this on the object rather than tracking arbitration in a side spreadsheet." . # ---- Business semantics pr:hasBusinessDefinition a owl:DatatypeProperty ; rdfs:label "business definition" ; rdfs:range xsd:string . pr:hasTechnicalDefinition a owl:DatatypeProperty ; rdfs:label "technical definition" ; rdfs:range xsd:string . pr:hasAcronym a owl:DatatypeProperty ; rdfs:label "acronym" ; rdfs:range xsd:string . pr:hasSynonym a owl:DatatypeProperty ; rdfs:label "synonym" ; rdfs:range xsd:string . pr:hasBusinessRule a owl:DatatypeProperty ; rdfs:label "business rule" ; rdfs:range xsd:string . # ---- Metric pr:hasFormula a owl:DatatypeProperty ; rdfs:label "formula" ; rdfs:range xsd:string . pr:hasUnit a owl:DatatypeProperty ; rdfs:label "unit" ; rdfs:range xsd:string ; rdfs:comment "From the Units LoV. Note the LoV currently mixes physical units, currencies (ISO 4217) and value types (Index, Rate, Count) - three different concepts that should eventually be split." . pr:hasGranularity a owl:DatatypeProperty ; rdfs:label "granularity (label)" ; rdfs:range xsd:string ; rdfs:comment "Human-readable grain label, e.g. 'SKU x Customer x Day'. Keep in sync with hasGrainDimension, which is the machine-readable form." . pr:hasTimeAggregation a owl:DatatypeProperty ; rdfs:label "time aggregation" ; rdfs:range xsd:string . pr:isKPI a owl:DatatypeProperty ; rdfs:label "is KPI (deprecated)" ; rdfs:range xsd:boolean ; owl:deprecated true ; dcterms:isReplacedBy pr:KPI ; rdfs:comment "Duplicated the KPI class. Two ways to say the same thing are two ways to diverge." . # ---- Data Element pr:hasFormat a owl:DatatypeProperty ; rdfs:label "logical format" ; rdfs:range xsd:string . pr:hasExampleValue a owl:DatatypeProperty ; rdfs:label "example value" ; rdfs:range xsd:string . pr:hasSourceSystem a owl:DatatypeProperty ; rdfs:label "source system (deprecated)" ; rdfs:range xsd:string ; owl:deprecated true ; dcterms:isReplacedBy pr:sourcedFrom ; rdfs:comment "Free text. 'Which objects depend on MDM Product?' was unanswerable because MDM Product was a string, not a node." . pr:hasSchemaName a owl:DatatypeProperty ; rdfs:label "schema name (deprecated)" ; rdfs:range xsd:string ; owl:deprecated true ; dcterms:isReplacedBy pr:Schema . # ---- Physical identity (the join keys with the real warehouse) pr:physicalName a owl:DatatypeProperty , owl:FunctionalProperty ; rdfs:label "physical name" ; rdfs:range xsd:string ; rdfs:comment "Recorded verbatim, never altered (NR-009). Must NOT be carried by a Metric - that is a layer leak; under BR-013 the physical name belongs on the Data Element." . pr:fullyQualifiedName a owl:DatatypeProperty , owl:FunctionalProperty ; rdfs:label "fully qualified name" ; rdfs:range xsd:string ; rdfs:comment "DATABASE.SCHEMA.RELATION[.COLUMN]. The actual join key against INFORMATION_SCHEMA: a bare physical name is ambiguous as soon as the same column name exists in two tables." . pr:sourceIdentifier a owl:DatatypeProperty , owl:FunctionalProperty ; rdfs:label "source identifier" ; rdfs:range xsd:string ; rdfs:comment "Native immutable id in the source system (Snowflake object id, Tableau LUID, Looker id). Makes reconciliation idempotent and survives renames, which names do not." . pr:harvestedOn a owl:DatatypeProperty ; rdfs:label "harvested on" ; rdfs:range xsd:dateTime ; rdfs:comment "Staleness marker. An Observed Object not refreshed by the last run is a deletion candidate, not a fact." . pr:hasPhysicalDataType a owl:DatatypeProperty ; rdfs:label "physical data type" ; rdfs:range xsd:string . pr:isNullable a owl:DatatypeProperty ; rdfs:label "is nullable" ; rdfs:range xsd:boolean . pr:ordinalPosition a owl:DatatypeProperty ; rdfs:label "ordinal position" ; rdfs:range xsd:integer . pr:hasViewDefinition a owl:DatatypeProperty ; rdfs:label "view definition" ; rdfs:range xsd:string . pr:hasVendor a owl:DatatypeProperty ; rdfs:label "vendor" ; rdfs:range xsd:string . pr:definedBy a owl:DatatypeProperty ; rdfs:label "defined by (code URI)" ; rdfs:range xsd:anyURI ; rdfs:comment "Git URI of the code behind a Transformation. Connects the graph to the repository." . # ---- Usage evidence (the rationalisation argument) pr:approximateRowCount a owl:DatatypeProperty ; rdfs:label "approximate row count" ; rdfs:range xsd:integer . pr:lastQueriedOn a owl:DatatypeProperty ; rdfs:label "last queried on" ; rdfs:range xsd:dateTime ; pr:harvestSource "SNOWFLAKE.ACCOUNT_USAGE.ACCESS_HISTORY" ; rdfs:comment "Lets the model say 'documented but unused for eight months'. A rationalisation argument that costs nothing and is denominated in warehouse spend." . pr:queryCount30d a owl:DatatypeProperty ; rdfs:label "query count (30 days)" ; rdfs:range xsd:integer . # ---- BI pr:hasExpression a owl:DatatypeProperty ; rdfs:label "BI expression" ; rdfs:range xsd:string ; rdfs:comment "The calculated-field formula, Tableau or LookML. Compared against the Metric formula to detect definition drift." . ################################################################# # DISJOINTNESS ################################################################# [] a owl:AllDisjointClasses ; owl:members ( pr:CuratedObject pr:ObservedObject ) . [] a owl:AllDisjointClasses ; owl:members ( pr:OwnershipLayerObject pr:BusinessLayerObject pr:LogicalLayerObject pr:PhysicalLayerObject pr:ConsumptionLayerObject ) . [] a owl:AllDisjointClasses ; owl:members ( pr:BusinessObject pr:DataObject pr:DataAsset pr:DataProduct ) . [] a owl:AllDisjointClasses ; owl:members ( pr:BusinessConcept pr:Metric ) . [] a owl:AllDisjointClasses ; owl:members ( pr:BaseTable pr:View pr:MaterializedView pr:ExternalTable ) . [] a owl:AllDisjointClasses ; owl:members ( pr:PrimaryKey pr:ForeignKeyConstraint ) . [] a owl:AllDisjointClasses ; owl:members ( pr:BIWorkspace pr:BIDataSource pr:BIField pr:BIReport ) .