@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix schema: <http://schema.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix vs: <http://www.w3.org/2003/06/sw-vocab-status/ns#> .
@prefix skyocean: <https://skyocean.io/ontology/> .
@prefix donation: <https://skyocean.io/ontology/donation/> .
@prefix trade: <https://skyocean.io/ontology/trade/> .
@prefix sec: <https://w3id.org/security#> .

# Ontology Definition
skyocean: a owl:Ontology ;
    dct:title "Skyocean Ontology" ;
    dct:description "A specialized vocabulary for agricultural commodities trading in decentralized knowledge graphs" ;
    dct:creator "Skyocean Team" ;
    dct:issued "2023-10-01" ;
    dct:modified "2026-09-11" ;
    owl:versionInfo "2.1.32" ;
    # v2.1.32 (2026-09-11) — WIDENED skyocean:contributingAttestations from
    #   rdfs:range skyocean:InstitutionalAttestation to the new union class
    #   skyocean:ConvergenceEvidence (InstitutionalAttestation ∪ Document), and made
    #   the three convergence COUNT/SCORE comments mode-aware.
    #   Cause: the SIM-003 convergence record lists 20 entries, mostly Documents, so
    #   the flagship record VIOLATED ITS OWN DECLARED RANGE and a range-enforcing
    #   validator would fail it against our own vocabulary. Binding constraint:
    #   SIM-003 is published and cannot be re-minted, so the fix had to make the
    #   existing record conformant. Widening does; a document-set successor term
    #   would leave the old term permanently broken by its own published data.
    #   The concept was never wrong — in document-set mode the contributing evidence
    #   genuinely IS documents-as-attestations; only the type constraint was too narrow.
    #   The count terms carried the same attestation-only framing three more times:
    #   attestationCount, independentAttestorCount and verificationStrength now say
    #   MODE-DEPENDENT and say what they are NOT, so a reader cannot compare a
    #   document-set figure with a count of attestation KAs on the public graph.
    #   Source: audit-dashboard/report-convergence-labels-2026-09-10.md, Sebastian's
    #   least-impact ruling. No term removed, no term retyped, nothing re-minted.
    # v2.1.31 (2026-09-04) — DECLARED (not minted) sec:nonce, the W3C Security
    #   Vocabulary predicate <https://w3id.org/security#nonce>. PRIVATE tier, no
    #   rdfs:domain, xsd:string. Standards-first: a nonce is a solved problem with a
    #   published term, so minting skyocean:nonce would have been a second name for
    #   something the web already names — and this one has to mean the same thing to an
    #   auditor holding only the private half, which is exactly what a shared vocabulary
    #   buys. `sec` is bound in the KA @context so the CURIE expands for every reader.
    #   Reason (EU-DATA-COMPLIANCE B2/B3, K1): V10 leaves are unsalted keccak256 and the
    #   folded root is public, so a low-entropy leaf is brute-forceable and the anchor is
    #   personal data rather than anonymous data (EDPB §52). One 256-bit random leaf per
    #   KA makes the private root a hiding commitment (§53) and makes erasure per-record:
    #   destroy the private half and the nonce goes with it (§64). Existing 60 clearance
    #   KAs are NOT re-minted (learning-trail doctrine) — it applies from the next mint.
    # v2.1.30 (2026-09-02) — added skyocean:referencesSimulatedParty (xsd:boolean,
    #   PUBLIC, no rdfs:domain). MINTED rather than reused: skyocean:provenance was
    #   the closest existing term and classifies the EMITTER's environment, not the
    #   SUBJECT's nature — a staging-emitted KA about a fixture is already correctly
    #   'production-staging', so the two are orthogonal and one field cannot carry
    #   both. Same test WaypointTransit was minted under (v2.1.23): no existing
    #   value fits, and reusing one would be a wrong claim on a permanent record.
    # v2.1.25 (2026-08-05) — SEMANTIC ONLY, no term changes: required-ness
    #   spans the public ∪ private layer union; relocate-never-delete.
    #   Canonical text: jsonld-safe-mode-runbook.md §6.1. Recorded here so the
    #   version referenced by the runbooks exists in the artifact itself.
    # v2.1.27 (2026-08-14) — resolved the duplicate donation:contributorCount
    #   declaration (two conflicting rdfs:domain assertions read as an
    #   intersection, not an alternative); DonorAggregateReceipt survives.
    # v2.1.26 (2026-08-13) — added donation:fundingModel (closed enum
    #   public|institutional|mixed; #private). Kit-is-a-commodity ruling:
    #   commodity lines reuse existing terms (skyocean:productSpecification
    #   as spec-UAL array + donation:packingList v2 payload) — no new terms.
    rdfs:comment "The Skyocean Ontology is designed to facilitate global trade of agricultural commodities and traceable humanitarian donation programs with an emphasis on transparency, traceability, and efficient financing." .

# Classes

skyocean:Trade a rdfs:Class ;
    rdfs:label "Trade" ;
    rdfs:comment "The core class representing a complete trade transaction between parties in the Skyocean ecosystem." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:CommodityTrade a rdfs:Class ;
    rdfs:label "CommodityTrade" ;
    rdfs:comment "A specialized trade of agricultural commodities" ;
    rdfs:subClassOf skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:Commodity a rdfs:Class ;
    rdfs:label "Commodity" ;
    rdfs:comment "Represents physical agricultural goods being traded in the Skyocean ecosystem" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:TradeParty a rdfs:Class ;
    rdfs:label "TradeParty" ;
    rdfs:comment "Entities involved in a trade transaction (buyer, seller, consignee, etc.)" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:Document a rdfs:Class ;
    rdfs:label "Document" ;
    rdfs:comment "Trade-related documentation including their verification status" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:BlockchainTransaction a rdfs:Class ;
    rdfs:label "BlockchainTransaction" ;
    rdfs:comment "Records of trade events recorded on the blockchain" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:FinancingRecord a rdfs:Class ;
    rdfs:label "FinancingRecord" ;
    rdfs:comment "Details of trade financing arrangements and token positions" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:TradePrivateData a rdfs:Class ;
    rdfs:label "TradePrivateData" ;
    rdfs:comment "Private data related to a trade transaction" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:PaymentDetails a rdfs:Class ;
    rdfs:label "PaymentDetails" ;
    rdfs:comment "Details of payment and financing arrangements for a trade" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

# Properties

skyocean:tradeStatus a rdf:Property ;
    rdfs:label "tradeStatus" ;
    rdfs:comment "Current status of the trade transaction" ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:financingStatus a rdf:Property ;
    rdfs:label "financingStatus" ;
    rdfs:comment "Current status of trade financing" ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:documentStatus a rdf:Property ;
    rdfs:label "documentStatus" ;
    rdfs:comment "Status of a trade document" ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:verificationStatus a rdf:Property ;
    rdfs:label "verificationStatus" ;
    rdfs:comment "Verification status of a document" ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:role a rdf:Property ;
    rdfs:label "role" ;
    rdfs:comment "Role of an entity in the trade" ;
    rdfs:domain skyocean:TradeParty ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:walletAddress a rdf:Property ;
    rdfs:label "walletAddress" ;
    rdfs:comment "Blockchain wallet address" ;
    rdfs:domain skyocean:TradeParty ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:financierProfitRate a rdf:Property ;
    rdfs:label "financierProfitRate" ;
    rdfs:comment "Profit rate for the financier" ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:commodity a rdf:Property ;
    rdfs:label "commodity" ;
    rdfs:comment "The commodity being traded" ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:Commodity ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:requiredDocumentTypes a rdf:Property ;
    rdfs:label "requiredDocumentTypes" ;
    rdfs:comment "Types of documents required for the trade" ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:documentStatuses a rdf:Property ;
    rdfs:label "documentStatuses" ;
    rdfs:comment "Status information for required documents" ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:blockchainStatus a rdf:Property ;
    rdfs:label "blockchainStatus" ;
    rdfs:comment "Status of the trade on the blockchain" ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:blockchainTransactionId a rdf:Property ;
    rdfs:label "blockchainTransactionId" ;
    rdfs:comment "Transaction ID on the blockchain" ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:transactionTimeline a rdf:Property ;
    rdfs:label "transactionTimeline" ;
    rdfs:comment "Timeline information for the transaction" ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:referenceId a rdf:Property ;
    rdfs:label "referenceId" ;
    rdfs:comment "Reference to the public section URI" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:consignee a rdf:Property ;
    rdfs:label "consignee" ;
    rdfs:comment "Consignee information" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:notifyParty a rdf:Property ;
    rdfs:label "notifyParty" ;
    rdfs:comment "Party to be notified" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:payment a rdf:Property ;
    rdfs:label "payment" ;
    rdfs:comment "Payment and financing details" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:range skyocean:PaymentDetails ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:documents a rdf:Property ;
    rdfs:label "documents" ;
    rdfs:comment "Detailed document information" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:range skyocean:Document ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:accessPermissions a rdf:Property ;
    rdfs:label "accessPermissions" ;
    rdfs:comment "Access control permissions" ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:grade a rdf:Property ;
    rdfs:label "grade" ;
    rdfs:comment "Quality grade of the commodity" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:certifications a rdf:Property ;
    rdfs:label "certifications" ;
    rdfs:comment "List of certifications or standards the commodity meets" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:specifications a rdf:Property ;
    rdfs:label "specifications" ;
    rdfs:comment "Technical specifications of the commodity" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:packaging a rdf:Property ;
    rdfs:label "packaging" ;
    rdfs:comment "Description of how the commodity is packaged" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:detailedSpecifications a rdf:Property ;
    rdfs:label "detailedSpecifications" ;
    rdfs:comment "Detailed technical specifications with thresholds" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:productionDetails a rdf:Property ;
    rdfs:label "productionDetails" ;
    rdfs:comment "Production method, origin, and other sensitive details" ;
    rdfs:domain skyocean:Commodity ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:paymentMethod a rdf:Property ;
    rdfs:label "paymentMethod" ;
    rdfs:comment "Method of payment (e.g., 'CAD' for Cash Against Documents)" ;
    rdfs:domain skyocean:PaymentDetails ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:paymentTerms a rdf:Property ;
    rdfs:label "paymentTerms" ;
    rdfs:comment "Terms of payment" ;
    rdfs:domain skyocean:PaymentDetails ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:financingRequired a rdf:Property ;
    rdfs:label "financingRequired" ;
    rdfs:comment "Whether financing is required for the trade" ;
    rdfs:domain skyocean:PaymentDetails ;
    rdfs:range xsd:boolean ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

skyocean:financingAmount a rdf:Property ;
    rdfs:label "financingAmount" ;
    rdfs:comment "Amount of financing required" ;
    rdfs:domain skyocean:PaymentDetails ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "stable" .

# ============================================================
# Convergence & Institutional Attestation (added v2.1.0)
# ============================================================
# Rationale: the on-chain smart contract keeps a minimal PaymentMethod enum
# (CAD, LetterOfCredit, OnChainEscrow). The richer classification of where a
# payment signal came from, and the broader model of independent institutional
# attestations whose convergence establishes trade truth, lives here in the DKG
# rather than in the contract. This keeps the contract simple and lets the
# ontology evolve without contract migrations.

skyocean:ConvergenceEvidence a rdfs:Class ;
    rdfs:label "ConvergenceEvidence" ;
    rdfs:comment "Union of the classes a ConvergenceRecord may cite as evidence: InstitutionalAttestation and Document. Exists so contributingAttestations has one range across both convergence modes." ;
    owl:unionOf ( skyocean:InstitutionalAttestation skyocean:Document ) ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:InstitutionalAttestation a rdfs:Class ;
    rdfs:label "InstitutionalAttestation" ;
    rdfs:comment "An independent observation by an operational institution (port authority, customs authority, inspection agency, carrier, condition monitor, payment rail, financial institution, or human verifier) about a trade event. Each attestation is recorded as a Knowledge Asset and feeds the convergence record for its trade." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:PaymentSource a rdfs:Class ;
    rdfs:label "PaymentSource" ;
    rdfs:comment "A record of an external signal confirming that payment has occurred, decoupled from the underlying rail. The same class represents signals from mobile money, national payment switches, regional settlement systems, SWIFT, letters of credit, cash-against-documents arrangements, on-chain escrow, and human-attested confirmations. Subclass of InstitutionalAttestation when the source is an institution." ;
    rdfs:subClassOf skyocean:InstitutionalAttestation ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:ConvergenceRecord a rdfs:Class ;
    rdfs:label "ConvergenceRecord" ;
    rdfs:comment "The aggregate cross-validated state of a trade, constructed from the convergence of independent institutional attestations. Used to compute verification strength without a single central validator." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Attestation properties

skyocean:attestorType a rdf:Property ;
    rdfs:label "attestorType" ;
    rdfs:comment "Category of institution making the attestation. Values: PortAuthority, CustomsAuthority, InspectionAgency, Carrier, ConditionMonitor, PaymentRail, FinancialInstitution, Human." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestorIdentity a rdf:Property ;
    rdfs:label "attestorIdentity" ;
    rdfs:comment "Name or identifier of the specific institution (e.g., 'Port of Tema', 'Ghana Revenue Authority', 'SGS', 'MTN MoMo')." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestationType a rdf:Property ;
    rdfs:label "attestationType" ;
    rdfs:comment "Nature of the observation. Values: VesselCall, CargoHandling, CustomsClearance, QualityInspection, ConditionReading, Departure, PaymentConfirmation, IncidentReport, ClaimDecision, ComplianceVerification, DeliveryScan (final-destination beneficiary delivery proof — donation campaigns last-mile; added v2.1.10), InlandHandover (custody change between inland-transport legs — added v2.1.10), KYCClearance (party KYC verification event by Fractal/ComplyCube/manual-ops; provider-agnostic — same enum value used regardless of which provider issued the credential; added v2.1.14 for Phase 1.8.9 Track I), ProvenanceTag (successor-KA pointing at an existing KA via schema:about to retroactively add skyocean:provenance metadata that vocab v2.1.15 introduced; emitted by scripts/retro-tag-provenance-1.8.9.js as part of Phase 1.8.9 Track J retro-tag pass 2026-05-21; reused InstitutionalAttestation class per best-part-is-no-part rather than minting a dedicated class), PortGateIn (terminal gate-in; the CLASS skyocean:PortGateIn has existed since v2.1.23 and its attestationType VALUE was never listed here — RECORDED 2026-08-21, found by the drift guard on its first run), ContainerLoaded (container loaded aboard the vessel; RECORDED 2026-08-21 — it had been emitted by the port-event handler since chunk-β without ever appearing in this list, which is how an unenforced enum drifts: the record now follows what actually ships), VesselCall (vessel arrival at a port; REUSED for 'vessel-arrived' rather than minting an Arrival value — an arrival IS a vessel call), CargoHandling (REUSED for 'discharged' — discharge is cargo handling), WaypointTransit (passage of a named waypoint that is NOT a port call — Suez, Panama, Gibraltar, Bosphorus; MINTED 2026-08-21 because no existing value fits and calling a canal transit a VesselCall or CargoHandling would be a wrong claim on a permanent record. Named for the general case so each waterway does not need its own value)." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestationTimestamp a rdf:Property ;
    rdfs:label "attestationTimestamp" ;
    rdfs:comment "Time at which the attesting institution recorded the event." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestationSignature a rdf:Property ;
    rdfs:label "attestationSignature" ;
    rdfs:comment "Cryptographic signature or integrity hash of the attestation payload, used for audit and non-repudiation." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tradeRef a rdf:Property ;
    rdfs:label "tradeRef" ;
    rdfs:comment "Reference to the Trade KA this attestation contributes to." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:eventCount a rdf:Property ;
    rdfs:label "eventCount" ;
    rdfs:comment "Number of source events folded into a consolidated InstitutionalAttestation KA (e.g., multiple raw verification-feed events rolled into one attestation by attestor + document pair). Enables auditors to verify the consolidation count without re-deriving from the raw feed. Added v2.1.11 per Sebastian-locked 2026-05-16 vocab-discipline rule (standards-first; no schema.org / GS1 / web3 equivalent for this fold-count semantic)." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# PaymentSource properties

skyocean:sourceType a rdf:Property ;
    rdfs:label "sourceType" ;
    rdfs:comment "Classification of the payment signal source. Values: MobileMoney, NationalSwitch, RegionalSettlement, SWIFT, LetterOfCredit, CashAgainstDocuments, OnChainEscrow, HumanAttested." ;
    rdfs:domain skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:sourceProvider a rdf:Property ;
    rdfs:label "sourceProvider" ;
    rdfs:comment "Specific provider or network that emitted the confirmation (e.g., 'MTN MoMo', 'GhIPSS', 'PAPSS', 'Deutsche Bank AG')." ;
    rdfs:domain skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:confirmationReference a rdf:Property ;
    rdfs:label "confirmationReference" ;
    rdfs:comment "External reference or transaction ID from the payment source (e.g., MoMo txn ID, SWIFT MT103 reference, LC number)." ;
    rdfs:domain skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:confirmedAmount a rdf:Property ;
    rdfs:label "confirmedAmount" ;
    rdfs:comment "Monetary amount the source confirms as settled." ;
    rdfs:domain skyocean:PaymentSource ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ConvergenceRecord properties

skyocean:attestationCount a rdf:Property ;
    rdfs:label "attestationCount" ;
    rdfs:comment "Cardinality of the assessed evidence set: equals |contributingAttestations|. MODE-DEPENDENT — read skyocean:convergenceMode before labelling or comparing. In `attestation` mode this is the number of InstitutionalAttestation KAs aggregated. In `document-set` mode each assessed DOCUMENT counts as its issuing authority's attestation, so this is NOT a count of InstitutionalAttestation KAs and is NOT comparable to the number of attestation KAs a reader can enumerate on the public graph." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:independentAttestorCount a rdf:Property ;
    rdfs:label "independentAttestorCount" ;
    rdfs:comment "Number of distinct INDEPENDENT authorities whose evidence the ConvergenceRecord aggregates. Skyocean's own operating entities are excluded (a platform confirming its own action is bookkeeping, not corroboration); one legal entity appearing in several roles is counted once. MODE-DEPENDENT — read skyocean:convergenceMode. In `document-set` mode the authorities are the assessed documents' issuers, which live on the private assertion; this figure therefore CANNOT be re-derived from public triples and is NOT a count of distinct skyocean:attestorIdentity values." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:verificationStrength a rdf:Property ;
    rdfs:label "verificationStrength" ;
    rdfs:comment "Computed score (0.0–1.0) summarising how strongly the trade is corroborated by independent evidence. MODE-DEPENDENT — read skyocean:convergenceMode: in `attestation` mode the evidence is independent institutional attestations; in `document-set` mode it is the assessed documents, each standing as its issuing authority's attestation, scored across the rulebook's axes (see rawComputation)." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:consensusStatus a rdf:Property ;
    rdfs:label "consensusStatus" ;
    rdfs:comment "Qualitative label derived from verificationStrength. Values: Insufficient, Partial, Strong, Full." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Insurance & Cargo Incident (added v2.2.0 candidate)
# ============================================================
# Rationale: cargo insurance is a first-class element of every commodity trade.
# Rather than treating insurance certificates as generic Documents, this
# section adds dedicated classes for the insurance policy, the cargo incident
# that may trigger a claim, and the claim itself. This enables the audit trail
# to follow a damaged-cargo scenario from incident → surveyor attestation →
# claim filing → claim approval → payout, and to redeploy payout funds back
# into trade capacity with full transparency.

