# GENERATED by governance/data_contract.py — do not edit.
#
# Regenerate:  python -m governance.data_contract --write
# Check:       python -m governance.data_contract --check
#
# Everything below is read from a register that already gates the build: the licence register
# (docs/LICENSE_REGISTER.md), the catalogue (catalog/products.py), the published dictionary
# (pipelines/publish/release.py), the freshness SLAs (quality/freshness_sla.yml) and the release
# floors (quality/floors.yml). Editing this file by hand makes it disagree with the pipeline it
# describes, which is the one thing a data contract must never do.
dataContractSpecification: 1.1.0
id: certvas-af-fund
info:
  title: African Company Fundamentals
  version: '2026.11'
  description: Point-in-time company fundamentals from primary filings, never exchange price feeds.
  owner: Certvas
  contact:
    name: Certvas
    email: mandase@certvas.com
    url: https://certvas.com/skus/af-fund.html
terms:
  usage: "Licensed per the Certvas Data Licence Agreement. Every row carries `license_class`, the register\
    \ code governing permitted use of the SOURCE it was extracted from — redistribution rights differ\
    \ per source and the register is authoritative:\n  - S001 GLEIF LEI Golden Copy (L1+L2) — CLEARED;\
    \ basis: CC0\n  - S009 African issuer annual reports / IR pages (company-published PDFs) — CLEARED_EXTRACT_ONLY;\
    \ basis: Facts extracted from public disclosures\n  - S012 Manually-curated public issuer identities\
    \ (non-LEI) — CLEARED; basis: Public fact (name + jurisdiction + exchange ticker from public exchange\
    \ listings)"
  limitations: "Derived from primary filings and official publications, never from exchange price feeds;\
    \ Certvas holds no market-data licence and publishes no prices. Source conditions that travel with\
    \ the data:\n  - S001: None\n  - S009: Extract facts only; no document republication; respect robots/ToS\
    \ per site; keep source PDF ref in raw for provenance\n  - S012: Identity facts only — no natural\
    \ persons; each seed row cites its public listing; used only to give a non-LEI issuer a `dataco_id`\
    \ so its S009 filings can be extracted\nAudit basis is not a column (added 2026-09-15). A vintage\
    \ is one published document, and an issuer's FIRST vintage can be an unaudited full-year results announcement,\
    \ with the audited statements arriving later as a restatement (a later `vintage_seq`, `restated` set\
    \ on the earlier row). Known case: Oando PLC FY2023, unaudited results May 2024 (net income 74,723,154\
    \ thousand naira) against audited statements November 2024 (60,277,168 thousand naira). `source_ref`\
    \ names the document behind every value."
  billing: Certvas — African Company Fundamentals Sample (free) — FREE; Certvas — African Company Fundamentals
    (AF-FUND) — $129
  noticePeriod: P30D
