Skip to content

Latest commit

 

History

History
171 lines (140 loc) · 9.82 KB

File metadata and controls

171 lines (140 loc) · 9.82 KB

Changelog

Notable changes to dds.yaml (the Data Definition Specification LinkML schema). Format loosely follows Keep a Changelog. The schema is not yet semver-versioned, so entries are dated.

[Unreleased] — DDS repositioning (standards-agnostic) — 2026-06-25

Repositions the schema as a standards-agnostic canonical model: ODM/Define-XML is one serialization facet applied by the output generator, not the source of the model. Applied as a series of atomic commits; each change validated with gen-linkml. Breaking (class/slot renames). Generated docs need a make docs refresh and downstream instances must migrate renamed names.

Fixed (§1)

  • Moved the required-OID slot_usage from the Governed mixin (which does not inherit Identifiable, where OID is defined) to GovernedElement (§1.2).
  • Demoted OMOP era mappings on Timing from narrow_mappings (false OWL subsumption) to related_mappings; kept FHIR Period/Age/Duration as narrow (§1.3).
  • Removed invalid from_schema: ncit:C… from OriginType/OriginSource (it must be a schema URI); provenance preserved in descriptions (§1.4).

Changed — identity (§0)

  • Neutral schema id (https://w3id.org/dds) and default_prefix: dds (added dds prefix) replacing the cdisc.org/odm defaults; description reframed as standards-agnostic. (Neutral namespace chosen over the doc's cdisc.org.)

Changed — renames (§2)

  • ReifiedConceptConcept; MetaDataVersionSpecification (tree_root); WhereClauseApplicabilityCondition (+ whereClauses slot → applicabilityConditions); ConditionLogicalPredicate (+ conditions slots → predicates/validationPredicates, collectionExceptionConditioncollectionExceptionPredicate, implementsConditionimplementsPredicate; external usdm:Condition/odm:ConditionDef mappings preserved); ODMFileMetadataODMSerializationMetadata; IsODMItemODMItemSerialization; IsODMStandardODMStandardReference.

Changed — structure (§3)

  • Detached ODMSerializationMetadata from Specification and ODMItemSerialization from Item (generator-applied, not canonical) (§3.1/§3.2).
  • Replaced NominalOccurrence (planned/actual conflation) with a TimingLandmark enum + free-form USDM ScheduledActivityInstance reference on Timing.relativeTo/relativeFrom (§3.3).
  • Added Specification.usdmStudyDesignId (defer study design to USDM) (§3.4).
  • Flipped Dataflow.analysisMethodAnalysis.inputDataflows (correct dependency direction) (§3.5).
  • Annotated ItemGroupType.ValueList as an ODM serialization hint (§3.6).

[Unreleased] — Queries, reusable checks, key split — 2026-06-25

Backward-compatible / additive. New classes/slots/enum only; one slot repurposed (keySequence) with a new sibling added. No existing instances populate the affected slots. Verified: gen-linkml and linkml-lint pass.

Added

  • Class Query (is_a GovernedElement, close_mappings: odm:Query): a reified, externally referenced query linked many-to-many to metadata and/or data elements via about (non-inlined OID references), with queryType, text, status, source. Catalogued in the new MetaDataVersion.queries collection (#2).
  • Class Check (is_a GovernedElement): a reusable validation check (e.g. a published CORE rule) linked many-to-many via appliesTo (non-inlined), with publishedBy, externalReference (uri/curie), severity, and optional expressions. Catalogued in the new MetaDataVersion.checks collection. RangeCheck.implementsCheck references a Check to connect inline checks to the reusable rule they implement (#1).
  • Enum QueryType (Internal/External) for Query.queryType (#2).
  • ItemGroup.uniqueKey: unordered set of Items establishing record uniqueness (carries the odm:ItemRef.KeySequence mapping) (#12).

Changed

  • ItemGroup.keySequence repurposed to mean sort order only (ordered, may include non-key Items); uniqueness moved to the new uniqueKey. Resolves the prior overloading of one slot for sorting + uniqueness + merge (#12).

[Unreleased] — DTA enablement — 2026-06-24

Backward-compatible / additive only. No classes or slots were removed, no new required fields were added to existing classes, and no inlining was changed on any slot used by existing instances. Verified: the full define files still load and validate, and examples/concept_method_example.json (the only file using the concept slots) is unaffected. Net change +209 lines (2562 → 2771).

Why

Representing a Data Transfer Agreement (DTA) exposed three structural gaps:

  1. A DTA could not be serialised as a self-contained artifact. ProvisionAgreement existed, but its provider/dataFlow/source were non-inlined references with no container reachable from the tree root — so the agreement couldn't hold its own parts.
  2. No agreement-level delivery timing. Timing existed only on concrete Dataset reporting periods, not as a transfer schedule on the flow/agreement.
  3. No structured home for legal/governance terms. hasPolicy was untyped, there was no DataConsumer (asymmetric with DataProvider), and confidentiality/permitted-use/ retention terms were unmodelled.

Design decisions taken (with the user, as a peer): the DTA is a standalone artifact that embeds a frozen snapshot of the agreed structure and links to the live spec for provenance; the canonical concept layer is referenced (Registry), not embedded; legal terms use ODRL; the schedule default is a domain-neutral ISO-8601 string so the model stays clinical-first but horizontal-ready.

Added

  • Prefix odrl (http://www.w3.org/ns/odrl/2/). Reason: legal terms are modelled with ODRL; the schema already used DPROD/DCAT, which express policy via ODRL.
  • ProvisionAgreement.hasPolicyPolicy (multivalued, inlined). Reason: the agreement is the legal instrument but previously had nowhere to carry its terms (gap 3).
  • Dataflow.deliveryScheduleany_of [string, Timing] (multivalued, inlined). Reason: agreement-level transfer cadence (gap 2). Default is an ISO-8601 repeating interval string (neutral); Timing remains available for clinical anchoring. Concrete reporting periods stay on Dataset via IsSdmxDataset.*.
  • DataProduct.provisionAgreementProvisionAgreement (multivalued, not inlined). Reason: lets a data product catalogue the DTAs governing its flows by OID/URI, while the DTA stays an independently maintained artifact.
  • Class DataConsumer (is_a Organization, close_mappings: sdmx:DataConsumer). Reason: restores symmetry with DataProvider; gives the demand side a typed home (consumesDataFrom, provisionAgreements) (gap 3).
  • Class Policy (exact_mappings: odrl:Policy, close_mappings: dcat:hasPolicy) with policyType, profile, assigner, assignee, and permission/prohibition/ obligation rule lists. Reason: structured legal terms for the DTA (gap 3).
  • Class Rule (odrl:Rule) with action, target, assigner/assignee, constraint. Reason: ODRL permission/prohibition/duty semantics.
  • Class Constraint (odrl:Constraint) with leftOperand/operator/rightOperand/ unit. Reason: expresses conditions such as purpose eq "safety-reporting".
  • Enum PolicyType (Set/Offer/Agreement, mapped to ODRL). Reason: typed Policy.policyType; a DTA is an ODRL Agreement.
  • Enum ConstraintOperator (eq/neq/lt/lteq/gt/gteq/isPartOf/isA/ isAnyOf/isNoneOf, mapped to ODRL). Reason: typed Constraint.operator.

Changed

  • ProvisionAgreement.provider, .dataFlow, .sourceinlined: true and Dataflow.structureinlined: true. Reason: a standalone DTA must be a self-contained, signable snapshot (gap 1). These slots are not used by existing instances, so the change is non-breaking.
  • ProvisionAgreement.consumer any_of now includes DataConsumer (ahead of DataProduct/Organization/string). Reason: allow the typed consumer; existing string/Organization values remain valid.
  • Dataset.hasPolicy and DataProduct.hasPolicyrange: Policy. Reason: both were untyped (no range); typing them makes governance terms machine-checkable. No existing file populated these slots, so no migration is needed.

Fixed

  • Declared the ncit prefix (http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#). Reason: ncit:* CURIEs were used in enum meanings but the prefix was undeclared (#14).
  • Parameter.required.ifabsent and DataStructureDefinition.evolvingStructure.ifabsent changed from the bare boolean false to the string 'False'. Reason: the metamodel types ifabsent as string/null, so an unquoted boolean failed validation (#23).
  • Analysis.analysisMethod: moved any_of out of the description text (it was indented under it, so it was inert) and set range: Method; the previously referenced AnalysisMethod class does not exist (#17).
  • Standardised string-type declarations: added schema-level default_range: string and removed the 52 redundant explicit range: string slot facets. any_of members (- range: string) are retained as they are explicit union alternatives. Semantically identical to the prior state, so no instances are affected (#13).

Notes / follow-ups

  • The schema has no version field; consider adding one to make changes citable.
  • Generated docs under docs/ are produced from the schema and need a gen-doc refresh to include the new classes.
  • A pinned copy of this schema lives in the data-definition-dta skill bundle (reference/define.yaml) and should be re-synced when the canonical schema changes.