skyocean:InsurancePolicy a rdfs:Class ;
    rdfs:label "InsurancePolicy" ;
    rdfs:comment "A cargo or marine insurance policy bound to one or more trades. Subclass of Document — the policy is itself a tradeable instrument with status, parties, and references — but carries dedicated insurance-specific properties." ;
    rdfs:subClassOf skyocean:Document ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:CargoIncident a rdfs:Class ;
    rdfs:label "CargoIncident" ;
    rdfs:comment "An event affecting cargo that may trigger an insurance claim — damage, loss, theft, contamination, delay, casualty. The CargoIncident KA captures what happened, where, when, and to what extent, attested by an independent surveyor and/or the responsible custodian (port, carrier)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:InsuranceClaim a rdfs:Class ;
    rdfs:label "InsuranceClaim" ;
    rdfs:comment "A formal claim filed against an InsurancePolicy in respect of a CargoIncident. Carries claim status, claimed amount, surveyor's loss assessment, insurer's decision, and payout details." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# InsurancePolicy properties

skyocean:policyNumber a rdf:Property ;
    rdfs:label "policyNumber" ;
    rdfs:comment "Insurer-issued policy reference (private layer — typically PII-adjacent)." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:insurer a rdf:Property ;
    rdfs:label "insurer" ;
    rdfs:comment "Insurer or syndicate underwriting the policy (e.g., 'Lloyd's of London correspondent', 'Munich Re')." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:coverageType a rdf:Property ;
    rdfs:label "coverageType" ;
    rdfs:comment "Type of insurance coverage. Values: Cargo, WarRisk, AllRisk, NamedPerils, Strike, ContingencyAndDelay." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:sumInsured a rdf:Property ;
    rdfs:label "sumInsured" ;
    rdfs:comment "Maximum insured value under the policy." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:deductible a rdf:Property ;
    rdfs:label "deductible" ;
    rdfs:comment "Self-insured retention before the policy responds." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:effectiveDate a rdf:Property ;
    rdfs:label "effectiveDate" ;
    rdfs:comment "Policy inception date." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:expiryDate a rdf:Property ;
    rdfs:label "expiryDate" ;
    rdfs:comment "Policy expiry date." ;
    rdfs:domain skyocean:InsurancePolicy ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# CargoIncident properties

skyocean:incidentType a rdf:Property ;
    rdfs:label "incidentType" ;
    rdfs:comment "Nature of the incident. Values: Damage, Loss, Theft, Contamination, Delay, Casualty, GeneralAverage, Quarantine." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:incidentLocation a rdf:Property ;
    rdfs:label "incidentLocation" ;
    rdfs:comment "Where the incident occurred (UN/LOCODE port code, lat/long for in-transit, or place name)." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:incidentDate a rdf:Property ;
    rdfs:label "incidentDate" ;
    rdfs:comment "Date and time the incident was reported or discovered." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:incidentDescription a rdf:Property ;
    rdfs:label "incidentDescription" ;
    rdfs:comment "Short descriptor of what happened (the private layer carries the full surveyor report text)." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:affectedQuantity a rdf:Property ;
    rdfs:label "affectedQuantity" ;
    rdfs:comment "Quantity of cargo affected (with unit code)." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range schema:QuantitativeValue ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:lossExtent a rdf:Property ;
    rdfs:label "lossExtent" ;
    rdfs:comment "Severity of loss. Values: Total, Partial, Constructive, Salvage, Marginal." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:surveyorRef a rdf:Property ;
    rdfs:label "surveyorRef" ;
    rdfs:comment "Reference to the InstitutionalAttestation issued by the independent loss adjuster / surveyor (attestorType: InspectionAgency, attestationType: IncidentReport)." ;
    rdfs:domain skyocean:CargoIncident ;
    rdfs:range skyocean:InstitutionalAttestation ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# InsuranceClaim properties

skyocean:claimNumber a rdf:Property ;
    rdfs:label "claimNumber" ;
    rdfs:comment "Insurer-issued claim reference (private layer)." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:policyRef a rdf:Property ;
    rdfs:label "policyRef" ;
    rdfs:comment "Reference to the InsurancePolicy under which this claim is filed." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range skyocean:InsurancePolicy ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:incidentRef a rdf:Property ;
    rdfs:label "incidentRef" ;
    rdfs:comment "Reference to the CargoIncident triggering the claim." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range skyocean:CargoIncident ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:claimStatus a rdf:Property ;
    rdfs:label "claimStatus" ;
    rdfs:comment "Status of the claim. Values: Filed, Acknowledged, UnderInvestigation, Approved, PartiallyApproved, Denied, Settled, Withdrawn." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:claimAmount a rdf:Property ;
    rdfs:label "claimAmount" ;
    rdfs:comment "Amount claimed by the policyholder." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:payoutAmount a rdf:Property ;
    rdfs:label "payoutAmount" ;
    rdfs:comment "Amount paid by the insurer (may differ from claim amount after surveyor adjustment and deductible)." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:payoutDate a rdf:Property ;
    rdfs:label "payoutDate" ;
    rdfs:comment "Date funds were credited to the policyholder." ;
    rdfs:domain skyocean:InsuranceClaim ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Logistics Module (added v2.1.2 candidate)
# ============================================================
# Rationale: a commodity trade is incomplete without its logistics record.
# The properties below capture the vessel, voyage, carrier, ports, BL number,
# and container count/type that every shipping leg carries. Semantics align
# with GS1 EPCIS and DCSA shipping vocabularies; the canonical mapping to
# those external IRIs is reserved for a future major version. Until then,
# Skyocean publishes these as its own terms.

skyocean:LogisticsRecord a rdfs:Class ;
    rdfs:label "LogisticsRecord" ;
    rdfs:comment "A summary of the logistics for a shipping leg of a trade — vessel, voyage, carrier, loading and discharge ports, BL reference, and container details. Attaches to a Trade via skyocean:logistics." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:logistics a rdf:Property ;
    rdfs:label "logistics" ;
    rdfs:comment "Reference from a Trade to its LogisticsRecord." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:LogisticsRecord ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:vessel a rdf:Property ;
    rdfs:label "vessel" ;
    rdfs:comment "Vessel name (semantics align with GS1/DCSA vessel reference)." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:vesselIMO a rdf:Property ;
    rdfs:label "vesselIMO" ;
    rdfs:comment "IMO ship identification number (7 digits) under the IMO ship-identification scheme." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:voyage a rdf:Property ;
    rdfs:label "voyage" ;
    rdfs:comment "Voyage reference issued by the carrier." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:carrier a rdf:Property ;
    rdfs:label "carrier" ;
    rdfs:comment "Carrier (shipping line) legal name." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:loadingPort a rdf:Property ;
    rdfs:label "loadingPort" ;
    rdfs:comment "Port of loading (UN/LOCODE plus place name)." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:dischargePort a rdf:Property ;
    rdfs:label "dischargePort" ;
    rdfs:comment "Port of discharge (UN/LOCODE plus place name)." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:billOfLading a rdf:Property ;
    rdfs:label "billOfLading" ;
    rdfs:comment "Bill of Lading reference number issued by the carrier." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:containerCount a rdf:Property ;
    rdfs:label "containerCount" ;
    rdfs:comment "Total container count for the shipping leg." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:containerType a rdf:Property ;
    rdfs:label "containerType" ;
    rdfs:comment "Container type description (e.g., '40-ft HC', 'flexitank-equipped 20-ft')." ;
    rdfs:domain skyocean:LogisticsRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Trade-level Extensions (added v2.1.2 candidate)
# ============================================================
# Self-consignment, corridor, cycle, funding-branch, payment-trigger, and
# inter-KA reference properties that every Skyocean trade carries. These
# are Skyocean-specific platform concepts (no schema.org equivalent).

skyocean:PublicTradeOverview a rdfs:Class ;
    rdfs:label "PublicTradeOverview" ;
    rdfs:comment "A typeable marker class indicating that a Trade KA is intended as a public-overview assertion (paired with a private TradePrivateData KA). Used as a secondary @type alongside skyocean:CommodityTrade." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:shipper a rdf:Property ;
    rdfs:label "shipper" ;
    rdfs:comment "Skyocean operating entity in the country of origin (Bill of Lading 'From'). Distinct from the legal Seller and from the fund-receiving entity." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:fundReceivingEntity a rdf:Property ;
    rdfs:label "fundReceivingEntity" ;
    rdfs:comment "Skyocean operating entity that receives institutional capital under the trade-finance facility (e.g., Skyocean DOOEL, Skyocean Lithuania UAB)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:corridor a rdf:Property ;
    rdfs:label "corridor" ;
    rdfs:comment "Trade corridor classification (e.g., 'Sudan', 'Ghana', 'EU')." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tradeType a rdf:Property ;
    rdfs:label "tradeType" ;
    rdfs:comment "Trade-structure classification (e.g., 'self-consignment-CAD', 'EXW-then-CFR-twoLeg')." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:cycleDays a rdf:Property ;
    rdfs:label "cycleDays" ;
    rdfs:comment "Total cycle length in days (origination to settlement)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tradeLegs a rdf:Property ;
    rdfs:label "tradeLegs" ;
    rdfs:comment "Ordered list of leg identifiers for a multi-leg trade (e.g., ['origin', 'export'] for an EXW-then-CFR cocoa-style structure). Single-leg trades typically omit this property." ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:timeline a rdf:Property ;
    rdfs:label "timeline" ;
    rdfs:comment "Trade-level timeline block carrying expected dates (origination, shipment, arrival, settlement). Properties are typically drawn from the trade: sub-namespace." ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:fundingBranch a rdf:Property ;
    rdfs:label "fundingBranch" ;
    rdfs:comment "Funding-branch classification per full-trade-flow.md. Values: 'A' (retail-only on-chain), 'B' (mixed institutional + retail on-chain), 'C' (institutional-only off-chain, no smart contract)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:paymentTrigger a rdf:Property ;
    rdfs:label "paymentTrigger" ;
    rdfs:comment "Payment-trigger classification used by the smart contract's _checkPaymentConditions evaluator. Values: 'OnDocumentsVerified', 'OnArrival', 'OnLoading', 'Manual'." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:relatedTrade a rdf:Property ;
    rdfs:label "relatedTrade" ;
    rdfs:comment "Reference from a child KA (FinancingRecord, Document, etc.) back to its parent Trade KA." ;
    rdfs:range skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:financingRecords a rdf:Property ;
    rdfs:label "financingRecords" ;
    rdfs:comment "Reference from a Trade to one or more FinancingRecord KAs (institutional + retail per-holder)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:FinancingRecord ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:paymentSource a rdf:Property ;
    rdfs:label "paymentSource" ;
    rdfs:comment "Reference from a Trade to one or more PaymentSource KAs that confirm settlement on this trade." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:PaymentSource ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:convergenceRecord a rdf:Property ;
    rdfs:label "convergenceRecord" ;
    rdfs:comment "Reference from a Trade to its ConvergenceRecord (or records, when multiple convergence events occur in a trade's lifecycle)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:ConvergenceRecord ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# On-chain anchoring properties (used in samples to optionally embed a richer
# anchor block; complements skyocean:blockchainTransactionId which carries the
# bytes32 tradeId on its own.)

skyocean:onChainAnchor a rdf:Property ;
    rdfs:label "onChainAnchor" ;
    rdfs:comment "Composite block on a Trade describing its on-chain anchor — network, contract address, transaction hash. Optional and additive to skyocean:blockchainTransactionId." ;
    rdfs:domain skyocean:Trade ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:network a rdf:Property ;
    rdfs:label "network" ;
    rdfs:comment "Blockchain network identifier (e.g., 'polygon', 'polygon-mumbai')." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:contract a rdf:Property ;
    rdfs:label "contract" ;
    rdfs:comment "Smart-contract address that issued the on-chain anchor (e.g., the SkyoceanTradeCore deployment)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:txHash a rdf:Property ;
    rdfs:label "txHash" ;
    rdfs:comment "Transaction hash of the createTrade call that issued the bytes32 tradeId. Distinct from skyocean:blockchainTransactionId, which is the tradeId itself." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Financing Extensions (added v2.1.2 candidate)
# ============================================================
# Detail properties on FinancingRecord — source descriptor, participant
# identity, capital amount, share, locked-token detail for retail.

skyocean:source a rdf:Property ;
    rdfs:label "source" ;
    rdfs:comment "Financing-source descriptor on a FinancingRecord. Values: 'institutional-trade-finance-facility', 'retail-skyt-capacity-activation', 'mixed-pool', 'institutional-tfa' (Branch C)." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:participant a rdf:Property ;
    rdfs:label "participant" ;
    rdfs:comment "DID of the participant in this FinancingRecord — institutional facility DID or retail-holder DID." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:participantLEI a rdf:Property ;
    rdfs:label "participantLEI" ;
    rdfs:comment "ISO 17442 Legal Entity Identifier for an institutional participant (where applicable)." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:participantCount a rdf:Property ;
    rdfs:label "participantCount" ;
    rdfs:comment "Number of distinct participants (used on retail-pool FinancingRecord roll-ups)." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:capitalProvided a rdf:Property ;
    rdfs:label "capitalProvided" ;
    rdfs:comment "Capital amount provided by this participant (or retail-pool aggregate)." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:percentageOfTotal a rdf:Property ;
    rdfs:label "percentageOfTotal" ;
    rdfs:comment "Share of total trade financing as a decimal (0.0–1.0)." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:totalSKYTLocked a rdf:Property ;
    rdfs:label "totalSKYTLocked" ;
    rdfs:comment "Aggregate SKYT amount locked in a retail-pool FinancingRecord." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:indicativeCycleMargin a rdf:Property ;
    rdfs:label "indicativeCycleMargin" ;
    rdfs:comment "Indicative trade-cycle margin descriptor (string with explicit not-guaranteed framing) — e.g., '~3.8% per ~55-day cycle (Sudan corridor; not guaranteed)'." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:lockedSKYT a rdf:Property ;
    rdfs:label "lockedSKYT" ;
    rdfs:comment "SKYT amount locked by an individual retail holder for this trade." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:lockedValue a rdf:Property ;
    rdfs:label "lockedValue" ;
    rdfs:comment "USD-equivalent value of the SKYT locked by an individual retail holder." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tier a rdf:Property ;
    rdfs:label "tier" ;
    rdfs:comment "Retail holder tier classification per Skyocean's tier model." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Private-layer wrappers and KYC references (added v2.1.2 candidate)
# ============================================================
# Wrapper objects and identifier-reference properties used inside
# skyocean:TradePrivateData and the paired private FinancingRecord KAs.
# Their content is typically drawn from schema.org (legalName, address,
# taxID, etc.); the wrappers themselves are Skyocean-specific groupings.

skyocean:supplierDetails a rdf:Property ;
    rdfs:label "supplierDetails" ;
    rdfs:comment "Wrapper carrying full supplier identification (schema:legalName, schema:address, schema:taxID, contact)." ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:buyerDetails a rdf:Property ;
    rdfs:label "buyerDetails" ;
    rdfs:comment "Wrapper carrying full buyer identification." ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:participantDetails a rdf:Property ;
    rdfs:label "participantDetails" ;
    rdfs:comment "Wrapper carrying full participant identification on a private FinancingRecord (institutional or retail)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:bankingDetails a rdf:Property ;
    rdfs:label "bankingDetails" ;
    rdfs:comment "Wrapper carrying banking detail (schema:bankName, BIC/SWIFT identifier, schema:accountId)." ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:settlementAccount a rdf:Property ;
    rdfs:label "settlementAccount" ;
    rdfs:comment "Wrapper carrying the institutional financier's settlement account detail on the private FinancingRecord." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:exactPricing a rdf:Property ;
    rdfs:label "exactPricing" ;
    rdfs:comment "Wrapper carrying exact contract pricing (unit price + total contract value) on the private trade KA." ;
    rdfs:domain skyocean:TradePrivateData ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:totalContractValue a rdf:Property ;
    rdfs:label "totalContractValue" ;
    rdfs:comment "Total contract value (private layer)." ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:facilityTermsRef a rdf:Property ;
    rdfs:label "facilityTermsRef" ;
    rdfs:comment "Reference to the executed Trade Finance Agreement governing an institutional FinancingRecord." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:beneficialOwnershipKYCRef a rdf:Property ;
    rdfs:label "beneficialOwnershipKYCRef" ;
    rdfs:comment "Internal Skyocean reference to the beneficial-ownership KYC dossier for an institutional financier." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:signingOfficer a rdf:Property ;
    rdfs:label "signingOfficer" ;
    rdfs:comment "Authorized signing officer for an institutional counterparty (name + role + DID)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:walletProvenance a rdf:Property ;
    rdfs:label "walletProvenance" ;
    rdfs:comment "Internal reference to a verified-wallet KYC linkage record for a retail holder." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:amlCheckRef a rdf:Property ;
    rdfs:label "amlCheckRef" ;
    rdfs:comment "Internal reference to the AML clearance record for a retail or institutional financier." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:sanctionsCheckRef a rdf:Property ;
    rdfs:label "sanctionsCheckRef" ;
    rdfs:comment "Internal reference to the sanctions screening record for a retail or institutional financier." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:governmentIdType a rdf:Property ;
    rdfs:label "governmentIdType" ;
    rdfs:comment "Type of government ID document on file for a retail holder. Values: 'passport', 'national-id', 'driver-licence'." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:governmentIdRef a rdf:Property ;
    rdfs:label "governmentIdRef" ;
    rdfs:comment "Internal Skyocean reference to the government-ID document record on file (the ID number itself is not stored as a literal)." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:jurisdictionOfResidence a rdf:Property ;
    rdfs:label "jurisdictionOfResidence" ;
    rdfs:comment "ISO 3166 country code of a retail holder's jurisdiction of residence." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# trade: sub-namespace (added v2.1.2 candidate)
# ============================================================
# Trade-domain properties under the trade: sub-namespace
# (https://skyocean.io/ontology/trade/), used for high-level commodity
# attributes and timeline dates that don't have a clean schema.org or
# external equivalent.

trade:quantity a rdf:Property ;
    rdfs:label "quantity" ;
    rdfs:comment "Quantity of the commodity (with schema:unitCode)." ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range schema:QuantitativeValue ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:origin a rdf:Property ;
    rdfs:label "origin" ;
    rdfs:comment "Country of origin of the commodity (ISO 3166 country name or code)." ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:destination a rdf:Property ;
    rdfs:label "destination" ;
    rdfs:comment "Country of destination of the commodity." ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:originatedAt a rdf:Property ;
    rdfs:label "originatedAt" ;
    rdfs:comment "Date the trade was originated in the Skyocean platform." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:expectedShipmentDate a rdf:Property ;
    rdfs:label "expectedShipmentDate" ;
    rdfs:comment "Expected shipment date." ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:expectedArrivalDate a rdf:Property ;
    rdfs:label "expectedArrivalDate" ;
    rdfs:comment "Expected arrival date at discharge port." ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

trade:expectedSettlementDate a rdf:Property ;
    rdfs:label "expectedSettlementDate" ;
    rdfs:comment "Expected settlement (trade-completion) date." ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Donation Extension (donation: namespace)
# ============================================================

# Classes

donation:DonationCampaign a rdfs:Class ;
    rdfs:label "DonationCampaign" ;
    rdfs:comment "A bounded humanitarian-aid campaign with a packing list, target amount, and delivery timeline. Identified by a backend-issued donation:campaignId (e.g. CMP-2026-SUD-001). Funding sources (wallets and/or bank accounts) are attached to the campaign and do not serve as its anchor." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:DonationContribution a rdfs:Class ;
    rdfs:label "DonationContribution" ;
    rdfs:comment "A single donor contribution to a campaign, via stablecoin or bank transfer" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:DonationDistribution a rdfs:Class ;
    rdfs:label "DonationDistribution" ;
    rdfs:comment "A delivery event recording kits distributed to beneficiaries, verified by state officials" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:DonationCampaignPrivate a rdfs:Class ;
    rdfs:label "DonationCampaignPrivate" ;
    rdfs:comment "Private assertion data for a campaign: supplier details, distribution plan, bank account, and access permissions" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:SupplyChainSignal a rdfs:Class ;
    rdfs:label "SupplyChainSignal" ;
    rdfs:comment "Real-time signals from IoT sensors, partner confirmations, or field reports linked to a campaign" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:DonationKit a rdfs:Class ;
    rdfs:label "DonationKit" ;
    rdfs:comment "Specification of a kit's contents — food, medicine, prevention items — with quantities and sourcing details" ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties

