id: https://optophi.com/pycharter/contracts/integration-dtos
name: pycharter_integration_dtos
title: PyCharter cross-package integration DTOs
description: |-
  Wire-format Data Transfer Objects for the opt-in handshake between
  pycharter and a decoupled sibling consumer (e.g. pyintake). Per the
  ``docs/proposals/cross-package-decoupling.md`` decision, neither
  package imports the other; both check in identical copies of this
  schema and derive their own Pydantic models locally. This file is
  the source of truth — the hand-authored Pydantic in
  ``src/pycharter/api/models/integration.py`` must be kept in sync
  with the shapes here.
license: Apache-2.0
version: 0.1.0

prefixes:
  linkml: https://w3id.org/linkml/
  pycharter: https://optophi.com/pycharter/

default_prefix: pycharter
default_range: string

imports:
  - linkml:types

# ---------------------------------------------------------------------------
# Subset roots (for documentation only — LinkML loaders treat them all
# as ordinary classes)
# ---------------------------------------------------------------------------

classes:

  ConceptCandidate:
    description: |-
      A single concept proposed by an external producer. May or may
      not exist in pycharter's concept registry already; the receiver
      decides whether to attach to an existing concept or auto-stage
      as a new candidate in the suggestion queue.
    slots:
      - concept_key
      - label
      - definition
      - tier_hint
      - confidence
      - evidence_refs
      - source_metadata

  RelationshipCandidate:
    description: |-
      A proposed relationship between two ``ConceptCandidate``s
      (keyed by ``concept_key``). The relationship type is
      free-form here; the receiver maps it onto its own
      relationship vocabulary at staging time.
    slots:
      - source_concept_key
      - target_concept_key
      - relationship_type
      - evidence_refs

  SuggestionBatch:
    description: |-
      A batch of concept and relationship candidates produced by an
      external synthesis run. Accepted at
      ``POST /api/v1/inbound/suggestions``; persisted into the
      governed suggestion queue.
    slots:
      - schema_version
      - batch_id
      - source_scheme
      - source_run_id
      - produced_at
      - actor
      - candidates
      - relationships

  SuggestionBatchReceipt:
    description: |-
      Server-side acknowledgment of a ``SuggestionBatch``. Counts
      how many candidates landed cleanly, how many were auto-staged
      as new (FREE-tier) suggestions, and how many were rejected with
      reasons. ``suggestion_ids`` is the inbound producer's
      back-reference to follow the lifecycle of each accepted item.
    slots:
      - schema_version
      - batch_id
      - accepted_count
      - auto_staged_count
      - rejected
      - suggestion_ids

  RejectionReason:
    description: |-
      Why a single inbound candidate was not staged. ``code`` is a
      stable identifier; ``detail`` is a human-readable message.
    slots:
      - concept_key
      - code
      - detail

  ContractSnapshot:
    description: |-
      A stable, versioned read-view of a pycharter contract for
      consumption by a sibling package's context-building code.
      Mirrors ``ContractConfig`` but carries the contract's
      ``format_version`` (DG-2) as a top-level field so receivers
      can refuse unknown formats fast.
    slots:
      - schema_version
      - contract_id
      - version
      - format_version
      - schema_payload
      - domain_schema
      - field_bindings
      - extraction_policy
      - ai_usage_policy

  FieldBindingDoc:
    description: |-
      Per-field semantic binding included in a ``ContractSnapshot``.
      Carries the primary target (LinkML class/slot or concept key)
      and its source ontology. Receivers should treat this as
      read-only context, never as a write target.
    slots:
      - field_path
      - primary_concept_key
      - primary_linkml_class
      - primary_linkml_slot
      - primary_concept_scheme
      - tags

  # -------------------------------------------------------------------------
  # Channel 1 — GroundedRecord stream (KB enrichment)
  # -------------------------------------------------------------------------

  GroundedRecord:
    description: |-
      One contract-validated record emitted to the knowledge-base
      substrate (Channel 1). Grounded (per-field concept pointers),
      policy-tagged, and provenance-stamped. Consumers ingest these as
      durable, bitemporal facts.
    slots:
      - schema_version
      - record_id
      - entity_ref
      - contract
      - produced_at
      - provenance
      - fields
      - ai_usage_policy_ref
      - content_hash

  ContractRef:
    description: |-
      Minimal reference to the pycharter contract that produced a
      ``GroundedRecord``.
    slots:
      - id
      - version
      - format_version

  Provenance:
    description: |-
      Pipeline provenance for a ``GroundedRecord``: which run / step /
      pipeline produced it, plus an optional source URI.
    slots:
      - run_id
      - step_id
      - pipeline_id
      - source_uri

  GroundedField:
    description: |-
      One field of a ``GroundedRecord``: its bound concept pointer,
      entity-modelling role, policy-gated value, optional match token,
      and per-field policy.
    slots:
      - field_path
      - concept_key
      - concept_scheme
      - role
      - value
      - value_type
      - match_token
      - referenced_entity_ref
      - binding_confidence
      - field_policy
    slot_usage:
      concept_key:
        required: false
        description: |-
          The bound concept's key (a resolvable pointer), or absent for
          unbound fields.

  FieldPolicy:
    description: |-
      Per-field governance flags controlling how a ``GroundedField`` may
      be used by AI consumers.
    slots:
      - embeddable
      - pii
      - redacted
      - match_mode

  VerificationReference:
    description: |-
      Metadata-only report of one persisted verification for an external
      action host. A receipt ID is not an action authorization token. Hosts
      resolve it through an authenticated read and apply their own policy.
    slots:
      - schema_version
      - receipt_id
      - contract_namespace
      - contract_name
      - contract_version
      - verdict
      - context_fingerprint
      - verified_at

