@prefix gs:      <https://schema.govfresh.com/v1/> .
@prefix schema:  <https://schema.org/> .
@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 dcterms: <http://purl.org/dc/terms/> .
@prefix skos:    <http://www.w3.org/2004/02/skos/core#> .

gs: a owl:Ontology ;
    dcterms:title "schemaGov core vocabulary" ;
    dcterms:description "Terms required to describe government entities that schema.org does not provide. A class here is a subclass of a schema.org class wherever one fits, and a property names the schema.org types it applies to and returns, so a consumer that understands only schema.org still reads a valid document." ;
    dcterms:publisher <https://govfresh.com> ;
    owl:versionInfo "1.0.0-draft" .

##  Design rule: mint nothing schema.org already covers.
##  Deliberately NOT minted, because schema.org has them:
##    org -> jurisdiction        use schema:areaServed  (range includes AdministrativeArea)
##    entity identity            use schema:identifier -> schema:PropertyValue (propertyID + value)
##    org hierarchy              use schema:parentOrganization / subOrganization / department
##    officeholding & terms      use schema:OrganizationRole + roleName/startDate/endDate
##    legislation status         use schema:legislationLegalForce
##    legislation amendments     use schema:legislationAmends / Repeals / Consolidates / Changes
##    meeting recurrence         use schema:eventSchedule -> schema:Schedule
##    project updates            use schema:Article / CreativeWork + schema:about -> gs:Project
##    project organizations      use schema:parentOrganization / member / funder
##    project lifecycle phase    use schema:DefinedTerm in a schema:DefinedTermSet

#################  Properties  #################

gs:governmentLevel a rdf:Property ;
    rdfs:label "government level" ;
    rdfs:comment "Tier of government this entity belongs to, as a gs:GovernmentLevel term. Levels differ by country, so the value is a DefinedTerm from an extensible set rather than a fixed enumeration." ;
    schema:domainIncludes schema:AdministrativeArea, schema:GovernmentOrganization ;
    schema:rangeIncludes schema:DefinedTerm ;
    rdfs:subPropertyOf schema:additionalType .

gs:organizationClassification a rdf:Property ;
    rdfs:label "organization classification" ;
    rdfs:comment "Kind of government body: legislature, executive, department, committee, agency, court, and so on. Corresponds to Popolo Organization.classification." ;
    schema:domainIncludes schema:GovernmentOrganization ;
    schema:rangeIncludes schema:DefinedTerm ;
    rdfs:subPropertyOf schema:additionalType .

gs:jurisdictionOf a rdf:Property ;
    rdfs:label "jurisdiction of" ;
    rdfs:comment "Inverse of schema:areaServed: the government organization that governs this area. Convenience only; schema:areaServed is normative." ;
    schema:domainIncludes schema:AdministrativeArea ;
    schema:rangeIncludes schema:GovernmentOrganization ;
    owl:inverseOf schema:areaServed .

gs:population a rdf:Property ;
    rdfs:label "population" ;
    rdfs:comment "Resident population of an area. schema.org has no population property. Carry the count as a schema:QuantitativeValue so the census date and source stay attached to the number." ;
    schema:domainIncludes schema:AdministrativeArea ;
    schema:rangeIncludes schema:QuantitativeValue .

gs:timeZone a rdf:Property ;
    rdfs:label "time zone" ;
    rdfs:comment "IANA time zone identifier for the area, e.g. 'Europe/Lisbon'. Used to resolve local meeting times." ;
    schema:domainIncludes schema:AdministrativeArea, schema:GovernmentOrganization ;
    schema:rangeIncludes schema:Text .

gs:sourceDataset a rdf:Property ;
    rdfs:label "source dataset" ;
    rdfs:comment "The dataset or API this record was derived from, for provenance and refresh." ;
    schema:domainIncludes schema:Thing ;
    schema:rangeIncludes schema:Dataset, schema:URL .

#################  Code lists  #################

gs:GovernmentLevel a schema:DefinedTermSet ;
    schema:name "Government level" ;
    rdfs:comment "Extensible. Publishers MAY add national terms via skos:broader onto a term here." .

gs:OrganizationClassification a schema:DefinedTermSet ;
    schema:name "Government organization classification" ;
    rdfs:comment "Aligned with Popolo Organization.classification and W3C ORG." .

#################  org profile  #################

gs:Post a rdfs:Class ;
    rdfs:label "Post" ;
    rdfs:comment "An office that exists independently of whoever holds it. A schema:Role binds a person to an organization for a time span, but when nobody holds the office there is no Role and the office still exists. Equivalent to Popolo Post. schema.org has no such concept." ;
    rdfs:subClassOf schema:Role .

gs:post a rdf:Property ;
    rdfs:label "post" ;
    rdfs:comment "The Post that this Role is a tenure in. Grouping Roles by Post yields a succession." ;
    schema:domainIncludes schema:Role ;
    schema:rangeIncludes gs:Post .

gs:roleClassification a rdf:Property ;
    rdfs:label "role classification" ;
    rdfs:comment "How an office is filled: elected, appointed, employed, ex officio, volunteer, hereditary. Mechanism-based rather than title-based, because titles do not translate across countries but mechanisms do." ;
    schema:domainIncludes gs:Post, schema:Role ;
    schema:rangeIncludes schema:DefinedTerm ;
    rdfs:subPropertyOf schema:additionalType .

gs:vacantSince a rdf:Property ;
    rdfs:label "vacant since" ;
    rdfs:comment "Date from which a Post has been unfilled. A vacancy is publishable information: omitting it is indistinguishable from never having collected it." ;
    schema:domainIncludes gs:Post ;
    schema:rangeIncludes schema:Date .

gs:termDuration a rdf:Property ;
    rdfs:label "term duration" ;
    rdfs:comment "Nominal length of one term of an office, as an ISO 8601 duration. Nominal, not actual: a specific tenure's real dates live on the Role." ;
    schema:domainIncludes gs:Post ;
    schema:rangeIncludes schema:Duration .

gs:maximumTermCount a rdf:Property ;
    rdfs:label "maximum term count" ;
    rdfs:comment "Term limit on an office, where one applies." ;
    schema:domainIncludes gs:Post ;
    schema:rangeIncludes schema:Integer .

gs:representsJurisdiction a rdf:Property ;
    rdfs:label "represents jurisdiction" ;
    rdfs:comment "For a seat tied to a ward or district rather than the whole governed area: the Jurisdiction the holder represents. Distinct from the organization's own schema:areaServed, which is the territory the body governs as a whole." ;
    schema:domainIncludes schema:Role, gs:Post ;
    schema:rangeIncludes schema:AdministrativeArea .

gs:RoleClassification a schema:DefinedTermSet ;
    schema:name "Role classification" .

#################  code profile  #################

gs:codificationLevel a rdf:Property ;
    rdfs:label "codification level" ;
    rdfs:comment "The structural tier a piece of legislation occupies within a code. schema:hasPart nests parts but never says what kind of part; this is the one substantive gap in schema.org's ELI-derived legislation vocabulary." ;
    schema:domainIncludes schema:Legislation ;
    schema:rangeIncludes schema:DefinedTerm ;
    rdfs:subPropertyOf schema:additionalType .