donation:status a rdf:Property ;
    rdfs:label "status" ;
    rdfs:comment "Campaign status (Active, Funded, Procuring, Shipping, Delivered, Cancelled)" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Reused schema.org standard property (NOT a skyocean:*/donation:* term) — no rdfs:isDefinedBy
# skyocean: here because schema.org defines it; we assert its DonationCampaign domain + link the
# canonical definition via rdfs:seeAlso. Standards-first vocabulary discipline.
schema:validThrough a rdf:Property ;
    rdfs:label "validThrough" ;
    rdfs:comment "Campaign end date / funding deadline (after which contributions are no longer accepted). Reused schema.org standard property; mirrors trades.valid_through per the DB-mirrors-KA invariant (doctrine #102). Populated at campaign creation from the Donation Agreement digest or by operator input; optional." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:dateTime ;
    rdfs:seeAlso <http://schema.org/validThrough> ;
    vs:term_status "testing" .

donation:targetAmount a rdf:Property ;
    rdfs:label "targetAmount" ;
    rdfs:comment "Funding goal for the campaign" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:currentAmount a rdf:Property ;
    rdfs:label "currentAmount" ;
    rdfs:comment "Current funds received" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:campaignId a rdf:Property ;
    rdfs:label "campaignId" ;
    rdfs:comment "Canonical anchor identifier for the campaign, issued by the Skyocean backend (e.g. CMP-2026-SUD-001). Stable across on-chain and off-chain campaigns." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:fundingSource a rdf:Property ;
    rdfs:label "fundingSource" ;
    rdfs:comment "One or more funding sources attached to the campaign — a wallet, bank account, or rail (Revolut, SEPA, SWIFT, stablecoin). Reuses skyocean:PaymentSource." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range skyocean:PaymentSource ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:campaignWallet a rdf:Property ;
    rdfs:label "campaignWallet" ;
    rdfs:comment "Optional EVM wallet address (e.g. Polygon) when the campaign has an on-chain funding source. Not the anchor identifier — some campaigns are fully off-chain." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:consignedTo a rdf:Property ;
    rdfs:label "consignedTo" ;
    rdfs:comment "Skyocean in-region entity that receives the goods on consignment (e.g. Skyocean Sudan for the Sudan pilot)" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range skyocean:Party ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:packingList a rdf:Property ;
    rdfs:label "packingList" ;
    rdfs:comment "Campaign packing list (kits, quantities, specifications). Functional analog of a trade agreement in the core trading flow." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range donation:DonationKit ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:costSummary a rdf:Property ;
    rdfs:label "costSummary" ;
    rdfs:comment "Public top-level cost summary surfaced to donors (e.g. kits vs operations)" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:operationalCostBreakdown a rdf:Property ;
    rdfs:label "operationalCostBreakdown" ;
    rdfs:comment "Private detailed operational cost breakdown (freight, customs, insurance, last-mile logistics, platform & ops)" ;
    rdfs:domain donation:DonationCampaignPrivate ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# donation:contributorCount was declared HERE with rdfs:domain donation:DonationCampaign
# and AGAIN at its DonorAggregateReceipt declaration below. Resolved 2026-08-14 (v2.1.27)
# to the single declaration below. Two rdfs:domain assertions on one property are not
# "either/or" — RDF reads them as an INTERSECTION, so every subject carrying a
# contributorCount was being inferred to be a DonationCampaign AND a
# DonorAggregateReceipt at once. The duplicate was also the sole source of the 5
# duplicate quads in this file's parse (2876 quads, 2871 distinct).
#
# The receipt declaration is the correct survivor: a contributor count on a CAMPAIGN
# contradicts the public-minimum doctrine (the campaign anchor is existence + stage +
# region only), and the campaign-level count already lives in the DB rollup
# (donation_rollups.donor_count), derived from contributions rather than asserted.
# No builder emits this predicate today, so nothing in code changes.

donation:targetBeneficiaries a rdf:Property ;
    rdfs:label "targetBeneficiaries" ;
    rdfs:comment "Target number of families to be served" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:region a rdf:Property ;
    rdfs:label "region" ;
    rdfs:comment "Target distribution region" ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:campaignRef a rdf:Property ;
    rdfs:label "campaignRef" ;
    rdfs:comment "Reference to the parent campaign by donation:campaignId (and optionally KA UAL). Applies to contributions, distributions and supply-chain signals." ;
    rdfs:domain donation:DonationContribution, donation:DonationDistribution, donation:SupplyChainSignal ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:method a rdf:Property ;
    rdfs:label "method" ;
    rdfs:comment "Payment rail: stablecoin, revolut, sepa, swift, other" ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:paymentSource a rdf:Property ;
    rdfs:label "paymentSource" ;
    rdfs:comment "Rail-specific payment record (provider, reference, institutional flag) reused from the core Skyocean payments module" ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range skyocean:PaymentSource ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:onChainTxHash a rdf:Property ;
    rdfs:label "onChainTxHash" ;
    rdfs:comment "On-chain transaction hash for stablecoin contributions" ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Phase 2 Donations Wave 2 (SIM-003 prep, 2026-05-27) — settlement-chain
# tag for crypto-rail donations. Distinguishes testnet (base-sepolia)
# from mainnet (base-mainnet) on read so audit can scope by chain.
# Future-extensible: polygon, gnosis, etc. Optional on the DonationContribution
# public anchor; emitted only by server after on-chain verification succeeds.
skyocean:settlementChain a rdf:Property ;
    rdfs:label "settlementChain" ;
    rdfs:comment "Chain name where the on-chain value transfer settled (base-sepolia / base-mainnet / polygon / …). Set by server after onChainDonationVerify. Distinct from the DKG paranet chain (the KA itself lives on V8/Base regardless)." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:kycRef a rdf:Property ;
    rdfs:label "kycRef" ;
    rdfs:comment "KYC attestation reference for the donor. Required for every contribution — no anonymous donations." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:deliveryStatus a rdf:Property ;
    rdfs:label "deliveryStatus" ;
    rdfs:comment "Public delivery outcome: delivered, partially-delivered, not-delivered, plus recipient category" ;
    rdfs:domain donation:DonationDistribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:familiesServed a rdf:Property ;
    rdfs:label "familiesServed" ;
    rdfs:comment "Private. Number of families who received kits in a distribution event" ;
    rdfs:domain donation:DonationDistribution ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:kitsDistributed a rdf:Property ;
    rdfs:label "kitsDistributed" ;
    rdfs:comment "Private. Number of kits delivered in a distribution event" ;
    rdfs:domain donation:DonationDistribution ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:verifiedBy a rdf:Property ;
    rdfs:label "verifiedBy" ;
    rdfs:comment "State official, NGO or partner witness who confirmed distribution" ;
    rdfs:domain donation:DonationDistribution ;
    rdfs:range skyocean:Party ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:attestationRef a rdf:Property ;
    rdfs:label "attestationRef" ;
    rdfs:comment "Reference to an independent institutional attestation (customs, inspection, partner NGO) that feeds the convergence evaluator" ;
    rdfs:domain donation:DonationDistribution ;
    rdfs:range skyocean:InstitutionalAttestation ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:signalType a rdf:Property ;
    rdfs:label "signalType" ;
    rdfs:comment "Type of supply chain signal (IoT-Temperature, IoT-GPS, PartnerConfirmation, FieldReport, Verification)" ;
    rdfs:domain donation:SupplyChainSignal ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# v2.1.3 — Document-level enrichment (added 2026-05-04)
# ============================================================
# Properties needed to express the rich private-tier data on Document KAs:
# container/seal/lot/vessel cross-document identifiers, EDIFACT trail, SWIFT
# detail, EUDR DDS, cold-chain telemetry, AIS positions, document URLs, and
# donation-specific aggregate receipts/distribution observations.
#
# Where schema.org or GS1 already covers a concept, prefer those — these
# Skyocean terms are added only where no standard fits or where Skyocean
# semantics extend the standard meaningfully.

# --- Cross-document logistics identifiers ---

skyocean:containerNumber a rdf:Property ;
    rdfs:label "containerNumber" ;
    rdfs:comment "ISO 6346 container identifier (e.g., 'MEDU 4471001'). Per-container — distinct from skyocean:containerCount which counts the set. Cross-document join key for graph linkage between BL, Packing List, Phyto, SGS, Customs etc." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:sealNumber a rdf:Property ;
    rdfs:label "sealNumber" ;
    rdfs:comment "Tamper-evident seal number affixed to a container at loading. One per container. Cross-document join key." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:lotReference a rdf:Property ;
    rdfs:label "lotReference" ;
    rdfs:comment "Production lot reference (e.g., 'AR-LOT-2026-00471'). Cross-document join key linking supplier invoice, packing list, phytosanitary, and quality cert." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:imoNumber a rdf:Property ;
    rdfs:label "imoNumber" ;
    rdfs:comment "IMO (International Maritime Organization) number — globally-unique 7-digit vessel identifier." ;
    rdfs:domain skyocean:LogisticsRecord, skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:mmsiNumber a rdf:Property ;
    rdfs:label "mmsiNumber" ;
    rdfs:comment "MMSI (Maritime Mobile Service Identity) — 9-digit vessel radio identifier used by AIS feeds." ;
    rdfs:domain skyocean:LogisticsRecord, skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:vesselName a rdf:Property ;
    rdfs:label "vesselName" ;
    rdfs:comment "Vessel name (e.g., 'MV BALTIC TRADER'). Use schema:name on a schema:Vehicle subclass when expressing in JSON-LD with schema.org context." ;
    rdfs:domain skyocean:LogisticsRecord, skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:bookingReference a rdf:Property ;
    rdfs:label "bookingReference" ;
    rdfs:comment "Carrier booking reference (e.g., 'MSCU-BK-2026-00471'). Cross-document join key linking BL to PO and IOM consolidation manifest." ;
    rdfs:domain skyocean:LogisticsRecord, skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Cargo physical attributes ---

skyocean:grossWeight a rdf:Property ;
    rdfs:label "grossWeight" ;
    rdfs:comment "Gross weight including packaging and pallets/dunnage, in kilograms. For cargo measurement; for full quantity context use schema:weight with QuantitativeValue." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:netWeight a rdf:Property ;
    rdfs:label "netWeight" ;
    rdfs:comment "Net weight of the cargo itself, excluding packaging, in kilograms." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:hsCode a rdf:Property ;
    rdfs:label "hsCode" ;
    rdfs:comment "Harmonized System (HS) commodity classification code, used in customs declarations. Format like '0713.40.00'." ;
    rdfs:domain skyocean:Document, skyocean:Commodity ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Treatment / inspection methodology ---

skyocean:treatmentMethod a rdf:Property ;
    rdfs:label "treatmentMethod" ;
    rdfs:comment "Phytosanitary / disinfestation treatment method applied to the cargo (e.g., 'Methyl bromide fumigation, 48 mg/L for 24 h at 21°C')." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:treatmentDate a rdf:Property ;
    rdfs:label "treatmentDate" ;
    rdfs:comment "Date the phytosanitary / disinfestation treatment was applied." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:samplingMethod a rdf:Property ;
    rdfs:label "samplingMethod" ;
    rdfs:comment "Sampling method used by the inspection agency (e.g., 'ISO 24333:2009, composite sample of 30 incremental samples per container')." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:qualityParameters a rdf:Property ;
    rdfs:label "qualityParameters" ;
    rdfs:comment "Composite quality test results (parameter, measured value, spec, pass/fail). Free-form string in v2.1.3; future versions may model as a structured assertion." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- EDIFACT customs trail ---

skyocean:edifactMessageType a rdf:Property ;
    rdfs:label "edifactMessageType" ;
    rdfs:comment "EDIFACT message type used in the customs filing (e.g., 'CUSDEC', 'CUSRES', 'CUSCAR', 'IFTSTA', 'COARRI', 'COPRAR', 'CODECO')." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:edifactStatus a rdf:Property ;
    rdfs:label "edifactStatus" ;
    rdfs:comment "Outcome reference of the EDIFACT exchange (e.g., the response message ID or 'CUSRES accepted')." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- SWIFT MT103 inbound payment fields ---

skyocean:swiftUETR a rdf:Property ;
    rdfs:label "swiftUETR" ;
    rdfs:comment "Unique End-to-end Transaction Reference (UETR) from a SWIFT MT103 message — UUID format. Cross-document join key linking inbound payment confirmation to invoice and PO." ;
    rdfs:domain skyocean:Document, skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:senderReference a rdf:Property ;
    rdfs:label "senderReference" ;
    rdfs:comment "SWIFT MT103 Field 20 — sender's transaction reference. Often carries the buyer's PO number." ;
    rdfs:domain skyocean:Document, skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:beneficiaryReference a rdf:Property ;
    rdfs:label "beneficiaryReference" ;
    rdfs:comment "SWIFT MT103 Field 70 — reference for the beneficiary. Typically carries the trade ID + invoice reference." ;
    rdfs:domain skyocean:Document, skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Insurance fields (deductible already exists; adding the rest) ---

skyocean:insuredValue a rdf:Property ;
    rdfs:label "insuredValue" ;
    rdfs:comment "Insured value declared on the marine cargo / war-risk policy, typically 110% of CIF/CFR per ICC(A) standard. Use schema:price with currency for the JSON-LD value object." ;
    rdfs:domain skyocean:InsurancePolicy, skyocean:Document ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:premiumAmount a rdf:Property ;
    rdfs:label "premiumAmount" ;
    rdfs:comment "Premium paid to bind the policy. Use schema:price with currency for the JSON-LD value object." ;
    rdfs:domain skyocean:InsurancePolicy, skyocean:Document ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- AIS vessel position (composite) ---

skyocean:VesselPosition a rdfs:Class ;
    rdfs:label "VesselPosition" ;
    rdfs:comment "A single AIS position report from a vessel during a tracked voyage. A continuous AIS feed comprises many VesselPosition assertions." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:positionLat a rdf:Property ;
    rdfs:label "positionLat" ;
    rdfs:comment "Latitude in decimal degrees, WGS84." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:positionLon a rdf:Property ;
    rdfs:label "positionLon" ;
    rdfs:comment "Longitude in decimal degrees, WGS84." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:positionTimestamp a rdf:Property ;
    rdfs:label "positionTimestamp" ;
    rdfs:comment "Timestamp of the AIS position report (ISO 8601 UTC)." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:speedOverGround a rdf:Property ;
    rdfs:label "speedOverGround" ;
    rdfs:comment "Speed over ground in knots (SOG)." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:courseOverGround a rdf:Property ;
    rdfs:label "courseOverGround" ;
    rdfs:comment "Course over ground in degrees (COG, 0–359°)." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:navStatus a rdf:Property ;
    rdfs:label "navStatus" ;
    rdfs:comment "AIS navigational status (e.g., 'Underway using engine', 'At anchor', 'Moored')." ;
    rdfs:domain skyocean:VesselPosition ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:positionPingCount a rdf:Property ;
    rdfs:label "positionPingCount" ;
    rdfs:comment "Total number of AIS position pings captured for a tracked voyage. Used in the AIS feed Document KA to summarize feed density." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- EUDR (EU Deforestation Regulation) ---

skyocean:eudrOperator a rdf:Property ;
    rdfs:label "eudrOperator" ;
    rdfs:comment "Legal entity acting as the EUDR Operator that places the relevant commodity on the EU market and submits the Due Diligence Statement under Regulation (EU) 2023/1115." ;
    rdfs:domain skyocean:Document ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:eudrDDSReference a rdf:Property ;
    rdfs:label "eudrDDSReference" ;
    rdfs:comment "EU Information System reference number for the submitted EUDR Due Diligence Statement." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:ProductionPlot a rdfs:Class ;
    rdfs:label "ProductionPlot" ;
    rdfs:comment "A geolocated plot of land where a regulated commodity (e.g., cocoa, coffee, palm oil, soy) was produced. Required under EUDR for parcel-level traceability. Geometry expressed via GeoJSON polygon and centroid." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:plotGeometry a rdf:Property ;
    rdfs:label "plotGeometry" ;
    rdfs:comment "GeoJSON polygon or multipolygon describing the plot boundary." ;
    rdfs:domain skyocean:ProductionPlot ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:plotCentroid a rdf:Property ;
    rdfs:label "plotCentroid" ;
    rdfs:comment "Centroid latitude/longitude of the plot, WGS84 — convenience field for indexing." ;
    rdfs:domain skyocean:ProductionPlot ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:cutoffCompliance a rdf:Property ;
    rdfs:label "cutoffCompliance" ;
    rdfs:comment "Verification that a production plot was deforestation-free as of the EUDR cut-off date (31 December 2020) per remote-sensing analysis. Values: 'Verified', 'NotVerified', 'AtRisk'." ;
    rdfs:domain skyocean:ProductionPlot ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Cold-chain telemetry ---

skyocean:ColdChainLog a rdfs:Class ;
    rdfs:label "ColdChainLog" ;
    rdfs:comment "Container-level temperature + humidity telemetry log captured by an in-container data logger across a voyage." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:loggerSerial a rdf:Property ;
    rdfs:label "loggerSerial" ;
    rdfs:comment "Serial number of the temperature/humidity logger device (e.g., 'STM-44511-A')." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:loggerModel a rdf:Property ;
    rdfs:label "loggerModel" ;
    rdfs:comment "Model designation of the data logger device (e.g., 'Sensitech TempTale GEO 4')." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:readingInterval a rdf:Property ;
    rdfs:label "readingInterval" ;
    rdfs:comment "Logger sampling interval as ISO 8601 duration (e.g., 'PT15M' = 15 minutes)." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:duration ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:temperatureRange a rdf:Property ;
    rdfs:label "temperatureRange" ;
    rdfs:comment "Min–max temperature range observed across the voyage, in degrees Celsius." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:humidityRange a rdf:Property ;
    rdfs:label "humidityRange" ;
    rdfs:comment "Min–max relative humidity range observed across the voyage (% RH)." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:temperatureExcursion a rdf:Property ;
    rdfs:label "temperatureExcursion" ;
    rdfs:comment "Number of temperature excursion events outside spec tolerance during the voyage. 0 = within tolerance." ;
    rdfs:domain skyocean:ColdChainLog ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Document URL (private) ---

skyocean:documentURL a rdf:Property ;
    rdfs:label "documentURL" ;
    rdfs:comment "Pointer to the original document file in private storage (e.g., S3 signed URL). Always private-tier — never appears in a Document KA's public assertion. Equivalent to schema:url qualified with skyocean:visibility 'private'." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- Donation v2.1.3 additions ---