# ---------------------------------------------------------------------------
# Slot definitions
# ---------------------------------------------------------------------------

slots:

  schema_version:
    description: |-
      Version of THIS schema (the integration DTO catalog), e.g.
      "0.1". Receivers reject batches whose schema_version is outside
      the supported range.
    range: string
    required: true

  batch_id:
    description: Client-generated UUID for idempotency.
    range: string
    required: true

  source_scheme:
    description: |-
      Scheme key in the producer's vocabulary, for traceability only.
      The receiver does NOT use this to map concepts — its own
      scheme is selected via the receiving endpoint's auth context
      or config.
    range: string

  source_run_id:
    description: Producer-side run identifier, propagated to provenance.
    range: string

  produced_at:
    description: ISO 8601 timestamp the batch was produced.
    range: datetime

  actor:
    description: Audit tag for who/what produced the batch.
    range: string

  candidates:
    description: Zero or more concept candidates.
    range: ConceptCandidate
    multivalued: true
    inlined_as_list: true

  relationships:
    description: Zero or more relationship candidates.
    range: RelationshipCandidate
    multivalued: true
    inlined_as_list: true

  concept_key:
    description: Stable identifier in the producer's vocabulary.
    range: string
    required: true

  label:
    description: Human-readable display name.
    range: string

  definition:
    description: One-line description of the concept.
    range: string

  tier_hint:
    description: |-
      Suggested tier for staging ("core", "domain", "free"). The
      receiver may override based on its own governance policy.
    range: TierEnum

  confidence:
    description: Producer's confidence score in [0, 1].
    range: float
    minimum_value: 0.0
    maximum_value: 1.0

  evidence_refs:
    description: |-
      Producer-side references to the evidence backing this
      candidate (e.g. "doc:abc#chunk:42"). Opaque to the receiver.
    range: string
    multivalued: true

  source_metadata:
    description: |-
      Producer-defined free-form metadata. Stored under provenance
      on the suggestion row; not interpreted by the receiver.
    range: string

  source_concept_key:
    description: The originating concept (must appear in ``candidates``).
    range: string
    required: true

  target_concept_key:
    description: The target concept (must appear in ``candidates``).
    range: string
    required: true

  relationship_type:
    description: |-
      Producer-side relationship label (e.g. "has_values",
      "is_a", "exact_match"). The receiver maps to its own
      vocabulary on accept.
    range: string
    required: true

  accepted_count:
    description: Number of candidates that matched an existing concept.
    range: integer
    required: true

  auto_staged_count:
    description: Number of candidates staged as new FREE-tier suggestions.
    range: integer
    required: true

  rejected:
    description: One entry per rejected candidate.
    range: RejectionReason
    multivalued: true
    inlined_as_list: true

  suggestion_ids:
    description: |-
      Pycharter-side suggestion row ids for every accepted /
      auto-staged candidate, in the same order as ``candidates``.
    range: string
    multivalued: true

  code:
    description: Stable rejection-code identifier.
    range: string
    required: true

  detail:
    description: Human-readable rejection detail.
    range: string

  contract_id:
    description: Pycharter contract identifier.
    range: string
    required: true

  version:
    description: Contract version (semver).
    range: string
    required: true

  format_version:
    description: |-
      Pycharter's DG-2 artifact format version on this contract.
      Receivers refuse formats they don't recognise.
    range: string
    required: true

  schema_payload:
    description: The contract's inline JSON Schema.
    range: string

  domain_schema:
    description: |-
      Optional ``name:version`` reference to the contract's primary
      LinkML vocabulary.
    range: string

  field_bindings:
    description: One ``FieldBindingDoc`` per field bound on this contract.
    range: FieldBindingDoc
    multivalued: true
    inlined_as_list: true

  extraction_policy:
    description: |-
      The contract's declared ``ExtractionPolicy`` as a JSON object,
      when one is declared: whether and when concept extraction fires,
      which extractors are permitted, and the tier ceiling for the
      suggestions produced. Consumers that run extraction MUST read it —
      a contract declaring no policy has not consented to extraction.
      Optional and additive (stays within schema_version 0.1).
    range: string

  ai_usage_policy:
    description: |-
      The contract's declared ``AIUsagePolicy`` (CF-1 shape) as a JSON
      object, when one is declared. Consumers that embed, index, or
      otherwise feed contract data to AI systems MUST read and obey
      this policy. Optional and additive — absent on contracts that
      declare no policy (GV-106; stays within schema_version 0.1).
    range: string

  field_path:
    description: The contract field path.
    range: string
    required: true

  primary_concept_key:
    description: |-
      Concept-target primary binding's ``concept_key``. Mutually
      exclusive with ``primary_linkml_class`` + ``primary_linkml_slot``.
    range: string

  primary_linkml_class:
    description: LinkML class name for primary class/slot bindings.
    range: string

  primary_linkml_slot:
    description: LinkML slot name for primary class/slot bindings.
    range: string

  primary_concept_scheme:
    description: "``name:version`` of the concept scheme the primary lives in."
    range: string

  tags:
    description: Free-form tags on the binding.
    range: string
    multivalued: true

  # GroundedRecord (Channel 1) slots

  record_id:
    description: Globally unique record identifier (e.g. "orders@2.1/r-88f2").
    range: string
    required: true

  entity_ref:
    description: |-
      The record's own entity, minted from its identity-role field
      (e.g. "customer:C-1001"); absent when no identity is declared.
    range: string

  contract:
    description: Reference to the producing contract.
    range: ContractRef
    inlined: true
    required: true

  provenance:
    description: Pipeline provenance for the record.
    range: Provenance
    inlined: true
    required: true

  fields:
    description: The record's grounded fields.
    range: GroundedField
    multivalued: true
    inlined_as_list: true
    required: true

  ai_usage_policy_ref:
    description: |-
      Pointer to the governing AIUsagePolicy; the full policy is
      resolved out-of-band by the consumer.
    range: string

  content_hash:
    description: SHA-256 over the canonical record body; the consumer's idempotency key.
    range: string
    required: true

  id:
    description: Pycharter contract identifier.
    range: string
    required: true

  run_id:
    description: Pipeline run identifier.
    range: string
    required: true

  step_id:
    description: Pipeline step identifier.
    range: string

  pipeline_id:
    description: Contributing pipeline identifier (lineage / drift).
    range: string

  source_uri:
    description: Optional URI of the record's source.
    range: string

  concept_scheme:
    description: "``name:version`` of the bound concept's scheme."
    range: string

  role:
    description: |-
      Entity-modelling role of the field's binding
      (identity / reference / attribute).
    range: string

  value:
    description: |-
      JSON-encoded typed value. Policy-gated: omitted / redacted for
      restricted fields.
    range: string

  value_type:
    description: Logical value type (string, integer, decimal, date, ...).
    range: string

  match_token:
    description: |-
      Salted HMAC join key; present only when ``match_mode`` is "token".
      A linking key only — never surfaced to agents.
    range: string

  referenced_entity_ref:
    description: The entity this field references; present only when role is "reference".
    range: string

  binding_confidence:
    description: Binding confidence in [0, 1].
    range: float
    minimum_value: 0.0
    maximum_value: 1.0

  field_policy:
    description: Per-field governance policy.
    range: FieldPolicy
    inlined: true
    required: true

  embeddable:
    description: Whether this field may be embedded for semantic search.
    range: boolean
    required: true

  pii:
    description: Whether this field carries PII.
    range: boolean
    required: true

  redacted:
    description: Whether the value was redacted at source.
    range: boolean
    required: true

  match_mode:
    description: How the field may be used for entity linking (raw / token / none).
    range: string
    required: true

  receipt_id:
    description: Opaque identifier of a persisted verification receipt.
    range: string
    required: true

  contract_namespace:
    description: |-
      Namespace of the exact contract version; JSON null means the global
      namespace. The JSON key is required even though LinkML treats null as
      an absent value.
    range: string
    annotations:
      wire_required_nullable: true

  contract_name:
    description: Name of the exact contract version that was verified.
    range: string
    required: true

  contract_version:
    description: Immutable version of the contract that was verified.
    range: string
    required: true

  verdict:
    description: Completed contract-verification result; errors have no verdict.
    range: VerificationVerdictEnum
    required: true

  context_fingerprint:
    description: Fingerprint of the governed context and effective policy projection.
    range: string
    required: true
    pattern: ^sha256:[0-9a-f]{64}$

  verified_at:
    description: Timezone-aware timestamp when verification completed.
    range: datetime
    required: true

# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------

enums:

  TierEnum:
    description: |-
      Pycharter's three concept tiers. Producers may suggest a tier;
      receivers govern the final landing tier.
    permissible_values:
      core:
        description: Canonical, governed concepts.
      domain:
        description: Team-owned, governed within their domain.
      free:
        description: Unmoderated; default landing for new suggestions.

  VerificationVerdictEnum:
    description: Completed contract-verification verdicts.
    permissible_values:
      accepted:
        description: The exact executable contract rules passed.
      rejected:
        description: The candidate did not pass the executable contract rules.