gs:enactedAt a rdf:Property ;
    rdfs:label "enacted at" ;
    rdfs:comment "The Meeting at which legislation was adopted. schema:legislationPassedBy records which body passed it, but not the sitting; without this the vote record cannot be reached from the law." ;
    schema:domainIncludes schema:Legislation ;
    schema:rangeIncludes gs:Meeting .

gs:CodificationLevel a schema:DefinedTermSet ;
    schema:name "Codification level" .

gs:LegislationType a schema:DefinedTermSet ;
    schema:name "Legislation type" .

#################  meetings profile  #################

gs:Meeting a rdfs:Class ;
    rdfs:label "Meeting" ;
    rdfs:comment "A sitting of a government body. Minted because schema:Event cannot distinguish a council meeting from a concert, and discovery depends on that distinction. All scheduling, status, location and media properties are inherited from Event unchanged." ;
    rdfs:subClassOf schema:Event .

gs:AgendaItem a rdfs:Class ;
    rdfs:label "Agenda item" ;
    rdfs:comment "One numbered piece of business at a meeting. schema:ListItem supplies the ordering; this adds the decision and the link to the legislation considered." ;
    rdfs:subClassOf schema:ListItem .

gs:VoteEvent a rdfs:Class ;
    rdfs:label "Vote event" ;
    rdfs:comment "A single vote taken by a body, with its tally. Modelled on Popolo VoteEvent rather than schema:VoteAction, which is built around choosing a candidate and cannot express aye, nay or abstain on a motion." ;
    rdfs:subClassOf schema:Event .

gs:Vote a rdfs:Class ;
    rdfs:label "Vote" ;
    rdfs:comment "One member's cast vote within a VoteEvent. Equivalent to Popolo Vote." ;
    rdfs:subClassOf schema:Intangible .

gs:agendaItem a rdf:Property ;
    rdfs:label "agenda item" ;
    rdfs:comment "The ordered business of a meeting." ;
    schema:domainIncludes gs:Meeting ;
    schema:rangeIncludes gs:AgendaItem .

gs:voteEvent a rdf:Property ;
    rdfs:label "vote event" ;
    rdfs:comment "A vote taken on an agenda item. More than one is normal: an amendment, then the main motion." ;
    schema:domainIncludes gs:AgendaItem ;
    schema:rangeIncludes gs:VoteEvent .

gs:result a rdf:Property ;
    rdfs:label "result" ;
    rdfs:comment "The decision reached on an agenda item, or the outcome of a vote. Absent means not yet decided, which is distinct from a decision of no action." ;
    schema:domainIncludes gs:AgendaItem, gs:VoteEvent ;
    schema:rangeIncludes schema:DefinedTerm .

gs:count a rdf:Property ;
    rdfs:label "count" ;
    rdfs:comment "The tally of a vote, one entry per option. Equivalent to Popolo Count." ;
    schema:domainIncludes gs:VoteEvent ;
    schema:rangeIncludes schema:StructuredValue .

gs:vote a rdf:Property ;
    rdfs:label "vote" ;
    rdfs:comment "An individual cast vote. Publishing counts alone is valid; publishing individual votes is what makes a record auditable." ;
    schema:domainIncludes gs:VoteEvent ;
    schema:rangeIncludes gs:Vote .

gs:voter a rdf:Property ;
    rdfs:label "voter" ;
    rdfs:comment "The person who cast a vote." ;
    schema:domainIncludes gs:Vote ;
    schema:rangeIncludes schema:Person .

gs:option a rdf:Property ;
    rdfs:label "option" ;
    rdfs:comment "How a vote was cast or counted: yes, no, abstain, absent, excused, not voting." ;
    schema:domainIncludes gs:Vote ;
    schema:rangeIncludes schema:DefinedTerm .

gs:requiredMajority a rdf:Property ;
    rdfs:label "required majority" ;
    rdfs:comment "The threshold that applied to a vote. Without it a reader cannot tell whether a 4-3 vote carried." ;
    schema:domainIncludes gs:VoteEvent ;
    schema:rangeIncludes schema:Text .

gs:minutes a rdf:Property ;
    rdfs:label "minutes" ;
    rdfs:comment "The adopted minutes of a meeting, once approved. Distinct from the agenda, which is published beforehand." ;
    schema:domainIncludes gs:Meeting ;
    schema:rangeIncludes schema:CreativeWork, schema:URL .

gs:agendaDocument a rdf:Property ;
    rdfs:label "agenda document" ;
    rdfs:comment "The published agenda for a meeting." ;
    schema:domainIncludes gs:Meeting ;
    schema:rangeIncludes schema:CreativeWork, schema:URL .

gs:recording a rdf:Property ;
    rdfs:label "recording" ;
    rdfs:comment "Audio or video of the proceedings." ;
    schema:domainIncludes gs:Meeting ;
    schema:rangeIncludes schema:MediaObject .

gs:VoteOption a schema:DefinedTermSet ;
    schema:name "Vote option" .

#################  requests profile  #################

gs:ServiceRequest a rdfs:Class ;
    rdfs:label "Service request" ;
    rdfs:comment "One report of a problem or request for service. schema.org has no service request, complaint, case, or incident concept of any kind, so this is minted outright rather than derived. Mirrors Open311 GeoReport v2, which remains the source model." ;
    rdfs:subClassOf schema:Intangible .

gs:serviceRequestId a rdf:Property ;
    rdfs:label "service request id" ;
    rdfs:comment "The publisher's own request number as shown to the public. Open311 service_request_id." ;
    schema:domainIncludes gs:ServiceRequest ;
    schema:rangeIncludes schema:Text ;
    rdfs:subPropertyOf schema:identifier .

gs:serviceCode a rdf:Property ;
    rdfs:label "service code" ;
    rdfs:comment "Stable code identifying a requestable service. Open311 service_code." ;
    schema:domainIncludes schema:GovernmentService, gs:ServiceRequest ;
    schema:rangeIncludes schema:Text .

gs:requestStatus a rdf:Property ;
    rdfs:label "request status" ;
    rdfs:comment "Progress of a service request. schema:ActionStatusType has only four values, none of which distinguish rejected from completed, so a dedicated code list is used." ;
    schema:domainIncludes gs:ServiceRequest ;
    schema:rangeIncludes schema:DefinedTerm .

gs:statusNote a rdf:Property ;
    rdfs:label "status note" ;
    rdfs:comment "Public explanation of a request's current status. Open311 status_notes." ;
    schema:domainIncludes gs:ServiceRequest ;
    schema:rangeIncludes schema:Text .

gs:agencyResponsible a rdf:Property ;
    rdfs:label "agency responsible" ;
    rdfs:comment "The government organization handling a service request. Open311 agency_responsible." ;
    schema:domainIncludes gs:ServiceRequest ;
    schema:rangeIncludes schema:GovernmentOrganization ;
    rdfs:subPropertyOf schema:provider .

gs:expectedResolutionDate a rdf:Property ;
    rdfs:label "expected resolution date" ;
    rdfs:comment "When the authority expects to resolve the request. Open311 expected_datetime." ;
    schema:domainIncludes gs:ServiceRequest ;
    schema:rangeIncludes schema:DateTime .