donation:DonorAggregateReceipt a rdfs:Class ;
    rdfs:label "DonorAggregateReceipt" ;
    rdfs:comment "Per-rail aggregate of donor contributions for a campaign (e.g., total stablecoin / SEPA / SWIFT for CMP-2026-SUD-001). Issued continuously as contributions arrive; final aggregate at campaign close. Public-tier shows totals; private-tier links per-contribution detail." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:contributionRail a rdf:Property ;
    rdfs:label "contributionRail" ;
    rdfs:comment "The receiving rail used for an aggregate or single contribution: 'stablecoin', 'sepa', 'swift', 'revolut'." ;
    rdfs:domain donation:DonorAggregateReceipt, donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:aggregateAmount a rdf:Property ;
    rdfs:label "aggregateAmount" ;
    rdfs:comment "Total contribution amount across the rail at the time of receipt issuance." ;
    rdfs:domain donation:DonorAggregateReceipt ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:contributorCount a rdf:Property ;
    rdfs:label "contributorCount" ;
    rdfs:comment "Number of distinct contributors on the rail at the time of receipt issuance. Private-tier — donor identities never surface; counts may." ;
    rdfs:domain donation:DonorAggregateReceipt ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:DistributionObservation a rdfs:Class ;
    rdfs:label "DistributionObservation" ;
    rdfs:comment "Independent observation of a donation distribution event by an external NGO or partner agency (e.g., IOM Sudan country office). Distinct from donation:DonationDistribution which is the operational delivery record; this class captures the third-party witness." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:LastMileAcknowledgment a rdfs:Class ;
    rdfs:label "LastMileAcknowledgment" ;
    rdfs:comment "Distribution acknowledgment from the in-region last-mile coordinator (e.g., Khartoum State Ministry of Social Welfare). State-authority sign-off on receipt and onward distribution to identified beneficiary households." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:campaignOperator a rdf:Property ;
    rdfs:label "campaignOperator" ;
    rdfs:comment "Skyocean operating entity that operates the donation campaign (e.g., Skyocean DOOEL — campaign operator and fund-receiving entity). Distinct from the consignee that takes title in the destination country." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:sourceOfFunds a rdf:Property ;
    rdfs:label "sourceOfFunds" ;
    rdfs:comment "Public-tier description of which receiving rails the campaign accepts (e.g., 'Stablecoin receiving wallet (USDC/USDT) · SEPA donation account · SWIFT correspondent'). Reveals channels, not donor identities." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:fundingModel a rdf:Property ;
    rdfs:label "fundingModel" ;
    rdfs:comment "Branch-D funding model of a donation campaign as a CLOSED enum: public (open public donations) | institutional (institutional funders only) | mixed (public + institutional). The structured funding-side fact — replaces the free-text field on the campaign form (donation:sourceOfFunds remains the optional rails narrative). #private by the most-protective default: advertising institutional backing on the public anchor is a scammer surface (same family as the W1.1b relocations). Added v2.1.26 (2026-08-13, kit-is-a-commodity + funding-model-as-a-field ruling)." ;
    rdfs:domain donation:DonationCampaign ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Party Reputation System (added 2.1.4 — 2026-05-07)
# ============================================================
# Anti-abuse mechanism for trade-party honesty. Each party-DID accumulates
# reputation events (positive = clean trade closure; negative = divergence
# between declared role and observed behaviour). Detection is purely
# DID-equality reconciliation between declared parties (at trade creation)
# and observed parties (from PaymentSource KA + BillOfLading KA at
# completeTrade). No name normalization, no fuzzy matching.

skyocean:PartyReputation a rdfs:Class ;
    rdfs:label "PartyReputation" ;
    rdfs:comment "Aggregate reputation record for a party-DID. Score reflects observed honesty: declared role vs. observed behaviour across all trades the party has been bound to. Persistent across trades — anchored to party-DID, not to any single trade." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:ReputationEvent a rdfs:Class ;
    rdfs:label "ReputationEvent" ;
    rdfs:comment "A single observation that affects a party's reputation. Emitted on completeTrade (positive event for clean closure) or when reconciliation detects divergence (negative event). Each event references the trade context and an evidence UAL pointing to the on-chain KA that surfaced the observation." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:DivergenceEvent a rdfs:Class ;
    rdfs:label "DivergenceEvent" ;
    rdfs:comment "Subclass of ReputationEvent representing a detected divergence between a party's declared role and observed behaviour on a specific trade. Examples: claimed buyer's party-DID does not match BL final consignee party-DID; payment source party-DID is not on the declared parties list." ;
    rdfs:subClassOf skyocean:ReputationEvent ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:reputationOf a rdf:Property ;
    rdfs:label "reputationOf" ;
    rdfs:comment "The party-DID that this reputation record or event applies to. Reputation is per-DID; the same legal entity registered under multiple DIDs accumulates separate reputations per DID (intentional — DID is the unit of identity)." ;
    rdfs:domain skyocean:PartyReputation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:reputationScore a rdf:Property ;
    rdfs:label "reputationScore" ;
    rdfs:comment "Current numeric reputation score for a party-DID. Range and scoring algorithm specified in the implementation; a higher score indicates more observed clean trade closures relative to divergence events." ;
    rdfs:domain skyocean:PartyReputation ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:totalTradesObserved a rdf:Property ;
    rdfs:label "totalTradesObserved" ;
    rdfs:comment "Count of trades the party-DID has been bound to that have reached completeTrade and been reconciled. Denominator for divergence rate." ;
    rdfs:domain skyocean:PartyReputation ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:divergenceCount a rdf:Property ;
    rdfs:label "divergenceCount" ;
    rdfs:comment "Count of DivergenceEvent records associated with this party-DID across all trades." ;
    rdfs:domain skyocean:PartyReputation ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:reputationLastUpdated a rdf:Property ;
    rdfs:label "reputationLastUpdated" ;
    rdfs:comment "Timestamp of the most recent reputation event affecting this party-DID." ;
    rdfs:domain skyocean:PartyReputation ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:eventType a rdf:Property ;
    rdfs:label "eventType" ;
    rdfs:comment "Type of reputation event. Standardized values include: 'clean-trade-closure', 'claimed-buyer-not-final-consignee', 'claimed-seller-not-shipper', 'payment-source-undisclosed-third-party', 'manual-admin-adjustment'. New values may be added as detection patterns mature." ;
    rdfs:domain skyocean:ReputationEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:scoreDelta a rdf:Property ;
    rdfs:label "scoreDelta" ;
    rdfs:comment "Signed delta applied to the party's reputation score by this event. Positive for clean closures; negative for divergence events. Magnitude configured per event type." ;
    rdfs:domain skyocean:ReputationEvent ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tradeContext a rdf:Property ;
    rdfs:label "tradeContext" ;
    rdfs:comment "Reference to the trade (SKY-2026-XXXXX or CMP-2026-XXX-X anchor) on which this reputation event was observed." ;
    rdfs:domain skyocean:ReputationEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:declaredRole a rdf:Property ;
    rdfs:label "declaredRole" ;
    rdfs:comment "The role the party declared at trade creation (e.g., 'buyer', 'seller'). Used in DivergenceEvent records to capture what the party claimed before observed behaviour contradicted it." ;
    rdfs:domain skyocean:DivergenceEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:observedRole a rdf:Property ;
    rdfs:label "observedRole" ;
    rdfs:comment "The role the party-DID was observed playing in the actual trade execution (e.g., 'pass-through-intermediary' when a declared buyer was not the BL final consignee). Used in DivergenceEvent records to capture what the on-chain or document evidence shows." ;
    rdfs:domain skyocean:DivergenceEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:evidenceUAL a rdf:Property ;
    rdfs:label "evidenceUAL" ;
    rdfs:comment "Universal Asset Locator pointing to the on-chain Knowledge Asset that contains the observation evidence for this reputation event (e.g., the PaymentSource KA showing the actual payment-source DID, or the BillOfLading KA showing the actual final consignee)." ;
    rdfs:domain skyocean:ReputationEvent ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:occurredAt a rdf:Property ;
    rdfs:label "occurredAt" ;
    rdfs:comment "Timestamp when the reputation event was recorded (typically at completeTrade reconciliation)." ;
    rdfs:domain skyocean:ReputationEvent ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Quotation, Inquiry, Specification & Trade Pairing (added 2.1.5 — 2026-05-07)
# ============================================================
# Skyocean operates as principal in V1 — buys from supplier, sells to buyer.
# A Trade Agreement is created only when a BuyerInquiry is matched to a
# SupplierQuotation and the operator confirms the pairing. Pre-confirmation,
# inquiries and quotations live in the DB for ops review; on confirmation,
# the corresponding KAs are published and a Trade is created with TradeID
# referencing both. One Trade, one supply chain, multiple parties bound by role.

skyocean:CommoditySpecification a rdfs:Class ;
    rdfs:label "CommoditySpecification" ;
    rdfs:comment "Reusable product specification published once per product version by a supplier (or by Skyocean ops on the supplier's behalf in V1). References a supporting Document KA (the spec sheet PDF) and carries structured fields extracted from it. Many SupplierQuotation and Commodity instances reference the same CommoditySpecification — this is the shared definition layer that lets buyers compare across suppliers and lets reconciliation check delivered goods against the published spec." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:SupplierQuotation a rdfs:Class ;
    rdfs:label "SupplierQuotation" ;
    rdfs:comment "A supplier's commercial proposition addressed to Skyocean — price, quantity, validity, incoterm, delivery and payment terms, referencing a CommoditySpecification. Distinct from a buyer-facing offer in a marketplace; the audience of a SupplierQuotation is the operator. Pre-confirmation a quotation lives in the DB only; the KA is published when ops confirms supplier-DID pairing." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:BuyerInquiry a rdfs:Class ;
    rdfs:label "BuyerInquiry" ;
    rdfs:comment "A buyer's request addressed to Skyocean — what product is needed, target price/quantity, delivery location and deadline, payment terms preferred. Pre-match a BuyerInquiry lives in the DB; the KA is published when ops confirms it. If matched to a SupplierQuotation and ops confirms the pair, a Trade Agreement is created referencing both. If never matched by validity expiry the inquiry expires and the buyer is notified." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:ToleranceBand a rdfs:Class ;
    rdfs:label "ToleranceBand" ;
    rdfs:comment "Per-parameter tolerance specification on a trade agreement, modelled after Letter-of-Credit-style tolerances. Defines nominal/min/max for a measurable parameter (e.g., protein 18% +/- 2% means nominal=18, min=16, max=20). Reconciliation logic compares observed values against the band, not against a single equality target." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:SpecObservation a rdfs:Class ;
    rdfs:label "SpecObservation" ;
    rdfs:comment "An institutional measurement of an actual specification parameter on delivered goods (e.g., SGS lab measures protein at 17.4% on the delivered lot). Subclass of InstitutionalAttestation — an SGS report or inspector measurement IS an institutional attestation, with the attested fact being the measured value." ;
    rdfs:subClassOf skyocean:InstitutionalAttestation ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:SpecDiscrepancy a rdfs:Class ;
    rdfs:label "SpecDiscrepancy" ;
    rdfs:comment "Detected discrepancy between an observed specification value and the trade agreement's tolerance band. Subclass of DivergenceEvent (which is itself a subclass of ReputationEvent). Published whenever observed != nominal, regardless of in-tolerance flag — within-tolerance discrepancies are recorded as informational signal for pattern detection across many trades; out-of-tolerance discrepancies trigger DisputeFlag and reputation impact." ;
    rdfs:subClassOf skyocean:DivergenceEvent ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:DocumentaryDiscrepancy a rdfs:Class ;
    rdfs:label "DocumentaryDiscrepancy" ;
    rdfs:comment "Detected disagreement between two trade documents/attestations on a categorical identity field (e.g., the vessel named on the Bill of Lading vs the vessel on the carrier/port Departure attestation). Subclass of DivergenceEvent (itself a subclass of ReputationEvent). Distinct from SpecDiscrepancy: a SpecDiscrepancy is a measured commodity value outside a tolerance band (resolved by commercial renegotiation or price adjustment), whereas a DocumentaryDiscrepancy is a binary cross-document identity mismatch with no tolerance band (resolved by amending the erroneous document). A single documentary discrepancy raises an amendment-requested flag — a likely clerical error, not fraud; two or more discrepancies, or a contradicted core-regulatory document, escalate to full review." ;
    rdfs:subClassOf skyocean:DivergenceEvent ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:DisputeFlag a rdfs:Class ;
    rdfs:label "DisputeFlag" ;
    rdfs:comment "Mandatory flag published when a SpecDiscrepancy is out-of-tolerance, regardless of buyer's commercial decision (accept-anyway, reject, accept-with-renegotiation). The dispute flow with supplier runs in parallel to whatever next-step ops decides for the cargo (open-market resale, in-route diversion, return, etc.). DisputeFlag is operational tracking, not a reputation event itself — the discrepancy that triggered it carries the reputation impact." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:RejectionEvent a rdfs:Class ;
    rdfs:label "RejectionEvent" ;
    rdfs:comment "Recorded when the buyer rejects a delivery. Captures rejection grounds (out-of-tolerance, within-tolerance-vexatious, commercial-other) and the operator's chosen next step (open-market resale, in-route diversion, self-consigned destination sale, price-renegotiate-redirect, return-to-origin). Vexatious rejection (within-tolerance reject without commercial cause) is a buyer-side reputation event; out-of-tolerance rejection compounds with the supplier-side SpecDiscrepancy." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:PriceAmendment a rdfs:Class ;
    rdfs:label "PriceAmendment" ;
    rdfs:comment "Bilateral mid-trade price change agreed between parties — both supplier and buyer (or buyer and Skyocean as principal) sign off on a new price. Distinct from PriceAdjustment which is automatic per pre-existing tolerance rules in the original trade agreement. PriceAmendment requires a new agreement; PriceAdjustment does not." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:PriceAdjustment a rdfs:Class ;
    rdfs:label "PriceAdjustment" ;
    rdfs:comment "Automatic price adjustment triggered by within-tolerance discrepancy under pre-existing trade-agreement clauses (e.g., 'price reduces proportionally for weight short within tolerance'). Mechanical, no new agreement signature required — the original trade agreement authorized the adjustment in advance. Distinct from PriceAmendment (bilateral renegotiation)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — CommoditySpecification

skyocean:specName a rdf:Property ;
    rdfs:label "specName" ;
    rdfs:comment "Human-readable identifier for the specification (e.g., 'Instant Fat Filled Milk Powder 28/10' for Bartex IFFMP 28/10)." ;
    rdfs:domain skyocean:CommoditySpecification ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:specVersion a rdf:Property ;
    rdfs:label "specVersion" ;
    rdfs:comment "Version label for the specification (e.g., 'rev-2024-10-14'). Suppliers may revise specs over time; older versions remain referenceable by historical trades." ;
    rdfs:domain skyocean:CommoditySpecification ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:publishedBySupplier a rdf:Property ;
    rdfs:label "publishedBySupplier" ;
    rdfs:comment "The supplier party-DID that published this specification. May be Skyocean ops on the supplier's behalf in V1; the supplier party-DID is still the canonical reference." ;
    rdfs:domain skyocean:CommoditySpecification ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:supportingDocument a rdf:Property ;
    rdfs:label "supportingDocument" ;
    rdfs:comment "Link to the Document KA carrying the source artifact (typically the spec sheet PDF). Multiple documents may support a single specification (cover letter, lab certificate, etc.)." ;
    rdfs:domain skyocean:CommoditySpecification ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:conformsToSpecification a rdf:Property ;
    rdfs:label "conformsToSpecification" ;
    rdfs:comment "Link from a Commodity instance (the goods in a trade) to the CommoditySpecification it conforms to. Lets reconciliation compare delivered goods against the published spec." ;
    rdfs:domain skyocean:Commodity ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — SupplierQuotation

skyocean:offeredBy a rdf:Property ;
    rdfs:label "offeredBy" ;
    rdfs:comment "The supplier party-DID that issued this quotation." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:productSpecification a rdf:Property ;
    rdfs:label "productSpecification" ;
    rdfs:comment "Link to the CommoditySpecification UAL the quotation references." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedPrice a rdf:Property ;
    rdfs:label "quotedPrice" ;
    rdfs:comment "Quoted price per unit of measure." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:priceCurrency a rdf:Property ;
    rdfs:label "priceCurrency" ;
    rdfs:comment "ISO 4217 currency code for quoted price (e.g., 'USD', 'EUR')." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedIncoterm a rdf:Property ;
    rdfs:label "quotedIncoterm" ;
    rdfs:comment "Incoterm under which the quotation is offered (e.g., 'CIF Sudan', 'FOB Gdansk', 'EXW Pasłęk')." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedQuantity a rdf:Property ;
    rdfs:label "quotedQuantity" ;
    rdfs:comment "Quantity offered in the quotation, expressed in quotedUnitOfMeasure." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedUnitOfMeasure a rdf:Property ;
    rdfs:label "quotedUnitOfMeasure" ;
    rdfs:comment "Unit of measure for quoted quantity (e.g., 'MT' for metric ton, 'kg', 'bag')." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotationValidUntil a rdf:Property ;
    rdfs:label "quotationValidUntil" ;
    rdfs:comment "Expiration date/time of the quotation. After this point, the quotation is no longer eligible for matching unless the supplier extends." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedPaymentTerms a rdf:Property ;
    rdfs:label "quotedPaymentTerms" ;
    rdfs:comment "Payment terms preferred by the supplier (e.g., 'LC at sight', 'CAD', 'TT 30 days', 'open account 60 days')." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:quotedDeliveryWindow a rdf:Property ;
    rdfs:label "quotedDeliveryWindow" ;
    rdfs:comment "Lead-time or delivery window the supplier is offering (e.g., '2-4 weeks from order', 'Q2 2026')." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:ingestedVia a rdf:Property ;
    rdfs:label "ingestedVia" ;
    rdfs:comment "Channel through which a quotation or inquiry was received: 'email', 'ui', 'api', 'erp-pull', 'manual-entry'. Metadata only — the same KA shape is produced regardless of source." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:resultedInTrade a rdf:Property ;
    rdfs:label "resultedInTrade" ;
    rdfs:comment "Forward-reference to the TradeID created when this quotation or inquiry was matched and ops-confirmed. Set once on confirmation; null while pending." ;
    rdfs:domain skyocean:SupplierQuotation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — BuyerInquiry

skyocean:requestedBy a rdf:Property ;
    rdfs:label "requestedBy" ;
    rdfs:comment "The buyer party-DID that issued this inquiry." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetCommodity a rdf:Property ;
    rdfs:label "targetCommodity" ;
    rdfs:comment "Description of the product being requested — may be free-text or structured criteria (HS code, generic name, spec key parameters)." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetPrice a rdf:Property ;
    rdfs:label "targetPrice" ;
    rdfs:comment "Buyer's target price per unit of measure (optional — buyer may request without naming a target)." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetCurrency a rdf:Property ;
    rdfs:label "targetCurrency" ;
    rdfs:comment "ISO 4217 currency code for target price." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetQuantity a rdf:Property ;
    rdfs:label "targetQuantity" ;
    rdfs:comment "Quantity requested by the buyer." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetDeliveryLocation a rdf:Property ;
    rdfs:label "targetDeliveryLocation" ;
    rdfs:comment "Buyer's required delivery location (e.g., 'Port Sudan', 'Khartoum warehouse', 'EXW seller premises')." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetDeliveryDeadline a rdf:Property ;
    rdfs:label "targetDeliveryDeadline" ;
    rdfs:comment "Buyer's required delivery deadline." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:targetPaymentTerms a rdf:Property ;
    rdfs:label "targetPaymentTerms" ;
    rdfs:comment "Payment terms preferred by the buyer." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:inquiryValidUntil a rdf:Property ;
    rdfs:label "inquiryValidUntil" ;
    rdfs:comment "Expiration date/time of the inquiry. If no match is confirmed by this point, the inquiry is marked expired and the buyer is notified." ;
    rdfs:domain skyocean:BuyerInquiry ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — Trade extension (links from Trade to Inquiry/Quotation/Replacement)

skyocean:basedOnInquiry a rdf:Property ;
    rdfs:label "basedOnInquiry" ;
    rdfs:comment "Link from a Trade Agreement to the BuyerInquiry UAL it was created in response to. Always present in V1 (every trade originates from a buyer-side inquiry; speculative/inventory trades are out of V1 scope)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:basedOnQuotation a rdf:Property ;
    rdfs:label "basedOnQuotation" ;
    rdfs:comment "Link from a Trade Agreement to the SupplierQuotation UAL it was matched against. Always present in V1." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:replacesTrade a rdf:Property ;
    rdfs:label "replacesTrade" ;
    rdfs:comment "When a buyer rejects delivery and ops finds a replacement buyer (open-market resale, in-route diversion, self-consigned destination sale), a new Trade is created and references the original via this property. Both Trades retain their immutable parties and history; this property records the goods-cargo continuity across trade records." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:tradeAgreementSignedAt a rdf:Property ;
    rdfs:label "tradeAgreementSignedAt" ;
    rdfs:comment "Timestamp when the Trade Agreement was confirmed by ops and the TradeID was created. Distinct from per-event timestamps within the trade lifecycle." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — ToleranceBand