models:
  gold_fundamentals:
    description: African Company Fundamentals — gold_fundamentals.
    type: table
    fields:
      dataco_id:
        type: string
        description: Stable canonical issuer key (LEI-anchored, or documented seed key for non-LEI issuers).
      period_end:
        type: date
        description: Reporting period end date.
      period_type:
        type: string
        description: FY / H1 / Qn — derived from the calendar against the issuer's fiscal year-end.
      statement:
        type: string
        description: income_statement / balance_sheet / cash_flow / per_share.
      line_item:
        type: string
        description: Taxonomy code, e.g. revenue, net_income, total_assets, eps_basic.
      value_reported:
        type: double
        description: Value in actual units (reporting scale applied; EPS left per-share).
      currency_reported:
        type: string
        description: ISO currency as printed in the source.
      value_usd:
        type: double
        description: CONVENIENCE ONLY — value_reported converted to USD. Null where no rate is cited.
          Reconcile and cite against value_reported + currency_reported, which are the as-reported figures;
          see conversion_ref for the rate used.
      conversion_ref:
        type: string
        description: The FX rate behind value_usd — source, rate and date. Null wherever value_usd is
          null. A converted figure with no citable rate is not published.
      extraction_confidence:
        type: double
        description: 0-1 model confidence for the extracted value.
      source_page:
        type: long
      source_doc_hash:
        type: string
      record_ref:
        type: string
        description: Stable id for this OBSERVATION (vintage), deterministic across rebuilds.
      vintage_seq:
        type: long
        description: 1 = originally filed, 2.. = each later restatement of the same key.
      is_as_reported:
        type: boolean
      restated:
        type: boolean
        description: A later vintage carries a DIFFERENT value for this key. Derived by comparing vintages;
          a re-observation of the same number is not a restatement.
      superseding_record_ref:
        type: string
        description: record_ref of the earliest later vintage that changed the value. Resolves within
          this table.
      observed_at:
        type: timestamp_tz
        description: When dataco captured the value.
      announcement_date:
        type: date
        description: AVAILABILITY date — when the filing became public. Null where no evidence tier produced
          a plausible date; never guessed.
      announcement_source:
        type: string
        description: 'Evidence tier behind announcement_date, in descending trust: disclosed (publication
          date stated by the issuer/exchange) / http_last_modified (the host''s Last-Modified for the
          filing) / pdf_creation_date (the PDF''s own metadata). Weight or exclude the weaker tiers as
          you see fit.'
      available_at:
        type: date
        description: FILTER AS-OF QUERIES ON THIS. coalesce(announcement_date, observed_at); never null.
          Where the announcement date is unevidenced it falls back to our own capture date, which is always
          LATER than true publication for a backfilled filing — so the fallback can only exclude a row
          from a window, never admit one before it was knowable.
      filing_lag_days:
        type: long
        description: announcement_date - period_end. Null where the announcement date is unevidenced —
          never defaulted to 0, because a lag measured against our capture date would describe when Certvas
          backfilled, not how fast the issuer reports. Per-market distributions ship in gold_filing_lag_stats.
      source_ref:
        type: string
        description: Source document hash + page, traceable to the filing.
      license_class:
        type: string
        description: License Register code governing permitted use of the source.
      valid_from:
        type: date
      valid_to:
        type: date
    quality: &id001
    - type: custom
      engine: certvas
      description: 'arithmetic cross-validation pass rate: min 0.8. Enforced by exports/release_gate.py
        — below its floor a release auto-HOLDs and does not publish.'
      specification: arithmetic_pass_rate min 0.8
    - type: custom
      engine: certvas
      description: 'dual-model agreement rate: min 0.95. Enforced by exports/release_gate.py — below its
        floor a release auto-HOLDs and does not publish.'
      specification: dual_model_agreement_rate min 0.95
    - type: custom
      engine: certvas
      description: 'minimum extraction confidence: min 0.85. Enforced by exports/release_gate.py — below
        its floor a release auto-HOLDs and does not publish.'
      specification: extraction_confidence_min min 0.85
    - type: custom
      engine: certvas
      description: 'Soda check failures: max 0. Enforced by exports/release_gate.py — below its floor
        a release auto-HOLDs and does not publish.'
      specification: soda_failures max 0
    - type: custom
      engine: certvas
      description: 'Pandera schema failures: max 0. Enforced by exports/release_gate.py — below its floor
        a release auto-HOLDs and does not publish.'
      specification: pandera_failures max 0
    - type: custom
      engine: certvas
      description: 'Arelle XBRL validation errors: max 0. Enforced by exports/release_gate.py — below
        its floor a release auto-HOLDs and does not publish.'
      specification: arelle_errors max 0
  gold_fundamentals_as_reported:
    description: African Company Fundamentals — gold_fundamentals_as_reported.
    type: table
    fields:
      dataco_id:
        type: string
        description: Stable canonical issuer key (LEI-anchored, or documented seed key for non-LEI issuers).
      period_end:
        type: date
        description: Reporting period end date.
      period_type:
        type: string
        description: FY / H1 / Qn — derived from the calendar against the issuer's fiscal year-end.
      statement:
        type: string
        description: income_statement / balance_sheet / cash_flow / per_share.
      line_item:
        type: string
        description: Taxonomy code, e.g. revenue, net_income, total_assets, eps_basic.
      value_reported:
        type: double
        description: Value in actual units (reporting scale applied; EPS left per-share).
      currency_reported:
        type: string
        description: ISO currency as printed in the source.
      value_usd:
        type: double
        description: CONVENIENCE ONLY — value_reported converted to USD. Null where no rate is cited.
          Reconcile and cite against value_reported + currency_reported, which are the as-reported figures;
          see conversion_ref for the rate used.
      conversion_ref:
        type: string
        description: The FX rate behind value_usd — source, rate and date. Null wherever value_usd is
          null. A converted figure with no citable rate is not published.
      extraction_confidence:
        type: double
        description: 0-1 model confidence for the extracted value.
      source_page:
        type: long
      source_doc_hash:
        type: string
      record_ref:
        type: string
        description: Stable id for this OBSERVATION (vintage), deterministic across rebuilds.
      was_later_restated:
        type: boolean
      superseding_record_ref:
        type: string
        description: record_ref of the earliest later vintage that changed the value. Resolves within
          this table.
      observed_at:
        type: timestamp_tz
        description: When dataco captured the value.
      announcement_date:
        type: date
        description: AVAILABILITY date — when the filing became public. Null where no evidence tier produced
          a plausible date; never guessed.
      announcement_source:
        type: string
        description: 'Evidence tier behind announcement_date, in descending trust: disclosed (publication
          date stated by the issuer/exchange) / http_last_modified (the host''s Last-Modified for the
          filing) / pdf_creation_date (the PDF''s own metadata). Weight or exclude the weaker tiers as
          you see fit.'
      available_at:
        type: date
        description: FILTER AS-OF QUERIES ON THIS. coalesce(announcement_date, observed_at); never null.
          Where the announcement date is unevidenced it falls back to our own capture date, which is always
          LATER than true publication for a backfilled filing — so the fallback can only exclude a row
          from a window, never admit one before it was knowable.
      filing_lag_days:
        type: long
        description: announcement_date - period_end. Null where the announcement date is unevidenced —
          never defaulted to 0, because a lag measured against our capture date would describe when Certvas
          backfilled, not how fast the issuer reports. Per-market distributions ship in gold_filing_lag_stats.
      source_ref:
        type: string
        description: Source document hash + page, traceable to the filing.
      license_class:
        type: string
        description: License Register code governing permitted use of the source.
    quality: *id001
servicelevels:
  freshness:
    description: "Maximum age of the newest observation, per table, from quality/freshness_sla.yml. Suspensions\
      \ are stated rather than hidden:\n  - gold_fundamentals: 2 days"
    timestampField: observed_at
  availability:
    description: 'No uptime commitment. Certvas is a sole trader and the API is best-effort: automated
      checks alert the founder when it fails, but there is no on-call rota. Data is delivered as versioned
      files, which do not depend on the API being up.'
  support:
    description: No contractual response time. One person, one time zone (Africa/Gaborone, UTC+2). mandase@certvas.com
      is read daily on working days.
  backup:
    description: No stated recovery objective. Raw source documents are immutable and archived; a published
      pack is reproducible from them, but no RTO or RPO is promised.
  retention:
    description: No deletion schedule. Published versions are permanent by design — a point-in-time dataset
      whose history can be withdrawn is not point-in-time. Superseded versions stay resolvable via their
      DOI.