gs:requestAttribute a rdf:Property ;
    rdfs:label "request attribute" ;
    rdfs:comment "A question asked when submitting a request for this service. Open311 Service Definition attribute, expressed as a schema:PropertyValueSpecification so no form-field vocabulary needed minting." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:PropertyValueSpecification .

gs:valueOption a rdf:Property ;
    rdfs:label "value option" ;
    rdfs:comment "A permitted value for a list-type request attribute. Open311 values[]." ;
    schema:domainIncludes schema:PropertyValueSpecification ;
    schema:rangeIncludes schema:DefinedTerm .

gs:isRealtime a rdf:Property ;
    rdfs:label "is realtime" ;
    rdfs:comment "Whether submitting a request returns an identifier immediately. Open311 type: realtime versus batch or blackbox." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:Boolean .

gs:ServiceRequestStatus a schema:DefinedTermSet ;
    schema:name "Service request status" .

#################  budget profile  #################

gs:Budget a rdfs:Class ;
    rdfs:label "Budget" ;
    rdfs:comment "A government's fiscal plan for one period, at one phase of the budget cycle. schema.org has no budget, fiscal, expenditure or appropriation concept; schema:MonetaryAmount is a value type, not a model. Mirrors the Fiscal Data Package, which remains the source model." ;
    rdfs:subClassOf schema:Dataset .

gs:BudgetLine a rdfs:Class ;
    rdfs:label "Budget line" ;
    rdfs:comment "One allocated amount within a budget, classified along the Fiscal Data Package dimensions." ;
    rdfs:subClassOf schema:Intangible .

gs:budgetPhase a rdf:Property ;
    rdfs:label "budget phase" ;
    rdfs:comment "Where in the budget cycle a figure comes from: proposed, approved, adjusted or executed. The field publishers most often omit and the one that matters most, since a figure without its phase is not comparable to any other figure." ;
    schema:domainIncludes gs:Budget, gs:BudgetLine ;
    schema:rangeIncludes schema:DefinedTerm .

gs:budgetLine a rdf:Property ;
    rdfs:label "budget line" ;
    rdfs:comment "A line within a budget." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes gs:BudgetLine .

gs:budget a rdf:Property ;
    rdfs:label "budget" ;
    rdfs:comment "The budget a line belongs to." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes gs:Budget .

gs:direction a rdf:Property ;
    rdfs:label "direction" ;
    rdfs:comment "Whether a budget line is revenue, expenditure or a financing movement. Required, because a bare amount cannot be interpreted without it." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:DefinedTerm .

gs:functionalClassification a rdf:Property ;
    rdfs:label "functional classification" ;
    rdfs:comment "What the money is for, as a COFOG code. Administrative structures differ in every country, so this is the dimension that makes budgets internationally comparable." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:DefinedTerm .

gs:economicClassification a rdf:Property ;
    rdfs:label "economic classification" ;
    rdfs:comment "What kind of transaction a line is, as a GFSM 2014 code: salaries, goods, interest, capital." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:DefinedTerm .

gs:administrativeClassification a rdf:Property ;
    rdfs:label "administrative classification" ;
    rdfs:comment "Which body spends a line, as a reference to a GovernmentOrganization rather than a free-text department name." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:GovernmentOrganization .

gs:programClassification a rdf:Property ;
    rdfs:label "program classification" ;
    rdfs:comment "The publisher's own programme or activity code." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:Text .

gs:fundSource a rdf:Property ;
    rdfs:label "fund source" ;
    rdfs:comment "The fund or financing source a line draws on." ;
    schema:domainIncludes gs:BudgetLine ;
    schema:rangeIncludes schema:Text .

gs:fiscalYear a rdf:Property ;
    rdfs:label "fiscal year" ;
    rdfs:comment "The publisher's label for the budget period. A label only: fiscal years begin in different months in different countries, so startDate and endDate carry the actual period." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes schema:Text .

gs:adoptedBy a rdf:Property ;
    rdfs:label "adopted by" ;
    rdfs:comment "The body that adopted a budget, usually the legislature." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes schema:GovernmentOrganization .

gs:BudgetPhase a schema:DefinedTermSet ;
    schema:name "Budget phase" .

gs:COFOG a schema:DefinedTermSet ;
    schema:name "COFOG functional classification" .

gs:EconomicClassification a schema:DefinedTermSet ;
    schema:name "GFSM economic classification" .

gs:supersedes a rdf:Property ;
    rdfs:label "supersedes" ;
    rdfs:comment "An earlier version this one revises, such as an approved budget superseding the proposed one. Both are retained: comparing phases is most of what budget transparency is for. For legislation use the precise ELI properties (legislationAmends, legislationRepeals) instead." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes schema:Thing .

gs:legislation a rdf:Property ;
    rdfs:label "legislation" ;
    rdfs:comment "The appropriation ordinance or act giving a budget legal force. Joins the budget profile to the code profile." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes schema:Legislation .

#################  procurement profile  #################

gs:ContractingProcess a rdfs:Class ;
    rdfs:label "Contracting process" ;
    rdfs:comment "One complete procurement, from planning through tender, award and contract, identified by an ocid. schema.org has no tender, procurement, bid or solicitation concept; schema:Demand and schema:Offer are retail constructs carrying GTIN, SKU and warranty semantics that do not apply to public procurement. Mirrors the Open Contracting Data Standard, which remains the source model." ;
    rdfs:subClassOf schema:Intangible .

gs:Tender a rdfs:Class ;
    rdfs:label "Tender" ;
    rdfs:comment "The solicitation: what is being bought, how bids are invited, on what timetable." ;
    rdfs:subClassOf schema:Intangible .

gs:Award a rdfs:Class ;
    rdfs:label "Award" ;
    rdfs:comment "The decision to give a contract to a supplier. Distinct from schema:award, which is a prize or honour." ;
    rdfs:subClassOf schema:Intangible .

gs:Contract a rdfs:Class ;
    rdfs:label "Contract" ;
    rdfs:comment "The signed agreement resulting from an award, and what was actually paid under it." ;
    rdfs:subClassOf schema:Intangible .

gs:Party a rdfs:Class ;
    rdfs:label "Party" ;
    rdfs:comment "An organization taking part in a contracting process, with the roles it plays. Usually a private company, so a plain schema:Organization rather than a GovernmentOrganization." ;
    rdfs:subClassOf schema:Organization .

gs:ocid a rdf:Property ;
    rdfs:label "ocid" ;
    rdfs:comment "Open Contracting ID: a globally unique identifier for a contracting process, carrying a registered publisher prefix. The join key that makes OCDS data aggregatable across publishers." ;
    schema:domainIncludes gs:ContractingProcess ;
    schema:rangeIncludes schema:Text ;
    rdfs:subPropertyOf schema:identifier .

gs:procurementMethod a rdf:Property ;
    rdfs:label "procurement method" ;
    rdfs:comment "How bids were invited: open, selective, limited or direct. The field that makes non-competitive awards visible." ;
    schema:domainIncludes gs:Tender ;
    schema:rangeIncludes schema:DefinedTerm .