skyocean:parameter a rdf:Property ;
    rdfs:label "parameter" ;
    rdfs:comment "The measurable parameter the tolerance band applies to (e.g., 'protein', 'moisture', 'fat', 'weight', 'count')." ;
    rdfs:domain skyocean:ToleranceBand ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:nominalValue a rdf:Property ;
    rdfs:label "nominalValue" ;
    rdfs:comment "Nominal/target value for the parameter (e.g., 18% protein)." ;
    rdfs:domain skyocean:ToleranceBand ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:minValue a rdf:Property ;
    rdfs:label "minValue" ;
    rdfs:comment "Lower bound of the tolerance band (e.g., 16% protein for 18% +/- 2%). Observed values below this trigger out-of-tolerance discrepancy." ;
    rdfs:domain skyocean:ToleranceBand ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:maxValue a rdf:Property ;
    rdfs:label "maxValue" ;
    rdfs:comment "Upper bound of the tolerance band. Observed values above this trigger out-of-tolerance discrepancy." ;
    rdfs:domain skyocean:ToleranceBand ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:bandUnit a rdf:Property ;
    rdfs:label "bandUnit" ;
    rdfs:comment "Unit of measure for the tolerance band's values (e.g., '%', 'kg', 'count')." ;
    rdfs:domain skyocean:ToleranceBand ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:toleranceBands a rdf:Property ;
    rdfs:label "toleranceBands" ;
    rdfs:comment "Collection of ToleranceBand instances on a Trade Agreement, one per measurable parameter being constrained. Empty if the trade does not specify tolerances; reconciliation falls back to nominal-equality in that case." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range skyocean:ToleranceBand ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — SpecObservation

skyocean:observedParameter a rdf:Property ;
    rdfs:label "observedParameter" ;
    rdfs:comment "The parameter that was observed (matches a ToleranceBand.parameter on the Trade Agreement)." ;
    rdfs:domain skyocean:SpecObservation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:observedValue a rdf:Property ;
    rdfs:label "observedValue" ;
    rdfs:comment "The actual measured value." ;
    rdfs:domain skyocean:SpecObservation ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:observationUnit a rdf:Property ;
    rdfs:label "observationUnit" ;
    rdfs:comment "Unit of measure for observedValue (must match the corresponding ToleranceBand.bandUnit)." ;
    rdfs:domain skyocean:SpecObservation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:observationMethod a rdf:Property ;
    rdfs:label "observationMethod" ;
    rdfs:comment "Method by which the observation was made (e.g., 'SGS-lab', 'inspector-onsite', 'customs-weighing', 'self-declared-supplier')." ;
    rdfs:domain skyocean:SpecObservation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — SpecDiscrepancy

skyocean:discrepancyParameter a rdf:Property ;
    rdfs:label "discrepancyParameter" ;
    rdfs:comment "Parameter on which the discrepancy was detected. For a SpecDiscrepancy this is a commodity spec (e.g., 'moisture', 'polarization'); for a DocumentaryDiscrepancy it is a cross-document identity field (e.g., 'vessel', 'carrier', 'blNumber', 'port'). Domain is the DivergenceEvent parent so both subclasses share it." ;
    rdfs:domain skyocean:DivergenceEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:discrepancyMagnitude a rdf:Property ;
    rdfs:label "discrepancyMagnitude" ;
    rdfs:comment "Signed magnitude of the discrepancy: positive = above nominal, negative = below nominal. Used for analytics across trades (e.g., does this supplier consistently deliver at lower-end of tolerance?)." ;
    rdfs:domain skyocean:SpecDiscrepancy ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:withinTolerance a rdf:Property ;
    rdfs:label "withinTolerance" ;
    rdfs:comment "True if the observed value falls within the trade-agreement tolerance band; false if out-of-tolerance. Drives downstream actions: in-tolerance discrepancies are informational only; out-of-tolerance trigger DisputeFlag and reputation impact. For a DocumentaryDiscrepancy (a binary identity mismatch with no tolerance band) this is always false — an identity mismatch is by definition out-of-tolerance. Domain is the DivergenceEvent parent so both subclasses share it." ;
    rdfs:domain skyocean:DivergenceEvent ;
    rdfs:range xsd:boolean ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:relatedObservation a rdf:Property ;
    rdfs:label "relatedObservation" ;
    rdfs:comment "Link to the SpecObservation UAL that surfaced this discrepancy (e.g., the SGS lab report KA)." ;
    rdfs:domain skyocean:SpecDiscrepancy ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — DocumentaryDiscrepancy

skyocean:documentValue a rdf:Property ;
    rdfs:label "documentValue" ;
    rdfs:comment "The value asserted by the document of record (referenced via relatedDocument) on the discrepancyParameter — e.g., the vessel name printed on the Bill of Lading. String-typed: cross-document discrepancies compare categorical identity fields, not measured quantities." ;
    rdfs:domain skyocean:DocumentaryDiscrepancy ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestedValue a rdf:Property ;
    rdfs:label "attestedValue" ;
    rdfs:comment "The value asserted by the contradicting attestation (referenced via relatedAttestation) on the discrepancyParameter — e.g., the vessel name on the carrier/port Departure attestation that conflicts with documentValue." ;
    rdfs:domain skyocean:DocumentaryDiscrepancy ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:relatedDocument a rdf:Property ;
    rdfs:label "relatedDocument" ;
    rdfs:comment "Link to the Document KA UAL whose value (documentValue) is one side of the documentary discrepancy. For a version-chained document this is the current head of the schema:identifier chain (e.g., the corrected Bill of Lading)." ;
    rdfs:domain skyocean:DocumentaryDiscrepancy ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:relatedAttestation a rdf:Property ;
    rdfs:label "relatedAttestation" ;
    rdfs:comment "Link to the attestation KA UAL whose value (attestedValue) is the contradicting side of the documentary discrepancy (e.g., the Departure attestation). The audit layer reads skyocean:attestorType off this attestation's public anchor to weight the discrepancy by attestor authority (CustomsAuthority / PortAuthority > Carrier)." ;
    rdfs:domain skyocean:DocumentaryDiscrepancy ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — DisputeFlag

skyocean:relatedDiscrepancy a rdf:Property ;
    rdfs:label "relatedDiscrepancy" ;
    rdfs:comment "Link to the SpecDiscrepancy UAL that triggered this dispute flag." ;
    rdfs:domain skyocean:DisputeFlag ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:disputeStatus a rdf:Property ;
    rdfs:label "disputeStatus" ;
    rdfs:comment "Current status of the dispute: 'open', 'in-resolution', 'resolved-supplier-credit', 'resolved-no-credit', 'closed'." ;
    rdfs:domain skyocean:DisputeFlag ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:flaggedBy a rdf:Property ;
    rdfs:label "flaggedBy" ;
    rdfs:comment "Party who initiated the dispute flag — typically Skyocean operator, occasionally the buyer or insurer." ;
    rdfs:domain skyocean:DisputeFlag ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:flaggedAt a rdf:Property ;
    rdfs:label "flaggedAt" ;
    rdfs:comment "Timestamp when the dispute flag was raised." ;
    rdfs:domain skyocean:DisputeFlag ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — RejectionEvent

skyocean:rejectedBy a rdf:Property ;
    rdfs:label "rejectedBy" ;
    rdfs:comment "Party-DID who rejected the delivery (typically the buyer)." ;
    rdfs:domain skyocean:RejectionEvent ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rejectionReason a rdf:Property ;
    rdfs:label "rejectionReason" ;
    rdfs:comment "Free-text explanation of the rejection." ;
    rdfs:domain skyocean:RejectionEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rejectionGrounds a rdf:Property ;
    rdfs:label "rejectionGrounds" ;
    rdfs:comment "Categorical grounds: 'out-of-tolerance' (compounds with supplier-side SpecDiscrepancy), 'within-tolerance-vexatious' (buyer-side reputation hit), 'commercial-other' (e.g., buyer cancellation, force majeure)." ;
    rdfs:domain skyocean:RejectionEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rejectedAt a rdf:Property ;
    rdfs:label "rejectedAt" ;
    rdfs:comment "Timestamp of rejection." ;
    rdfs:domain skyocean:RejectionEvent ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:nextStepDecision a rdf:Property ;
    rdfs:label "nextStepDecision" ;
    rdfs:comment "Operator's chosen next-step for the rejected cargo: 'open-market-resale', 'in-route-diversion', 'self-consigned-destination-sale', 'price-renegotiate-redirect', 'return-to-origin'. Recorded after ops decides; null until then. If a replacement Trade is created, that Trade carries skyocean:replacesTrade pointing to the original." ;
    rdfs:domain skyocean:RejectionEvent ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — PriceAmendment

skyocean:originalPrice a rdf:Property ;
    rdfs:label "originalPrice" ;
    rdfs:comment "The price stated in the original trade agreement, prior to amendment or adjustment." ;
    rdfs:domain skyocean:PriceAmendment ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:amendedPrice a rdf:Property ;
    rdfs:label "amendedPrice" ;
    rdfs:comment "The new bilaterally-agreed price under the amendment." ;
    rdfs:domain skyocean:PriceAmendment ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:amendmentReason a rdf:Property ;
    rdfs:label "amendmentReason" ;
    rdfs:comment "Reason for the amendment (e.g., 'extended payment terms granted in exchange for price increase', 'split shipment fee absorbed by seller', 'force majeure renegotiation')." ;
    rdfs:domain skyocean:PriceAmendment ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:agreedBy a rdf:Property ;
    rdfs:label "agreedBy" ;
    rdfs:comment "Parties who consented to the amendment. Bilateral amendments require both supplier-leg and buyer-leg counterparties to be present." ;
    rdfs:domain skyocean:PriceAmendment ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# Properties — PriceAdjustment

skyocean:adjustedPrice a rdf:Property ;
    rdfs:label "adjustedPrice" ;
    rdfs:comment "The new price after automatic adjustment per pre-existing trade-agreement clauses." ;
    rdfs:domain skyocean:PriceAdjustment ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:adjustmentTrigger a rdf:Property ;
    rdfs:label "adjustmentTrigger" ;
    rdfs:comment "What triggered the automatic adjustment: 'weight-shortfall', 'within-tolerance-quality-discount', 'split-shipment-allowance', etc." ;
    rdfs:domain skyocean:PriceAdjustment ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:adjustmentRule a rdf:Property ;
    rdfs:label "adjustmentRule" ;
    rdfs:comment "Reference to the trade-agreement clause that authorized this automatic adjustment, so the adjustment is auditable back to its commercial basis." ;
    rdfs:domain skyocean:PriceAdjustment ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:adjustmentMagnitude a rdf:Property ;
    rdfs:label "adjustmentMagnitude" ;
    rdfs:comment "Signed adjustment amount (positive = price increase, negative = price reduction)." ;
    rdfs:domain skyocean:PriceAdjustment ;
    rdfs:range xsd:decimal ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Document KA Properties (added 2.1.6 — 2026-05-08)
# ============================================================
# Phase 1.7.5.2 formalises 5 properties on skyocean:Document that have
# been in de-facto use across visibility templates and trade-samples
# but were not previously declared. The validator's prefix-only check
# accepts them today; declaring them tightens the ontology vs. its
# already-de-facto usage and gives downstream tooling (audit dashboard,
# partner agents) explicit type contracts to work against. No new
# classes; no breaking changes.

skyocean:documentType a rdf:Property ;
    rdfs:label "documentType" ;
    rdfs:comment "The type/class of document, expressed as a PascalCase string identifier. Validated at api ingress via services/documentKaService.js VALID_DOCUMENT_TYPES allowlist (69 entries as of 2026-08-13; canonical list maintained in code, not vocab, since values are runtime enum strings rather than ontology structural terms — matches GS1 / Schema.org / UCP / UN-EDIFACT convention for trade-document type catalogues). RETIRED: MarineCargoInsurance (2026-06-10, replaced by InsuranceCertificate + PRIVATE skyocean:insuranceType). Catalogue families: commercial-financial (CommercialInvoice, SupplierInvoice, ServiceProviderInvoice, BankPaymentConfirmation, DonorAggregateReceipt, DonationAgreement, TradeFinanceAgreement, SalesContract, PurchaseAgreement, MonetaryGrant) + logistics-shipping (BillOfLading, InlandTransport, PackingList, ConsolidationManifest, BulkConsolidationPlan, BulkSupplierProcurementOrder, BulkOilLoadingSurvey, TankCleanlinessWallWashCertificate, BookingConfirmation, CharterParty, WarehouseReceipt, ShippingInstruction, MatesReceipt, ArrivalNotice, CargoReleaseOrder, DeliveryOrder, GatePass, EquipmentInterchangeReceipt, VerifiedGrossMassDeclaration, Waybill, InventoryReport, ContainerDispositionRecord) + customs-regulatory (ExportCustomsDeclaration, ImportCustomsClearance, CertificateOfOrigin, EUDRDueDiligenceStatement, HumanitarianImportApproval, PharmaceuticalImportAuthorisation, DutyExemptionCertificate) + inspection-quality-health (QualityInspection, InspectionCertificate, PhytosanitaryCertificate, VeterinaryHealthCertificate, HealthSanitaryCertificate, CocoaGradingCertificate, FumigationCertificate, RadiationFreeCertificate, GMPCertificate, CertificateOfAnalysis, WHOPharmaceuticalPrequalification) + insurance-loss (InsuranceCertificate, InsuranceClaimNotification, IndependentLossSurveyReport) + telemetry-IoT (AISVesselPositionFeed, ColdChainTelemetryLog, ContainerTelemetryLog) + donation-distribution-humanitarian (DistributionObservationReport, DistributionAcknowledgment, NeedsAssessment, DistributionPlan, ProofOfDistribution, DonorReport) + funding-side rail-neutral (CurrencyConversionRecord, FundingCloseStatement, FundUtilisationStatement) + meta (ProductSpecification, CommercialOffer, BuyerInquiry, PlatformDocumentation). 2026-08-13 batch of 22 added standards-first per Sebastian ruling (UNTDED/UN-EDIFACT 1001 terms, SOLAS VGM, schema:MonetaryGrant, IASC/OCHA practice terms; adversarially verified; bind to the TERM never the numeric code). Funder-mix guardrail: no documentType value encodes WHO funded — funding rail and funder mix are funding-side facts and never fork trade-side classes. New values added without vocab bump; vocab bump only required for new structural terms (new properties or classes). Distinct from skyocean:requiredDocumentTypes which is a Trade-level property listing required document types for a given trade." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:issuer a rdf:Property ;
    rdfs:label "issuer" ;
    rdfs:comment "The entity that issued this document. Recorded as a string (legal name or party-DID) for V1; may evolve to a typed link to skyocean:TradeParty when Phase 1.7.5.4's per-role projection refactor formalises party identity in KA payloads." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:sha256 a rdf:Property ;
    rdfs:label "sha256" ;
    rdfs:comment "Hex-encoded SHA-256 hash of the document file content (typically prefixed '0x'). Audit hash for tamper-evidence: any consumer can recompute the hash on the file they receive and compare against this value." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:storageUrl a rdf:Property ;
    rdfs:label "storageUrl" ;
    rdfs:comment "Storage location reference for the document file (e.g. an S3 key 's3://bucket/path' or just the key fragment for storage-agnostic resolution). Lives in the private layer of the Document KA — visible to the operator and per-role-projected callers, never on the public anchor." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:uploaderUserId a rdf:Property ;
    rdfs:label "uploaderUserId" ;
    rdfs:comment "Identifier of the user who uploaded this document (matches users.user_id in the parties/users schema). Lives in the private layer; used for audit-trail attribution and for ABAC checks ('can this user see this document?')." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:integer ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# DonationContribution donor-attribution properties (added 2.1.7 — 2026-05-12)
# ============================================================
# Phase 1.8.6.1 introduces typed donor-attribution properties on
# donation:DonationContribution. The 'donor attribution toggle' design
# (Sebastian-locked 2026-05-12) requires three new typed properties so
# that the toggle, the donor reference, and the public display name
# are first-class ontology citizens rather than schema:additionalProperty
# blobs. This supports cryptographically-defending donor attribution
# claims at Phase 2.5+ when external auditors walk the DKG for charity
# verifications. Amount + timestamp continue to reuse schema:price
# (schema:MonetaryAmount value + currency) and schema:dateCreated; no
# new properties for those. No new classes; no breaking changes.
#
# Always-public on DonationContribution KA public anchor (per the
# Sebastian-locked toggle): campaignRef + dateCreated + schema:price +
# opaque contributor identifier. donation:publicDisplayName is emitted
# in the public anchor ONLY when donation:isPublicAttribution = true.

donation:contributorRef a rdf:Property ;
    rdfs:label "contributorRef" ;
    rdfs:comment "Reference to the donor party. Holds a typed link to the donor's skyocean:TradeParty record (party-DID surfaced via schema:identifier in the embedded reference). In the public anchor of the KA the DID is treated as opaque to public consumers; in role-projected layers consumers with the appropriate role see the full identity. Donor party_type is set to 'donor' on first DonationContribution emission for new sign-ups; existing financiers/merchants making donations get attribution to their existing party-DID (multi-DID-per-user model per Phase 1.7.5.1 user_party_dids schema)." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:isPublicAttribution a rdf:Property ;
    rdfs:label "isPublicAttribution" ;
    rdfs:comment "Boolean flag (default false = anonymous) controlling whether the donor's KYC legal name is included in the public anchor of the DonationContribution KA. ONE toggle, donor-controlled at contribution time. Amount + timestamp + opaque donor identifier remain always-public regardless of this flag — campaign totals and per-donation amounts are cryptographically verifiable to external auditors even for anonymous contributions. Sebastian-locked design 2026-05-12." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:boolean ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

donation:publicDisplayName a rdf:Property ;
    rdfs:label "publicDisplayName" ;
    rdfs:comment "Donor's KYC-derived legal name surfaced in the public anchor when donation:isPublicAttribution = true. For individual donors: 'firstName + lastName' from KYC record. For institutional donors: full 'legalName' from KYC record — institutions choosing public attribution go fully public, not half-way (Sebastian-locked 2026-05-13). KYC-derived (no donor-supplied freeform name in V1). Null/absent when isPublicAttribution = false (donor remains 'Anonymous' in public views). Phase 1.8.7 user-tier migration preserves the donor's original publicDisplayName attribution choices on historical contributions." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# DonationContribution wallet-privacy property (added 2.1.8 — 2026-05-13)
# ============================================================
# Phase 1.8.6.1.1 hotfix introduces a redacted public display identifier
# for the DonationContribution KA public anchor. The 1.8.6.1 implementation
# placed the full donor party-DID `did:skyocean:donor:wallet:<full_address>`
# in the public anchor — Sebastian flagged this as a privacy regression
# (full Ethereum wallet exposure chains the donor to on-chain activity +
# balance + cross-platform identity correlation). The fix moves full
# contributorRef to private/role-projected layers only; the public anchor
# carries the redacted `contributorDisplay` instead.

