# 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-tender
info:
  title: African Public Procurement
  version: '2026.09'
  description: Zambian and South African public tenders normalised onto OCDS, licence-clean.
  owner: Certvas
  contact:
    name: Certvas
    email: mandase@certvas.com
    url: https://certvas.com/skus/af-tender.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  - S007 South Africa OCPO Transparency Portal (eTenders) — CLEARED; basis: Explicit\
    \ open license incl. commercial use\n  - S034 Nigeria NOCOPO federal OCDS (BPP) — CLEARED; basis:\
    \ ODC-PDDL — publisher's own licence page names PDDL with Share/Create/Adapt grants (VERIFIED 2026-08-08,\
    \ evidence docs/licenses/S034/); site Terms-page boilerplate conflict recorded in evidence — /license\
    \ is the data-directed instrument\n  - S043 Zambia ZPPA e-GP OCDS — CLEARED; basis: ODC-PDDL — publisher's\
    \ OWN licence page (zppa.org.zm/ocds-license) names the ODC Public Domain Dedication and Licence with\
    \ Share/Adapt grants — strongest possible grant, commercial reuse unrestricted (VERIFIED 2026-08-09,\
    \ evidence docs/licenses/S043/). OCP registry lists CC BY 4.0 (discrepancy recorded; both permit commercial\
    \ reuse — the publisher's data-directed /ocds-license controls). Same instrument as Nigeria S034."
  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  - S007: Attribution; OCDS format\n  - S034: Attribution to BPP good\
    \ practice; date-sanity + ocid-dedupe guardrails REQUIRED before first run (award dates 1949–2919,\
    \ 93 bad ocid prefixes, batch release-dates); federal completeness caveat in SKU docs; PDF /license\
    \ at first ingest; changedetection watch on /license; no natural persons\n  - S043: Attribution to\
    \ ZPPA good practice (CC-BY 4.0 conservative fallback → encode attribution regardless); OCDS date-sanity\
    \ + ocid-dedupe guardrails per S034 before first run; no natural persons"
  billing: Certvas — African Public Procurement Sample (free) — FREE; Certvas — African Public Procurement
    (AF-TENDER) — $129
  noticePeriod: P30D
models:
  gold_tender:
    description: African Public Procurement — gold_tender.
    type: table
    fields:
      ocid:
        type: string
        description: Open Contracting ID — globally unique process identifier.
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      tender_id:
        type: string
      title:
        type: string
        description: Tender title as published.
      status:
        type: string
        description: Tender status from the OCDS release.
      category:
        type: string
        description: Procurement category (goods / works / services).
      sector:
        type: string
      sector_source:
        type: string
      value_amount:
        type: double
        description: 'Tender value exactly as published — NOT normalised. SA eTenders (S007) sends 0 on
          every release rather than omitting the field, so a 0 here means ''not disclosed'', not ''no
          value''. The roll-up tables apply that reading: they sum only positive amounts and report NULL
          where a group discloses none.'
      value_currency:
        type: string
        description: ISO currency of the value, as published; may be stated even where no amount is. In
          the roll-up tables this column reports 'MIXED' when a group spans more than one currency, and
          the group's total is NULL — values are never summed across currencies and no FX conversion is
          applied.
      release_date:
        type: timestamp_ntz
        description: OCDS release date.
      tender_start:
        type: timestamp_ntz
      tender_end:
        type: timestamp_ntz
      buyer_name:
        type: string
        description: Procuring entity (organization only).
      buyer_id:
        type: string
      observed_at:
        type: timestamp_tz
      source_ref:
        type: string
        description: Reference back to the OCDS release package.
      license_class:
        type: string
        description: License Register code (OCDS feed is openly licensed).
    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_tender_award:
    description: African Public Procurement — gold_tender_award.
    type: table
    fields:
      ocid:
        type: string
        description: Open Contracting ID — globally unique process identifier.
      award_id:
        type: string
      title:
        type: string
        description: Tender title as published.
      status:
        type: string
        description: Tender status from the OCDS release.
      award_date:
        type: timestamp_ntz
      value_amount:
        type: double
        description: 'Tender value exactly as published — NOT normalised. SA eTenders (S007) sends 0 on
          every release rather than omitting the field, so a 0 here means ''not disclosed'', not ''no
          value''. The roll-up tables apply that reading: they sum only positive amounts and report NULL
          where a group discloses none.'
      value_currency:
        type: string
        description: ISO currency of the value, as published; may be stated even where no amount is. In
          the roll-up tables this column reports 'MIXED' when a group spans more than one currency, and
          the group's total is NULL — values are never summed across currencies and no FX conversion is
          applied.
      supplier_id:
        type: string
      supplier_name:
        type: string
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      observed_at:
        type: timestamp_tz
      source_ref:
        type: string
        description: Reference back to the OCDS release package.
      license_class:
        type: string
        description: License Register code (OCDS feed is openly licensed).
    quality: *id001
  gold_tender_party_published:
    description: African Public Procurement — gold_tender_party_published.
    type: table
    fields:
      ocid:
        type: string
        description: Open Contracting ID — globally unique process identifier.
      party_id:
        type: string
      name:
        type: string
        description: 'Party name exactly as published, in gold_tender_party_published. MAY BE EMPTY: three
          of 3,831 parties in the SA eTenders feed (S007) carry a party_id and a role but no name, and
          that is reproduced rather than filled or dropped. An invented name would be fabrication and
          a dropped row would silently lose an otherwise complete award record, so the blank is carried
          as the fact it is. Natural persons are excluded from this table entirely — a blank name is a
          publisher omission, not a suppression.'
      roles:
        type: string
      identifier_scheme:
        type: string
      identifier_id:
        type: string
      party_type:
        type: string
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      observed_at:
        type: timestamp_tz
      source_ref:
        type: string
        description: Reference back to the OCDS release package.
      license_class:
        type: string
        description: License Register code (OCDS feed is openly licensed).
    quality: *id001
  gold_tender_supplier_stats:
    description: African Public Procurement — gold_tender_supplier_stats.
    type: table
    fields:
      supplier_name:
        type: string
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      award_count:
        type: long
      tender_count:
        type: long
      total_award_value:
        type: double
      currency:
        type: string
      first_award_date:
        type: timestamp_ntz
      last_award_date:
        type: timestamp_ntz
    quality: *id001
  gold_tender_buyer_stats:
    description: African Public Procurement — gold_tender_buyer_stats.
    type: table
    fields:
      buyer_name:
        type: string
        description: Procuring entity (organization only).
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      tender_count:
        type: long
      total_tender_value:
        type: double
      currency:
        type: string
      first_tender_date:
        type: timestamp_ntz
      last_tender_date:
        type: timestamp_ntz
    quality: *id001
  gold_tender_monthly:
    description: African Public Procurement — gold_tender_monthly.
    type: table
    fields:
      country:
        type: string
        description: ISO country code of the procuring jurisdiction.
      month:
        type: date
      category:
        type: string
        description: Procurement category (goods / works / services).
      tender_count:
        type: long
      total_value:
        type: double
      currency:
        type: string
    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_tender: 20 days (SUSPENDED until 2026-10-01 — refresh-tenders\
      \ schedule frozen on the GitHub Actions budget; the table drifts by design until then)"
    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.