gs:procurementMethodRationale a rdf:Property ;
    rdfs:label "procurement method rationale" ;
    rdfs:comment "Why a procurement method was chosen. Expected whenever the method is direct: a sole-source award without a stated reason is the most common audit finding in public procurement." ;
    schema:domainIncludes gs:Tender ;
    schema:rangeIncludes schema:Text .

gs:mainProcurementCategory a rdf:Property ;
    rdfs:label "main procurement category" ;
    rdfs:comment "Goods, works, services or consulting services." ;
    schema:domainIncludes gs:Tender ;
    schema:rangeIncludes schema:DefinedTerm .

gs:classification a rdf:Property ;
    rdfs:label "classification" ;
    rdfs:comment "What is being bought, as a scheme-qualified code: CPV in the EU, UNSPSC globally, NIGP in much of the US." ;
    schema:domainIncludes gs:Tender ;
    schema:rangeIncludes schema:PropertyValue .

gs:tender a rdf:Property ;
    schema:domainIncludes gs:ContractingProcess ; schema:rangeIncludes gs:Tender ;
    rdfs:label "tender" ; rdfs:comment "The solicitation stage of a contracting process." .

gs:award a rdf:Property ;
    schema:domainIncludes gs:ContractingProcess ; schema:rangeIncludes gs:Award ;
    rdfs:label "award" ; rdfs:comment "An award made in a contracting process. Distinct from schema:award, a prize." .

gs:contract a rdf:Property ;
    schema:domainIncludes gs:ContractingProcess ; schema:rangeIncludes gs:Contract ;
    rdfs:label "contract" ; rdfs:comment "A contract signed in a contracting process." .

gs:party a rdf:Property ;
    schema:domainIncludes gs:ContractingProcess ; schema:rangeIncludes gs:Party ;
    rdfs:label "party" ; rdfs:comment "An organization involved in a contracting process." .

gs:supplier a rdf:Property ;
    schema:domainIncludes gs:Award ; schema:rangeIncludes gs:Party ;
    rdfs:label "supplier" ; rdfs:comment "A party awarded a contract. Always a reference: a supplier name as free text cannot be joined across contracts, which is how repeat awards to connected parties stay invisible." .

gs:amountPaid a rdf:Property ;
    schema:domainIncludes gs:Contract ; schema:rangeIncludes schema:MonetaryAmount ;
    rdfs:label "amount paid" ; rdfs:comment "Total transacted to date under a contract. Kept distinct from the contract value so that overruns are visible." .

gs:ProcurementMethod a schema:DefinedTermSet ; schema:name "Procurement method" .
gs:ProcurementCategory a schema:DefinedTermSet ; schema:name "Procurement category" .
gs:PartyRole a schema:DefinedTermSet ; schema:name "Party role" .

gs:status a rdf:Property ;
    rdfs:label "status" ;
    rdfs:comment "Stage-specific status of a tender, award or contract. The permitted values differ by stage and are defined in each schema rather than in one shared list, because 'active' means something different for a tender than for a contract." ;
    schema:domainIncludes gs:Tender, gs:Award, gs:Contract ;
    schema:rangeIncludes schema:DefinedTerm .

gs:role a rdf:Property ;
    rdfs:label "role" ;
    rdfs:comment "What an organization does in a contracting process. One organization may hold several roles in the same process." ;
    schema:domainIncludes gs:Party ;
    schema:rangeIncludes schema:DefinedTerm .

gs:dateSigned a rdf:Property ;
    schema:domainIncludes gs:Contract ; schema:rangeIncludes schema:Date ;
    rdfs:label "date signed" ; rdfs:comment "When a contract was signed." .

gs:numberOfTenderers a rdf:Property ;
    schema:domainIncludes gs:Tender ; schema:rangeIncludes schema:Integer ;
    rdfs:label "number of tenderers" ; rdfs:comment "How many bids were received. A competitive method that attracted one bid is not a competition, and only this field reveals that." .

gs:document a rdf:Property ;
    schema:domainIncludes gs:Tender, gs:Award, gs:Contract ; schema:rangeIncludes schema:URL ;
    rdfs:label "document" ; rdfs:comment "A published document relating to this stage." .

gs:tenderId a rdf:Property ; schema:domainIncludes gs:Tender ; schema:rangeIncludes schema:Text ;
    rdfs:label "tender id" ; rdfs:subPropertyOf schema:identifier .
gs:awardId a rdf:Property ; schema:domainIncludes gs:Award, gs:Contract ; schema:rangeIncludes schema:Text ;
    rdfs:label "award id" ; rdfs:subPropertyOf schema:identifier .
gs:contractId a rdf:Property ; schema:domainIncludes gs:Contract ; schema:rangeIncludes schema:Text ;
    rdfs:label "contract id" ; rdfs:subPropertyOf schema:identifier .
gs:procurementMethodDetails a rdf:Property ; schema:domainIncludes gs:Tender ; schema:rangeIncludes schema:Text ;
    rdfs:label "procurement method details" ; rdfs:comment "The publisher's own name for the procedure used." .

#################  catalog profile  #################

gs:PublisherManifest a rdfs:Class ;
    rdfs:label "Publisher manifest" ;
    rdfs:comment "The discovery document that makes a publisher's schemaGov data findable, served at /.well-known/schemaGov.json per RFC 8615. The only document in schemaGov with a fixed, conventional location: everything else is discovered through it." ;
    rdfs:subClassOf schema:CreativeWork .

gs:ProfileEndpoint a rdfs:Class ;
    rdfs:label "Profile endpoint" ;
    rdfs:comment "One published profile and the URL serving it. Entries in a manifest form the routing table for a publisher." ;
    rdfs:subClassOf schema:EntryPoint .

gs:profileEndpoint a rdf:Property ;
    rdfs:label "profile endpoint" ;
    rdfs:comment "A profile this publisher serves, and where." ;
    schema:domainIncludes gs:PublisherManifest ;
    schema:rangeIncludes gs:ProfileEndpoint .

gs:profile a rdf:Property ;
    rdfs:label "profile" ;
    rdfs:comment "Which schemaGov profile an endpoint or dataset serves." ;
    schema:domainIncludes gs:ProfileEndpoint, schema:Dataset ;
    schema:rangeIncludes schema:Text .

gs:specVersion a rdf:Property ;
    rdfs:label "spec version" ;
    rdfs:comment "The schemaGov version a publisher targets, so a consumer can detect one pinned to an older profile." ;
    schema:domainIncludes gs:PublisherManifest ;
    schema:rangeIncludes schema:Text .

gs:dataTheme a rdf:Property ;
    rdfs:label "data theme" ;
    rdfs:comment "Subject category of a dataset, from the EU data-theme vocabulary used by DCAT-AP." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:DefinedTerm .

gs:updateFrequency a rdf:Property ;
    rdfs:label "update frequency" ;
    rdfs:comment "How often a dataset is refreshed. DCAT dct:accrualPeriodicity. A dataset with no stated cadence cannot be told apart from an abandoned one." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Duration, schema:Text .