donation:contributorDisplay a rdf:Property ;
    rdfs:label "contributorDisplay" ;
    rdfs:comment "Human-readable contributor identifier for the public anchor of the DonationContribution KA. Format depends on auth path: wallet donors → truncated address using the standard Web3 convention '0x1234...5678' (first 6 + last 4 hex chars — matches Etherscan + MetaMask + every standard wallet UX donors are familiar with; Sebastian-locked 2026-05-13). Auth-session individual donors → 'Anonymous' default; first+last KYC name when donation:isPublicAttribution = true. Auth-session institutional donors → 'Anonymous Institution' default; full legalName when donation:isPublicAttribution = true (institutions opting public go fully public, not half-way). Always-present on public anchor; full donor identity via donation:contributorRef restricted to private + role-projected layers only." ;
    rdfs:domain donation:DonationContribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Title Transfer module (added 2.1.9 — 2026-05-13)
# ============================================================
# V1 mechanism for transferring legal title to goods from the Skyocean
# operating entity acting as consignee to the buyer (commodity trades)
# OR to the local distribution partner (donation campaigns). V1 = BL
# endorsement by Skyocean operator on buyer-payment confirmation
# (commodity) OR on delivery confirmation (donation). Operator emits a
# skyocean:TitleTransfer KA recording the title-transfer event (who →
# who, mechanism, supporting documents, operator who effected the
# transfer, timestamp).
#
# Production lifecycle adds Phase 5.5 between Payment Confirmed (Phase
# 5) and Completion (Phase 6). For Phase 1.8.8 wiring scope: see
# internal/technicals/platform/production/action-plan.md §1.8.8.

skyocean:TitleTransfer a rdfs:Class ;
    rdfs:label "TitleTransfer" ;
    rdfs:comment "An attestation recording the legal transfer of title to goods. V1 mechanism: Bill of Lading endorsement by the Skyocean operator on buyer-payment confirmation (commodity trades) or delivery confirmation (donation campaigns). Anchored to the trade via skyocean:tradeRef. Lifecycle position: Phase 5.5, between Payment Confirmed (Phase 5) and Completion (Phase 6). Issued by the Skyocean operator using the operatorAuthGate c′ synthetic operator party-DID convention (Phase 1.8.1)." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:transferredFrom a rdf:Property ;
    rdfs:label "transferredFrom" ;
    rdfs:comment "Party from whom title transferred. For commodity trades: typically the Skyocean operating entity acting as consignee in the destination country (e.g., did:skyocean:operating-entity:sudan). For donation campaigns: the Skyocean operating entity managing campaign delivery (e.g., did:skyocean:operating-entity:lithuania)." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:transferredTo a rdf:Property ;
    rdfs:label "transferredTo" ;
    rdfs:comment "Party to whom title transferred. For commodity trades: external buyer DID (e.g., did:skyocean:buyer:sudan:SD-BUY-2026-XXXXX). For donation campaigns: local distribution partner DID (e.g., did:skyocean:institution:DIST-SUD-XXXXX)." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:transferMechanism a rdf:Property ;
    rdfs:label "transferMechanism" ;
    rdfs:comment "Mechanism by which title was effected. V1 enum values: BL_ENDORSEMENT (Bill of Lading endorsement by Skyocean operator — commodity trades), DELIVERY_ACKNOWLEDGEMENT (signed distribution acknowledgement by local partner — donation campaigns; even when a BL exists for shipping, donation title transfers to the local distribution partner via their signed delivery receipt, not via BL endorsement, because donations are not purchases). Future enum values (V2+, not pre-declared per best-part-is-no-part): NOTARIZED_TITLE_DEED, WAREHOUSE_RECEIPT_TRANSFER, ON_CHAIN_TOKEN_TRANSFER." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:transferStatus a rdf:Property ;
    rdfs:label "transferStatus" ;
    rdfs:comment "Status of the title transfer event. Enum values: Pending (transfer initiated, awaiting operator action), Effected (transfer completed and recorded), Failed (transfer attempt rejected or reversed)." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:effectedBy a rdf:Property ;
    rdfs:label "effectedBy" ;
    rdfs:comment "Skyocean operator party-DID who effected the title transfer, using the operatorAuthGate c′ synthetic operator party-DID convention from Phase 1.8.1 — did:skyocean:operator:auth-service:<admin_users.uuid> in V1; wallet-derived DID at Phase 2.5+ end-state when admin actions emit signed OperatorAction KAs to the DKG (project_skyocean_operator_auth_gate.md memory)." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range skyocean:TradeParty ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:supportingDocuments a rdf:Property ;
    rdfs:label "supportingDocuments" ;
    rdfs:comment "Multi-valued links to skyocean:Document KAs that support the title transfer — typically the endorsed Bill of Lading for commodity trades, or the Delivery Acknowledgement for donation campaigns. Each supporting document a separate value." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range skyocean:Document ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# TitleTransfer private-layer additions (v2.1.13 — 2026-05-18)
# Surfaced during Phase 1.8.8 HALT 1 design pass; declares 2 new skyocean: predicates
# for the TitleTransfer private layer per standards-first vocab-discipline rule
# (no schema.org / GS1 / web3 / international equivalent exists for either).
# Third candidate signingOfficerIdentity deferred per best-part-is-no-part — operator
# c′ DID is sufficient for V1; declare when a real legal-counsel signoff use case
# surfaces.
# ============================================================

skyocean:endorsementNarrative a rdf:Property ;
    rdfs:label "endorsementNarrative" ;
    rdfs:comment "Free-text private description of the title transfer event (e.g., 'endorsed by Operator Jane Doe at Skyocean Sudan office on 2026-07-19'). Carries the human-readable provenance that supplements the structured public-anchor fields (mechanism + status + party DIDs + date). PRIVATE layer only; donors + public observers do not see the narrative." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:endorsedDocumentUrl a rdf:Property ;
    rdfs:label "endorsedDocumentUrl" ;
    rdfs:comment "Private S3/IPFS URL pointing to the scanned/digital artifact of the endorsed Bill of Lading (BL_ENDORSEMENT mechanism) or signed Delivery Acknowledgement (DELIVERY_ACKNOWLEDGEMENT mechanism). Distinct from skyocean:supportingDocuments which references Document KAs by UAL — endorsedDocumentUrl is the direct inline artifact reference for the title-transfer event itself. PRIVATE layer only; operator + recipient role-projection see the URL." ;
    rdfs:domain skyocean:TitleTransfer ;
    rdfs:range xsd:anyURI ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# KYC-KA emission private-layer predicates (v2.1.14 — 2026-05-19)
# Surfaced during Phase 1.8.9 Track I design pass. Declares 5 new skyocean:
# predicates for the KYC clearance attestation private layer per standards-first
# vocab-discipline rule (no schema.org / GS1 / international equivalent for the
# underlying KYC-credential semantic).
# All 5 reused on the skyocean:InstitutionalAttestation class with
# attestationType='KYCClearance'. skyocean:internalOpsNotes is multi-domain
# (replaces existing-but-undeclared usage across TitleTransfer + Document +
# DonationDistribution + InstitutionalAttestation surfaces).
# ============================================================

skyocean:providerCredentialId a rdf:Property ;
    rdfs:label "providerCredentialId" ;
    rdfs:comment "Private KYC-provider-issued credential ID (e.g., Fractal user_id, ComplyCube applicant_id, Sumsub applicantId, future-provider equivalent). Provider-agnostic field — the value semantic is 'whatever identifier the provider uses for the cleared credential.' PRIVATE layer only on InstitutionalAttestation KAs with attestationType='KYCClearance'." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:jurisdiction a rdf:Property ;
    rdfs:label "jurisdiction" ;
    rdfs:comment "Private jurisdiction code where KYC was performed (ISO 3166-1 alpha-2 country code; e.g., 'GB', 'DE', 'AE'). Distinct from the attestee party's residence country — this is where the provider was operating when issuing the credential. PRIVATE layer only on InstitutionalAttestation KAs with attestationType='KYCClearance'." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:kycLevel a rdf:Property ;
    rdfs:label "kycLevel" ;
    rdfs:comment "Private KYC verification level applied (e.g., 'basic' / 'enhanced' / 'institutional-kyb'). Provider-agnostic enum — different providers use different internal naming but the semantic ('how rigorous was the verification') maps consistently. PRIVATE layer only on InstitutionalAttestation KAs with attestationType='KYCClearance'." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:attestationCredentialHash a rdf:Property ;
    rdfs:label "attestationCredentialHash" ;
    rdfs:comment "Private SHA-256 hash of the underlying credential blob (verifiable-credential JSON, KYC report PDF, provider attestation payload). Enables auditor to detect tampering between issuance and KA emission without exposing the credential contents in the public anchor. PRIVATE layer only on InstitutionalAttestation KAs with attestationType='KYCClearance'." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:internalOpsNotes a rdf:Property ;
    rdfs:label "internalOpsNotes" ;
    rdfs:comment "Private free-text operator notes attached to a KA event. Multi-domain: applicable to InstitutionalAttestation (KYC clearance, claim decision, etc.) + TitleTransfer (BL endorsement narrative supplement) + Document (uploader notes) + DonationDistribution (operator delivery commentary). Replaces existing-but-previously-undeclared usage across these surfaces (declared v2.1.14 retroactively per standards-first vocab-discipline rule). PRIVATE layer only." ;
    rdfs:domain skyocean:InstitutionalAttestation, skyocean:TitleTransfer, skyocean:Document, donation:DonationDistribution ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Treasury source-account linkage on FinancingRecord (added 2.1.9 — 2026-05-13)
# ============================================================
# Each institutional financier (any participant on a FinancingRecord —
# including Skyocean own-capital cases where a regional Skyocean entity
# is the financier) has a source bank account from which their capital
# originated. The destination side (Skyocean fundReceivingEntity's
# bank) is already addressable via the Trade-level
# skyocean:fundReceivingEntity property. This new sourceAccount
# surfaces the financier-side bank.
#
# Per-institution allocation visibility (audit dashboard's "where is
# my money" question) walks the existing trade graph filtered by
# institution party-DID; this property surfaces the source side of
# each financing flow. Internal accounting (how much of the financier's
# capital went to which freight forwarder, supplier, etc.) is V2+
# scope; V1 surfaces only who contributed FROM where + who paid TO
# where (buyer-payment destination).

skyocean:sourceAccount a rdf:Property ;
    rdfs:label "sourceAccount" ;
    rdfs:comment "Institutional financier's bank account from which their capital originated. Lives in the private layer of the paired FinancingRecord KA (TradePrivateData). Structure: object with schema:bankName + schema:identifier (SWIFT BIC) + schema:accountId (account number, redacted in samples). Visible to the institution + Skyocean operator; not visible to other financiers on the same trade. Applies symmetrically to Skyocean own-capital cases — a regional Skyocean entity (e.g., Skyocean Lithuania, Skyocean Argentina, any operating-entity:<region>) acting as financier names that entity's own bank as the source account. V1 scope: who contributed from where. V2+: internal accounting of how the capital was allocated downstream (freight, supplier, etc.) — out of V1 scope per Sebastian-locked 2026-05-13." ;
    rdfs:domain skyocean:FinancingRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Provenance tagging — env-emitter classification on every KA
# (v2.1.15 — 2026-05-21; Sebastian-locked via cross-chat v1.6 coordination 2026-05-19)
# Bridge from v1.5 hand-curated audit-side allowlist to v2 DB-driven
# audit-as-module integration. Audit-public deployments filter by
# allowlist per environment (see feedback_skyocean_provenance_discipline
# memory). Fail-closed default: untagged KAs excluded from audit surfaces.
# Standards-first carve-out justified: no schema.org / GS1 / W3C / PROV-O
# equivalent for the "which environment emitted this KA" semantic
# (PROV-O is agent/activity-focused, not env-classification).
# Layer placement: PUBLIC anchor — audit needs filter at discovery time
# without authenticated reads.
# ============================================================

skyocean:referencesSimulatedParty a rdf:Property ;
    rdfs:label "referencesSimulatedParty" ;
    rdfs:comment "TRUE when any party this asset references is a provisioned TEST FIXTURE rather than a real counterparty. Asserted about the SUBJECT, not the emitter — deliberately ORTHOGONAL to skyocean:provenance, which classifies the environment that minted the asset: a staging-emitted asset about a fixture is correctly 'production-staging' AND referencesSimulatedParty true, and one field cannot carry both facts. MINTED (2026-09-02) rather than reusing a provenance enum value, on the same test WaypointTransit was minted under at v2.1.23 — no existing value fits, and reusing one would be a wrong claim on a permanent record. PUBLIC layer BY NECESSITY, not preference: the attestee on a clearance is opaqued (FIX#12), so an anonymous reader cannot resolve who an assertion is about; if this marker were private, a fixture clearance would be indistinguishable from a real one to exactly the reader it exists for. ALWAYS EMITTED, true AND false — emit-only-when-true would make ABSENCE read as 'real', so a builder that forgot the property would produce assets indistinguishable from genuine ones; always-emitting makes absence mean 'minted before this property existed', which is a detectable state rather than a silent claim. An absence must never read as a fact. Derived at BUILD from parties.is_simulated over every referenced party (OR-ed), never caller-supplied — a caller-supplied flag is one a caller can forget. GUARD: no asset with this true may mint under skyocean:provenance 'production'; enforced at build, before a name is taken, so the refusal burns no kaId. NO rdfs:domain — applies to any KA class universally, following skyocean:provenance." ;
    rdfs:range xsd:boolean ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:provenance a rdf:Property ;
    rdfs:label "provenance" ;
    rdfs:comment "Environment-emitter classification on every KA. Enables audit-side surfaces to filter the V8 paranet by deployment context without per-anchor curation. Enum values (5): 'production' (real production-app trades on V8 mainnet; reserved for post-mainnet-activation-gate; no KAs today), 'production-staging' (real production-app trades on V8 testnet — Base Sepolia — emitted from the production app's staging env; current state for all real-app KAs), 'audit-demo' (audit dashboard curated demo cohort; 9 anchors from audit-build), 'ccp-smoke' (CCP integration LIVE-fire test publishes — e.g., the 2 LIVE KYCClearance KAs from Phase 1.8.9 HALT 2.B test sweep), 'manual-debug' (one-off paranet writes for diagnostics). NO rdfs:domain — applies to any KA class universally (no abstract skyocean:KnowledgeAsset superclass at v1; Phase 2.5+ vocab hygiene can introduce one if a second universal-property pattern emerges). PUBLIC layer. Mainnet-cutover forward-action: drop 'production-staging' from audit.skyocean.io allowlist when V8 mainnet activates (per mainnet activation gate checklist)." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================
# Inland Transport module (added 2.1.10 — 2026-05-14)
# ============================================================
# Donation campaigns (and some commodity flows where Skyocean takes
# the goods past port discharge) don't close at port arrival or buyer
# payment — there's an inland transport leg (port → warehouse →
# distribution points) and a last-mile leg (warehouse → beneficiary
# household or end-recipient location). This module captures inland
# transport legs as their own KA + extends the attestationType enum
# with DeliveryScan (final-destination beneficiary proof-of-delivery
# scan; typically an IoT-device-attested event) and InlandHandover
# (custody change between inland-transport legs).
#
# For donation campaigns where Skyocean transfers title to a local
# distribution partner via DELIVERY_ACKNOWLEDGEMENT (Pattern B):
# Skyocean's KA emission stops at the handover; the local partner
# reports back distribution events (typically signed reports +
# optionally IoT scans Skyocean's operator submits on the partner's
# behalf if Skyocean retained operational visibility).
#
# For donation campaigns where Skyocean handles last-mile directly
# (Pattern A): Skyocean's operator emits InlandTransport + DeliveryScan
# attestations per distribution event all the way to final beneficiary.
# The campaign closes only when all planned distributions are completed
# (not at port arrival or any single payment event).

skyocean:InlandTransport a rdfs:Class ;
    rdfs:label "InlandTransport" ;
    rdfs:comment "An inland (post-port-discharge) transport leg that moves cargo from one location to another within the destination country (e.g., Port Sudan → Khartoum warehouse, Khartoum warehouse → distribution point in River Nile State). Donation campaigns + Skyocean-handled commodity last-mile cases use this class to extend the audit trail past port arrival. Anchored to the trade or campaign via skyocean:tradeRef." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:transportMode a rdf:Property ;
    rdfs:label "transportMode" ;
    rdfs:comment "Mode of inland transport. V1 enum values: TRUCK, RAIL, COMBINED (multi-modal — e.g., truck + rail), AIR (rare for commodity but used in humanitarian airdrops or critical medicine). V2+ values not pre-declared per best-part-is-no-part." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:vehicleRef a rdf:Property ;
    rdfs:label "vehicleRef" ;
    rdfs:comment "Vehicle identifier for the inland transport leg — typically a truck license plate or carrier-issued route identifier. May be private-layer for security reasons (driver identifiability + route predictability)." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:originLocation a rdf:Property ;
    rdfs:label "originLocation" ;
    rdfs:comment "Origin of the inland transport leg — typically a port (UN/LOCODE), warehouse, or named distribution hub. Free text in V1; structured GLN reference at V2+." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:destinationLocation a rdf:Property ;
    rdfs:label "destinationLocation" ;
    rdfs:comment "Destination of the inland transport leg — warehouse, distribution point, or for last-mile a beneficiary cluster identifier (e.g., 'Khartoum North district 7' rather than exact household address; full address goes to private layer)." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:departedAt a rdf:Property ;
    rdfs:label "departedAt" ;
    rdfs:comment "Timestamp of inland-transport-leg departure (ISO 8601 UTC). Distinct from schema:dateCreated which records when the KA was published." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:arrivedAt a rdf:Property ;
    rdfs:label "arrivedAt" ;
    rdfs:comment "Timestamp of inland-transport-leg arrival at destination (ISO 8601 UTC). Departure + arrival pair gives end-to-end leg duration for audit + reconciliation." ;
    rdfs:domain skyocean:InlandTransport ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:relatedInlandTransport a rdf:Property ;
    rdfs:label "relatedInlandTransport" ;
    rdfs:comment "Reference from an InstitutionalAttestation (typically DeliveryScan or InlandHandover) back to the InlandTransport KA whose leg the attestation belongs to. Enables the audit dashboard to thread the full inland-and-last-mile chain from port to beneficiary, attestation-by-attestation along each leg." ;
    rdfs:domain skyocean:InstitutionalAttestation ;
    rdfs:range skyocean:InlandTransport ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ============================================================================
# Vocab v2.1.12 additions (2026-05-17) — retrofitting 8 predicates already
# emitted by production kaBuilders but previously undeclared. Surfaced during
# audit-chat v1.2 publish phase + vocab-discipline patch #3 sweep. All 8 stay
# skyocean:* per standards-first rule (no schema.org / GS1 / web3 / international
# equivalent for the underlying semantic). The 9th flagged predicate
# (skyocean:expectedArrivalDate) substituted to schema:expectedArrivalUntil in
# the api repo — does NOT need vocab declaration.
# ============================================================================

