diff --git a/adalbert-contracts/README.md b/adalbert-contracts/README.md
new file mode 100644
index 0000000..e17e87d
--- /dev/null
+++ b/adalbert-contracts/README.md
@@ -0,0 +1,177 @@
+# Adalbert: Data Contracts and Data-Use Policies
+
+**An ODRL 2.2 profile with deterministic evaluation semantics for data governance.**
+
+Adalbert provides a formal, standards-based approach to data contracts and data-use policies. It uses ODRL 2.2 terms for all standard constructs and adds only genuinely new extensions for lifecycle management, bilateral duties, recurrence, and structured operand resolution.
+
+---
+
+## What This Is
+
+This folder contains the Adalbert data governance framework as a contribution to EKGF/dprod, complementing the `dprod-contracts` approach with:
+
+1. **Data contracts** — bilateral agreements between data providers and consumers (like dprod-contracts)
+2. **Data-use policies** — organizational access controls, purpose restrictions, classification rules (unique to Adalbert)
+3. **Formal semantics** — normative evaluation specification amenable to formal verification
+4. **ODRL 2.2 compliance** — every Adalbert policy is a valid ODRL 2.2 policy
+
+## Key Differentiators
+
+| Capability | dprod-contracts | Adalbert |
+|---|---|---|
+| Data contracts | Yes | Yes |
+| Data-use policies | No | **Yes** |
+| Formal semantics | No | **Yes** (normative, verification-ready) |
+| Bilateral duties | Via Promise subclass | **Via standard odrl:Duty** |
+| Lifecycle states | Status enum | **Formal state machine** (Pending → Active → Fulfilled/Violated) |
+| Recurrence | ICalSchedule class | **RRULE property** + deadline window |
+| Operand resolution | Unspecified | **Structured paths** (agent.role, asset.classification, context.purpose) |
+| Constraint vocabulary | Minimal | **33 operands** across 15 categories |
+| ODRL compatibility | Custom Rule subclass | **Standard Rule types** (Permission, Duty, Prohibition) |
+
+---
+
+## Folder Contents
+
+```
+adalbert-contracts/
+├── README.md # This file
+├── adalbert-core.ttl # OWL ontology (ODRL profile extension)
+├── adalbert-shacl.ttl # SHACL validation shapes
+├── adalbert-prof.ttl # W3C DXPROF profile metadata
+├── adalbert-due.ttl # Data use vocabulary (operands, actions, values)
+├── examples/
+│ ├── data-contract.ttl # Bilateral contract with provider SLA + consumer duties
+│ ├── data-use-policy.ttl # Role-based access control with purpose constraints
+│ ├── dprod-translated.ttl # dprod-contracts examples translated to Adalbert
+│ └── baseline.ttl # Comprehensive test suite (8 contracts, 2 subscriptions)
+└── docs/
+ ├── DATA-CONTRACTS.md # Data contract authoring guide
+ ├── DATA-USE-POLICIES.md # Data-use policy authoring guide
+ ├── SPECIFICATION.md # Technical vocabulary reference
+ ├── SEMANTICS.md # Formal evaluation semantics (normative)
+ └── DPROD-Adalbert-Comparison.md # Comparison with dprod-contracts
+```
+
+---
+
+## Quick Start
+
+### Data Contract (bilateral agreement)
+
+```turtle
+@prefix odrl: .
+@prefix adalbert: .
+@prefix adalbert-due: .
+@prefix xsd: .
+
+ex:contract a adalbert:DataContract ;
+ odrl:profile ,
+ ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:marketPrices ;
+ adalbert:state adalbert:Active ;
+
+ # Provider SLA: daily delivery with 30-min window
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=DAILY;BYHOUR=6;BYMINUTE=0" ;
+ adalbert:deadline "PT30M"^^xsd:duration
+ ] ;
+
+ # Consumer: may read
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read
+ ] ;
+
+ # Consumer: must report monthly
+ odrl:obligation [
+ a odrl:Duty ;
+ odrl:action adalbert-due:report ;
+ adalbert:deadline "P30D"^^xsd:duration
+ ] ;
+
+ # No redistribution
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute
+ ] .
+```
+
+### Data-Use Policy (organizational access control)
+
+```turtle
+ex:policy a odrl:Set ;
+ odrl:profile ,
+ ;
+ odrl:target ex:employeeData ;
+
+ # HR Analytics: read for analytics purpose only
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:assignee ex:hrAnalytics ;
+ odrl:action odrl:read ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:analytics
+ ]
+ ] ;
+
+ # No ML training on employee data
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:use ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:processingMode ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:modelTraining
+ ]
+ ] .
+```
+
+---
+
+## Relationship to dprod-contracts
+
+Adalbert and dprod-contracts are complementary approaches to the same problem space. See `docs/DPROD-Adalbert-Comparison.md` for a detailed comparison and `examples/dprod-translated.ttl` for all 8 dprod-contracts examples expressed in Adalbert.
+
+Key architectural difference: dprod-contracts introduces `dprod:Promise` as a new `odrl:Rule` subclass. Adalbert uses standard `odrl:Duty`, `odrl:Permission`, and `odrl:Prohibition`, making every Adalbert policy a valid ODRL 2.2 policy that any ODRL processor can partially understand.
+
+---
+
+## SHACL Validation
+
+Validate any Adalbert policy against the SHACL shapes:
+
+```bash
+shacl validate --shapes adalbert-shacl.ttl --data examples/data-contract.ttl
+```
+
+---
+
+## Namespaces
+
+| Prefix | Namespace | Role |
+|--------|-----------|------|
+| `odrl:` | `http://www.w3.org/ns/odrl/2/` | Primary — all standard ODRL constructs |
+| `adalbert:` | `https://vocabulary.bigbank/adalbert/` | Extensions only (State, deadline, recurrence, DataContract, Subscription) |
+| `adalbert-due:` | `https://vocabulary.bigbank/adalbert/due/` | Data use vocabulary (operands, actions, concept values) |
+
+---
+
+## References
+
+- [ODRL 2.2 Information Model](https://www.w3.org/TR/odrl-model/)
+- [W3C ODRL Profile Best Practices](https://www.w3.org/community/reports/odrl/CG-FINAL-profile-bp-20240808.html)
+- [W3C Market Data Profile](https://www.w3.org/2021/md-odrl-profile/v1/)
+- [EKGF DPROD](https://ekgf.github.io/dprod/)
+
+---
+
+**Version**: 0.7 | **Date**: 2026-02-16
diff --git a/adalbert-contracts/adalbert-core.ttl b/adalbert-contracts/adalbert-core.ttl
new file mode 100644
index 0000000..ed1a3a2
--- /dev/null
+++ b/adalbert-contracts/adalbert-core.ttl
@@ -0,0 +1,306 @@
+# =============================================================================
+# Adalbert Core Ontology — ODRL 2.2 Profile Extension
+# Version: 0.7
+# Date: 2026-02-04
+# =============================================================================
+# Adalbert is a proper ODRL 2.2 profile. It uses ODRL terms wherever ODRL
+# defines them and only adds terms for genuinely new capabilities:
+#
+# - Duty lifecycle (State + state property)
+# - Deadline on duties
+# - Recurrence on duties (RFC 5545 RRULE)
+# - Duty party roles (subject, object)
+# - Data contracts and subscriptions (domain subtypes)
+# - Asset/party hierarchy (partOf, memberOf)
+# - Structured operand resolution (resolutionPath)
+# - Runtime references (RuntimeReference, currentAgent, currentDateTime)
+# - Logical negation (not)
+#
+# Everything else — Rule types, Policy types, Constraint types, operators,
+# core properties — comes from ODRL 2.2 directly.
+# =============================================================================
+
+@prefix adalbert: .
+@prefix rl2: .
+@prefix odrl: .
+@prefix owl: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix xsd: .
+@prefix dcterms: .
+@prefix skos: .
+
+# =============================================================================
+# ONTOLOGY DECLARATION
+# =============================================================================
+
+ a owl:Ontology ;
+ dcterms:title "Adalbert Core Ontology"@en ;
+ dcterms:description """
+ Adalbert: a proper ODRL 2.2 profile for deterministic data governance.
+
+ Uses ODRL terms for all standard constructs (Rule types, Policy types,
+ Constraint types, operators, core properties). Adds only:
+ - Explicit duty lifecycle (Pending -> Active -> Fulfilled/Violated)
+ - Deadline property on odrl:Duty
+ - Recurrence property on odrl:Duty (RFC 5545 RRULE)
+ - Duty party roles (subject = duty bearer, object = affected party)
+ - Data contract and subscription subtypes
+ - Asset/party hierarchy properties
+ - Structured operand resolution via resolutionPath
+ - Runtime references for dynamic right-operand values
+ - Logical negation (not) on LogicalConstraint
+
+ Adalbert policies are valid ODRL 2.2 policies. Any ODRL processor can
+ partially understand them; Adalbert-aware processors handle the
+ extensions.
+ """@en ;
+ dcterms:created "2026-02-02"^^xsd:date ;
+ dcterms:modified "2026-02-06"^^xsd:date ;
+ owl:versionInfo "0.7" ;
+ owl:versionIRI ;
+ rdfs:seeAlso ,
+ .
+
+# =============================================================================
+# PROFILE CONSTRAINTS (documentation of ODRL usage)
+# =============================================================================
+# Adalbert fixes odrl:conflict to odrl:prohibit (declared at profile level in adalbert-prof.ttl).
+# Adalbert does not use: odrl:Ticket, odrl:Request, odrl:AssetCollection,
+# odrl:PartyCollection, odrl:remedy, odrl:consequence, odrl:xone.
+
+# =============================================================================
+# LIFECYCLE STATE (genuinely new)
+# =============================================================================
+
+adalbert:State a owl:Class ;
+ rdfs:label "State"@en ;
+ skos:definition "Unified lifecycle state for duties and contracts."@en ;
+ owl:oneOf (adalbert:Pending adalbert:Active adalbert:Fulfilled adalbert:Violated) ;
+ rdfs:comment """
+ Four states cover both duty and contract lifecycles.
+
+ On duties (evaluated during Eval):
+ - Pending: condition not yet satisfied
+ - Active: condition met, action required
+ - Fulfilled: action performed
+ - Violated: deadline passed without performance
+
+ On contracts/subscriptions (administrative, not evaluated at request time):
+ - Pending: not yet in force
+ - Active: in force
+ - Fulfilled: obligations complete
+ - Violated: breached
+
+ Unified by design: the same four transitions apply to both domains,
+ and a single state property avoids proliferating parallel enums.
+ The formal semantics (§4.1) tracks only duty state during evaluation;
+ contract state is managed by external administrative processes.
+ """@en .
+
+adalbert:Pending a adalbert:State ;
+ rdfs:label "Pending"@en ;
+ skos:definition "Condition not yet satisfied; not yet in force."@en .
+
+adalbert:Active a adalbert:State ;
+ rdfs:label "Active"@en ;
+ skos:definition "Condition satisfied, action required; in force."@en .
+
+adalbert:Fulfilled a adalbert:State ;
+ rdfs:label "Fulfilled"@en ;
+ skos:definition "Action performed; obligations complete."@en .
+
+adalbert:Violated a adalbert:State ;
+ rdfs:label "Violated"@en ;
+ skos:definition "Deadline passed without performance; breached."@en .
+
+adalbert:state a owl:ObjectProperty ;
+ rdfs:label "state"@en ;
+ skos:definition "Current lifecycle state."@en ;
+ rdfs:domain [ owl:unionOf (odrl:Duty adalbert:DataContract adalbert:Subscription) ] ;
+ rdfs:range adalbert:State .
+
+# =============================================================================
+# DEADLINE (genuinely new)
+# =============================================================================
+
+adalbert:deadline a owl:DatatypeProperty ;
+ rdfs:label "deadline"@en ;
+ skos:definition "Time constraint for duty fulfillment."@en ;
+ rdfs:domain odrl:Duty ;
+ rdfs:comment """
+ Supports multiple forms:
+ - xsd:dateTime: absolute deadline (e.g., 2026-12-31T23:59:59Z)
+ - xsd:duration: relative to activation (e.g., P30D, PT24H)
+
+ For duration: deadline = activationTime + duration.
+ No rdfs:range declared because the range is a union of datatypes;
+ SHACL enforces the allowed types.
+ """@en .
+
+# =============================================================================
+# RECURRENCE (genuinely new)
+# =============================================================================
+
+adalbert:recurrence a owl:DatatypeProperty ;
+ rdfs:label "recurrence"@en ;
+ skos:definition "RFC 5545 RRULE defining when duty instances are generated."@en ;
+ rdfs:domain odrl:Duty ;
+ rdfs:range xsd:string ;
+ rdfs:comment """
+ An RFC 5545 RRULE string (e.g., FREQ=DAILY;BYHOUR=6;BYMINUTE=0).
+ Defines the schedule on which duty instances are created.
+ Each instance follows the standard duty lifecycle independently.
+ The deadline property defines the per-instance fulfillment window.
+ Any iCal-compliant library can parse the value.
+ """@en .
+
+# =============================================================================
+# CONTRACT CLASSES (genuinely new — domain subtypes)
+# =============================================================================
+
+adalbert:DataContract a owl:Class ;
+ rdfs:label "Data Contract"@en ;
+ skos:definition "Policy offer defining data access terms."@en ;
+ rdfs:subClassOf odrl:Offer ;
+ rdfs:comment """
+ A DataContract is an Offer from a data provider.
+ It defines permissions, duties, and prohibitions for data access.
+
+ When accepted (subscribed), becomes a Subscription (Agreement).
+ """@en .
+
+adalbert:Subscription a owl:Class ;
+ rdfs:label "Subscription"@en ;
+ skos:definition "Activated data contract binding provider and consumer."@en ;
+ rdfs:subClassOf odrl:Agreement ;
+ owl:disjointWith adalbert:DataContract ;
+ rdfs:comment """
+ A Subscription is an activated DataContract.
+ - assigner: data provider (from contract)
+ - assignee: data consumer (subscriber)
+
+ Bilateral: both parties may have active duties.
+ """@en .
+
+# =============================================================================
+# CONTRACT PROPERTIES (genuinely new)
+# =============================================================================
+
+adalbert:subscribesTo a owl:ObjectProperty ;
+ rdfs:label "subscribes to"@en ;
+ skos:definition "The contract this subscription activates."@en ;
+ rdfs:domain adalbert:Subscription ;
+ rdfs:range adalbert:DataContract .
+
+adalbert:effectiveDate a owl:DatatypeProperty ;
+ rdfs:label "effective date"@en ;
+ skos:definition "When the contract/subscription becomes effective."@en ;
+ rdfs:domain [ owl:unionOf (adalbert:DataContract adalbert:Subscription) ] ;
+ rdfs:range xsd:dateTime .
+
+adalbert:expirationDate a owl:DatatypeProperty ;
+ rdfs:label "expiration date"@en ;
+ skos:definition "When the contract/subscription expires."@en ;
+ rdfs:domain [ owl:unionOf (adalbert:DataContract adalbert:Subscription) ] ;
+ rdfs:range xsd:dateTime .
+
+# =============================================================================
+# HIERARCHY EXTENSIONS (genuinely new)
+# =============================================================================
+
+adalbert:partOf a owl:ObjectProperty, owl:TransitiveProperty ;
+ rdfs:label "part of"@en ;
+ skos:definition "Asset contained in larger asset."@en ;
+ rdfs:subPropertyOf odrl:partOf ;
+ rdfs:domain odrl:Asset ;
+ rdfs:range odrl:Asset ;
+ rdfs:comment "Transitive asset hierarchy. Bridges to ODRL via rdfs:subPropertyOf odrl:partOf — ODRL processors with RDFS reasoning can interpret Adalbert hierarchies. Transitivity and typed domains are Adalbert additions not inherited by the base property."@en .
+
+adalbert:memberOf a owl:ObjectProperty, owl:TransitiveProperty ;
+ rdfs:label "member of"@en ;
+ skos:definition "Party member of group/organization."@en ;
+ rdfs:subPropertyOf odrl:partOf ;
+ rdfs:domain odrl:Party ;
+ rdfs:range odrl:Party ;
+ rdfs:comment "Transitive party hierarchy. Bridges to ODRL via rdfs:subPropertyOf odrl:partOf — ODRL processors with RDFS reasoning can interpret Adalbert hierarchies. Transitivity and typed domains are Adalbert additions not inherited by the base property."@en .
+
+# =============================================================================
+# DUTY PARTY ROLES (genuinely new)
+# =============================================================================
+
+adalbert:subject a owl:ObjectProperty ;
+ rdfs:label "subject"@en ;
+ skos:definition "Party bearing the duty (must perform the action)."@en ;
+ rdfs:subPropertyOf odrl:assignee ;
+ rdfs:domain odrl:Duty ;
+ rdfs:range odrl:Party ;
+ rdfs:comment "The duty bearer. Bridges to ODRL via rdfs:subPropertyOf odrl:assignee (itself a sub-property of odrl:function). Aligns with md:subject (W3C Market Data) and rl2:subject."@en .
+
+adalbert:object a owl:ObjectProperty ;
+ rdfs:label "object"@en ;
+ skos:definition "Party affected by the duty action."@en ;
+ rdfs:subPropertyOf odrl:function ;
+ rdfs:domain odrl:Duty ;
+ rdfs:range odrl:Party ;
+ rdfs:comment "The party affected by or receiving the result of the duty action (e.g., who is notified, who receives the report). Bridges to ODRL via rdfs:subPropertyOf odrl:function. Generic alternative to ODRL Common Vocabulary party functions (informedParty, compensatedParty, etc.) — use those when the specific semantics fits, use adalbert:object for consistency or when no specific function applies. Aligns with md:object (W3C Market Data) and rl2:counterparty."@en .
+
+# =============================================================================
+# OPERAND RESOLUTION (genuinely new)
+# =============================================================================
+
+adalbert:resolutionPath a owl:DatatypeProperty ;
+ rdfs:label "resolution path"@en ;
+ skos:definition "Dot-separated path from canonical root to value."@en ;
+ rdfs:domain odrl:LeftOperand ;
+ rdfs:range xsd:string ;
+ rdfs:comment """
+ Path must start with a canonical root: agent, asset, context.
+ Examples: agent.role, asset.classification, context.purpose.
+ Resolution: resolve(path, Env) -> Value
+ """@en .
+
+# =============================================================================
+# RUNTIME REFERENCES (genuinely new)
+# =============================================================================
+
+adalbert:RuntimeReference a owl:Class ;
+ rdfs:label "Runtime Reference"@en ;
+ skos:definition "Value resolved at evaluation time."@en .
+
+adalbert:currentAgent a adalbert:RuntimeReference, odrl:Party ;
+ rdfs:label "current agent"@en ;
+ skos:definition "The requesting agent."@en ;
+ rdfs:comment """
+ Reserved for constraint identity comparisons. Runtime resolution
+ in right-operand position requires RL2 (rl2:rightOperandRef).
+ Typed as both RuntimeReference and odrl:Party for ODRL processor
+ compatibility. For rules applying to any requesting agent, omit
+ odrl:assignee (standard ODRL); do not use currentAgent as assignee.
+ """@en .
+
+adalbert:currentDateTime a odrl:LeftOperand, adalbert:RuntimeReference ;
+ rdfs:label "current date time"@en ;
+ skos:definition "Evaluation timestamp."@en ;
+ rdfs:seeAlso odrl:dateTime ;
+ rdfs:comment "Equivalent to odrl:dateTime in constraint evaluation. Dual-typed as RuntimeReference to enable resolution at evaluation time."@en .
+
+# =============================================================================
+# LOGICAL NEGATION (genuinely new — ODRL lacks this)
+# =============================================================================
+
+adalbert:not a owl:ObjectProperty ;
+ rdfs:label "not"@en ;
+ skos:definition "Logical negation on a constraint."@en ;
+ rdfs:domain odrl:LogicalConstraint ;
+ rdfs:range [ owl:unionOf (odrl:Constraint odrl:LogicalConstraint) ] ;
+ rdfs:comment """
+ ODRL defines odrl:and and odrl:or on LogicalConstraint but lacks
+ negation. Adalbert adds adalbert:not following the same pattern:
+ _:lc a odrl:LogicalConstraint ;
+ adalbert:not _:c1 .
+ """@en .
+
+# =============================================================================
+# END OF ONTOLOGY
+# =============================================================================
diff --git a/adalbert-contracts/adalbert-due.ttl b/adalbert-contracts/adalbert-due.ttl
new file mode 100644
index 0000000..b027dd3
--- /dev/null
+++ b/adalbert-contracts/adalbert-due.ttl
@@ -0,0 +1,597 @@
+# =============================================================================
+# Adalbert Data Use Profile (DUE)
+# Version: 0.7
+# Date: 2026-02-03
+# =============================================================================
+# Complete data governance vocabulary: operands, actions, concept values.
+#
+# All operands are typed as odrl:LeftOperand (not adalbert:LeftOperand).
+# Actions from ODRL Common Vocabulary are used directly (odrl:use, odrl:read,
+# odrl:display, odrl:distribute, odrl:delete, odrl:modify, odrl:aggregate,
+# odrl:anonymize, odrl:derive). DUE-only actions use the adalbert-due: prefix.
+# Action hierarchy uses odrl:includedIn.
+# Operand resolution uses adalbert:resolutionPath (Adalbert extension).
+# =============================================================================
+
+@prefix adalbert: .
+@prefix adalbert-due: .
+@prefix odrl: .
+@prefix skos: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix owl: .
+@prefix xsd: .
+@prefix dcterms: .
+@prefix org: .
+
+# =============================================================================
+# PROFILE DECLARATION
+# =============================================================================
+
+ a owl:Ontology ;
+ dcterms:title "Adalbert Data Use Profile"@en ;
+ dcterms:description """
+ Complete data governance vocabulary for Adalbert.
+
+ Covers:
+ - Purpose and classification constraints
+ - Asset metadata (class, market, benchmark)
+ - Jurisdiction and residency requirements
+ - Retention and processing controls
+ - Audit and logging requirements
+ - Identity and access control (role, org, project)
+ - Environment and network constraints
+ - Data freshness (timeliness, delay)
+ - Usage modes (display, non-display, derive)
+ - Derivation constraints (commingled, non-substitutive)
+ - Consent and legal basis
+ - Obligation actions (reporting, delivery, notification)
+
+ Actions from ODRL Common Vocabulary are used directly (odrl:use,
+ odrl:read, odrl:display, etc.). DUE adds domain-specific actions
+ (nonDisplay, conformTo, log, notify, report, deliver, etc.).
+ All operands are odrl:LeftOperand with adalbert:resolutionPath.
+ """@en ;
+ dcterms:created "2026-02-03"^^xsd:date ;
+ owl:versionInfo "0.7" ;
+ owl:imports .
+
+# =============================================================================
+# CONCEPT SCHEME
+# =============================================================================
+
+adalbert-due:scheme a skos:ConceptScheme ;
+ rdfs:label "Adalbert DUE Vocabulary"@en ;
+ skos:definition "Concept scheme for the Adalbert Data Use vocabulary."@en .
+
+# =============================================================================
+# PURPOSE OPERANDS
+# =============================================================================
+
+odrl:purpose adalbert:resolutionPath "context.purpose" ;
+ rdfs:comment "Purpose values are skos:Concept instances. Add skos:broader links when a purpose hierarchy is needed."@en .
+
+# Purpose taxonomy
+adalbert-due:analytics a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "analytics"@en ;
+ skos:definition "General analytical use."@en .
+
+adalbert-due:research a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "research"@en ;
+ skos:definition "Research and development."@en .
+
+adalbert-due:compliance a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "compliance"@en ;
+ skos:definition "Regulatory compliance."@en .
+
+adalbert-due:operations a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "operations"@en ;
+ skos:definition "Operational use."@en .
+
+# =============================================================================
+# CLASSIFICATION OPERANDS
+# =============================================================================
+
+adalbert-due:classification a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "classification"@en ;
+ skos:definition "Data classification level."@en ;
+ adalbert:resolutionPath "asset.classification" .
+
+adalbert-due:sensitivity a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "sensitivity"@en ;
+ skos:definition "Data sensitivity type."@en ;
+ adalbert:resolutionPath "asset.sensitivity" .
+
+# Classification values
+adalbert-due:public a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "public"@en .
+adalbert-due:internal a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "internal"@en .
+adalbert-due:confidential a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "confidential"@en .
+adalbert-due:restricted a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "restricted"@en .
+
+# Sensitivity values
+adalbert-due:pii a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "PII"@en ;
+ skos:definition "Personally Identifiable Information."@en .
+adalbert-due:mnpi a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "MNPI"@en ;
+ skos:definition "Material Non-Public Information."@en .
+adalbert-due:phi a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "PHI"@en ;
+ skos:definition "Protected Health Information."@en .
+
+# =============================================================================
+# ASSET METADATA OPERANDS
+# =============================================================================
+
+adalbert-due:assetClass a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "asset class"@en ;
+ skos:definition "Financial instrument or data classification."@en ;
+ adalbert:resolutionPath "asset.class" ;
+ rdfs:comment "E.g., equity, fixed-income, fx, commodity, reference."@en .
+
+adalbert-due:market a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "market"@en ;
+ skos:definition "Trading venue or market of origin."@en ;
+ adalbert:resolutionPath "asset.market" ;
+ rdfs:comment "E.g., NYSE, LSE, CME, OTC."@en .
+
+adalbert-due:isBenchmark a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "is benchmark"@en ;
+ skos:definition "Whether asset is a benchmark or index."@en ;
+ adalbert:resolutionPath "asset.isBenchmark" ;
+ rdfs:comment "Benchmarks often have stricter usage constraints."@en .
+
+# =============================================================================
+# JURISDICTION OPERANDS
+# =============================================================================
+
+adalbert-due:jurisdiction a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "jurisdiction"@en ;
+ skos:definition "Legal jurisdiction governing data use."@en ;
+ adalbert:resolutionPath "context.jurisdiction" .
+
+adalbert-due:residency a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "residency"@en ;
+ skos:definition "Data residency location."@en ;
+ adalbert:resolutionPath "asset.residency" .
+
+# =============================================================================
+# TEMPORAL OPERANDS
+# =============================================================================
+
+adalbert-due:retentionPeriod a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "retention period"@en ;
+ skos:definition "Maximum time data may be retained."@en ;
+ adalbert:resolutionPath "asset.retentionPeriod" .
+
+adalbert-due:expiry a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "expiry"@en ;
+ skos:definition "Expiration date of the policy."@en ;
+ adalbert:resolutionPath "asset.expiry" .
+
+# =============================================================================
+# PROCESSING OPERANDS
+# =============================================================================
+
+adalbert-due:processingMode a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "processing mode"@en ;
+ skos:definition "How data is processed."@en ;
+ adalbert:resolutionPath "context.processingMode" .
+
+adalbert-due:human a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "human"@en .
+adalbert-due:automated a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "automated"@en .
+adalbert-due:modelTraining a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "model training"@en .
+adalbert-due:inference a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "inference"@en .
+
+# =============================================================================
+# AUDIT OPERANDS
+# =============================================================================
+
+adalbert-due:auditRequired a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "audit required"@en ;
+ skos:definition "Whether audit logging is required."@en ;
+ adalbert:resolutionPath "asset.auditRequired" .
+
+# =============================================================================
+# IDENTITY OPERANDS
+# =============================================================================
+
+adalbert-due:role a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "role"@en ;
+ skos:definition "Role of the requesting agent."@en ;
+ adalbert:resolutionPath "agent.role" .
+
+adalbert-due:organization a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "organization"@en ;
+ skos:definition "Organization of the requesting agent."@en ;
+ adalbert:resolutionPath "agent.organization" ;
+ rdfs:comment "Hierarchy via org:subOrganizationOf."@en .
+
+adalbert-due:costCenter a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "cost center"@en ;
+ skos:definition "Cost center of the requesting agent."@en ;
+ adalbert:resolutionPath "agent.costCenter" .
+
+adalbert-due:project a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "project"@en ;
+ skos:definition "Project context of the request."@en ;
+ adalbert:resolutionPath "context.project" .
+
+adalbert-due:recipientType a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "recipient type"@en ;
+ skos:definition "Type of data recipient."@en ;
+ adalbert:resolutionPath "agent.recipientType" ;
+ rdfs:comment "E.g., internal, external, professional, retail."@en .
+
+# Recipient type values
+adalbert-due:internalRecipient a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "internal recipient"@en ;
+ skos:definition "Recipient within the same organization."@en .
+adalbert-due:externalRecipient a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "external recipient"@en ;
+ skos:definition "Recipient outside the organization."@en .
+adalbert-due:professional a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "professional"@en ;
+ skos:definition "Licensed professional user."@en .
+adalbert-due:retail a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "retail"@en ;
+ skos:definition "Retail/individual user."@en .
+
+# =============================================================================
+# ENVIRONMENT OPERANDS
+# =============================================================================
+
+adalbert-due:environment a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "environment"@en ;
+ skos:definition "Execution environment."@en ;
+ adalbert:resolutionPath "context.environment" .
+
+adalbert-due:production a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "production"@en .
+adalbert-due:staging a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "staging"@en .
+adalbert-due:development a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "development"@en .
+adalbert-due:sandbox a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "sandbox"@en .
+
+adalbert-due:network a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "network"@en ;
+ skos:definition "Network zone of the request."@en ;
+ adalbert:resolutionPath "context.network" .
+
+adalbert-due:internalNetwork a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "internal network"@en .
+adalbert-due:externalNetwork a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "external network"@en .
+adalbert-due:cloudNetwork a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "cloud network"@en .
+
+# =============================================================================
+# SERVICE LEVEL OPERANDS
+# =============================================================================
+
+adalbert-due:availability a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "availability"@en ;
+ skos:definition "Service availability percentage."@en ;
+ adalbert:resolutionPath "context.availability" ;
+ rdfs:comment "Typically measured as uptime percentage over a period (e.g., 99.9%)."@en .
+
+adalbert-due:latency a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "latency"@en ;
+ skos:definition "Response latency at a given percentile."@en ;
+ adalbert:resolutionPath "context.latency" ;
+ rdfs:comment "Measured as duration (e.g., P99 latency <= PT0.2S)."@en .
+
+adalbert-due:throughput a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "throughput"@en ;
+ skos:definition "Request throughput capacity."@en ;
+ adalbert:resolutionPath "context.throughput" ;
+ rdfs:comment "Measured in requests per second."@en .
+
+# =============================================================================
+# DATA QUALITY OPERANDS
+# =============================================================================
+
+adalbert-due:completeness a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "completeness"@en ;
+ skos:definition "Data completeness percentage."@en ;
+ adalbert:resolutionPath "asset.completeness" ;
+ rdfs:comment "Percentage of non-null required fields."@en .
+
+adalbert-due:accuracy a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "accuracy"@en ;
+ skos:definition "Data accuracy percentage."@en ;
+ adalbert:resolutionPath "asset.accuracy" ;
+ rdfs:comment "Percentage of records passing validation rules."@en .
+
+# =============================================================================
+# TIMELINESS OPERANDS
+# =============================================================================
+
+adalbert-due:timeliness a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "timeliness"@en ;
+ skos:definition "Required data freshness category."@en ;
+ adalbert:resolutionPath "asset.timeliness" .
+
+adalbert-due:delayMinutes a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "delay minutes"@en ;
+ skos:definition "Maximum acceptable delay in minutes."@en ;
+ adalbert:resolutionPath "asset.delayMinutes" .
+
+# Timeliness values
+adalbert-due:realtime a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "real-time"@en ;
+ skos:definition "Data with minimal latency (sub-second)."@en .
+adalbert-due:nearRealtime a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "near real-time"@en ;
+ skos:definition "Data with short delay (seconds to minutes)."@en .
+adalbert-due:delayed a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "delayed"@en ;
+ skos:definition "Data with significant delay (15+ minutes)."@en .
+adalbert-due:endOfDay a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "end of day"@en ;
+ skos:definition "Data available after market close."@en .
+adalbert-due:historical a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "historical"@en ;
+ skos:definition "Historical/archived data."@en .
+
+# =============================================================================
+# CONSENT AND LEGAL BASIS
+# =============================================================================
+
+adalbert-due:legalBasis a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "legal basis"@en ;
+ skos:definition "Legal basis for processing."@en ;
+ adalbert:resolutionPath "context.legalBasis" .
+
+adalbert-due:consent a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "consent"@en .
+adalbert-due:contract a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "contract"@en .
+adalbert-due:legalObligation a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "legal obligation"@en .
+adalbert-due:vitalInterest a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "vital interest"@en .
+adalbert-due:publicTask a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "public task"@en .
+adalbert-due:legitimateInterest a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "legitimate interest"@en .
+
+adalbert-due:consentId a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "consent ID"@en ;
+ skos:definition "Reference to consent record."@en ;
+ adalbert:resolutionPath "context.consentId" .
+
+# =============================================================================
+# ACCESS PATTERN OPERANDS
+# =============================================================================
+
+adalbert-due:accessPattern a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "access pattern"@en ;
+ skos:definition "Type of data access."@en ;
+ adalbert:resolutionPath "context.accessPattern" .
+
+adalbert-due:batch a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "batch"@en .
+adalbert-due:streaming a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "streaming"@en .
+adalbert-due:interactive a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "interactive"@en .
+adalbert-due:api a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "API"@en .
+
+adalbert-due:volumeLimit a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "volume limit"@en ;
+ skos:definition "Maximum data volume per request."@en ;
+ adalbert:resolutionPath "context.volumeLimit" .
+
+adalbert-due:rateLimit a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "rate limit"@en ;
+ skos:definition "Maximum requests per time period."@en ;
+ adalbert:resolutionPath "context.rateLimit" .
+
+# =============================================================================
+# CHANNEL OPERANDS
+# =============================================================================
+
+adalbert-due:channel a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "channel"@en ;
+ skos:definition "Communication or delivery channel."@en ;
+ adalbert:resolutionPath "context.channel" ;
+ rdfs:comment "E.g., email, chat, phone, api, sftp."@en .
+
+adalbert-due:serviceWindow a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "service window"@en ;
+ skos:definition "Time window during which a service is available."@en ;
+ adalbert:resolutionPath "context.serviceWindow" ;
+ rdfs:comment "E.g., business-hours, 24x7, weekdays."@en .
+
+# =============================================================================
+# SUBSCRIPTION OPERANDS
+# =============================================================================
+
+adalbert-due:subscriptionTier a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "subscription tier"@en ;
+ skos:definition "Access tier or subscription level."@en ;
+ adalbert:resolutionPath "context.subscriptionTier" ;
+ rdfs:comment "E.g., free, basic, premium, enterprise."@en .
+
+# =============================================================================
+# DERIVATION OPERANDS
+# =============================================================================
+
+adalbert-due:derivationType a odrl:LeftOperand, skos:Concept ;
+ rdfs:label "derivation type"@en ;
+ skos:definition "Type of derivation being performed."@en ;
+ adalbert:resolutionPath "context.derivationType" .
+
+adalbert-due:commingled a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "commingled"@en ;
+ skos:definition "Derived data mixed with other sources."@en .
+adalbert-due:nonSubstitutive a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "non-substitutive"@en ;
+ skos:definition "Derived data cannot substitute for original."@en .
+adalbert-due:newProduct a skos:Concept ;
+ skos:inScheme adalbert-due:scheme ;
+ rdfs:label "new product"@en ;
+ skos:definition "Substantially transformed into new product."@en .
+
+# =============================================================================
+# ODRL COMMON VOCABULARY ACTIONS (used directly)
+# =============================================================================
+# These actions come from ODRL 2.2 Common Vocabulary. DUE uses them directly
+# rather than redefining them. ODRL already defines their includedIn hierarchy.
+#
+# odrl:use — General use (top of hierarchy)
+# odrl:read — Read/view (includedIn odrl:use)
+# odrl:display — Display to human users (includedIn odrl:use)
+# odrl:distribute — Distribute to third parties (includedIn odrl:use)
+# odrl:delete — Delete the asset (includedIn odrl:use)
+# odrl:modify — Modify the asset (includedIn odrl:use)
+# odrl:aggregate — Aggregate with other data (includedIn odrl:use)
+# odrl:anonymize — Remove identifying information (includedIn odrl:use)
+# odrl:derive — Create derived data (includedIn odrl:use)
+
+# =============================================================================
+# DUE-SPECIFIC ACTIONS (no ODRL equivalent)
+# =============================================================================
+
+adalbert-due:nonDisplay a odrl:Action, skos:Concept ;
+ rdfs:label "non-display"@en ;
+ skos:definition "Use data for automated/programmatic purposes."@en ;
+ odrl:includedIn odrl:use ;
+ rdfs:comment "Algorithmic use: models, automation, calculations."@en .
+
+adalbert-due:conformTo a odrl:Action, skos:Concept ;
+ rdfs:label "conform to"@en ;
+ skos:definition "Conform to a schema or specification."@en ;
+ rdfs:seeAlso dcterms:conformsTo ;
+ rdfs:comment """Provider governance duty: ensure data conforms to published schema.
+ The duty target (odrl:target) is the schema/specification — the same resource
+ that dct:conformsTo would point to as a static metadata assertion. conformTo
+ is the operational counterpart: an ongoing obligation to maintain conformance.
+ No odrl:includedIn — conformTo is a duty-only action (schema/quality SLA).
+ The includedIn hierarchy governs permission subsumption (granting odrl:use
+ implicitly grants sub-actions). conformTo never appears in permissions, so
+ chaining it to odrl:use would create a false subsumption."""@en .
+
+adalbert-due:log a odrl:Action, skos:Concept ;
+ rdfs:label "log"@en ;
+ skos:definition "Log access to the asset."@en ;
+ odrl:includedIn odrl:inform .
+
+adalbert-due:notify a odrl:Action, skos:Concept ;
+ rdfs:label "notify"@en ;
+ skos:definition "Notify relevant parties."@en ;
+ odrl:includedIn odrl:inform .
+
+adalbert-due:report a odrl:Action, skos:Concept ;
+ rdfs:label "report"@en ;
+ skos:definition "Submit usage reports."@en ;
+ odrl:includedIn odrl:inform ;
+ rdfs:comment "Typically an assignee duty: report usage to data owner."@en .
+
+adalbert-due:deliver a odrl:Action, skos:Concept ;
+ rdfs:label "deliver"@en ;
+ skos:definition "Deliver data to consumer."@en ;
+ odrl:includedIn odrl:distribute ;
+ rdfs:comment "Typically an assigner duty in data contracts."@en .
+
+# =============================================================================
+# SPECIALIZED ACTIONS
+# =============================================================================
+
+adalbert-due:calculateIndex a odrl:Action, skos:Concept ;
+ rdfs:label "calculate index"@en ;
+ skos:definition "Use data for index/benchmark calculation."@en ;
+ odrl:includedIn odrl:derive .
+
+adalbert-due:algorithmicTrading a odrl:Action, skos:Concept ;
+ rdfs:label "algorithmic trading"@en ;
+ skos:definition "Use data for automated trading decisions."@en ;
+ odrl:includedIn adalbert-due:nonDisplay .
+
+# =============================================================================
+# DATA MANIPULATION ACTIONS
+# =============================================================================
+
+adalbert-due:query a odrl:Action, skos:Concept ;
+ rdfs:label "query"@en ;
+ skos:definition "Query/select data."@en ;
+ odrl:includedIn odrl:read .
+
+adalbert-due:export a odrl:Action, skos:Concept ;
+ rdfs:label "export"@en ;
+ skos:definition "Export data outside the system."@en ;
+ odrl:includedIn odrl:distribute .
+
+adalbert-due:copy a odrl:Action, skos:Concept ;
+ rdfs:label "copy"@en ;
+ skos:definition "Copy data to another location."@en ;
+ odrl:includedIn odrl:reproduce .
+
+adalbert-due:link a odrl:Action, skos:Concept ;
+ rdfs:label "link"@en ;
+ skos:definition "Link/join with other datasets."@en ;
+ odrl:includedIn odrl:aggregate .
+
+adalbert-due:profile a odrl:Action, skos:Concept ;
+ rdfs:label "profile"@en ;
+ skos:definition "Create profiles from data."@en ;
+ odrl:includedIn odrl:derive .
+
+# =============================================================================
+# END OF PROFILE
+# =============================================================================
diff --git a/adalbert-contracts/adalbert-prof.ttl b/adalbert-contracts/adalbert-prof.ttl
new file mode 100644
index 0000000..ca0f0aa
--- /dev/null
+++ b/adalbert-contracts/adalbert-prof.ttl
@@ -0,0 +1,88 @@
+# =============================================================================
+# Adalbert Profile Declaration (DXPROF)
+# Version: 0.7
+# Date: 2026-02-04
+# =============================================================================
+# W3C Profiles Vocabulary metadata for Adalbert.
+# Adalbert is a proper ODRL 2.2 profile — it uses ODRL terms and adds
+# only genuinely new extensions.
+# =============================================================================
+
+@prefix adalbert: .
+@prefix prof: .
+@prefix role: .
+@prefix dct: .
+@prefix odrl: .
+@prefix owl: .
+@prefix xsd: .
+
+# =============================================================================
+# BASE SPECIFICATION
+# =============================================================================
+
+odrl:core a dct:Standard ;
+ dct:title "ODRL Information Model 2.2"@en ;
+ dct:identifier .
+
+# =============================================================================
+# Adalbert CORE PROFILE
+# =============================================================================
+
+ a prof:Profile ;
+ dct:title "Adalbert Core"@en ;
+ dct:description """
+ Proper ODRL 2.2 profile for deterministic data governance.
+ Uses ODRL terms for standard constructs; adds lifecycle state,
+ deadline, recurrence, data contracts, hierarchy extensions,
+ operand resolution, runtime references, and logical negation.
+ """@en ;
+ prof:isProfileOf odrl:core ;
+ prof:hasToken "adalbert"^^xsd:token ;
+ odrl:conflict odrl:prohibit ;
+
+ prof:hasResource [
+ a prof:ResourceDescriptor ;
+ dct:title "Adalbert Specification"@en ;
+ prof:hasRole role:specification ;
+ prof:hasArtifact
+ ] , [
+ a prof:ResourceDescriptor ;
+ dct:title "Adalbert Formal Semantics"@en ;
+ prof:hasRole role:specification ;
+ prof:hasArtifact
+ ] , [
+ a prof:ResourceDescriptor ;
+ dct:title "Adalbert Core Ontology"@en ;
+ prof:hasRole role:vocabulary ;
+ dct:conformsTo ;
+ prof:hasArtifact
+ ] , [
+ a prof:ResourceDescriptor ;
+ dct:title "Adalbert SHACL Shapes"@en ;
+ prof:hasRole role:validation ;
+ dct:conformsTo ;
+ prof:hasArtifact
+ ] .
+
+# =============================================================================
+# DATA USE PROFILE
+# =============================================================================
+
+ a prof:Profile ;
+ dct:title "Adalbert Data Use (DUE)"@en ;
+ dct:description "Complete data governance vocabulary: operands, actions, concept values."@en ;
+ prof:isProfileOf ;
+ prof:isTransitiveProfileOf odrl:core ;
+ prof:hasToken "adalbert-due"^^xsd:token ;
+
+ prof:hasResource [
+ a prof:ResourceDescriptor ;
+ dct:title "Adalbert DUE Vocabulary"@en ;
+ prof:hasRole role:vocabulary ;
+ dct:conformsTo ;
+ prof:hasArtifact
+ ] .
+
+# =============================================================================
+# END
+# =============================================================================
diff --git a/adalbert-contracts/adalbert-shacl.ttl b/adalbert-contracts/adalbert-shacl.ttl
new file mode 100644
index 0000000..5fd4f36
--- /dev/null
+++ b/adalbert-contracts/adalbert-shacl.ttl
@@ -0,0 +1,552 @@
+# =============================================================================
+# Adalbert SHACL Shapes
+# Version: 0.7
+# Date: 2026-02-04
+# =============================================================================
+# Validation shapes for Adalbert policies.
+# All shapes target ODRL classes and use ODRL properties.
+# Adalbert-specific extensions are validated where they appear on ODRL types.
+# =============================================================================
+
+@prefix adalbert: .
+@prefix adalbert-due: .
+@prefix adalbertsh: .
+@prefix odrl: .
+@prefix sh: .
+@prefix xsd: .
+@prefix rdf: .
+@prefix rdfs: .
+
+# =============================================================================
+# REUSABLE PROPERTY GROUPS
+# =============================================================================
+
+adalbertsh:StatePropertyGroup
+ sh:path adalbert:state ;
+ sh:maxCount 1 ;
+ sh:in (adalbert:Pending adalbert:Active adalbert:Fulfilled adalbert:Violated) ;
+ sh:message "State must be Pending, Active, Fulfilled, or Violated." .
+
+adalbertsh:ProfilePropertyGroup
+ sh:path odrl:profile ;
+ sh:minCount 1 ;
+ sh:hasValue ;
+ sh:message "Adalbert policies must declare odrl:profile ." .
+
+adalbertsh:NonEmptyClausesConstraint a sh:NodeShape ;
+ sh:or (
+ [ sh:property [ sh:path odrl:permission ; sh:minCount 1 ] ]
+ [ sh:property [ sh:path odrl:prohibition ; sh:minCount 1 ] ]
+ [ sh:property [ sh:path odrl:obligation ; sh:minCount 1 ] ]
+ ) ;
+ sh:message "Policy must have at least one permission, prohibition, or obligation." .
+
+# =============================================================================
+# POLICY SHAPE — profile and conflict declaration
+# =============================================================================
+
+adalbertsh:PolicyShape a sh:NodeShape ;
+ sh:targetClass odrl:Policy ;
+ sh:name "Policy Shape" ;
+
+ sh:property [
+ sh:path odrl:profile ;
+ sh:minCount 1 ;
+ sh:hasValue ;
+ sh:message "Adalbert policies must declare odrl:profile ."
+ ] .
+
+# =============================================================================
+# SET SHAPE
+# =============================================================================
+
+adalbertsh:SetShape a sh:NodeShape ;
+ sh:targetClass odrl:Set ;
+ sh:name "Set Shape" ;
+
+ sh:property adalbertsh:ProfilePropertyGroup ;
+
+ sh:node adalbertsh:NonEmptyClausesConstraint ;
+
+ # odrl:target is optional on Sets (formal semantics: Asset?).
+ # When present, inherited by rules that omit their own target.
+ sh:property [
+ sh:path odrl:target ;
+ sh:message "Set policy may declare a policy-level target (inherited by rules)."
+ ] .
+
+# =============================================================================
+# OFFER SHAPE
+# =============================================================================
+
+adalbertsh:OfferShape a sh:NodeShape ;
+ sh:targetClass odrl:Offer ;
+ sh:name "Offer Shape" ;
+
+ sh:property adalbertsh:ProfilePropertyGroup ;
+
+ sh:node adalbertsh:NonEmptyClausesConstraint ;
+
+ # Offer requires assigner
+ sh:property [
+ sh:path odrl:assigner ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Offer must have exactly one assigner."
+ ] .
+
+# =============================================================================
+# AGREEMENT SHAPE
+# =============================================================================
+
+adalbertsh:AgreementShape a sh:NodeShape ;
+ sh:targetClass odrl:Agreement ;
+ sh:name "Agreement Shape" ;
+
+ sh:property adalbertsh:ProfilePropertyGroup ;
+
+ sh:node adalbertsh:NonEmptyClausesConstraint ;
+
+ sh:property [
+ sh:path odrl:assigner ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Agreement must have exactly one assigner."
+ ] ;
+
+ sh:property [
+ sh:path odrl:assignee ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Agreement must have exactly one assignee."
+ ] .
+
+# =============================================================================
+# PERMISSION SHAPE
+# =============================================================================
+
+adalbertsh:PermissionShape a sh:NodeShape ;
+ sh:targetClass odrl:Permission ;
+ sh:name "Permission Shape" ;
+
+ sh:property [
+ sh:path odrl:action ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Permission must have exactly one action."
+ ] ;
+
+ sh:property [
+ sh:path odrl:target ;
+ sh:maxCount 1 ;
+ sh:message "Permission may have at most one target (inherits from policy if absent)."
+ ] .
+
+# =============================================================================
+# PROHIBITION SHAPE
+# =============================================================================
+
+adalbertsh:ProhibitionShape a sh:NodeShape ;
+ sh:targetClass odrl:Prohibition ;
+ sh:name "Prohibition Shape" ;
+
+ sh:property [
+ sh:path odrl:action ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Prohibition must have exactly one action."
+ ] ;
+
+ sh:property [
+ sh:path odrl:target ;
+ sh:maxCount 1 ;
+ sh:message "Prohibition may have at most one target (inherits from policy if absent)."
+ ] .
+
+# =============================================================================
+# DUTY SHAPE
+# =============================================================================
+
+adalbertsh:DutyShape a sh:NodeShape ;
+ sh:targetClass odrl:Duty ;
+ sh:name "Duty Shape" ;
+
+ sh:property [
+ sh:path odrl:action ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Duty must have exactly one action."
+ ] ;
+
+ sh:property [
+ sh:path adalbert:deadline ;
+ sh:maxCount 1 ;
+ sh:or (
+ [ sh:datatype xsd:dateTime ]
+ [ sh:datatype xsd:duration ]
+ ) ;
+ sh:message "Deadline must be xsd:dateTime or xsd:duration."
+ ] ;
+
+ sh:property [
+ sh:path adalbert:recurrence ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:string ;
+ sh:pattern "^FREQ=(SECONDLY|MINUTELY|HOURLY|DAILY|WEEKLY|MONTHLY|YEARLY)" ;
+ sh:message "Recurrence must be a valid RFC 5545 RRULE starting with FREQ=."
+ ] ;
+
+ sh:property [
+ sh:path adalbert:subject ;
+ sh:maxCount 1 ;
+ sh:class odrl:Party ;
+ sh:message "Duty subject must be a single odrl:Party."
+ ] ;
+
+ sh:property [
+ sh:path adalbert:object ;
+ sh:maxCount 1 ;
+ sh:class odrl:Party ;
+ sh:message "Duty object must be a single odrl:Party."
+ ] ;
+
+ sh:property adalbertsh:StatePropertyGroup .
+
+# =============================================================================
+# CONSTRAINT SHAPE
+# =============================================================================
+
+adalbertsh:ConstraintShape a sh:NodeShape ;
+ sh:targetClass odrl:Constraint ;
+ sh:name "Constraint Shape" ;
+
+ sh:property [
+ sh:path odrl:leftOperand ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Constraint must have exactly one leftOperand."
+ ] ;
+
+ sh:property [
+ sh:path odrl:operator ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Constraint must have exactly one operator."
+ ] ;
+
+ sh:property [
+ sh:path odrl:rightOperand ;
+ sh:minCount 1 ;
+ sh:message "Constraint must have a rightOperand."
+ ] .
+
+# =============================================================================
+# LOGICAL CONSTRAINT SHAPE
+# =============================================================================
+
+adalbertsh:LogicalConstraintShape a sh:NodeShape ;
+ sh:targetClass odrl:LogicalConstraint ;
+ sh:name "Logical Constraint Shape" ;
+
+ # Must have exactly one of: odrl:and, odrl:or, adalbert:not
+ sh:xone (
+ [ sh:property [ sh:path odrl:and ; sh:minCount 1 ; sh:maxCount 1 ] ]
+ [ sh:property [ sh:path odrl:or ; sh:minCount 1 ; sh:maxCount 1 ] ]
+ [ sh:property [ sh:path adalbert:not ; sh:minCount 1 ; sh:maxCount 1 ] ]
+ ) ;
+ sh:message "LogicalConstraint must have exactly one of: odrl:and, odrl:or, or adalbert:not." .
+
+# =============================================================================
+# DATA CONTRACT SHAPE
+# =============================================================================
+
+adalbertsh:DataContractShape a sh:NodeShape ;
+ sh:targetClass adalbert:DataContract ;
+ sh:name "Data Contract Shape" ;
+
+ sh:property adalbertsh:ProfilePropertyGroup ;
+
+ sh:node adalbertsh:NonEmptyClausesConstraint ;
+
+ sh:property [
+ sh:path odrl:assigner ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "DataContract must have exactly one assigner."
+ ] ;
+
+ sh:property adalbertsh:StatePropertyGroup ;
+
+ sh:property [
+ sh:path adalbert:effectiveDate ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:dateTime
+ ] ;
+
+ sh:property [
+ sh:path adalbert:expirationDate ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:dateTime
+ ] .
+
+# =============================================================================
+# SUBSCRIPTION SHAPE
+# =============================================================================
+
+adalbertsh:SubscriptionShape a sh:NodeShape ;
+ sh:targetClass adalbert:Subscription ;
+ sh:name "Subscription Shape" ;
+
+ sh:property adalbertsh:ProfilePropertyGroup ;
+
+ sh:node adalbertsh:NonEmptyClausesConstraint ;
+
+ # Explicit party constraints — Subscription is subClassOf Agreement,
+ # but without RDFS entailment AgreementShape won't target Subscription
+ # instances. Duplicate the party requirements here.
+ sh:property [
+ sh:path odrl:assigner ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Subscription must have exactly one assigner (data provider)."
+ ] ;
+
+ sh:property [
+ sh:path odrl:assignee ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:message "Subscription must have exactly one assignee (data consumer)."
+ ] ;
+
+ sh:property [
+ sh:path adalbert:subscribesTo ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:class adalbert:DataContract ;
+ sh:message "Subscription must reference exactly one DataContract."
+ ] ;
+
+ sh:property adalbertsh:StatePropertyGroup ;
+
+ sh:property [
+ sh:path adalbert:effectiveDate ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:dateTime
+ ] ;
+
+ sh:property [
+ sh:path adalbert:expirationDate ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:dateTime
+ ] .
+
+# =============================================================================
+# LEFT OPERAND SHAPE
+# =============================================================================
+# sh:minCount 0: resolutionPath is optional in the shape because ODRL's
+# built-in left operands (odrl:dateTime, etc.) don't have it. Adalbert
+# profile operands MUST provide it — enforced by convention and DUE.
+#
+# The sh:pattern validates the root prefix only. Full path grammar enforcement
+# (identifier syntax, depth constraints, traversal rejection) is a runtime
+# concern per Adalbert_Semantics.md §6.2, not expressible in SHACL.
+
+adalbertsh:LeftOperandShape a sh:NodeShape ;
+ sh:targetClass odrl:LeftOperand ;
+ sh:name "Left Operand Shape" ;
+
+ sh:property [
+ sh:path adalbert:resolutionPath ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:string ;
+ sh:pattern "^(agent|asset|context)\\." ;
+ sh:message "resolutionPath must start with agent., asset., or context."
+ ] .
+
+# =============================================================================
+# DUE OPERAND SHAPE — enforce resolutionPath on all DUE operands
+# =============================================================================
+# Unlike generic LeftOperandShape (which allows absent resolutionPath for ODRL
+# built-in operands like odrl:dateTime), DUE operands MUST declare a path.
+#
+# Validation model: this shape validates the DUE vocabulary itself, not
+# individual policies. The sh:targetNode list references operand IRIs
+# defined in adalbert-due.ttl. To validate, load both the DUE vocabulary
+# and this shapes graph:
+# shacl validate --shapes adalbert-shacl.ttl --data adalbert-due.ttl
+# Policy-level validation (constraint structure, cardinality) is handled
+# by ConstraintShape and LeftOperandShape above.
+
+adalbertsh:DUEOperandShape a sh:NodeShape ;
+ sh:name "DUE Operand Shape" ;
+ sh:description "DUE operands must declare a resolution path." ;
+ sh:targetNode
+ odrl:purpose ,
+ adalbert-due:classification ,
+ adalbert-due:sensitivity ,
+ adalbert-due:assetClass ,
+ adalbert-due:market ,
+ adalbert-due:isBenchmark ,
+ adalbert-due:jurisdiction ,
+ adalbert-due:residency ,
+ adalbert-due:retentionPeriod ,
+ adalbert-due:expiry ,
+ adalbert-due:processingMode ,
+ adalbert-due:auditRequired ,
+ adalbert-due:role ,
+ adalbert-due:organization ,
+ adalbert-due:costCenter ,
+ adalbert-due:project ,
+ adalbert-due:recipientType ,
+ adalbert-due:environment ,
+ adalbert-due:network ,
+ adalbert-due:timeliness ,
+ adalbert-due:delayMinutes ,
+ adalbert-due:legalBasis ,
+ adalbert-due:consentId ,
+ adalbert-due:accessPattern ,
+ adalbert-due:volumeLimit ,
+ adalbert-due:rateLimit ,
+ adalbert-due:derivationType ;
+
+ sh:property [
+ sh:path adalbert:resolutionPath ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:string ;
+ sh:pattern "^(agent|asset|context)\\." ;
+ sh:message "DUE operands must have exactly one resolutionPath starting with agent., asset., or context."
+ ] .
+
+# =============================================================================
+# PROFILE SHAPE — reject RL2-only and unsupported ODRL constructs
+# =============================================================================
+# Each shape targets nodes that use a rejected feature and declares a
+# constraint that always fails: sh:maxCount 0 on the targeted property
+# (for property-based rejections) or on rdf:type (for class-based
+# rejections, since any typed node has rdf:type >= 1).
+
+adalbertsh:RejectXoneShape a sh:NodeShape ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX odrl:
+ SELECT ?this WHERE {
+ ?this odrl:xone ?list .
+ }
+ """
+ ] ;
+ sh:property [
+ sh:path odrl:xone ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support xone operator."
+ ] .
+
+adalbertsh:RejectRemedyShape a sh:NodeShape ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX odrl:
+ SELECT ?this WHERE {
+ ?this odrl:remedy ?r .
+ }
+ """
+ ] ;
+ sh:property [
+ sh:path odrl:remedy ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:remedy. Deferred to RL2."
+ ] .
+
+adalbertsh:RejectConsequenceShape a sh:NodeShape ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX odrl:
+ SELECT ?this WHERE {
+ ?this odrl:consequence ?c .
+ }
+ """
+ ] ;
+ sh:property [
+ sh:path odrl:consequence ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:consequence. Deferred to RL2."
+ ] .
+
+adalbertsh:RejectTicketShape a sh:NodeShape ;
+ sh:targetClass odrl:Ticket ;
+ sh:property [
+ sh:path rdf:type ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:Ticket."
+ ] .
+
+adalbertsh:RejectRequestShape a sh:NodeShape ;
+ sh:targetClass odrl:Request ;
+ sh:property [
+ sh:path rdf:type ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:Request."
+ ] .
+
+adalbertsh:RejectAssetCollectionShape a sh:NodeShape ;
+ sh:targetClass odrl:AssetCollection ;
+ sh:property [
+ sh:path rdf:type ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:AssetCollection. Use adalbert:partOf hierarchy instead."
+ ] .
+
+adalbertsh:RejectPartyCollectionShape a sh:NodeShape ;
+ sh:targetClass odrl:PartyCollection ;
+ sh:property [
+ sh:path rdf:type ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:PartyCollection. Use adalbert:memberOf hierarchy instead."
+ ] .
+
+adalbertsh:RejectInheritAllowedShape a sh:NodeShape ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX odrl:
+ SELECT ?this WHERE {
+ ?this odrl:inheritAllowed ?v .
+ }
+ """
+ ] ;
+ sh:property [
+ sh:path odrl:inheritAllowed ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:inheritAllowed."
+ ] .
+
+adalbertsh:RejectInheritFromShape a sh:NodeShape ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX odrl:
+ SELECT ?this WHERE {
+ ?this odrl:inheritFrom ?p .
+ }
+ """
+ ] ;
+ sh:property [
+ sh:path odrl:inheritFrom ;
+ sh:maxCount 0 ;
+ sh:severity sh:Violation ;
+ sh:message "Adalbert does not support odrl:inheritFrom."
+ ] .
+
+# =============================================================================
+# END OF SHAPES
+# =============================================================================
diff --git a/adalbert-contracts/docs/DATA-CONTRACTS.md b/adalbert-contracts/docs/DATA-CONTRACTS.md
new file mode 100644
index 0000000..d8a29dd
--- /dev/null
+++ b/adalbert-contracts/docs/DATA-CONTRACTS.md
@@ -0,0 +1,578 @@
+# Adalbert Contracts Guide
+
+A guide for data platform teams using Adalbert for data contracts and subscriptions.
+
+---
+
+## Overview
+
+Adalbert models internal data sharing agreements as ODRL 2.2 policies. A **DataContract** is an offer from a data provider. A **Subscription** is an activated contract binding provider and consumer.
+
+```
+DataContract (Offer) Subscription (Agreement)
+┌──────────────────┐ ┌──────────────────────┐
+│ Provider duties │ accept │ Provider duties │
+│ Consumer rights │ ──────> │ Consumer rights │
+│ Prohibitions │ │ Consumer duties │
+│ Recurrence rules │ │ Prohibitions │
+└──────────────────┘ │ State tracking │
+ └──────────────────────┘
+```
+
+---
+
+## Key Concepts
+
+### DataContract (Offer)
+
+An `adalbert:DataContract` is a subclass of `odrl:Offer`. It specifies:
+
+- **Provider** (`odrl:assigner`): the data team providing data
+- **Target** (`odrl:target`): the data asset(s) covered — inherited by rules unless overridden
+- **Provider duties** (`odrl:obligation` with `adalbert:subject` = provider): SLAs like delivery, notification, schema conformance
+- **Consumer permissions** (`odrl:permission`): what consumers can do with the data
+- **Consumer duties** (`odrl:obligation` without subject in Offer): obligations consumers accept upon subscribing
+- **Prohibitions** (`odrl:prohibition`): what consumers cannot do
+
+### Subscription (Agreement)
+
+An `adalbert:Subscription` is a subclass of `odrl:Agreement`. It adds:
+
+- **Consumer** (`odrl:assignee`): the subscribing team
+- **Effective/expiration dates**: contract period
+- **State tracking**: lifecycle state on duties and the subscription itself
+
+### Provider Duties
+
+Provider duties use DUE actions:
+
+| Action | Description | Example |
+|--------|-------------|---------|
+| `adalbert-due:deliver` | Deliver data to consumers | Daily market data delivery |
+| `adalbert-due:notify` | Send notifications | Schema change notification |
+| `adalbert-due:conformTo` | Maintain conformance to a standard | Schema/quality SLA |
+
+### Consumer Duties
+
+| Action | Description | Example |
+|--------|-------------|---------|
+| `adalbert-due:report` | Submit usage reports | Monthly usage reporting |
+
+### Permissions
+
+Standard ODRL actions apply:
+
+| Action | Description |
+|--------|-------------|
+| `odrl:display` | Display data |
+| `adalbert-due:nonDisplay` | Non-display (algorithmic) use |
+| `odrl:derive` | Create derived products |
+| `odrl:read` | Read data |
+
+---
+
+## Step-by-Step Cookbook
+
+Create your first DataContract in five steps.
+
+### Step 1: Declare the Contract
+
+Every contract starts with a type, profile declaration, and provider identity.
+
+```turtle
+@prefix odrl: .
+@prefix adalbert: .
+@prefix adalbert-due: .
+@prefix xsd: .
+
+ex:contract a adalbert:DataContract ;
+ odrl:profile ,
+ ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:marketPrices ;
+ adalbert:state adalbert:Active .
+```
+
+### Step 2: Add Provider Duties (SLAs)
+
+Provider duties declare what the data team commits to. The provider is identified by `adalbert:subject` on each duty. Use `adalbert:object` to identify who is affected (e.g., who receives notifications).
+
+Rules inherit `odrl:target` from the policy unless they target a different asset.
+
+```turtle
+ # Daily delivery by 06:30 (target inherited from policy)
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=DAILY;BYHOUR=6;BYMINUTE=0" ;
+ adalbert:deadline "PT30M"^^xsd:duration
+ ] ;
+
+ # Schema conformance (different target — not inherited)
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:marketDataSchema
+ ] ;
+```
+
+### Step 3: Add Consumer Permissions
+
+Permissions define what subscribers can do. In an Offer, omit `odrl:assignee` — it is filled when the subscription is created. Target is inherited from the policy.
+
+```turtle
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:display
+ ] ;
+
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action adalbert-due:nonDisplay ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:recipientType ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:internal
+ ]
+ ] ;
+```
+
+### Step 4: Add Consumer Duties and Prohibitions
+
+Consumer duties activate upon subscription. Prohibitions apply to all subscribers.
+
+```turtle
+ # Consumer must report usage monthly (different target — not inherited)
+ odrl:obligation [
+ a odrl:Duty ;
+ odrl:action adalbert-due:report ;
+ odrl:target ex:usageStats ;
+ adalbert:deadline "P30D"^^xsd:duration
+ ] ;
+
+ # No external redistribution (target inherited from policy)
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute
+ ] .
+```
+
+### Step 5: Create a Subscription
+
+When a consumer accepts the contract, create a Subscription (Agreement) referencing the contract:
+
+```turtle
+ex:subscription a adalbert:Subscription ;
+ odrl:profile ,
+ ;
+ adalbert:subscribesTo ex:contract ;
+ odrl:assigner ex:dataTeam ;
+ odrl:assignee ex:analyticsTeam ;
+ adalbert:effectiveDate "2026-02-01T00:00:00Z"^^xsd:dateTime ;
+ adalbert:expirationDate "2026-12-31T23:59:59Z"^^xsd:dateTime .
+```
+
+The subscription materializes all duties from the contract with explicit `adalbert:subject` on each.
+
+---
+
+## Provider Duty Patterns
+
+### Timeliness Pattern (Delivery SLA)
+
+Scheduled data delivery with a fulfillment window. Target inherited from policy.
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=DAILY;BYHOUR=6;BYMINUTE=0" ;
+ adalbert:deadline "PT30M"^^xsd:duration
+] .
+```
+
+**DCON equivalent**: `ProviderTimelinessPromise`
+
+### Schema Pattern (Schema Conformance)
+
+Provider guarantees data conforms to a published schema. Target differs from policy — specify explicitly.
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:marketDataSchema
+] .
+```
+
+**DCON equivalent**: `ProviderSchemaPromise`
+
+### Notification Pattern (Change Notification)
+
+Provider must notify consumers before making changes, with a lead time expressed as a duration deadline. Use `adalbert:object` to identify who is notified.
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ adalbert:object ex:consumer ;
+ odrl:action adalbert-due:notify ;
+ odrl:target ex:schemaChanges ;
+ adalbert:deadline "P14D"^^xsd:duration
+] .
+```
+
+**DCON equivalent**: `ProviderChangeNotificationPromise`
+
+### Quality SLA Pattern
+
+Provider guarantees data quality via `conformTo` with a constraint. This replaces DCON's `ProviderQualityPromise`.
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:riskMetricsSchema ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:timeliness ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:realtime
+ ]
+] .
+```
+
+The constraint can check any DUE operand — timeliness, classification, environment, etc.
+
+---
+
+## Recurrence
+
+Recurring duties use `adalbert:recurrence` — an RFC 5545 RRULE string. Combined with `adalbert:deadline`, this defines a schedule and fulfillment window.
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=DAILY;BYHOUR=6;BYMINUTE=0" ;
+ adalbert:deadline "PT30M"^^xsd:duration
+] .
+```
+
+This means: deliver market prices daily at 06:00 (target inherited from policy), with a 30-minute window to fulfill.
+
+### Common RRULE Patterns
+
+| Pattern | RRULE |
+|---------|-------|
+| Daily at 06:00 | `FREQ=DAILY;BYHOUR=6;BYMINUTE=0` |
+| Weekly on Monday | `FREQ=WEEKLY;BYDAY=MO` |
+| Monthly on the 1st | `FREQ=MONTHLY;BYMONTHDAY=1` |
+| Every 15 minutes | `FREQ=MINUTELY;INTERVAL=15` |
+| Hourly | `FREQ=HOURLY` |
+
+Each generated instance follows the standard duty lifecycle independently (Pending -> Active -> Fulfilled/Violated).
+
+---
+
+## Common Patterns Quick Reference
+
+### Simple File Drop
+
+Read-only access, no recurrence, no consumer duties. Target inherited from policy.
+
+```turtle
+ex:contract a adalbert:DataContract ;
+ odrl:profile ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:referenceData ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read
+ ] ;
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:modify
+ ] .
+```
+
+### API with SLA
+
+Daily delivery, schema conformance, display + non-display, monthly reporting. Target inherited from policy unless overridden.
+
+```turtle
+ex:contract a adalbert:DataContract ;
+ odrl:profile ,
+ ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:customerData ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=DAILY;BYHOUR=7;BYMINUTE=0" ;
+ adalbert:deadline "PT30M"^^xsd:duration
+ ] ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:customerSchema
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:display
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action adalbert-due:nonDisplay
+ ] ;
+ odrl:obligation [
+ a odrl:Duty ;
+ odrl:action adalbert-due:report ;
+ odrl:target ex:usageStats ;
+ adalbert:deadline "P30D"^^xsd:duration
+ ] ;
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute
+ ] .
+```
+
+### Mission-Critical Service
+
+High-frequency delivery with quality SLA and change notification. Target inherited from policy unless overridden.
+
+```turtle
+ex:contract a adalbert:DataContract ;
+ odrl:profile ,
+ ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:riskMetrics ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:deliver ;
+ adalbert:recurrence "FREQ=MINUTELY;INTERVAL=1" ;
+ adalbert:deadline "PT30S"^^xsd:duration
+ ] ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:riskSchema ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:timeliness ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:realtime
+ ]
+ ] ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:notify ;
+ odrl:target ex:schemaChanges ;
+ adalbert:deadline "P14D"^^xsd:duration
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:display
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action adalbert-due:nonDisplay
+ ] .
+```
+
+### Multi-Dataset Contract
+
+A single contract covering multiple targets. When a policy has multiple targets, rules must specify their target explicitly — inheritance is ambiguous.
+
+```turtle
+ex:contract a adalbert:DataContract ;
+ odrl:profile ;
+ odrl:assigner ex:dataTeam ;
+ odrl:target ex:marketPrices , ex:referenceData , ex:riskMetrics ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:marketPrices
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:referenceData
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:riskMetrics
+ ] .
+```
+
+---
+
+## Advanced Topics
+
+### Target Inheritance
+
+`odrl:target` at the policy level is inherited by rules that don't declare their own target. This reduces redundancy:
+
+```turtle
+ex:contract a adalbert:DataContract ;
+ odrl:target ex:marketPrices ; # policy-level target
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read # inherits ex:marketPrices
+ ] ;
+ odrl:obligation [
+ a odrl:Duty ;
+ adalbert:subject ex:dataTeam ;
+ odrl:action adalbert-due:conformTo ;
+ odrl:target ex:marketDataSchema # different target — explicit
+ ] .
+```
+
+**Rules**:
+- Single-target policy: rules inherit the target unless they specify a different one
+- Multi-target policy: rules must specify their target (inheritance is ambiguous)
+- Named duty instances (standalone): always specify their target
+
+### Multi-Asset Contracts
+
+A contract can cover multiple targets. When multiple targets exist, each rule must specify its own target (inheritance is ambiguous):
+
+```turtle
+ex:contract odrl:target ex:asset1 , ex:asset2 ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:asset1
+ ] ;
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:display ;
+ odrl:target ex:asset2
+ ] .
+```
+
+### Team Delegation
+
+Use `adalbert:memberOf` to model team hierarchies. A permission granted to a team applies to its members via hierarchy subsumption during evaluation:
+
+```turtle
+ex:analyst a odrl:Party ;
+ adalbert:memberOf ex:analyticsTeam .
+
+ex:analyticsTeam a odrl:Party ;
+ adalbert:memberOf ex:tradingDivision .
+```
+
+### Version Chains
+
+Use `prov:wasRevisionOf` to link contract versions:
+
+```turtle
+ex:contract-v2 a adalbert:DataContract ;
+ prov:wasRevisionOf ex:contract-v1 .
+
+ex:contract-v3 a adalbert:DataContract ;
+ prov:wasRevisionOf ex:contract-v2 .
+```
+
+Subscriptions reference the specific contract version they activate:
+
+```turtle
+ex:subscription adalbert:subscribesTo ex:contract-v2 .
+```
+
+### Expiration
+
+Contracts and subscriptions can have explicit expiration dates:
+
+```turtle
+ex:subscription a adalbert:Subscription ;
+ adalbert:effectiveDate "2026-01-15T00:00:00Z"^^xsd:dateTime ;
+ adalbert:expirationDate "2026-12-31T23:59:59Z"^^xsd:dateTime .
+```
+
+---
+
+## Lifecycle
+
+Duties and contracts share four states:
+
+```
+ condition true
+Pending ──────────────> Active
+ | |
+ action done | | deadline passed
+ v v
+ Fulfilled Violated
+```
+
+- **Pending**: condition not yet met / not yet in force
+- **Active**: condition met, action required / in force
+- **Fulfilled**: action performed / obligations complete
+- **Violated**: deadline passed / breached
+
+---
+
+## Versioning
+
+Contracts can be versioned using `prov:wasRevisionOf`:
+
+```turtle
+ex:contract-v2 a adalbert:DataContract ;
+ prov:wasRevisionOf ex:contract-v1 .
+```
+
+Subscriptions reference the contract they activate via `adalbert:subscribesTo`:
+
+```turtle
+ex:subscription adalbert:subscribesTo ex:contract-v2 .
+```
+
+---
+
+## Complete Example
+
+See [examples/data-contract.ttl](../examples/data-contract.ttl) for a full working contract with bilateral duties, recurrence, schema conformance, and subscription.
+
+For comprehensive test data covering all patterns, see [examples/baseline.ttl](../examples/baseline.ttl).
+
+---
+
+## DCON Migration
+
+If migrating from DCON, see [adalbert-term-mapping.md](adalbert-term-mapping.md) for complete property equivalents and [comparisons/comparison-dcon.md](comparisons/comparison-dcon.md) for the supersession analysis.
+
+---
+
+## Validation Checklist
+
+1. Every policy declares `odrl:profile ` and ``
+2. Conflict strategy (`odrl:conflict odrl:prohibit`) is inherited from the profile — do not repeat per-policy
+3. DataContract has `odrl:assigner` (provider)
+4. Subscription has both `odrl:assigner` and `odrl:assignee`
+5. Subscription has `adalbert:subscribesTo` referencing a DataContract
+6. Each duty has exactly one `odrl:action`
+7. Each permission and prohibition has exactly one `odrl:action` and one `odrl:target`
+8. Provider duties have `adalbert:subject` set to the provider
+9. Deadlines use `xsd:dateTime` or `xsd:duration`
+10. Recurrence uses a valid RFC 5545 RRULE starting with `FREQ=`
+11. Constraints have `leftOperand`, `operator`, and `rightOperand`
+12. LogicalConstraints use exactly one of `odrl:and`, `odrl:or`, or `adalbert:not`
+13. Validate against SHACL shapes:
+
+```bash
+shacl validate --shapes ontology/adalbert-shacl.ttl --data my-contract.ttl
+```
diff --git a/adalbert-contracts/docs/DATA-USE-POLICIES.md b/adalbert-contracts/docs/DATA-USE-POLICIES.md
new file mode 100644
index 0000000..57493d2
--- /dev/null
+++ b/adalbert-contracts/docs/DATA-USE-POLICIES.md
@@ -0,0 +1,551 @@
+# Adalbert Policy Writers Guide
+
+A guide for data stewards writing data use policies with Adalbert.
+
+---
+
+## 1. When to Use Policies vs Contracts
+
+Adalbert supports two document types for different purposes:
+
+| Type | ODRL Base | Use Case | Parties |
+|------|-----------|----------|---------|
+| **Policy** (`odrl:Set`) | Set | Organizational rules, access controls | None (applies to anyone matching constraints) |
+| **Offer / Contract** (`adalbert:DataContract`) | Offer | Bilateral agreements between teams | Provider (assigner) required |
+| **Subscription** (`adalbert:Subscription`) | Agreement | Activated contract | Both parties required |
+
+Use **policies** (`odrl:Set`) when:
+- Writing organizational data governance rules
+- Defining access controls by role, purpose, or classification
+- Setting restrictions that apply universally (no specific consumer)
+- Encoding regulatory requirements (GDPR, data residency)
+
+Use **contracts** when two specific teams need a bilateral agreement with SLAs. See [contracts-guide.md](contracts-guide.md) for contract authoring.
+
+---
+
+## 2. Quick Start
+
+A minimal data use policy:
+
+```turtle
+@prefix odrl: .
+@prefix adalbert: .
+@prefix adalbert-due: .
+@prefix xsd: .
+
+ex:policy a odrl:Set ;
+ odrl:profile ,
+ ;
+ odrl:target ex:customerData ;
+
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:assignee ex:analyticsTeam ;
+ odrl:action odrl:read ;
+ odrl:target ex:customerData ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:analytics
+ ]
+ ] ;
+
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute ;
+ odrl:target ex:customerData
+ ] .
+```
+
+This policy says: the analytics team may read customer data for analytics purposes, and no one may distribute it.
+
+---
+
+## 3. Permission Patterns
+
+### Purpose-Restricted Permission
+
+Grant access only for a specific purpose.
+
+```turtle
+odrl:permission [
+ a odrl:Permission ;
+ odrl:assignee ex:complianceTeam ;
+ odrl:action odrl:read ;
+ odrl:target ex:transactionData ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:compliance
+ ]
+] .
+```
+
+### Classification-Based Permission
+
+Grant access based on the data's classification level.
+
+```turtle
+odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:classification ;
+ odrl:operator odrl:isAnyOf ;
+ odrl:rightOperand (adalbert-due:public adalbert-due:internal)
+ ]
+] .
+```
+
+### Role-Based Permission
+
+Grant access based on the requesting agent's role.
+
+```turtle
+odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:role ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand "data-analyst"
+ ]
+] .
+```
+
+### Time-Limited Permission
+
+Grant access only before a certain date.
+
+```turtle
+odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert:currentDateTime ;
+ odrl:operator odrl:lt ;
+ odrl:rightOperand "2026-12-31T23:59:59Z"^^xsd:dateTime
+ ]
+] .
+```
+
+---
+
+## 4. Prohibition Patterns
+
+### No External Distribution
+
+```turtle
+odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute ;
+ odrl:target ex:data
+] .
+```
+
+### No PII Processing
+
+Prohibit use of data classified as PII for certain processing modes.
+
+```turtle
+odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:use ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:LogicalConstraint ;
+ odrl:and (
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:sensitivity ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:pii
+ ]
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:processingMode ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:modelTraining
+ ]
+ )
+ ]
+] .
+```
+
+### No Commingling
+
+Prohibit mixing data with other sources.
+
+```turtle
+odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:derive ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:derivationType ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:commingled
+ ]
+] .
+```
+
+---
+
+## 5. Constraint Patterns
+
+Constraints restrict when rules apply. An `odrl:Constraint` has three parts:
+
+| Part | Property | Description |
+|------|----------|-------------|
+| Left operand | `odrl:leftOperand` | What to check (from DUE vocabulary) |
+| Operator | `odrl:operator` | How to compare (`eq`, `neq`, `lt`, `gt`, `lteq`, `gteq`, `isAnyOf`, `isNoneOf`, `isAllOf`) |
+| Right operand | `odrl:rightOperand` | Expected value(s) |
+
+### Purpose Constraint
+
+```turtle
+odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:analytics
+] .
+```
+
+### Classification Constraint
+
+```turtle
+odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:classification ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:confidential
+] .
+```
+
+### Jurisdiction Constraint
+
+```turtle
+odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:jurisdiction ;
+ odrl:operator odrl:isAnyOf ;
+ odrl:rightOperand ("US" "UK" "EU")
+] .
+```
+
+### Retention Constraint
+
+```turtle
+odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:retentionPeriod ;
+ odrl:operator odrl:lteq ;
+ odrl:rightOperand "P7Y"^^xsd:duration
+] .
+```
+
+### Environment Constraint
+
+```turtle
+odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:environment ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:production
+] .
+```
+
+---
+
+## 6. DUE Operands Quick Reference
+
+All operands are `odrl:LeftOperand` with `adalbert:resolutionPath`.
+
+### Agent Operands (resolved from requesting agent)
+
+| Operand | Resolution Path | Values / Type |
+|---------|----------------|---------------|
+| `adalbert-due:role` | `agent.role` | String |
+| `adalbert-due:organization` | `agent.organization` | IRI |
+| `adalbert-due:costCenter` | `agent.costCenter` | String |
+| `adalbert-due:recipientType` | `agent.recipientType` | `internal`, etc. |
+
+### Asset Operands (resolved from target asset)
+
+| Operand | Resolution Path | Values / Type |
+|---------|----------------|---------------|
+| `adalbert-due:classification` | `asset.classification` | `public`, `internal`, `confidential`, `restricted` |
+| `adalbert-due:sensitivity` | `asset.sensitivity` | `pii`, `mnpi`, `phi` |
+| `adalbert-due:assetClass` | `asset.class` | String (equity, fx, etc.) |
+| `adalbert-due:market` | `asset.market` | String (NYSE, LSE, etc.) |
+| `adalbert-due:isBenchmark` | `asset.isBenchmark` | Boolean |
+| `adalbert-due:residency` | `asset.residency` | String (country) |
+| `adalbert-due:retentionPeriod` | `asset.retentionPeriod` | `xsd:duration` |
+| `adalbert-due:expiry` | `asset.expiry` | `xsd:dateTime` |
+| `adalbert-due:timeliness` | `asset.timeliness` | `realtime`, `nearRealtime`, `delayed`, `endOfDay`, `historical` |
+| `adalbert-due:delayMinutes` | `asset.delayMinutes` | Integer |
+| `adalbert-due:auditRequired` | `asset.auditRequired` | Boolean |
+
+### Context Operands (resolved from request context)
+
+| Operand | Resolution Path | Values / Type |
+|---------|----------------|---------------|
+| `odrl:purpose` | `context.purpose` | `analytics`, `research`, `compliance`, `operations` |
+| `adalbert-due:jurisdiction` | `context.jurisdiction` | String (country) |
+| `adalbert-due:environment` | `context.environment` | `production`, `staging`, `development`, `sandbox` |
+| `adalbert-due:network` | `context.network` | `internalNetwork`, `externalNetwork`, `cloudNetwork` |
+| `adalbert-due:processingMode` | `context.processingMode` | `human`, `automated`, `modelTraining`, `inference` |
+| `adalbert-due:legalBasis` | `context.legalBasis` | `consent`, `contract`, `legalObligation`, `vitalInterest`, `publicTask`, `legitimateInterest` |
+| `adalbert-due:consentId` | `context.consentId` | String |
+| `adalbert-due:accessPattern` | `context.accessPattern` | `batch`, `streaming`, `interactive`, `api` |
+| `adalbert-due:volumeLimit` | `context.volumeLimit` | Integer |
+| `adalbert-due:rateLimit` | `context.rateLimit` | Integer |
+| `adalbert-due:derivationType` | `context.derivationType` | `commingled`, `nonSubstitutive`, `newProduct` |
+| `adalbert-due:project` | `context.project` | String |
+
+---
+
+## 7. DUE Actions Quick Reference
+
+### ODRL Common Vocabulary (used directly)
+
+| Action | Definition | Hierarchy |
+|--------|------------|-----------|
+| `odrl:use` | General use | Top |
+| `odrl:read` | Read/view | `includedIn use` |
+| `odrl:display` | Display to users | `includedIn use` |
+| `odrl:distribute` | Distribute to third parties | `includedIn use` |
+| `odrl:delete` | Delete the asset | `includedIn use` |
+| `odrl:modify` | Modify the asset | `includedIn use` |
+| `odrl:aggregate` | Aggregate with other data | `includedIn use` |
+| `odrl:anonymize` | Remove identifying info | `includedIn use` |
+| `odrl:derive` | Create derived data | `includedIn use` |
+
+### DUE-Specific Actions
+
+| Action | Definition | Parent |
+|--------|------------|--------|
+| `adalbert-due:nonDisplay` | Automated/programmatic use | `use` |
+| `adalbert-due:conformTo` | Conform to schema/spec | None |
+| `adalbert-due:log` | Log access | `inform` |
+| `adalbert-due:notify` | Notify parties | `inform` |
+| `adalbert-due:report` | Submit reports | `inform` |
+| `adalbert-due:deliver` | Deliver data | `distribute` |
+| `adalbert-due:query` | Query/select | `read` |
+| `adalbert-due:export` | Export outside system | `distribute` |
+| `adalbert-due:copy` | Copy to another location | `reproduce` |
+| `adalbert-due:link` | Link/join datasets | `aggregate` |
+| `adalbert-due:profile` | Create profiles | `derive` |
+| `adalbert-due:calculateIndex` | Index calculation | `derive` |
+| `adalbert-due:algorithmicTrading` | Automated trading | `nonDisplay` |
+
+Action hierarchy uses `odrl:includedIn`. A permission on `odrl:use` implicitly permits all actions below it.
+
+---
+
+## 8. Combining Constraints
+
+### Logical AND
+
+All conditions must be true. Use `odrl:LogicalConstraint` with `odrl:and`:
+
+```turtle
+odrl:constraint [
+ a odrl:LogicalConstraint ;
+ odrl:and (
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:compliance
+ ]
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:legalBasis ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:legitimateInterest
+ ]
+ )
+] .
+```
+
+### Logical OR
+
+At least one condition must be true. Use `odrl:or`:
+
+```turtle
+odrl:constraint [
+ a odrl:LogicalConstraint ;
+ odrl:or (
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:compliance
+ ]
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:operations
+ ]
+ )
+] .
+```
+
+### Logical NOT
+
+Negate a constraint. Use `adalbert:not`:
+
+```turtle
+odrl:constraint [
+ a odrl:LogicalConstraint ;
+ adalbert:not [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:environment ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:production
+ ]
+] .
+```
+
+This means: the constraint is satisfied when the environment is **not** production.
+
+A `LogicalConstraint` must have exactly one of `odrl:and`, `odrl:or`, or `adalbert:not`.
+
+---
+
+## 9. Common Policy Patterns
+
+### Internal Analytics Only
+
+```turtle
+ex:policy a odrl:Set ;
+ odrl:profile ,
+ ;
+ odrl:target ex:data ;
+
+ odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:LogicalConstraint ;
+ odrl:and (
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand odrl:purpose ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:analytics
+ ]
+ [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:recipientType ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:internal
+ ]
+ )
+ ]
+ ] ;
+
+ odrl:prohibition [
+ a odrl:Prohibition ;
+ odrl:action odrl:distribute ;
+ odrl:target ex:data
+ ] .
+```
+
+### Jurisdiction-Restricted
+
+```turtle
+odrl:permission [
+ a odrl:Permission ;
+ odrl:action odrl:read ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:jurisdiction ;
+ odrl:operator odrl:isAnyOf ;
+ odrl:rightOperand ("US" "UK")
+ ]
+] .
+```
+
+### Retention-Limited
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ odrl:action odrl:delete ;
+ odrl:target ex:data ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:retentionPeriod ;
+ odrl:operator odrl:gt ;
+ odrl:rightOperand "P5Y"^^xsd:duration
+ ]
+] .
+```
+
+### Audit-Required
+
+```turtle
+odrl:obligation [
+ a odrl:Duty ;
+ odrl:action adalbert-due:log ;
+ odrl:target ex:accessLog ;
+ odrl:constraint [
+ a odrl:Constraint ;
+ odrl:leftOperand adalbert-due:classification ;
+ odrl:operator odrl:eq ;
+ odrl:rightOperand adalbert-due:confidential
+ ] ;
+ adalbert:deadline "PT1H"^^xsd:duration
+] .
+```
+
+---
+
+## 10. Policy Review Checklist
+
+1. Every policy declares `odrl:profile ` and ``
+2. Conflict strategy (`odrl:conflict odrl:prohibit`) is inherited from the profile — do not repeat per-policy
+3. Policy has at least one `odrl:target`
+4. Each permission and prohibition has exactly one `odrl:action` and one effective `odrl:target` — either declared on the rule or inherited from the policy-level target (rule-level `odrl:target` may be omitted when a policy-level target exists)
+5. Each duty has exactly one `odrl:action`
+6. Each constraint has `leftOperand`, `operator`, and `rightOperand`
+7. LogicalConstraints use exactly one of `odrl:and`, `odrl:or`, or `adalbert:not`
+8. Resolution paths match canonical roots (`agent.`, `asset.`, `context.`)
+9. Prohibitions cover the intended restrictions (prohibition overrides permission)
+10. Duties have appropriate deadlines where time-sensitive
+11. Classification and sensitivity values match the DUE vocabulary
+12. Validate against SHACL shapes:
+
+```bash
+shacl validate --shapes ontology/adalbert-shacl.ttl --data my-policy.ttl
+```
+
+---
+
+## Further Reading
+
+- [adalbert-overview.md](adalbert-overview.md) — What is Adalbert?
+- [adalbert-specification.md](adalbert-specification.md) — Technical vocabulary reference
+- [adalbert-term-mapping.md](adalbert-term-mapping.md) — Business term -> property mapping
+- [examples/data-use-policy.ttl](../examples/data-use-policy.ttl) — Complete working policy example
+- [examples/baseline.ttl](../examples/baseline.ttl) — Comprehensive test data
+
+---
+
+**Version**: 0.7 | **Date**: 2026-02-04
diff --git a/adalbert-contracts/docs/DPROD-Adalbert-Comparison.md b/adalbert-contracts/docs/DPROD-Adalbert-Comparison.md
new file mode 100644
index 0000000..aea0938
--- /dev/null
+++ b/adalbert-contracts/docs/DPROD-Adalbert-Comparison.md
@@ -0,0 +1,207 @@
+# DPROD-Contracts vs Adalbert: Comparison Report
+
+A comparison of the two ODRL-based data contract approaches contributed to EKGF/dprod.
+
+---
+
+## Overview
+
+Both `dprod-contracts` and `adalbert-contracts` extend ODRL 2.2 for data governance. They share the same goal — formalizing bilateral data agreements between providers and consumers — but differ in scope, architecture, and formality.
+
+| Dimension | dprod-contracts | adalbert-contracts |
+|---|---|---|
+| **Scope** | Data contracts only | Data contracts + data-use policies |
+| **ODRL relationship** | Custom Rule subclass (Promise) | Proper ODRL 2.2 profile (Duty, Permission, Prohibition) |
+| **Formal semantics** | No | Yes (normative, verification-ready) |
+| **Lifecycle** | 4 statuses (Pending, Active, Expired, Cancelled) | 4 states (Pending, Active, Fulfilled, Violated) with formal transitions |
+| **Bilateral duties** | Via ProviderPromise / ConsumerPromise | Via `adalbert:subject` / `adalbert:object` on standard `odrl:Duty` |
+| **Recurrence** | `dprod:ICalSchedule` class + `dprod:icalRule` | `adalbert:recurrence` property (direct RRULE string on Duty) |
+| **Validation** | SHACL shapes | SHACL shapes |
+| **W3C Profile declaration** | ODRL Profile in ontology | Separate W3C DXPROF declaration |
+
+---
+
+## Architectural Differences
+
+### 1. Promise vs Duty
+
+**dprod-contracts** introduces `dprod:Promise` as a new `odrl:Rule` subclass, disjoint with `odrl:Duty`, `odrl:Permission`, and `odrl:Prohibition`. This creates a parallel class hierarchy:
+
+```
+odrl:Rule
+├── odrl:Permission
+├── odrl:Prohibition
+├── odrl:Duty
+└── dprod:Promise ← new Rule type
+ ├── dprod:ProviderPromise
+ │ ├── dprod:ProviderTimelinessPromise
+ │ ├── dprod:ProviderSchemaPromise
+ │ ├── dprod:ProviderServiceLevelPromise
+ │ └── ...
+ └── dprod:ConsumerPromise
+```
+
+**Adalbert** uses standard `odrl:Duty` for all obligations, distinguishing provider from consumer duties via `adalbert:subject`:
+
+```
+odrl:Rule (unchanged)
+├── odrl:Permission
+├── odrl:Prohibition
+└── odrl:Duty
+ ├── with adalbert:subject = provider → provider duty
+ └── with adalbert:subject = consumer → consumer duty
+```
+
+**Implication**: Adalbert policies are valid ODRL 2.2 — any ODRL processor can partially understand them. dprod-contracts requires Promise-aware processing.
+
+### 2. Data-Use Policies
+
+**dprod-contracts** focuses exclusively on bilateral contracts between named parties.
+
+**Adalbert** also supports `odrl:Set` policies — organizational rules that apply to anyone matching constraints:
+
+- Role-based access control
+- Purpose restrictions
+- Classification-based permissions
+- Environment constraints
+- Jurisdiction requirements
+- Retention limits
+
+This is a key differentiator. Real-world data governance requires both contracts (bilateral) and policies (organizational).
+
+### 3. Formal Semantics
+
+**dprod-contracts** defines classes and properties but not evaluation behavior.
+
+**Adalbert** includes a normative formal semantics document defining:
+
+- `Eval : Request × PolicySet × State → Decision × DutySet` (total function)
+- Deterministic conflict resolution (Prohibition > Permission)
+- Duty lifecycle state machine (Pending → Active → Fulfilled/Violated)
+- Operand resolution from canonical roots (agent, asset, context)
+- Recurrence expansion via RFC 5545 RRULE
+
+This makes Adalbert amenable to formal verification (Dafny, Why3, Coq).
+
+### 4. Recurrence
+
+**dprod-contracts**:
+```turtle
+dprod:hasSchedule [
+ a dprod:ICalSchedule ;
+ dprod:icalRule "FREQ=DAILY;BYHOUR=6;BYMINUTE=0"
+] .
+```
+
+**Adalbert**:
+```turtle
+adalbert:recurrence "FREQ=DAILY;BYHOUR=6;BYMINUTE=0" ;
+adalbert:deadline "PT30M"^^xsd:duration .
+```
+
+Adalbert is more concise (property on Duty vs. nested class) and adds `deadline` for the per-instance fulfillment window.
+
+### 5. Operand Resolution
+
+**dprod-contracts** does not define how constraint operands resolve.
+
+**Adalbert** defines `adalbert:resolutionPath` — dot-separated paths from canonical roots:
+
+```
+agent.role, agent.organization, agent.costCenter
+asset.classification, asset.market, asset.isBenchmark
+context.purpose, context.environment, context.legalBasis
+```
+
+This enables deterministic constraint evaluation across implementations.
+
+---
+
+## Mapping Table
+
+### Classes
+
+| dprod-contracts | Adalbert | Notes |
+|---|---|---|
+| `dprod:DataContract` | `adalbert:DataContract` | Both subclass `odrl:Agreement` / `odrl:Offer` |
+| `dprod:DataOffer` | `adalbert:DataContract` | Adalbert DataContract is an Offer; Subscription is the Agreement |
+| `dprod:Promise` | `odrl:Duty` | Standard ODRL type |
+| `dprod:ProviderPromise` | `odrl:Duty` + `adalbert:subject` | Subject identifies provider |
+| `dprod:ConsumerPromise` | `odrl:Permission` / `odrl:Prohibition` / `odrl:Duty` | Split by semantics |
+| `dprod:ProviderTimelinessPromise` | `odrl:Duty` + `adalbert-due:deliver` + `adalbert:recurrence` | |
+| `dprod:ProviderSchemaPromise` | `odrl:Duty` + `adalbert-due:conformTo` | |
+| `dprod:ProviderServiceLevelPromise` | `odrl:Duty` + `adalbert-due:conformTo` + constraints | |
+| `dprod:ServiceLevelTarget` | `odrl:Constraint` | Expressed as constraint on duty |
+| `dprod:ICalSchedule` | `adalbert:recurrence` (string property) | Simpler, same RRULE syntax |
+
+### Properties
+
+| dprod-contracts | Adalbert | Notes |
+|---|---|---|
+| `dprod:contractStatus` | `adalbert:state` | Similar lifecycle, different value names |
+| `dprod:providerPromise` | `odrl:obligation` | Standard ODRL property |
+| `dprod:consumerPromise` | `odrl:permission` / `odrl:obligation` / `odrl:prohibition` | Split by semantics |
+| `dprod:hasSchedule` / `dprod:icalRule` | `adalbert:recurrence` | Direct RRULE on Duty |
+| `dprod:hasEffectivePeriod` | `adalbert:effectiveDate` + `adalbert:expirationDate` | |
+| `dprod:noticePeriod` | `adalbert:deadline` | Duration on notification duty |
+| `dprod:supersedes` | `prov:wasRevisionOf` | Standard provenance |
+| `dprod:hasServiceLevelTarget` | `odrl:constraint` on duty | |
+| `dprod:hasPricing` | Not in scope | Adalbert focuses on rights, not pricing |
+
+### Actions
+
+| dprod-contracts | Adalbert | Notes |
+|---|---|---|
+| `dprod:deliverOnSchedule` | `adalbert-due:deliver` | `includedIn odrl:distribute` |
+| `dprod:maintainSchema` | `adalbert-due:conformTo` | Duty-only action |
+| `dprod:maintainQuality` | `adalbert-due:conformTo` + constraint | Quality as constrained conformance |
+| `dprod:notifyChange` | `adalbert-due:notify` | `includedIn odrl:inform` |
+| `dprod:notifyTermination` | `adalbert-due:notify` + `adalbert:deadline` | Deadline = notice period |
+| `dprod:meetServiceLevel` | `adalbert-due:conformTo` + constraints | SLA as constrained conformance |
+| `dprod:provideSupport` | `adalbert-due:notify` | Best fit |
+| `dprod:reportUsage` | `adalbert-due:report` | `includedIn odrl:inform` |
+| `dprod:query` | `adalbert-due:query` | `includedIn odrl:read` |
+| `dprod:access` | `odrl:use` | Standard ODRL |
+| `dprod:deriveInsights` | `odrl:derive` | Standard ODRL |
+| `dprod:aggregate` | `odrl:aggregate` | Standard ODRL |
+| `dprod:anonymize` | `odrl:anonymize` | Standard ODRL |
+| `dprod:shareInternally` | `odrl:distribute` + constraint | Internal-only via constraint |
+| `dprod:restrictPurpose` | `odrl:Prohibition` on `odrl:distribute` | Prohibition, not action |
+| `dprod:deleteOnExpiry` | `odrl:Duty` with `odrl:delete` | Standard ODRL action |
+
+### Status Values
+
+| dprod-contracts | Adalbert | Notes |
+|---|---|---|
+| `dprod:ContractStatusPending` | `adalbert:Pending` | Same semantics |
+| `dprod:ContractStatusActive` | `adalbert:Active` | Same semantics |
+| `dprod:ContractStatusExpired` | `adalbert:Fulfilled` | Adalbert: natural completion = Fulfilled |
+| `dprod:ContractStatusCancelled` | `adalbert:Violated` | Adalbert: early termination = Violated |
+
+---
+
+## What Adalbert Adds Beyond dprod-contracts
+
+1. **Data-use policies** (`odrl:Set`) — organizational rules, access controls, not just bilateral contracts
+2. **Formal semantics** — total evaluation function, deterministic conflict resolution, verifiable
+3. **Duty lifecycle** — formal state machine with Pending → Active → Fulfilled/Violated transitions
+4. **Structured operand resolution** — `resolutionPath` from canonical roots (agent, asset, context)
+5. **Rich constraint vocabulary** — 33 operands across purpose, classification, jurisdiction, environment, timeliness, SLA metrics, data quality, channels, subscription tiers, legal basis, etc.
+6. **Logical negation** — `adalbert:not` (ODRL lacks this)
+7. **Target inheritance** — policy-level `odrl:target` inherited by rules
+8. **Party hierarchies** — `adalbert:partOf` (assets) and `adalbert:memberOf` (parties) with transitivity
+
+## What dprod-contracts Adds Beyond Adalbert
+
+1. **Pricing** — `dprod:hasPricing` with `schema:PriceSpecification` (marketplace scenarios). Adalbert intentionally does not address pricing, focusing on rights and obligations.
+2. **Promise class hierarchy** — richer typing for different commitment types (may aid discovery)
+
+---
+
+## Translated Examples
+
+See `examples/dprod-translated.ttl` for all 8 dprod-contracts examples translated to Adalbert, demonstrating that Adalbert can express the same contracts while adding lifecycle tracking, deterministic evaluation, and structured constraints.
+
+---
+
+**Version**: 0.7 | **Date**: 2026-02-16
diff --git a/adalbert-contracts/docs/SEMANTICS.md b/adalbert-contracts/docs/SEMANTICS.md
new file mode 100644
index 0000000..da297b4
--- /dev/null
+++ b/adalbert-contracts/docs/SEMANTICS.md
@@ -0,0 +1,1127 @@
+---
+title: "Adalbert Formal Semantics"
+subtitle: "Deterministic Policy Evaluation for Data Governance"
+version: "0.7"
+status: "Draft"
+date: 2026-02-03
+abstract: |
+ Adalbert is a proper ODRL 2.2 profile with deterministic, total evaluation
+ semantics and bilateral agreement support. This document specifies the formal
+ semantics in a style amenable to mechanization in Dafny, Why3, or similar
+ verification frameworks.
+---
+
+## 1. Introduction
+
+Adalbert addresses semantic gaps in ODRL 2.2:
+
+1. **Duty Ambiguity**: ODRL conflates pre-conditions with post-obligations
+2. **Unilateral Agreements**: ODRL evaluates only from assignee perspective
+3. **Undefined States**: ODRL permits evaluation to be "undefined"
+
+Adalbert provides:
+
+- Explicit duty lifecycle with state machine semantics
+- Bilateral agreement evaluation (grantor and grantee duties)
+- Total evaluation functions (always terminate with defined result)
+- Clear separation of Condition (pre-requisite) from Duty (obligation)
+- Path-based operand resolution with formal grammar and security constraints
+
+### 1.1 Scope and Runtime Boundary
+
+This specification defines **evaluation semantics** — the contract a conformant engine
+must satisfy. The `State` parameter in `Eval` is an opaque input provided by the
+runtime environment. Adalbert specifies what decision and state transitions *should*
+result from evaluation, but does not define:
+
+- How `State` is persisted or managed between evaluations
+- Event-driven triggers for duty activation or deadline enforcement
+- Protocols for requirement fulfillment claims or re-evaluation
+
+These operational concerns are out of scope for a declarative policy profile.
+Implementations requiring runtime state management, event processing, and enforcement
+protocols should consult RL2, which extends Adalbert's evaluation semantics with a
+complete operational protocol layer.
+
+### 1.2 Notation
+
+- `×` for Cartesian product
+- `→` for function types
+- `∪` for union
+- `∈` for set membership
+- `⊥` for undefined/bottom value
+- `⟦e⟧` for denotation of expression `e`
+- `Γ ⊢ e : τ` for typing judgement ("in context Γ, expression e has type τ")
+
+### 1.2 Document Status
+
+This document is **normative** for Adalbert implementations.
+
+---
+
+## 2. Type System
+
+The type system ensures well-formed policies.
+
+### 2.1 Typing Judgements
+
+We use:
+
+```
+Γ ⊢ e : τ
+```
+
+Where Γ is a typing context mapping identifiers to types.
+
+### 2.2 Types
+
+```
+τ ::= Agent | Action | Asset | Condition | Time | Duration | Boolean | Value | Norm | State | Policy
+```
+
+### 2.3 Key Typing Rules
+
+Permission:
+
+```
+Γ ⊢ a : Agent Γ ⊢ x : Action Γ ⊢ s : Asset Γ ⊢ c : Condition
+---------------------------------------------------------------------------
+ Γ ⊢ Permission(a, x, s, c) : Norm
+```
+
+Duty:
+
+```
+Γ ⊢ a : Agent Γ ⊢ x : Action Γ ⊢ s : Asset
+Γ ⊢ c : Condition Γ ⊢ dl : Deadline Γ ⊢ r : Recurrence
+--------------------------------------------------------------------------
+ Γ ⊢ Duty(a, x, s, c, dl, r) : Norm
+```
+
+Prohibition:
+
+```
+Γ ⊢ a : Agent Γ ⊢ x : Action Γ ⊢ s : Asset Γ ⊢ c : Condition
+---------------------------------------------------------------------------
+ Γ ⊢ Prohibition(a, x, s, c) : Norm
+```
+
+AtomicConstraint:
+
+```
+Γ ⊢ left : LeftOperand Γ ⊢ op : ComparisonOperator Γ ⊢ right : Value
+-------------------------------------------------------------------------------
+ Γ ⊢ AtomicConstraint(left, op, right) : Condition
+```
+
+Logical connectives follow standard typing rules for Boolean-valued expressions.
+
+---
+
+## 3. Abstract Syntax
+
+We define Adalbert's abstract syntax using a typed algebraic grammar.
+
+### 3.1 Syntactic Domains
+
+| Domain | Symbol | Description |
+|--------|--------|-------------|
+| Agents | **A** | Set of agent identifiers |
+| Actions | **X** | Set of action identifiers |
+| Assets | **S** | Set of asset identifiers |
+| Values | **V** | Set of atomic values (strings, numbers, URIs) |
+| Time | **T** | Time domain (ISO 8601 instants) |
+| Duration | **D** | Duration domain (ISO 8601 durations) |
+
+### 3.2 Norms
+
+```
+Norm ::= Permission(subject: Agent, action: Action, asset: Asset, condition: Condition?)
+ | Duty(subject: Agent, action: Action, asset: Asset,
+ object: Agent?, condition: Condition?, deadline: Deadline?, recurrence: Recurrence?)
+ | Prohibition(subject: Agent, action: Action, asset: Asset, condition: Condition?)
+
+Deadline ::= AbsoluteDeadline(time: Time)
+ | RelativeDeadline(duration: Duration)
+
+Recurrence ::= RRule(rule: String)
+```
+
+**Notes**:
+
+- `Permission` corresponds to `odrl:Permission`; `Prohibition` to `odrl:Prohibition`; `Duty` to `odrl:Duty`.
+- The formal `subject` parameter maps to `adalbert:subject` on duties (rdfs:subPropertyOf `odrl:assignee`) and to `odrl:assignee` on permissions/prohibitions.
+- The formal `object` parameter (duties only) maps to `adalbert:object` — the party affected by the duty action (e.g., who is notified). Not used in norm matching.
+- `AbsoluteDeadline`: Fixed point in time (e.g., 2026-12-31T23:59:59Z)
+- `RelativeDeadline`: Duration from activation (e.g., P30D, PT24H)
+
+**Abstract-to-RDF Name Mapping**:
+
+| Abstract Syntax | RDF Encoding | Notes |
+|---|---|---|
+| `Permission` | `odrl:Permission` | |
+| `Duty` | `odrl:Duty` | |
+| `Prohibition` | `odrl:Prohibition` | |
+| `subject` (Permission/Prohibition) | `odrl:assignee` | Party to whom the norm applies |
+| `subject` (Duty) | `adalbert:subject` | Party bearing the duty (rdfs:subPropertyOf odrl:assignee) |
+| `object` (Duty) | `adalbert:object` | Party affected by the duty action (metadata, not used in matching) |
+| `grantor` | `odrl:assigner` | Party granting rights |
+| `grantee` | `odrl:assignee` | Party receiving rights (policy-level) |
+| `condition` | `odrl:constraint` | |
+| `Set` | `odrl:Set` | |
+| `Offer` | `odrl:Offer` | `DataContract` is a subtype |
+| `Agreement` | `odrl:Agreement` | `Subscription` is a subtype |
+| `lte` | `odrl:lteq` | |
+| `gte` | `odrl:gteq` | |
+| `recurrence` | `adalbert:recurrence` | RFC 5545 RRULE string |
+
+### 3.3 Conditions
+
+```
+Condition ::= AtomicConstraint(leftOperand: LeftOperand,
+ operator: ComparisonOperator,
+ rightOperand: Value)
+ | And(operands: Condition+)
+ | Or(operands: Condition+)
+ | Not(operand: Condition)
+
+ComparisonOperator ::= eq | neq | lt | lte | gt | gte | isAnyOf | isNoneOf
+
+RuntimeRef ::= currentAgent | currentDateTime
+```
+
+**Notes**:
+
+- `leftOperand` is drawn from profile-defined operands with `resolutionPath`, or dual-typed `RuntimeReference` operands (e.g., `currentDateTime`)
+- Dynamic value resolution on the left side uses `LeftOperand` with `adalbert:resolutionPath` or dual-typed `RuntimeReference` operands resolved via `resolveRuntime`
+- Right operands are literal values. Identity binding via runtime references in right-operand position is deferred to RL2 (`rl2:rightOperandRef`)
+
+### 3.4 Policies
+
+```
+Policy ::= Set(target: Asset?, clauses: Norm+, condition: Condition?)
+ | Offer(grantor: Agent, grantee: Agent?, target: Asset?, clauses: Norm+, condition: Condition?)
+ | Agreement(grantor: Agent, grantee: Agent, target: Asset?, clauses: Norm+, condition: Condition?)
+```
+
+**Notes**:
+
+- `Set`: Unilateral declaration, no parties. Maps to `odrl:Set` in the RDF encoding.
+- `Offer`: Proposal from grantor, grantee optional (open offer). Maps to `odrl:Offer`. `DataContract` is a subtype of `Offer`.
+- `Agreement`: Bilateral binding, both parties identified. Maps to `odrl:Agreement`. `Subscription` is a subtype of `Agreement`.
+- The formal `grantor` parameter maps to `odrl:assigner` (the party granting rights) in the RDF encoding.
+- The formal `grantee` parameter maps to `odrl:assignee` (the party receiving rights) in the RDF encoding.
+
+### 3.5 Requests
+
+```
+Request ::= Request(agent: Agent, action: Action, asset: Asset, context: Context)
+
+Context ::= Map
+```
+
+**Note**: Context keys correspond to the second segment of resolution paths (e.g., the path `context.purpose` resolves by looking up `"purpose"` in `Context`).
+
+---
+
+## 4. Semantic Domains
+
+### 4.1 State
+
+```
+Σ = {
+ clock : Time,
+ state : Duty → State,
+ activatedAt : Duty → Time?, // When duty became Active
+ performed : Set<(Agent, Action, Asset, Time)>
+}
+
+State ::= Pending | Active | Fulfilled | Violated
+```
+
+**Notes**:
+
+- `State` is a unified lifecycle enum shared by duties, contracts, and subscriptions. The formal semantics tracks duty state during evaluation; contract and subscription state is administrative (not evaluated at request time).
+- Terminal states (`Fulfilled`, `Violated`) are permanent — see §9.4.
+
+**Initial state** Σ₀:
+
+```
+Σ₀ = {
+ clock = currentSystemTime,
+ state = λd. Pending,
+ activatedAt = λd. ⊥,
+ performed = ∅
+}
+```
+
+**State Update Notation**: We use `Σ[f ↦ v]` to denote state update:
+
+```
+Σ[state(d) ↦ Active] =
+ (Σ.clock, Σ.state[d ↦ Active], Σ.activatedAt, Σ.performed)
+
+Σ[state(d) ↦ Active, activatedAt(d) ↦ t] =
+ (Σ.clock, Σ.state[d ↦ Active], Σ.activatedAt[d ↦ t], Σ.performed)
+```
+
+### 4.2 Environment
+
+```
+Env = {
+ agent : Agent, // Canonical root: agent
+ action : Action,
+ asset : Asset, // Canonical root: asset
+ context : Context, // Canonical root: context
+ Σ : Σ
+}
+```
+
+The three canonical roots (`agent`, `asset`, `context`) are the entry points for `deref` path resolution (see §6.3).
+
+**Environment Construction**: Given a Request `R = (a, x, s, ctx)` and state Σ:
+
+```
+buildEnv(R, Σ) = {
+ agent = R.agent,
+ action = R.action,
+ asset = R.asset,
+ context = R.context,
+ Σ = Σ
+}
+```
+
+### 4.3 Decision
+
+```
+Decision ::= Permit | Deny | NotApplicable
+```
+
+### 4.4 Evaluation Result
+
+```
+Result = {
+ decision : Decision,
+ grantorDuties : Set, // Duties on the grantor (data provider)
+ granteeDuties : Set, // Duties on the grantee (data consumer)
+ violations : Set,
+ explanation : Explanation
+}
+```
+
+---
+
+## 5. Duty Lifecycle
+
+### 5.1 State Diagram
+
+```
+ condition becomes true
+ ┌─────────────────────────────────────┐
+ │ ▼
+ ┌───────┐ ┌────────┐
+ │Pending│ │ Active │
+ └───────┘ └────────┘
+ │ │
+ action performed │ │ deadline exceeded
+ ▼ ▼
+ ┌──────────┐ ┌─────────┐
+ │Fulfilled │ │Violated │
+ └──────────┘ └─────────┘
+```
+
+### 5.2 Transition Rules
+
+**Rule D-ACTIVATE** (Pending → Active):
+
+```
+Σ.state(duty) = Pending
+duty.condition = ⊥ ∨ ⟦duty.condition⟧(Env) = true
+─────────────────────────────────────────────────
+Σ' = Σ[state(duty) ↦ Active, activatedAt(duty) ↦ Σ.clock]
+```
+
+Activation is **condition-driven**: when the duty's condition first evaluates to true (or the duty has no condition), the duty becomes active.
+
+**Rule D-FULFILL** (Active → Fulfilled):
+
+```
+Σ.state(duty) = Active
+performed(duty.subject, duty.action, duty.asset, Σ) = true
+effectiveDeadline(duty, Σ) ≥ Σ.clock ∨ effectiveDeadline(duty, Σ) = ∞
+────────────────────────────────────────────────────────────────────────
+Σ' = Σ[state(duty) ↦ Fulfilled]
+```
+
+Fulfillment is **event-driven**: when a performed action matches the duty's required action (including narrower actions via `includedIn` subsumption), the duty is fulfilled.
+
+**Rule D-VIOLATE** (Active → Violated):
+
+```
+Σ.state(duty) = Active
+Σ.clock > effectiveDeadline(duty, Σ)
+performed(duty.subject, duty.action, duty.asset, Σ) = false
+────────────────────────────────────────────────────────────
+Σ' = Σ[state(duty) ↦ Violated]
+```
+
+Violation is **time-driven**: when the deadline passes without fulfillment, the duty is violated.
+
+**Algorithmic form** (for implementation):
+
+```
+updateDutyStates(duties, Env, Σ) =
+ foldl(updateOneDuty(Env), Σ, duties)
+
+updateOneDuty(Env)(Σ, d) =
+ case Σ.state(d) of
+ Pending → if d.condition = ⊥ ∨ ⟦d.condition⟧(Env)
+ then Σ[state(d) ↦ Active, activatedAt(d) ↦ Σ.clock]
+ else Σ
+ Active → if performed(d.subject, d.action, d.asset, Σ)
+ then Σ[state(d) ↦ Fulfilled]
+ else if Σ.clock > effectiveDeadline(d, Σ)
+ then Σ[state(d) ↦ Violated]
+ else Σ
+ _ → Σ -- Fulfilled/Violated are terminal
+```
+
+### 5.3 Effective Deadline
+
+```
+effectiveDeadline(duty, Σ) =
+ case duty.deadline of
+ ⊥ → ∞
+ AbsoluteDeadline(t) → t
+ RelativeDeadline(d) → Σ.activatedAt(duty) + d
+```
+
+### 5.4 Match Semantics
+
+Action and asset matching support hierarchy subsumption:
+
+```
+x₁ matches x₂ ⟺ x₁ = x₂ ∨ x₁ includedIn⁺ x₂
+s₁ matches s₂ ⟺ s₁ = s₂ ∨ s₁ partOf⁺ s₂
+```
+
+Where `includedIn⁺` and `partOf⁺` are the transitive closures of `odrl:includedIn` and `adalbert:partOf` respectively.
+
+Agent matching supports hierarchy subsumption:
+
+```
+a₁ matches a₂ ⟺ a₁ = a₂ ∨ a₁ memberOf⁺ a₂
+```
+
+Where `memberOf⁺` is the transitive closure of `adalbert:memberOf`.
+
+The subsumption-aware performed check is:
+
+```
+performed(a, x, s, Σ) :=
+ ∃(a', x', s', t) ∈ Σ.performed :
+ a' = a ∧ (x' = x ∨ x' includedIn⁺ x) ∧ s' matches s
+```
+
+`Σ.performed` records exact actions as they occur. `performed()` is the query-time subsumption check used in all fulfillment and violation rules. This is a bounded graph traversal over the `odrl:includedIn` hierarchy.
+
+### 5.5 Recurrence Semantics
+
+A duty with a `recurrence` field defines a recurring obligation. The recurrence value is an RFC 5545 RRULE string (e.g., `FREQ=DAILY;BYHOUR=6;BYMINUTE=0`).
+
+**Instance Generation**:
+
+```
+expand : Recurrence × Time → Set