gs:accessRights a rdf:Property ;
    rdfs:label "access rights" ;
    rdfs:comment "Whether the data itself is public, restricted, or non-public. DCAT dct:accessRights. Publishing restricted metadata is legitimate and useful; publishing it without saying so is not." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Text .

gs:accessUrl a rdf:Property ;
    rdfs:label "access url" ;
    rdfs:comment "A landing page or API root where there is no direct download. DCAT dcat:accessURL, as distinct from dcat:downloadURL." ;
    schema:domainIncludes schema:DataDownload ;
    schema:rangeIncludes schema:URL .

gs:DataTheme a schema:DefinedTermSet ;
    schema:name "Data theme" .

#################  alerts profile  #################

gs:Alert a rdfs:Class ;
    rdfs:label "Alert" ;
    rdfs:comment "A public warning or notice issued by a government. Modelled on OASIS CAP 1.2. schema:SpecialAnnouncement exists but every property on it is pandemic-specific and it carries no severity, urgency, certainty or expiry, so it serves only as a discovery projection." ;
    rdfs:subClassOf schema:CreativeWork .

gs:AlertInfo a rdfs:Class ;
    rdfs:label "Alert info" ;
    rdfs:comment "One language variant of an alert's content. CAP separates alert from info precisely so a warning can be issued in several languages at once." ;
    rdfs:subClassOf schema:Intangible .

gs:AlertArea a rdfs:Class ;
    rdfs:label "Alert area" ;
    rdfs:comment "Where an alert applies. Geometry is referenced by URL rather than embedded: a warning polygon is thousands of coordinate pairs, and alerts travel over constrained channels." ;
    rdfs:subClassOf schema:Intangible .

gs:alertIdentifier a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes schema:Text ;
    rdfs:label "alert identifier" ; rdfs:subPropertyOf schema:identifier .
gs:alertStatus a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "alert status" ;
    rdfs:comment "CAP status. Exercise and test messages must never render as real; publishing them without this field is dangerous." .
gs:messageType a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "message type" ;
    rdfs:comment "CAP msgType. An update or cancel must reference the alert it supersedes." .
gs:scope a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "scope" .
gs:alertInfo a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes gs:AlertInfo ;
    rdfs:label "alert info" .
gs:area a rdf:Property ; schema:domainIncludes gs:Alert ; schema:rangeIncludes gs:AlertArea ;
    rdfs:label "area" .
gs:urgency a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "urgency" ; rdfs:comment "How soon responsive action should be taken. CAP urgency." .
gs:severity a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "severity" ; rdfs:comment "Intensity of the threat to life or property. CAP severity." .
gs:certainty a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "certainty" ; rdfs:comment "Confidence that the event will occur. CAP certainty. Together with urgency and severity this is what lets a system decide whether to interrupt someone." .
gs:responseType a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "response type" ; rdfs:comment "What the public should do, machine-readable and separate from the free-text instruction." .
gs:instruction a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:Text ;
    rdfs:label "instruction" ; rdfs:comment "What the public should do. The field that makes an alert actionable rather than merely informative." .
gs:expires a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DateTime ;
    rdfs:label "expires" ; rdfs:comment "When the alert ceases to apply. An alert with no expiry stays on screens indefinitely and trains people to ignore alerts." .
gs:onset a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DateTime ; rdfs:label "onset" .
gs:effective a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:DateTime ; rdfs:label "effective" .
gs:headline a rdf:Property ; schema:domainIncludes gs:AlertInfo ; schema:rangeIncludes schema:Text ; rdfs:label "headline" .
gs:areaDescription a rdf:Property ; schema:domainIncludes gs:AlertArea ; schema:rangeIncludes schema:Text ; rdfs:label "area description" .
gs:geometry a rdf:Property ; schema:domainIncludes gs:AlertArea ; schema:rangeIncludes schema:URL ;
    rdfs:label "geometry" ; rdfs:comment "URL of a GeoJSON polygon (RFC 7946, WGS84). Referenced, never embedded." .
gs:relatedAlert a rdf:Property ; schema:domainIncludes gs:ServiceRequest ; schema:rangeIncludes gs:Alert ;
    rdfs:label "related alert" ;
    rdfs:comment "An alert this service request relates to. A service disruption is both: the disruption is an alert, reports about it are requests." .

gs:AlertCategory a schema:DefinedTermSet ; schema:name "Alert category" .
gs:ResponseType a schema:DefinedTermSet ; schema:name "Response type" .

gs:duplicateOf a rdf:Property ; schema:domainIncludes gs:ServiceRequest ; schema:rangeIncludes gs:ServiceRequest ;
    rdfs:label "duplicate of" ;
    rdfs:comment "The request this one duplicates. A reference rather than prose: a status note saying 'duplicate of 2025-104882' cannot be followed by a machine." .

gs:StatusChange a rdfs:Class ; rdfs:subClassOf schema:Intangible ;
    rdfs:label "Status change" ;
    rdfs:comment "One timestamped step in a service request's progress." .

gs:statusHistory a rdf:Property ; schema:domainIncludes gs:ServiceRequest ; schema:rangeIncludes gs:StatusChange ;
    rdfs:label "status history" ;
    rdfs:comment "How a request progressed over time. Current state alone hides how long a request sat unassigned, which is the number residents and service-level measurement actually need." .

gs:conformanceLevel a rdf:Property ;
    rdfs:label "conformance level" ;
    rdfs:comment "The schemaGov conformance level a document claims: core, standard or extended. Deliberately NOT dcterms:conformsTo, which means an external standard the resource follows and is typed as an IRI - a bare level name expanded there becomes a broken relative IRI, which is exactly what happened before this term existed." ;
    schema:domainIncludes schema:Thing ;
    schema:rangeIncludes schema:DefinedTerm .

gs:applicableLegislation a rdf:Property ;
    rdfs:label "applicable legislation" ;
    rdfs:comment "Legislation that mandates or governs a dataset, typically as an ELI URI. Observed on real EU portals, where the Open Data Directive requires certain datasets to be published; this is a direct join from the catalog profile to the code profile." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Legislation, schema:URL .

gs:hvdCategory a rdf:Property ;
    rdfs:label "high value dataset category" ;
    rdfs:comment "EU High Value Dataset category URI, from the Open Data Directive implementing regulation. A legal classification, not a subject theme." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:URL .

gs:highValueDataset a rdf:Property ;
    rdfs:label "high value dataset" ;
    rdfs:comment "Whether this dataset is designated a High Value Dataset under the EU Open Data Directive." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Boolean .

gs:spatialReferenceSystem a rdf:Property ;
    rdfs:label "spatial reference system" ;
    rdfs:comment "The coordinate reference system of a dataset's geometry, as an EPSG code such as 'epsg:2157'. GeoJSON mandates WGS84, but national grids are in daily use everywhere, so an international profile cannot assume it." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Text .

gs:provenanceStatement a rdf:Property ;
    rdfs:label "provenance statement" ;
    rdfs:comment "Free-text statement of where a dataset came from." ;
    schema:domainIncludes schema:Dataset ;
    schema:rangeIncludes schema:Text .