skyocean:contributingAttestations a rdf:Property ;
    rdfs:label "contributingAttestations" ;
    rdfs:comment "Multi-valued reference list of the EVIDENCE ITEMS that fed into a ConvergenceRecord's cross-validation. In `attestation` convergence mode these are InstitutionalAttestation KAs; in `document-set` mode each assessed Document counts as its issuing authority's attestation and is listed here directly. |contributingAttestations| equals attestationCount by definition. Enables auditors to trace exactly which items were aggregated to compute verificationStrength and consensusStatus." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range skyocean:ConvergenceEvidence ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:expectedShipmentDate a rdf:Property ;
    rdfs:label "expectedShipmentDate" ;
    rdfs:comment "Planned (not actual) date the cargo is expected to depart origin. xsd:date format (day-precision). No schema.org expected-shipment equivalent exists — schema:shipDate is the completed-event single date on Order which doesn't fit the planning semantic. Distinct from skyocean:actualShipmentDate (if declared later) which would record the realized departure event." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:date ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:portOfLoading a rdf:Property ;
    rdfs:label "portOfLoading" ;
    rdfs:comment "Origin port where cargo is loaded onto the primary carrier. Free-text string for V1 (typically combines port name + UN/LOCODE, e.g., 'Rosario, ARROS'). Phase 2.5+ vocab hygiene may upgrade to a typed link to a Port class if a logistics-port ontology is adopted. No schema.org logistics-port term; GS1's ShipFromLocation is too generic." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:portOfDischarge a rdf:Property ;
    rdfs:label "portOfDischarge" ;
    rdfs:comment "Destination port where cargo is offloaded from the primary carrier. Same shape conventions as skyocean:portOfLoading. Distinct from final delivery location (which may be inland past the port — covered by skyocean:InlandTransport + last-mile attestations)." ;
    rdfs:domain skyocean:Trade ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rawComputation a rdf:Property ;
    rdfs:label "rawComputation" ;
    rdfs:comment "Stringified computation provenance: raw inputs + formula + intermediate values, enabling recompute-to-verify without trusting Skyocean's runtime. Opaque-blob xsd:string. RETIREMENT IS SCOPED, NOT GLOBAL (v2.1.29, 2026-08-27): it is retired from the DOCUMENT-MODE ConvergenceRecord at engine 1.0.16 only. On a 53-document campaign that one literal encoded to 62,225 bytes against the node's 60,000-byte cap (raw 57,113 — the overflow was JSON-encoding inflation, not content), so it was SUPERSEDED THERE by skyocean:rawComputationAxes + skyocean:rawComputationDocuments. It is NOT retired for its two other live emitters, which carry DIFFERENT content under the same name: (a) the attestation-mode ConvergenceRecord's Phase-1.6 shape {satisfiedWeight, totalWeight, requiredCount}, and (b) skyocean:ColdChainLog's reading-recompute {engine, readingCount, usableCount, excursionCount, ...} — note (b) is OUTSIDE the rdfs:domain declared below, a pre-existing mismatch recorded here rather than silently widened. So term_status stays 'testing': marking a term archaic while three builders emit it would be a name over-promising its own limits. It is NEVER reused with changed content on the document mode: a reader of an anchored record cannot tell which meaning a redefined field held, so 1.0.16+ readers take the two new predicates, <=1.0.15 readers take this one, and the engineVersion stamped in configSnapshot decides which." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rawComputationAxes a rdf:Property ;
    rdfs:label "rawComputationAxes" ;
    rdfs:comment "Stringified per-axis computation provenance on a ConvergenceRecord (engine 1.0.16+): every axis's weight, score, checks and abstention notes — the half of the old skyocean:rawComputation that carries HOW the verdict was computed. Split from that predicate because the combined literal exceeded the node's 60,000-byte encoded cap on a 53-document campaign; the split keeps the whole computation ON-CHAIN rather than trimming it or moving audit substance to an off-chain store. Coverage, scored weight and the published strength all stay re-derivable from this predicate plus skyocean:axisScores. Opaque-blob xsd:string." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rawComputationDocuments a rdf:Property ;
    rdfs:label "rawComputationDocuments" ;
    rdfs:comment "Stringified contributing-document provenance on a ConvergenceRecord (engine 1.0.16+): per document the type, URN, UAL and the LOCKED ORIGIN MARKERS (docOrigin, issuingAuthorityClass) — the half of the old skyocean:rawComputation that carries WHAT the verdict was computed over. Distinct from skyocean:contributingAttestations, which carries kaUAL only: the origin markers are what the discrepancy-severity model keys on, so the two are not interchangeable and neither substitutes for the other. Includes the configSnapshot (rulebook name, version, engineVersion) that identifies the rules in force at mint time. Opaque-blob xsd:string." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rawMetadata a rdf:Property ;
    rdfs:label "rawMetadata" ;
    rdfs:comment "Stringified structured-data blob carrying class-specific metadata that hasn't been promoted to typed properties yet. Currently used on ToleranceBand (delta thresholds + units) and CommoditySpecification (keySpecFields). Opaque-blob xsd:string for V1. Phase 2.5+ vocab hygiene refactors each consumer into typed structured properties (e.g., ToleranceBand.delta + ToleranceBand.unit; CommoditySpec.specFields[]). Distinct from documentKaService's earlier skyocean:rawMetadata which was retired to schema:fileFormat + schema:contentSize in vocab-discipline patch #2 (api 9540cd8)." ;
    rdfs:domain skyocean:ToleranceBand, skyocean:CommoditySpecification ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rawPayload a rdf:Property ;
    rdfs:label "rawPayload" ;
    rdfs:comment "Stringified payload blob carrying raw source data that hasn't been parsed into typed properties. Distinct from skyocean:rawMetadata (class-specific metadata) and skyocean:rawComputation (provenance) — rawPayload is the original-input form (e.g., raw EDIFACT message, raw partner-API JSON, raw IoT-feed payload) preserved alongside the typed-extracted form for audit replay. Opaque-blob xsd:string." ;
    rdfs:domain skyocean:Document, skyocean:InstitutionalAttestation ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:rulebookName a rdf:Property ;
    rdfs:label "rulebookName" ;
    rdfs:comment "Reference to the convergence rulebook used to evaluate a ConvergenceRecord (e.g., 'default.json' for Branch A retail + Branch C institutional/donation; 'branch-b-default.json' for Branch B mixed retail+institutional with contracts). Filename-as-string for V1; Phase 2.5+ may upgrade to a typed ConvergenceRulebook class if rulebooks become first-class on-chain artifacts." ;
    rdfs:domain skyocean:ConvergenceRecord ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ═══════════════════════════════════════════════════════════════════
# Phase 2 P2-F3 — PurchaseAgreement (procurement sub-record)
# Sebastian-locked 2026-05-23.
#
# Distinct from the buyer-facing Trade KA (the financed Trade Agreement
# the financiers see). PurchaseAgreement is the supplier→Skyocean
# procurement leg ("we bought this sugar specifically to fill that
# sale"). Linked to the parent Trade via skyocean:tradeRef. One PA per
# Trade in V1 (UNIQUE on purchase_agreements.trade_ref). Carries the
# cost basis from which margin is derived against the buyer-facing
# Trade price.
#
# Standards-first reuse:
#   schema:seller / schema:buyer  — schema.org parties on the agreement
#   schema:dateCreated            — signing date
#   skyocean:tradeRef             — link to parent Trade KA
#   skyocean:internalOpsNotes     — operator scratchpad (existing)
#   skyocean:provenance           — Track J classifier (existing)
# ═══════════════════════════════════════════════════════════════════

skyocean:PurchaseAgreement a rdfs:Class ;
    rdfs:label "PurchaseAgreement" ;
    rdfs:comment "A supplier→Skyocean procurement agreement, linked to a parent skyocean:Trade via skyocean:tradeRef. The procurement leg behind the buyer-facing Trade Agreement (the financed contract). Carries the cost basis (private layer) from which trade-cycle margin is calculated against the buyer-facing price. One PurchaseAgreement per Trade in V1; bulk-procurement patterns (multiple PAs per Trade) are Phase 2.5+ scope." ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementIncoterm a rdf:Property ;
    rdfs:label "procurementIncoterm" ;
    rdfs:comment "Incoterm (INCOTERMS 2020) for the procurement leg. V1 enum: FOB, FAS, EXW, DAP, CIF, CFR, DDP, FCA, CIP, CPT, DPU. Separate from any incoterm on the buyer-facing Trade KA — the procurement leg may be FAS-origin while the sales leg is CIF-destination." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementIncotermLocation a rdf:Property ;
    rdfs:label "procurementIncotermLocation" ;
    rdfs:comment "Named place per Incoterms (e.g., 'Santos' for FAS Santos, 'Antwerp' for FOB Antwerp). Free text in V1; structured UN/LOCODE reference at V2+." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementCommodityRef a rdf:Property ;
    rdfs:label "procurementCommodityRef" ;
    rdfs:comment "Reference to the commodity being procured. Free-text descriptor in V1 (e.g., 'ICUMSA 45 white refined cane sugar'); future typed-CommoditySpecification URN reference at V2+." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementStatus a rdf:Property ;
    rdfs:label "procurementStatus" ;
    rdfs:comment "Procurement lifecycle status. V1 enum: Pending | Signed | Performed | Cancelled. Distinct from skyocean:tradeStatus on the parent Trade (PurchaseAgreement may be Performed while parent Trade is still Shipped)." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:costBasis a rdf:Property ;
    rdfs:label "costBasis" ;
    rdfs:comment "Unit cost per unit (typically per MT or per kg) for the procurement leg. Structured as schema:MonetaryAmount with schema:value + schema:currency + schema:unitCode. PRIVATE per §8b (commercially sensitive — the trade-cycle margin = buyer-price - costBasis × quantity, and exposing costBasis would leak margin to the buyer/financier)." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementTotalCost a rdf:Property ;
    rdfs:label "procurementTotalCost" ;
    rdfs:comment "Total procurement cost (unit_cost × quantity). schema:MonetaryAmount. PRIVATE per §8b for the same reason as skyocean:costBasis." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range schema:MonetaryAmount ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:procurementPaymentTerms a rdf:Property ;
    rdfs:label "procurementPaymentTerms" ;
    rdfs:comment "Payment terms to the supplier (e.g., 'Net 30 from BL date', 'CAD against shipping docs'). Free text in V1. PRIVATE per §8b (supplier-relationship commercial detail)." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:supplierSpec a rdf:Property ;
    rdfs:label "supplierSpec" ;
    rdfs:comment "Detailed supplier-side commodity specification — mill grade, micro-bacterial, packaging detail, etc. Carried as opaque JSON string in V1 (Q24 pattern). PRIVATE per §8b — the full supplier spec is procurement-side detail not authorised for the public anchor." ;
    rdfs:domain skyocean:PurchaseAgreement ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- P2-F5: PaymentSource direction (added 2026-05-23 for Phase 2 SIM-001 S5) ---
# PaymentSource was inbound-only in Phase 1 (buyer → Skyocean settlement). Phase 2
# adds outbound (Skyocean → supplier procurement payment). Direction-aware §8b
# routing: outbound payments suppress confirmedAmount from the public anchor
# (would leak procurement cost basis); inbound retains the existing public shape
# for back-compat. Payer/payee identities reuse schema:sender + schema:recipient
# (standards-first, no mint — both are sub-properties of schema:participant).

skyocean:paymentDirection a rdf:Property ;
    rdfs:label "paymentDirection" ;
    rdfs:comment "Direction of the payment from Skyocean's perspective. V1 enum: inbound (buyer → Skyocean settlement; the default for back-compat with Phase 1 emissions) | outbound (Skyocean → supplier procurement payment) | institutional-capital-inflow (financier → Skyocean facility funding — a SWIFT/wire confirming institutional capital arrived in Skyocean's receiving account, funding a TFA; pairs with skyocean:aboutTfa. Added v2.1.20 for Phase 3.B 2.5c). Added v2.1.16 for Phase 2 SIM-001 S5 (procurement-leg outbound)." ;
    rdfs:domain skyocean:PaymentSource ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# --- A7 successor-append (added v2.1.17 — Phase 2 DTW Phase 1, 2026-05-23) ---
# A7 is the version-chain pattern: when a Document KA was published with
# placeholder storageUrl + zero-hash (because the real PDF render landed via
# a downstream pipeline like the Document Template Workstream), the successor
# KA publishes the SAME logical document with the REAL storageUrl + sha256 in
# its private layer, and a PUBLIC pointer back to the predecessor via
# skyocean:supersedes. The chain is queryable publicly (audit can follow the
# version graph) while file-level intel stays in the private layer per §8b.
# rdfs:subPropertyOf schema:isBasedOn anchors the semantic in schema.org.

skyocean:supersedes a rdf:Property ;
    rdfs:label "supersedes" ;
    rdfs:comment "Pointer to the predecessor KA that this KA replaces. The successor carries updated content (real storageUrl + sha256 after the placeholder version was published with zero-hash) while the predecessor stays on-chain for audit immutability. PUBLIC by design — the chain of version pointers is the audit-of-changes signal. Added v2.1.17 for Phase 2 DTW Phase 1 (A7 successor-append backfill pattern)." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:anyURI ;
    rdfs:subPropertyOf schema:isBasedOn ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

skyocean:supersededAt a rdf:Property ;
    rdfs:label "supersededAt" ;
    rdfs:comment "ISO 8601 UTC timestamp when this successor KA was published, replacing its skyocean:supersedes target. Pairs with skyocean:supersedes for chain ordering. Added v2.1.17 alongside skyocean:supersedes." ;
    rdfs:domain skyocean:Document ;
    rdfs:range xsd:dateTime ;
    rdfs:isDefinedBy skyocean: ;
    vs:term_status "testing" .

# ═══════════════════════════════════════════════════════════════════════════
# Phase 3.B vocab-discipline patch #5 + cost-basis classes (v2.1.20, 2026-06-04)
# ═══════════════════════════════════════════════════════════════════════════

# --- Patch #5: TFA / financing / funding predicates (were prefix-gated only) ---
skyocean:tfaNumber a rdf:Property ; rdfs:label "tfaNumber" ; rdfs:comment "System-assigned Trade Finance Agreement number (year-scoped TFA-YYYY-NNN). Public reference across the TFA Document KA, FinancingRecord, and capital-inflow PaymentSource. Added v2.1.20." ; rdfs:domain skyocean:Document ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:institutionReference a rdf:Property ; rdfs:label "institutionReference" ; rdfs:comment "The financier's own printed reference on the signed TFA (informational; the system tfaNumber is canonical). Added v2.1.20." ; rdfs:domain skyocean:Document ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:institutionKycKa a rdf:Property ; rdfs:label "institutionKycKa" ; rdfs:comment "Citation from a TFA Document KA to the financier institution's KYCClearance KA (audit walk TFA → KYB → party DID). Added v2.1.20." ; rdfs:domain skyocean:Document ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:signeeKycKa a rdf:Property ; rdfs:label "signeeKycKa" ; rdfs:comment "Citation from a TFA Document KA to the Skyocean signee entity's KYCClearance KA. The same UAL is reused across every facility for that entity (cross-sim entity reuse). Added v2.1.20." ; rdfs:domain skyocean:Document ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:financedUnderTfa a rdf:Property ; rdfs:label "financedUnderTfa" ; rdfs:comment "Links a FinancingRecord drawdown to the TFA it draws on (the facility debited). Enables the audit walk financing → TFA → institution → KYB. Added v2.1.20." ; rdfs:domain skyocean:FinancingRecord ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:aboutTfa a rdf:Property ; rdfs:label "aboutTfa" ; rdfs:comment "Links a PaymentSource recording institutional capital inflow to the TFA being funded; enables computing funded_amount per facility for drawdown gating. Added v2.1.20." ; rdfs:domain skyocean:PaymentSource ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:valueDate a rdf:Property ; rdfs:label "valueDate" ; rdfs:comment "Bank value date of a funds transfer / payment. Added v2.1.20." ; rdfs:domain skyocean:PaymentSource ; rdfs:range xsd:date ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# --- Cost-basis classes: finance the cost, not the sale (Sebastian-locked 2026-06-04) ---
sec:nonce a rdf:Property ;
    rdfs:label "nonce" ;
    rdfs:comment "W3C Security Vocabulary nonce, DECLARED here rather than minted — the term is <https://w3id.org/security#nonce> and Skyocean does not own it. One 256-bit random value (64 lowercase hex) stamped into EVERY KA's PRIVATE half at the universal chokepoint (services/ontology-validator.js _finalizeUniversalProperties), the same stamp-once point that emits skyocean:referencesSimulatedParty. PRIVATE TIER ONLY and never public: the public allowlist refuses undeclared predicates, and a negative vector in the suite pins that the nonce is not among them. NO rdfs:domain — it applies to every KA class, so a domain would be a lie about which classes carry it. Purpose (EU-DATA-COMPLIANCE B2/B3): V10 Merkle leaves are unsalted keccak256 over each canonical triple and only the FOLDED root is public, so a low-entropy private leaf (a BL number, a registration number, a tax ID) is brute-forceable — which under EDPB §52 makes the anchor personal data rather than anonymous data. A random leaf turns the private root into a hiding commitment (§53): the anchor reveals nothing about its siblings even under full enumeration, and the verify-batch endpoint stops being a confirm-a-guess oracle. It is also the erasure mechanism (§64): the nonce lives only where the private half lives, so deleting that half destroys it, per KA, taking nothing else down. Verification is unchanged for a holder — the nonce is one of the leaves and re-folds like any other; what it removes is reconstruction by someone who does NOT hold the private half, which is why verify-clearance-anchor.js folds the STORED private half rather than a rebuilt template. Added v2.1.31 (2026-09-04, K1)." ;
    rdfs:range xsd:string ;
    rdfs:isDefinedBy <https://w3id.org/security#> ;
    vs:term_status "stable" .