gs:totalAmount a rdf:Property ;
    rdfs:label "total amount" ;
    rdfs:comment "The total of a budget, as distinct from the amount of a single line. Deliberately not schema:amount: sharing one predicate with BudgetLine.amount makes a budget total and a line indistinguishable in RDF." ;
    schema:domainIncludes gs:Budget ;
    schema:rangeIncludes schema:MonetaryAmount ;
    rdfs:subPropertyOf schema:amount .

#################  permits profile  #################

gs:permitNumber a rdf:Property ;
    rdfs:label "permit number" ;
    rdfs:comment "The reference an authority uses publicly for a permit." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Text ;
    rdfs:subPropertyOf schema:identifier .

gs:permitType a rdf:Property ;
    rdfs:label "permit type" ;
    rdfs:comment "The kind of permission granted. Generic rather than national: the same permission is a building permit, planning permission, a permis de construire or a Baugenehmigung depending on the country." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:DefinedTerm ;
    rdfs:subPropertyOf schema:additionalType .

gs:permitStatus a rdf:Property ;
    rdfs:label "permit status" ;
    rdfs:comment "Where an application has reached. A permit record with no status cannot be told apart from an application that was never decided." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:DefinedTerm .

gs:workType a rdf:Property ;
    rdfs:label "work type" ;
    rdfs:comment "The nature of construction works. Distinguishing new build from alteration is what makes permit data usable as a housing-supply indicator rather than only a compliance record." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:DefinedTerm .

gs:applicationDate a rdf:Property ;
    rdfs:label "application date" ;
    rdfs:comment "When an application was received. With decisionDate this makes processing time measurable, which is the question residents and developers actually ask." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Date .

gs:decisionDate a rdf:Property ;
    rdfs:label "decision date" ;
    rdfs:comment "When a permit was granted or refused." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Date .

gs:completionDate a rdf:Property ;
    rdfs:label "completion date" ;
    rdfs:comment "When permitted works were finished and signed off." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Date .

gs:premises a rdf:Property ;
    rdfs:label "premises" ;
    rdfs:comment "The place a permit applies to. schema:location does not have Permit in its domain, and a permit's subject is a property rather than an event venue." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Place .

gs:parcelIdentifier a rdf:Property ;
    rdfs:label "parcel identifier" ;
    rdfs:comment "Cadastral or tax-parcel reference for a property, scheme-qualified. Parcel numbering is national, so the scheme matters as much as the code." ;
    schema:domainIncludes schema:Place ;
    schema:rangeIncludes schema:PropertyValue .

gs:applicant a rdf:Property ;
    rdfs:label "applicant" ;
    rdfs:comment "Who applied for a permit. Optional by design: where the applicant is a private individual rather than a business, publishing their name against their home address is a disclosure decision the authority must take deliberately, not one the schema forces." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Organization, schema:Person .

gs:declaredValue a rdf:Property ;
    rdfs:label "declared value" ;
    rdfs:comment "Declared value of permitted works." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:MonetaryAmount .

gs:fee a rdf:Property ;
    rdfs:label "fee" ;
    rdfs:comment "Fee charged for a permit." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:MonetaryAmount .

gs:condition a rdf:Property ;
    rdfs:label "condition" ;
    rdfs:comment "A condition attached to a grant. A permit granted subject to conditions is not the same as one granted outright, and only this shows the difference." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Text .

gs:relatedLegislation a rdf:Property ;
    rdfs:label "related legislation" ;
    rdfs:comment "The provision a permit is granted under. Joins the permits profile to the code profile." ;
    schema:domainIncludes schema:GovernmentPermit ;
    schema:rangeIncludes schema:Legislation .

gs:PermitType a schema:DefinedTermSet ; schema:name "Permit type" .
gs:PermitStatus a schema:DefinedTermSet ; schema:name "Permit status" .
gs:WorkType a schema:DefinedTermSet ; schema:name "Work type" .

#################  elections profile  #################

gs:Election a rdfs:Class ;
    rdfs:label "Election" ;
    rdfs:comment "An electoral event on a given date, containing one or more contests. schema.org has no Election, Candidate, Ballot or constituency of any kind; only schema:PoliticalParty is reusable." ;
    rdfs:subClassOf schema:Event .

gs:Contest a rdfs:Class ;
    rdfs:label "Contest" ;
    rdfs:comment "One race or question on the ballot - the unit at which results are actually reported." ;
    rdfs:subClassOf schema:Intangible .

gs:Candidacy a rdfs:Class ;
    rdfs:label "Candidacy" ;
    rdfs:comment "One person standing in one contest. A candidacy rather than a candidate: the same person may stand in several contests, and party affiliation and result belong to the standing rather than to the person." ;
    rdfs:subClassOf schema:Intangible .

gs:BallotOption a rdfs:Class ;
    rdfs:label "Ballot option" ;
    rdfs:comment "An option put to voters in a ballot measure, named with schema:name. Kept distinct from a candidacy because a proposition is not a person." ;
    rdfs:subClassOf schema:Intangible .

gs:electionDate a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:Date ;
    rdfs:label "election date" ; rdfs:comment "Polling day; where voting spans several days, the final day." .
gs:electionType a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "election type" .
gs:electionStatus a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "election status" .
gs:administeredBy a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:GovernmentOrganization ;
    rdfs:label "administered by" ;
    rdfs:comment "The body running the election, which is frequently not the body being elected." .
gs:contest a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes gs:Contest ;
    rdfs:label "contest" .
gs:contestType a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "contest type" .
gs:electoralSystem a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "electoral system" ;
    rdfs:comment "How votes translate into outcomes. Required, because a result cannot be interpreted without it: 40% wins outright under first past the post, triggers a runoff under a two-round system, and yields a seat share under a party list." .
gs:seatsToFill a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:Integer ;
    rdfs:label "seats to fill" .
gs:candidacy a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes gs:Candidacy ;
    rdfs:label "candidacy" .
gs:ballotOption a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes gs:BallotOption ;
    rdfs:label "ballot option" .
gs:candidate a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:Person ;
    rdfs:label "candidate" ;
    rdfs:comment "The person standing. A reference, so a candidate who takes office is the same entity as the officeholder in the org profile." .
gs:party a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:PoliticalParty ;
    rdfs:label "party" ; rdfs:comment "Absent means the candidate stood as an independent." .
gs:ballotName a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:Text ;
    rdfs:label "ballot name" ; rdfs:comment "The name as printed on the ballot, often not the person's full legal name." .
gs:ballotOrder a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:Integer ;
    rdfs:label "ballot order" .
gs:voteCount a rdf:Property ; schema:domainIncludes gs:Candidacy, gs:BallotOption ; schema:rangeIncludes schema:Integer ;
    rdfs:label "vote count" .
gs:candidacyResult a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:DefinedTerm ;
    rdfs:label "candidacy result" ;
    rdfs:comment "Withdrawn and disqualified are distinguished from losing: a candidate who never faced the voters is not the same as one who did and lost." .
gs:incumbent a rdf:Property ; schema:domainIncludes gs:Candidacy ; schema:rangeIncludes schema:Boolean ;
    rdfs:label "incumbent" .
gs:registeredVoters a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:Integer ;
    rdfs:label "registered voters" .
gs:ballotsCast a rdf:Property ; schema:domainIncludes gs:Election ; schema:rangeIncludes schema:Integer ;
    rdfs:label "ballots cast" ;
    rdfs:comment "With registeredVoters this yields turnout. Publishing a derived percentage instead loses the ability to recompute it on a corrected register." .
gs:validVotes a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:Integer ; rdfs:label "valid votes" .
gs:invalidVotes a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:Integer ;
    rdfs:label "invalid votes" ;
    rdfs:comment "Spoiled and blank ballots, reported separately because they are a real signal and folding them into the total makes every share slightly wrong." .
gs:totalVotes a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes schema:Integer ; rdfs:label "total votes" .
gs:prevailed a rdf:Property ; schema:domainIncludes gs:BallotOption ; schema:rangeIncludes schema:Boolean ; rdfs:label "prevailed" .

gs:ElectoralSystem a schema:DefinedTermSet ; schema:name "Electoral system" .
gs:ElectionType a schema:DefinedTermSet ; schema:name "Election type" .
gs:ContestType a schema:DefinedTermSet ; schema:name "Contest type" .
gs:CandidacyResult a schema:DefinedTermSet ; schema:name "Candidacy result" .

gs:election a rdf:Property ; schema:domainIncludes gs:Contest ; schema:rangeIncludes gs:Election ;
    rdfs:label "election" ; rdfs:comment "The election a contest belongs to." .

gs:referencesIdentifier a rdf:Property ;
    rdfs:label "references identifier" ;
    rdfs:comment "CAP identifier of a superseded alert that is not present in this dataset. Alert feeds are windowed, so an update commonly supersedes an alert that has already expired out of the active feed. Without this, a publisher must downgrade the update to a plain alert, which turns 'this supersedes an earlier warning' into 'this is a new warning'." ;
    schema:domainIncludes gs:Alert ;
    schema:rangeIncludes schema:Text ;
    rdfs:subPropertyOf schema:identifier .

#################  geospatial  #################

gs:Boundary a rdfs:Class ;
    rdfs:label "Boundary" ;
    rdfs:comment "The extent of a governed area over a period of time. A separate citable entity rather than a field, because boundaries change and the change matters: a 2022 contest was fought on the 2022 boundary, and a record attributed to an area is anchored to the boundary in force at the time. Attaching one current geometry to a jurisdiction silently rewrites history." ;
    rdfs:subClassOf schema:Intangible .

gs:Geometry a rdfs:Class ;
    rdfs:label "Geometry" ;
    rdfs:comment "A shape on the earth, held by reference or inline. schema:GeoShape cannot do this: its polygon is a space-delimited text string with no CRS, no multipolygon and no interior rings, and schema.org's own GeospatialGeometry is a declared placeholder that was never filled in." ;
    rdfs:subClassOf schema:StructuredValue .

gs:boundary a rdf:Property ;
    rdfs:label "boundary" ;
    rdfs:comment "A Boundary of this area, including superseded ones." ;
    schema:domainIncludes schema:AdministrativeArea ;
    schema:rangeIncludes gs:Boundary .

gs:boundaryOf a rdf:Property ;
    rdfs:label "boundary of" ;
    rdfs:comment "The jurisdiction a Boundary is the extent of." ;
    schema:domainIncludes gs:Boundary ;
    schema:rangeIncludes schema:AdministrativeArea .

gs:geometry a rdf:Property ;
    rdfs:label "geometry" ;
    rdfs:comment "The shape itself." ;
    schema:domainIncludes gs:Boundary, gs:AlertArea ;
    schema:rangeIncludes gs:Geometry, schema:URL .

gs:geometryType a rdf:Property ;
    rdfs:label "geometry type" ;
    rdfs:comment "GeoJSON geometry type. MultiPolygon is the common case for real administrative areas, which have islands and exclaves." ;
    schema:domainIncludes gs:Geometry ;
    schema:rangeIncludes schema:Text .

gs:coordinates a rdf:Property ;
    rdfs:label "coordinates" ;
    rdfs:comment "Inline GeoJSON coordinates, for geometry specific to one record and small. Permitted because real CAP publishers embed the polygon in the alert itself, and a profile that only allowed references could not describe them." ;
    schema:domainIncludes gs:Geometry ;
    schema:rangeIncludes schema:Text .

gs:sourceReferenceSystem a rdf:Property ;
    rdfs:label "source reference system" ;
    rdfs:comment "The CRS a publisher's authoritative source is held in. Provenance, not a claim about the coordinates present: GeoJSON mandates WGS84 and forbids alternatives. Recording it matters because national-grid coordinates read as WGS84 land in the wrong hemisphere." ;
    schema:domainIncludes gs:Geometry ;
    schema:rangeIncludes schema:Text .

gs:simplified a rdf:Property ;
    rdfs:label "simplified" ;
    rdfs:comment "Whether a geometry is a generalised rendering for display. A simplified boundary is not the legal boundary, and using one to decide whether an address falls inside a district gives wrong answers at the edges." ;
    schema:domainIncludes gs:Geometry ;
    schema:rangeIncludes schema:Boolean .

gs:vertexCount a rdf:Property ;
    rdfs:label "vertex count" ;
    schema:domainIncludes gs:Geometry ; schema:rangeIncludes schema:Integer ;
    rdfs:comment "Approximate vertex count, where the publisher knows it." .

gs:authoritative a rdf:Property ;
    rdfs:label "authoritative" ;
    rdfs:comment "Whether a Boundary is the legally definitive extent rather than a published rendering of it." ;
    schema:domainIncludes gs:Boundary ;
    schema:rangeIncludes schema:Boolean .


#################  services profile  #################

gs:ServiceAtLocation a rdfs:Class ;
    rdfs:label "Service at location" ;
    rdfs:comment "One service delivered at one place, with the hours that apply there. Modelled as a join rather than a field on either side, following HSDS: a service and a location are independent, one office delivers many services, one service runs from many offices, and opening hours belong to the pairing." ;
    rdfs:subClassOf schema:Intangible .

gs:RequiredDocument a rdfs:Class ;
    rdfs:label "Required document" ;
    rdfs:comment "Something an applicant must bring or supply. The most common reason an application fails at the counter." ;
    rdfs:subClassOf schema:Intangible .

gs:ServiceCost a rdfs:Class ;
    rdfs:label "Service cost" ;
    rdfs:comment "What a service costs. A free service says so explicitly rather than omitting the field, because absence reads as unknown." ;
    rdfs:subClassOf schema:StructuredValue .

gs:serviceStatus a rdf:Property ;
    rdfs:label "service status" ;
    rdfs:comment "Whether a service is currently delivered. Defunct is distinguished from temporarily closed because a resident needs to know whether coming back later is worth it." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:DefinedTerm .

gs:lifeEvent a rdf:Property ;
    rdfs:label "life event" ;
    rdfs:comment "The circumstance a service relates to. People look for services by what is happening to them rather than by the department that runs them; the department that issues a birth certificate differs everywhere, the fact of a birth does not." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:DefinedTerm .