skyocean:CostEstimation a rdfs:Class ; rdfs:label "CostEstimation" ; rdfs:comment "Operational artifact (NOT a Document subclass — distinct lifecycle) capturing the pre-trade COST BASIS of executing a trade, line-itemized. Financing draws against this (financedAgainstCostEstimation), NOT the sale price — the financier funds cost, never Skyocean's margin. Versioned via skyocean:supersedes; status draft → signed-off → closed (→ closed when the trade's TotalTradeCosts publishes). ALL-PRIVATE V1 (operator + auditor only); public anchor minimal (tradeRef + status + currency + version). Added v2.1.20." ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:TotalTradeCosts a rdfs:Class ; rdfs:label "TotalTradeCosts" ; rdfs:comment "Operational artifact published at S31 trade close carrying the ACTUAL costs per line (each with sourceKa — the PaymentSource/Document UAL proving the actual) + variance vs the CostEstimation. A SEPARATE fact from CostEstimation (NOT a supersede). Powers the LLM-feedback learning loop — future estimates calibrate off historical TotalTradeCosts for similar commodity + corridor. ALL-PRIVATE V1; public anchor minimal (tradeRef + currency + closedAt + version). Added v2.1.20." ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:costEstimationStatus a rdf:Property ; rdfs:label "costEstimationStatus" ; rdfs:comment "Lifecycle status of a CostEstimation. Enum: draft | signed-off (financing may draw) | closed (the trade's TotalTradeCosts has published; actuals live in that separate KA). Added v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# Per-line cost predicates — used by BOTH CostEstimation (estimate) + TotalTradeCosts (actual). schema:MonetaryAmount; PRIVATE per §8b.
skyocean:procurementCost a rdf:Property ; rdfs:label "procurementCost" ; rdfs:comment "Cost of goods (manufacturer → Skyocean procurement leg). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:inlandLogisticsOriginCost a rdf:Property ; rdfs:label "inlandLogisticsOriginCost" ; rdfs:comment "Inland transport at origin (factory → load port). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:internationalFreightCost a rdf:Property ; rdfs:label "internationalFreightCost" ; rdfs:comment "International (ocean/air) freight, load port → discharge port. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:inlandLogisticsDestinationCost a rdf:Property ; rdfs:label "inlandLogisticsDestinationCost" ; rdfs:comment "Inland transport at destination (discharge port → delivery). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:cargoInsuranceCost a rdf:Property ; rdfs:label "cargoInsuranceCost" ; rdfs:comment "Marine/cargo insurance premium. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:customsHandlingCost a rdf:Property ; rdfs:label "customsHandlingCost" ; rdfs:comment "Customs duties, clearance + port handling. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:documentationCost a rdf:Property ; rdfs:label "documentationCost" ; rdfs:comment "Trade documentation, certification + legal. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:workingCapitalCost a rdf:Property ; rdfs:label "workingCapitalCost" ; rdfs:comment "Cost of working capital over the trade cycle (financier yield component of cost basis). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:contingencyReserve a rdf:Property ; rdfs:label "contingencyReserve" ; rdfs:comment "Contingency reserve for cost overruns. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:totalCostBasis a rdf:Property ; rdfs:label "totalCostBasis" ; rdfs:comment "Sum of all cost lines — the cost basis financing draws against (NOT the sale price). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
# Commodity-specific lines (added per trade type as applicable).
skyocean:pharmaComplianceCost a rdf:Property ; rdfs:label "pharmaComplianceCost" ; rdfs:comment "Pharma GDP/GMP compliance, cold-chain or ambient monitoring, regulatory. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:bulkSurveyingCost a rdf:Property ; rdfs:label "bulkSurveyingCost" ; rdfs:comment "Bulk-cargo surveying / draft survey (bulk commodities). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:perishableMonitoringCost a rdf:Property ; rdfs:label "perishableMonitoringCost" ; rdfs:comment "Perishable/reefer condition monitoring. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:hazmatHandlingCost a rdf:Property ; rdfs:label "hazmatHandlingCost" ; rdfs:comment "Hazardous-materials handling + compliance. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:humanitarianDeliveryCost a rdf:Property ; rdfs:label "humanitarianDeliveryCost" ; rdfs:comment "Last-mile humanitarian delivery / distribution costs. v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
# LLM grounding (per-line) + financing citation.
skyocean:lineConfidence a rdf:Property ; rdfs:label "lineConfidence" ; rdfs:comment "Per-line LLM-draft confidence 0–1 (CostEstimation drafting). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:lineSourceKa a rdf:Property ; rdfs:label "lineSourceKa" ; rdfs:comment "Per-line grounding UAL the LLM cited when drafting a CostEstimation line (e.g. a historical TotalTradeCosts or a Sales Contract / PA KA). v2.1.20." ; rdfs:domain skyocean:CostEstimation ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:financedAgainstCostEstimation a rdf:Property ; rdfs:label "financedAgainstCostEstimation" ; rdfs:comment "Links a FinancingRecord to the signed-off CostEstimation it draws against — proves the draw is on cost basis, not sale price. v2.1.20." ; rdfs:domain skyocean:FinancingRecord ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
# TotalTradeCosts-specific (actuals + variance + close).
skyocean:actualAmount a rdf:Property ; rdfs:label "actualAmount" ; rdfs:comment "Actual amount for a cost line at trade close (TotalTradeCosts). v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:sourceKa a rdf:Property ; rdfs:label "sourceKa" ; rdfs:comment "The PaymentSource/Document KA UAL that proved a TotalTradeCosts actual line. v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:costEstimationRef a rdf:Property ; rdfs:label "costEstimationRef" ; rdfs:comment "Links a TotalTradeCosts to the CostEstimation it reconciles against. v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:totalActualCost a rdf:Property ; rdfs:label "totalActualCost" ; rdfs:comment "Sum of actual cost lines at trade close. v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range schema:MonetaryAmount ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:varianceVsEstimate a rdf:Property ; rdfs:label "varianceVsEstimate" ; rdfs:comment "Total actual − estimated cost basis (signed; overrun positive). v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:varianceByLine a rdf:Property ; rdfs:label "varianceByLine" ; rdfs:comment "Per-line variance map (JSON; line → {estimate, actual, variance}). v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:closedAt a rdf:Property ; rdfs:label "closedAt" ; rdfs:comment "ISO 8601 UTC timestamp of trade close (TotalTradeCosts publish). v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:dateTime ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:closingNotes a rdf:Property ; rdfs:label "closingNotes" ; rdfs:comment "Operator closing notes at trade close (private). v2.1.20." ; rdfs:domain skyocean:TotalTradeCosts ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# --- Sale Incoterm on the Trade anchor (v2.1.21, 2026-06-04). procurementIncoterm
# already exists on PurchaseAgreement; this is the SALE-leg Incoterm that scopes
# which cost legs Skyocean bears (cost-estimation Incoterm-scoping). ---
skyocean:incoterm a rdf:Property ; rdfs:label "incoterm" ; rdfs:comment "Sale-leg INCOTERMS 2020 rule (Skyocean -> buyer), e.g. CIP, CFR, FOB. Scopes which cost legs the seller bears; the cost estimator omits buyer-borne legs accordingly. v2.1.21." ; rdfs:domain skyocean:Trade ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:incotermLocation a rdf:Property ; rdfs:label "incotermLocation" ; rdfs:comment "Named place for the sale Incoterm (e.g. 'Port Sudan'). The point up to which the seller bears carriage/insurance. v2.1.21." ; rdfs:domain skyocean:Trade ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# --- v2.1.22 (2026-06-10): S25 document-set convergence + Tier 1 close (Sebastian-locked) ---
# ConvergenceRecord document-set mode: PUBLIC anchor is default-deny minimal (3 public-optional
# process markers below); the VERDICT (verificationStrength/consensusStatus/counts + the 4 private
# predicates below) lives on the #private layer ONLY. Origin-marker enums live INSIDE the
# skyocean:rawComputation JSON blob (locked field names, not RDF predicates):
#   corroborationClass: externally-corroborated | partially-corroborated | converged-by-construction
#   docOrigin:          external-feed | operator-recorded
#   issuingAuthorityClass: independent | platform-simulated | platform

skyocean:convergenceMode a rdf:Property ; rdfs:label "convergenceMode" ; rdfs:comment "PUBLIC-optional process marker on a ConvergenceRecord: which engine produced it. Enum: attestation (Phase 1.6 rulebook engine; verdict public per legacy shape) | document-set (S25 engine; verdict PRIVATE per default-deny). Added v2.1.22." ; rdfs:domain skyocean:ConvergenceRecord ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:computedAt a rdf:Property ; rdfs:label "computedAt" ; rdfs:comment "PUBLIC-optional process marker: when the convergence computation ran (bound at publish; the deterministic compute itself is wall-clock-free — recompute-to-verify). Distinct from schema:dateCreated (mint time). Added v2.1.22." ; rdfs:domain skyocean:ConvergenceRecord ; rdfs:range xsd:dateTime ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:engineVersion a rdf:Property ; rdfs:label "engineVersion" ; rdfs:comment "PUBLIC-optional process marker: the convergence engine version that produced the verdict. Bumps on ANY output-format change even when scores are unchanged (quote-free emission discipline, doctrine #27). Added v2.1.22." ; rdfs:domain skyocean:ConvergenceRecord ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:axisScores a rdf:Property ; rdfs:label "axisScores" ; rdfs:comment "PRIVATE: compact per-axis score map as a JSON string literal (stringified — raw-blob shape discipline; quote-free values). The full per-check breakdown lives in skyocean:rawComputation. Added v2.1.22." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:discrepancyCount a rdf:Property ; rdfs:label "discrepancyCount" ; rdfs:comment "PRIVATE: count of failing checks across operative axes in a document-set convergence verdict. Added v2.1.22." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:integer ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:redFlagCount a rdf:Property ; rdfs:label "redFlagCount" ; rdfs:comment "PRIVATE: count of red-flagged axes (>=2 mismatches; axis score 0) in a document-set convergence verdict. Added v2.1.22." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:integer ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:convergenceScope a rdf:Property ; rdfs:label "convergenceScope" ; rdfs:comment "PRIVATE verdict-context marker: which gate this verdict serves. Enum: shipping-documents-verified (Tier 1 — the buyer-verification event, UCP 600/CAD analogue; buyer-bank payment-release gate) | trade-compliance (Tier 2 — post-customs + independent telemetry corroboration). Added v2.1.22." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:insuranceType a rdf:Property ; rdfs:label "insuranceType" ; rdfs:comment "PRIVATE sub-classification of an InsuranceCertificate Document (e.g. marine-cargo, inland-transit, war-risk). InsuranceCertificate is the canonical insurance doc type as of Tier 1 close (MarineCargoInsurance retired from the active allowlist; SIM-002 legacy KAs unaffected). Added v2.1.22." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# --- v2.1.23 (2026-06-10): Tier 2 chunk #1 — PortGateIn sovereign-authority Event KA (Sebastian-locked; PA1+PA2 reviewed) ---
# DOCTRINE #30 (Event KA vs Document KA): Event KAs are SOVEREIGN/PARTNER-AUTHORITY TELEMETRY ONLY —
# there is NO operator publish path (no c.3 equivalent). If no authority feed exists, the KA does not
# exist. Event KAs are APPEND-ONLY: an erroneous event is corrected by a SUBSEQUENT correction event
# referencing it (skyocean:correctsEvent below), never superseded or deleted — the error trail is itself
# audit record. Document KAs CAN supersede (#13/#14); Event KAs CANNOT — corrections ADD. Corollary:
# split deliveries (e.g. one container gating in later than its peers) = additional PortGateIn KAs,
# naturally handled by append-only.
# Public anchor = the inherited InstitutionalAttestation existence/process-marker shape ONLY (exact-key
# default-deny, doctrine #25); all operational gate content is PRIVATE (doctrine #12).

skyocean:PortGateIn a rdfs:Class ; rdfs:subClassOf skyocean:InstitutionalAttestation ; rdfs:label "PortGateIn" ; rdfs:comment "Container terminal gate-in event attested by a PORT AUTHORITY (attestorType=PortAuthority; attestorIdentity = the authority DID, which IS the structural location identifier, e.g. did:skyocean:port-authority:GRSKG). One KA may cover a consolidated multi-container gate movement (CODECO batching); per-container scans live on the PRIVATE layer (skyocean:containerScans). Inherits the 6 required public fields from InstitutionalAttestation via subClassOf closure — the minimal-public event shape. Dual @type emission ([PortGateIn, InstitutionalAttestation]) per the PaymentSource precedent so parent-class consumers still match. Added v2.1.23." ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:terminalName a rdf:Property ; rdfs:label "terminalName" ; rdfs:comment "PRIVATE: the terminal within the port (e.g. a container terminal operator name). Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:gateId a rdf:Property ; rdfs:label "gateId" ; rdfs:comment "PRIVATE: the physical/logical gate identifier at the terminal. Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:movementReference a rdf:Property ; rdfs:label "movementReference" ; rdfs:comment "PRIVATE: the terminal's own movement/visit reference for the gate event. Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:containerScans a rdf:Property ; rdfs:label "containerScans" ; rdfs:comment "PRIVATE: per-container gate-scan records as a JSON string literal (quote-free values per doctrine #27): [{containerNumber, gateTimestamp, vgmWeightKg, sealNumber, sealIntact, damageNote}]. Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:customsStatusFlag a rdf:Property ; rdfs:label "customsStatusFlag" ; rdfs:comment "PRIVATE: the customs status the gate system recorded at gate time (e.g. export-cleared-for-loading). The authority's own status is a fact-of-record per doctrine #29 clause (b) — which ENABLES publication but does not mandate it; Skyocean's V1 platform policy is minimal-public, so the customs authority's verdict is ALSO private (see skyocean:customsStatus, v2.1.24 — the customs-Document counterpart of this port-gate operational flag). On a PORT gate event this flag is operational detail. Added v2.1.23; cross-ref amended v2.1.24." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:gateOperator a rdf:Property ; rdfs:label "gateOperator" ; rdfs:comment "PRIVATE: the gate operator/inspector identifier recorded by the terminal system. Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
skyocean:correctsEvent a rdf:Property ; rdfs:label "correctsEvent" ; rdfs:comment "PRIVATE (RESERVED v2.1.23; no emitter yet): on a correction Event KA, cites the prior erroneous Event KA (UAL or URN) it corrects. Event KAs are append-only (doctrine #30) — corrections ADD a referencing event; nothing is superseded or deleted. Schema reserved ahead of the first real correction feed for forward stability. Added v2.1.23." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# --- v2.1.24 (2026-06-11): Tier 2 chunk #2 — ExportCustomsDeclaration partner feed (Sebastian-locked; PA1+PA2 reviewed) ---
# DOCTRINE #30 OPTION C refinement (formal text lands in telemetry-plan §9 at chunk close): KA class and
# arrival channel are ORTHOGONAL. Event KAs (PortGateIn) = authority-feed-only (no real-world document
# exists to upload). Document KAs (BillOfLading, customs declarations) record REAL-WORLD ARTIFACTS and are
# ALWAYS dual-path: operator c.3 upload (clearing-agent reality) OR partner feed — existence is never
# channel-gated; honesty lives in the markers (Documents.feed_source, docOrigin, issuingAuthorityClass,
# verificationStatus). Classification test (R1): "is this KA recording an ARTIFACT or a feed-attested
# EVENT?" — one real-world happening may yield BOTH (e.g. an EIR Document AND a PortGateIn Event).
# DOCTRINE #29(b) refinement (Sebastian-locked, chunk #2): the clause ENABLES publishing an authority's
# verdict as fact-of-record; it does NOT mandate it. Skyocean V1 platform policy = minimal-public default
# (verdict-bearing fields PRIVATE; KA existence + structural process markers public) — protects trades
# from competitive-intelligence surveillance. Public verdict disclosure stays a future per-trade-type
# option where regulators mandate it.

skyocean:customsStatus a rdf:Property ; rdfs:label "customsStatus" ; rdfs:comment "PRIVATE (typed predicate for queryability; Sebastian-locked chunk #2 override — verdict-bearing fields private by platform policy): the CUSTOMS AUTHORITY's verdict-of-record on a customs declaration Document KA (documentType ExportCustomsDeclaration / ImportCustomsClearance). Enum (code-enforced at the feed handler): cleared | cleared-with-conditions | amended | rejected | pending. Severity doctrine: red-flag is reserved for irreversible/fraud-class signals — a customs rejection is RECOVERABLE (amend, correct, resubmit) and classes as a convergence FLAG, never red-flag by content. 'amended' may be TRANSITIONAL (authority amended, clearance still expected — a content-change supersede of this Document typically follows, #13/#14) or TERMINAL for the declaration version it describes; readers must not assume finality (R5). DISTINCT FROM skyocean:customsStatusFlag (v2.1.23): that is the PORT GATE system's operational flag on a PortGateIn EVENT KA; this is the customs authority's own verdict on its declaration DOCUMENT. Added v2.1.24." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

# ============================================================
# v2.1.27 (2026-08-14) — PARITY BACKFILL: sixteen terms the builders were already
# emitting that this file had never declared.
#
# Found by the new ontology⇄builder parity test (edge-node-api
# test/ontologyBuilderParity.test.js), on its first run. Until that test existed,
# nothing stopped a builder minting a predicate the canonical file had never heard
# of: the ontology validator gates required-ness and prefix safety, not EXISTENCE.
# Every term below was therefore shipping inside real KAs with no declaration for a
# consumer to resolve against — the exact "silently incomplete" state the test was
# asked to make impossible.
#
# Domains are taken from the builder each term is emitted by, not guessed. Terms
# written into a #private layer take rdfs:domain skyocean:TradePrivateData, matching
# the convention already used by skyocean:customsStatus above.
# ============================================================

skyocean:reviewMode a rdf:Property ; rdfs:label "reviewMode" ; rdfs:comment "How a Document KA's fields came to be: 'digest' (LLM-extracted, operator-reviewed), 'manual-with-pdf' (operator transcribed with the PDF in-pane), 'feed-auto' / 'feed-degraded' (partner feed). PUBLIC on the Document anchor because it qualifies the confidence of everything else on the document without revealing content. Emitted by documentKaService.buildDocumentKa. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:Document ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:reviewedTerms a rdf:Property ; rdfs:label "reviewedTerms" ; rdfs:comment "JSON-stringified snapshot of the terms the operator CONFIRMED at review time, carried on the #private layer as the audit record of what a human actually affirmed — distinct from what the extractor proposed (skyocean:digestProvenance). Stringified because operator-supplied keys are not ontology-prefixed and JSON-LD safe mode rejects bare keys. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:digestProvenance a rdf:Property ; rdfs:label "digestProvenance" ; rdfs:comment "JSON-stringified per-field extraction grounding (value, confidence, source page, source snippet) as the extractor produced it, before operator review. Pairs with skyocean:reviewedTerms: proposed vs affirmed. #private — grounding quotes reproduce document text. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:extractorId a rdf:Property ; rdfs:label "extractorId" ; rdfs:comment "Identifier of the extractor build that produced a digest (model + prompt/tool-schema identity). Makes an extraction replayable and lets a later re-read be compared against the one the operator reviewed. #private. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:crossCheckDrift a rdf:Property ; rdfs:label "crossCheckDrift" ; rdfs:comment "JSON-stringified list of fields where the operator's confirmed value DIVERGED from the extracted one, captured on the Sales Contract's #private layer. Drift is evidence, not error: it records that a human overrode the machine and on which fields. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:operatorPartyDid a rdf:Property ; rdfs:label "operatorPartyDid" ; rdfs:comment "The operating-entity party DID that performed a distribution — the ACTOR, never a party to the underlying trade (see the multi-role party discipline: an operator acts, it does not take title). Emitted by buildDonationDistributionKa. Declared v2.1.27 (parity backfill)." ; rdfs:domain donation:DonationDistribution ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

donation:attestationCount a rdf:Property ; rdfs:label "attestationCount" ; rdfs:comment "How many attestations back a distribution. A COUNT rather than the attestation set: the public anchor proves that corroboration exists without exposing who attested or what they saw. Zero is meaningful (an unattested distribution), so it is emitted even when empty. Declared v2.1.27 (parity backfill)." ; rdfs:domain donation:DonationDistribution ; rdfs:range xsd:integer ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:participantRef a rdf:Property ; rdfs:label "participantRef" ; rdfs:comment "Opaque reference to the capital participant on a FinancingRecord's public anchor — an opaquePartyRef, never a raw DID, so the financier's identity does not surface publicly while the record stays joinable by anyone holding the mapping. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:FinancingRecord ; rdfs:range xsd:anyURI ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:participantLei a rdf:Property ; rdfs:label "participantLei" ; rdfs:comment "Legal Entity Identifier of an institutional capital participant. #private: an LEI is a direct de-anonymiser, and the public anchor deliberately carries only skyocean:participantRef. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:financingShare a rdf:Property ; rdfs:label "financingShare" ; rdfs:comment "This participant's share of the financing on a FinancingRecord. #private — a share is a commercial term, and with the facility total it re-derives the participant's exposure. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:tradeCycleMarginIndicative a rdf:Property ; rdfs:label "tradeCycleMarginIndicative" ; rdfs:comment "Indicative margin for the financed trade cycle. #private and INDICATIVE by name: it is a projection, not a settled figure, and publishing it would re-derive Skyocean's margin — the same reason capitalProvided is private (finance the cost basis, never the sale price). Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:retailPoolSkytLocked a rdf:Property ; rdfs:label "retailPoolSkytLocked" ; rdfs:comment "Total SKYT locked in the retail pool backing a financing record (Branch A). #private. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:retailHolderSkytLocked a rdf:Property ; rdfs:label "retailHolderSkytLocked" ; rdfs:comment "SKYT locked by an individual retail holder (Branch A). #private — a per-holder position is a personal financial fact. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:retailHolderUsdEq a rdf:Property ; rdfs:label "retailHolderUsdEq" ; rdfs:comment "USD equivalent of an individual retail holder's locked position at record time (Branch A). #private, same reasoning as skyocean:retailHolderSkytLocked. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:decimal ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:retailHolderTier a rdf:Property ; rdfs:label "retailHolderTier" ; rdfs:comment "Capacity-activation tier of an individual retail holder (Branch A). #private — tier is derived from holdings and so discloses them by proxy. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:TradePrivateData ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .

skyocean:nextStep a rdf:Property ; rdfs:label "nextStep" ; rdfs:comment "The remedial step recorded on a RejectionEvent — what has to happen for the rejected thing to proceed. Relocated off the public anchor: a rejection's EXISTENCE is public process, its remedy is commercial detail. Declared v2.1.27 (parity backfill)." ; rdfs:domain skyocean:RejectionEvent ; rdfs:range xsd:string ; rdfs:isDefinedBy skyocean: ; vs:term_status "testing" .