gs:eligibility a rdf:Property ;
    rdfs:label "eligibility" ;
    rdfs:comment "Who may use a service. schema:PeopleAudience carries age and geography; eligibilityCriteria carries what a structured audience cannot express." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:PeopleAudience .

gs:eligibilityCriteria a rdf:Property ;
    rdfs:label "eligibility criteria" ;
    schema:domainIncludes schema:PeopleAudience ; schema:rangeIncludes schema:Text ;
    rdfs:comment "Conditions no structured field captures: residency, income, tenure, immigration status." .

gs:applicationProcess a rdf:Property ;
    rdfs:label "application process" ;
    rdfs:comment "How to apply, in plain language. A service described without it is a listing rather than a route to anything." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:Text .

gs:requiredDocument a rdf:Property ;
    rdfs:label "required document" ;
    schema:domainIncludes schema:GovernmentService ; schema:rangeIncludes gs:RequiredDocument ;
    rdfs:label "required document" .

gs:cost a rdf:Property ;
    rdfs:label "cost" ;
    schema:domainIncludes schema:GovernmentService ; schema:rangeIncludes gs:ServiceCost .

gs:waiverAvailable a rdf:Property ;
    rdfs:label "waiver available" ;
    rdfs:comment "Whether a fee waiver or reduction exists. Publishing a fee without the waiver deters exactly the people the waiver is for." ;
    schema:domainIncludes gs:ServiceCost ;
    schema:rangeIncludes schema:Boolean .

gs:availableAtLocation a rdf:Property ;
    rdfs:label "available at location" ;
    schema:domainIncludes schema:GovernmentService ; schema:rangeIncludes gs:ServiceAtLocation .

gs:appointmentRequired a rdf:Property ;
    rdfs:label "appointment required" ;
    schema:domainIncludes gs:ServiceAtLocation ; schema:rangeIncludes schema:Boolean .

gs:interpretationAvailable a rdf:Property ;
    rdfs:label "interpretation available" ;
    rdfs:comment "Whether interpretation is offered for languages not listed in availableLanguage." ;
    schema:domainIncludes schema:GovernmentService ;
    schema:rangeIncludes schema:Boolean .

gs:accessibilityNote a rdf:Property ;
    rdfs:label "accessibility note" ;
    schema:domainIncludes schema:GovernmentService ; schema:rangeIncludes schema:Text .

gs:ServiceStatus a schema:DefinedTermSet ; schema:name "Service status" .
gs:LifeEvent a schema:DefinedTermSet ; schema:name "Life event" .

gs:free a rdf:Property ; schema:domainIncludes gs:ServiceCost ; schema:rangeIncludes schema:Boolean ;
    rdfs:label "free" ; rdfs:comment "Whether the service is free. Stated explicitly, because an absent cost reads as unknown rather than as nil." .
gs:optional a rdf:Property ; schema:domainIncludes gs:RequiredDocument ; schema:rangeIncludes schema:Boolean ;
    rdfs:label "optional" ; rdfs:comment "True where an alternative document is accepted." .


#################  projects profile  #################

gs:Project a rdfs:Class ;
    rdfs:label "Project" ;
    rdfs:comment "A government project or initiative: bounded work with a start, an intended end, and something it is meant to produce. Subclass of schema:Project, which sits under schema:Organization, so funder, member and parentOrganization are inherited unchanged. Minted so a consumer can tell a schemaGov project record from any other schema:Project. Status and lifecycle phase are separate properties: status says whether work is happening, phase says where in its lifecycle it is." ;
    rdfs:subClassOf schema:Project .

gs:Milestone a rdfs:Class ;
    rdfs:label "Milestone" ;
    rdfs:comment "A dated point of progress in a project. schema.org has no milestone type; schema:Event is the nearest base. Linked to its project with schema:about, because schema:superEvent accepts only an Event. Status and dates follow the Open Contracting Data Standard milestone." ;
    rdfs:subClassOf schema:Event .

gs:projectStatus a rdf:Property ;
    rdfs:label "project status" ;
    rdfs:comment "Whether work on the project is currently happening: proposed, planned, active, paused, completed or cancelled. schema:ActionStatusType is defined for Action and has no paused, cancelled or proposed, so a dedicated code list is used. Lifecycle phase is not a status; see gs:projectPhase. Health (on track, at risk) is deliberately not modelled." ;
    schema:domainIncludes gs:Project ;
    schema:rangeIncludes schema:DefinedTerm .

gs:projectPhase a rdf:Property ;
    rdfs:label "project phase" ;
    rdfs:comment "Where the project is in its lifecycle, as a schema:DefinedTerm belonging to a schema:DefinedTermSet that names the lifecycle scheme. Schemes differ by kind of project (a digital service moves through discovery to live, a capital project through design to construction), so no single list is mandated and publishers may reference their own." ;
    schema:domainIncludes gs:Project ;
    schema:rangeIncludes schema:DefinedTerm .

gs:expectedEndDate a rdf:Property ;
    rdfs:label "expected end date" ;
    rdfs:comment "When the project is currently planned to finish. schema:endDate on the same project is the actual end. OC4IDS period.endDate (planned) versus completion.endDate (actual)." ;
    schema:domainIncludes gs:Project ;
    schema:rangeIncludes schema:Date .

gs:produces a rdf:Property ;
    rdfs:label "produces" ;
    rdfs:comment "Something the project delivers or is delivering: a service, dataset, application, facility or document. Kept apart from the project because the project can finish while its output stays in operation. schema:serviceOutput points from a Service to what it generates, which is the wrong direction, and schema:result applies only to Action. No schema.org superproperty exists." ;
    schema:domainIncludes gs:Project ;
    schema:rangeIncludes schema:Thing .

gs:milestoneStatus a rdf:Property ;
    rdfs:label "milestone status" ;
    rdfs:comment "Whether a milestone has been reached: scheduled, met, notMet or partiallyMet. Values are those of the Open Contracting Data Standard milestone status." ;
    schema:domainIncludes gs:Milestone ;
    schema:rangeIncludes schema:DefinedTerm .

gs:dueDate a rdf:Property ;
    rdfs:label "due date" ;
    rdfs:comment "When the milestone is scheduled to be reached. OCDS milestone.dueDate." ;
    schema:domainIncludes gs:Milestone ;
    schema:rangeIncludes schema:Date .

gs:dateMet a rdf:Property ;
    rdfs:label "date met" ;
    rdfs:comment "When the milestone was actually reached. OCDS milestone.dateMet." ;
    schema:domainIncludes gs:Milestone ;
    schema:rangeIncludes schema:Date .

gs:ProjectStatus a schema:DefinedTermSet ; schema:name "Project status" ;
    rdfs:comment "Whether work on a project is happening now. Not the lifecycle phase, and not project health." .
gs:MilestoneStatus a schema:DefinedTermSet ; schema:name "Milestone status" ;
    rdfs:comment "Whether a milestone has been reached. The values are those of the Open Contracting Data Standard." .
gs:DigitalServicePhase a schema:DefinedTermSet ; schema:name "Digital service phase" ;
    rdfs:comment "The lifecycle of a digital government service, after the GOV.UK Service Manual. For digital services only." .
