{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://citytwin.ro/schema/city-model/v0.json","title":"CityTwin City Semantic Model","description":"Lightweight, open, evidence-first representation of a city. Transforms documents, open data and maps into entities and relations that can be placed on a map and queried by AI. Every important fact is traceable to a source. JSON-LD compatible (see @context).","version":"0.3.0","type":"object","required":["model_version","city","sources","entities"],"additionalProperties":false,"properties":{"@context":{"description":"Optional JSON-LD context for interoperability. Default points at the CityTwin vocabulary.","type":["string","object"],"default":"https://citytwin.ro/context/v0.jsonld"},"model_version":{"description":"Version of the City Semantic Model spec this instance conforms to. Older instances remain valid: 0.2.0 only ADDS optional fields (Indicator.history, generated.connector_runs), and 0.3.0 only ADDS two optional entity groups (entities.parcels, entities.utrs - urbanism at plot level).","type":"string","enum":["0.1.0","0.2.0","0.3.0"]},"city":{"$ref":"#/$defs/City"},"sources":{"description":"Registry of every source feeding the model. Entities cite these by id. This is the backbone of the evidence-first principle.","type":"array","items":{"$ref":"#/$defs/Source"}},"entities":{"type":"object","additionalProperties":false,"properties":{"zones":{"type":"array","items":{"$ref":"#/$defs/Zone"}},"projects":{"type":"array","items":{"$ref":"#/$defs/Project"}},"services":{"type":"array","items":{"$ref":"#/$defs/PublicService"}},"problems":{"type":"array","items":{"$ref":"#/$defs/UrbanProblem"}},"indicators":{"type":"array","items":{"$ref":"#/$defs/Indicator"}},"parcels":{"type":"array","items":{"$ref":"#/$defs/Parcel"}},"utrs":{"type":"array","items":{"$ref":"#/$defs/Utr"}}}},"layers":{"description":"Thematic / modeling layers (traffic flow, accessibility, bike network, etc.) as GeoJSON FeatureCollections. This is how modeling outputs are carried and rendered on the map.","type":"array","items":{"$ref":"#/$defs/ThematicLayer"}},"generated":{"$ref":"#/$defs/GenerationMeta"}},"$defs":{"ThematicLayer":{"description":"A modeling / thematic layer: a GeoJSON FeatureCollection plus how to read and render it.","type":"object","required":["id","kind","name","geojson"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"kind":{"type":"string","enum":["traffic_flow","accessibility","bike_network","pedestrian_zone","transit_network","parking","safety","emissions","other"]},"name":{"type":"string"},"description":{"type":["string","null"]},"value_field":{"type":["string","null"],"description":"Feature property holding the magnitude used for styling (e.g. 'flow', 'minutes')."},"unit":{"type":["string","null"]},"provenance":{"$ref":"#/$defs/Provenance"},"geojson":{"description":"A GeoJSON FeatureCollection (WGS84). Kept permissive on purpose.","type":"object","required":["type","features"],"properties":{"type":{"const":"FeatureCollection"},"features":{"type":"array"}}}}},"City":{"type":"object","required":["id","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"name":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2, e.g. RO."},"admin_level":{"type":"string","description":"e.g. municipality, town, commune."},"population":{"type":["integer","null"],"minimum":0},"centroid":{"$ref":"#/$defs/Point"},"bbox":{"description":"[minLon, minLat, maxLon, maxLat] (WGS84).","type":"array","items":{"type":"number"},"minItems":4,"maxItems":4},"crs":{"type":"string","default":"EPSG:4326"},"provenance":{"$ref":"#/$defs/Provenance"}}},"Source":{"description":"A document, dataset or map layer the model was built from.","type":"object","required":["id","type","title"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"type":"string","enum":["document","open_data","map_layer","api","manual","other"]},"title":{"type":"string"},"url":{"type":["string","null"],"format":"uri"},"publisher":{"type":["string","null"]},"published":{"type":["string","null"],"description":"ISO date or year."},"retrieved":{"type":["string","null"],"format":"date"},"license":{"type":["string","null"]},"format":{"type":["string","null"],"description":"e.g. pdf, geojson, csv, wms."}}},"Zone":{"description":"An urban zone: neighbourhood, district, sector or any area unit.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"zone"},"name":{"type":"string"},"geometry":{"$ref":"#/$defs/Geometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"zone_type":{"type":["string","null"],"description":"e.g. residential, industrial, historic, mixed, green."},"population":{"type":["integer","null"],"minimum":0},"risk_level":{"$ref":"#/$defs/Severity"},"relations":{"type":"object","additionalProperties":false,"properties":{"contains_projects":{"$ref":"#/$defs/IdList"},"has_problems":{"$ref":"#/$defs/IdList"},"has_services":{"$ref":"#/$defs/IdList"},"measured_by_indicators":{"$ref":"#/$defs/IdList"}}}}},"Project":{"description":"A planned or ongoing urban project. Not a paragraph in a PDF, but a structured entity.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"project"},"name":{"type":"string"},"geometry":{"$ref":"#/$defs/Geometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"status":{"type":["string","null"],"description":"Stadiul proiectului. Vocabular granular (recomandat, din 2 aug 2026): propus, planificat, bugetat, contractat, in_executie, finalizat, anulat. Valorile vechi (proposed/planned/in_progress/completed/cancelled) rămân valide pentru compatibilitate cu modelele existente - mapare veche->nouă: proposed->propus, planned->planificat, in_progress->in_executie, completed->finalizat, cancelled->anulat (vezi semantic-model/validate.py, STATUS_MIGRATION_OLD_TO_NEW).","enum":["propus","planificat","bugetat","contractat","in_executie","finalizat","anulat","proposed","planned","in_progress","completed","cancelled",null]},"budget":{"$ref":"#/$defs/Money"},"deadline":{"type":["string","null"],"description":"ISO date or free text term."},"objectives":{"type":"array","items":{"type":"string"}},"relations":{"type":"object","additionalProperties":false,"properties":{"affects_zones":{"$ref":"#/$defs/IdList"},"addresses_problems":{"$ref":"#/$defs/IdList"}}}}},"PublicService":{"description":"A public service facility: school, clinic, transport stop, utility, etc.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"service"},"name":{"type":"string"},"geometry":{"$ref":"#/$defs/Geometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"service_type":{"type":["string","null"],"description":"e.g. education, health, transport, water, energy, waste, green."},"capacity":{"type":["number","null"]},"capacity_unit":{"type":["string","null"]},"address":{"type":["string","null"]},"has_deficit":{"type":["boolean","null"]},"relations":{"type":"object","additionalProperties":false,"properties":{"serves_zones":{"$ref":"#/$defs/IdList"}}}}},"UrbanProblem":{"description":"An identified urban problem, pressure or risk.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"problem"},"name":{"type":"string"},"geometry":{"$ref":"#/$defs/Geometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"category":{"type":["string","null"],"description":"e.g. mobility, climate, services, housing, environment, safety."},"severity":{"$ref":"#/$defs/Severity"},"relations":{"type":"object","additionalProperties":false,"properties":{"affects_zones":{"$ref":"#/$defs/IdList"},"addressed_by_projects":{"$ref":"#/$defs/IdList"}}}}},"Indicator":{"description":"A measured value that characterises a zone or the city and justifies decisions.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"indicator"},"name":{"type":"string"},"geometry":{"$ref":"#/$defs/Geometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"value":{"type":["number","string","null"]},"unit":{"type":["string","null"]},"period":{"type":["string","null"],"description":"ISO date, year or range."},"history":{"description":"Full measured series for this indicator, oldest first. value/period above always mirror the LATEST entry. Written by connectors on scheduled runs (v0.2) - this is the twin's memory.","type":"array","items":{"type":"object","required":["period","value"],"additionalProperties":false,"properties":{"period":{"type":"string","description":"ISO date, year or range this value covers."},"value":{"type":["number","string"]},"recorded_at":{"type":["string","null"],"format":"date-time","description":"When the value was (last) written by a connector."}}}},"relations":{"type":"object","additionalProperties":false,"properties":{"measures_zones":{"$ref":"#/$defs/IdList"}}}}},"Utr":{"description":"Unitate teritorială de referință (U.T.R.): bucata de oraș pentru care regulamentul local de urbanism stabilește aceleași reguli de construire. Aici stau POT, CUT, regimul de înălțime, retragerile și funcțiunile permise sau interzise, împreună cu documentul care le prevede. Entitate OPȚIONALĂ (v0.3): un model fără urbanism rămâne valid.","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"utr"},"name":{"type":"string","description":"Numele UTR-ului așa cum apare în plan, de exemplu „Centru - Cetate”."},"code":{"type":["string","null"],"description":"Codul UTR-ului din documentația de urbanism, de exemplu „I.1” sau „M.U.T.R. II”."},"geometry":{"$ref":"#/$defs/AreaGeometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"functional_subzone":{"type":["string","null"],"description":"Subzona funcțională din regulament care dă indicii de mai jos, de exemplu „LI1 - locuire tradițională urbană” sau „ID1 - zone industriale”."},"pot_max":{"type":["number","null"],"minimum":0,"maximum":100,"description":"Procentul maxim de ocupare a terenului (POT), în procente: cât din suprafața parcelei poate fi acoperită de construcție la sol. 40 înseamnă 40%."},"cut_max":{"type":["number","null"],"exclusiveMinimum":0,"description":"Coeficientul maxim de utilizare a terenului (CUT): suprafața desfășurată maximă raportată la suprafața parcelei. Valoare fără unitate, de obicei între 0,3 și 4."},"psp_min":{"type":["number","null"],"minimum":0,"maximum":100,"description":"Procentul minim de spații plantate pe parcelă (PSP), în procente."},"height_max_m":{"type":["number","null"],"minimum":0,"description":"Regimul de înălțime exprimat în metri (înălțimea maximă admisă a clădirii)."},"height_max_levels":{"type":["number","null"],"minimum":0,"description":"Regimul de înălțime exprimat în niveluri supraterane. Poate fi fracționar, pentru că unele regulamente reglementează „numărul maxim de niveluri întregi” (de exemplu 1,6)."},"setbacks":{"description":"Retragerile minime obligatorii ale construcției față de limitele parcelei, în metri. Câmp lăsat gol când regulamentul nu dă o valoare unică, ci o regulă (bandă de construibilitate, jumătate din înălțime etc.).","type":["object","null"],"additionalProperties":false,"properties":{"front_m":{"type":["number","null"],"minimum":0,"description":"Retragerea față de aliniament (strada)."},"side_m":{"type":["number","null"],"minimum":0,"description":"Retragerea față de limitele laterale."},"rear_m":{"type":["number","null"],"minimum":0,"description":"Retragerea față de limita din spate."},"note":{"type":["string","null"],"description":"Regula, când nu se poate reduce la cifre."}}},"allowed_uses":{"type":"array","items":{"type":"string"},"description":"Funcțiunile permise, în cuvintele regulamentului (locuire individuală, comerț, servicii, învățământ etc.)."},"forbidden_uses":{"type":"array","items":{"type":"string"},"description":"Funcțiunile interzise."},"regulation_source":{"description":"Documentul de urbanism din care vin regulile și locul exact din el. Fără asta, un indicator urbanistic nu se poate apăra în fața nimănui.","type":["object","null"],"required":["document"],"additionalProperties":false,"properties":{"document":{"type":"string","description":"Denumirea documentului, de exemplu „Regulament Local de Urbanism aferent P.U.G. Municipiul Brașov”."},"article":{"type":["string","null"],"description":"Articolul, capitolul sau anexa, de exemplu „art. 3.2.1, subzona LI1”."},"url":{"type":["string","null"],"format":"uri"},"approved":{"type":["string","null"],"description":"Actul de aprobare (de exemplu „H.C.L. 144/2011”) sau, dacă documentul nu e aprobat, starea lui: „în consultare publică”."},"in_force":{"type":["boolean","null"],"description":"Adevărat doar dacă documentul este în vigoare. Un regulament aflat în consultare nu poate sta la baza unui certificat de urbanism."}}},"relations":{"type":"object","additionalProperties":false,"properties":{"covers_zones":{"$ref":"#/$defs/IdList"},"contains_parcels":{"$ref":"#/$defs/IdList"}}}}},"Parcel":{"description":"Parcelă (imobil): terenul pe care se verifică efectiv un proiect față de regulamentul UTR-ului în care se află. Entitate OPȚIONALĂ (v0.3).","type":"object","required":["id","type","name"],"additionalProperties":false,"properties":{"id":{"$ref":"#/$defs/Id"},"type":{"const":"parcel"},"name":{"type":"string","description":"Cum se numește parcela în vorbire: adresa, denumirea imobilului sau numărul cadastral."},"geometry":{"$ref":"#/$defs/AreaGeometry"},"tags":{"type":"array","items":{"type":"string"}},"provenance":{"$ref":"#/$defs/Provenance"},"area_sqm":{"type":["number","null"],"minimum":0,"description":"Suprafața terenului, în metri pătrați."},"utr":{"$ref":"#/$defs/IdOrNull","description":"UTR-ul în care se află parcela. Trebuie să fie id-ul unui UTR existent în model."},"address":{"type":["string","null"],"description":"Adresa poștală, dacă se cunoaște."},"cadastral_number":{"type":["string","null"],"description":"Numărul cadastral / numărul de carte funciară, dacă se cunoaște. Gol înseamnă că parcela nu e legată de cadastru."},"existing_use":{"type":["string","null"],"description":"Funcțiunea existentă pe teren (locuire, comerț, industrie, spațiu verde, învățământ etc.). Nu se confundă cu funcțiunea permisă de regulament."},"ownership":{"type":["string","null"],"enum":["public","privat","mixt","necunoscut",null],"description":"Regimul de proprietate. „necunoscut” este un răspuns cinstit și se preferă unei presupuneri."},"public_owner":{"type":["string","null"],"description":"Cine deține terenul când e proprietate publică (municipiu, județ, stat, instituție)."},"relations":{"type":"object","additionalProperties":false,"properties":{"in_zones":{"$ref":"#/$defs/IdList"},"affected_by_projects":{"$ref":"#/$defs/IdList"}}}}},"Provenance":{"description":"Links a fact to its sources, separates fact from assumption, and records confidence. Core of evidence-first AI.","type":"object","additionalProperties":false,"properties":{"sources":{"description":"Ids of Source entries supporting this entity/fact.","$ref":"#/$defs/IdList"},"excerpts":{"description":"Optional verbatim snippets (with source id) that ground the extraction.","type":"array","items":{"type":"object","required":["source","text"],"additionalProperties":false,"properties":{"source":{"$ref":"#/$defs/Id"},"text":{"type":"string"},"locator":{"type":["string","null"],"description":"e.g. page 12, section 3.2."}}}},"confidence":{"type":"number","minimum":0,"maximum":1},"is_assumption":{"type":"boolean","default":false,"description":"True when the value is inferred by AI rather than stated in a source."},"note":{"type":["string","null"]}}},"GenerationMeta":{"type":"object","additionalProperties":false,"properties":{"generator":{"type":"string","description":"Tool/model that produced this model."},"generated_at":{"type":["string","null"],"format":"date-time"},"data_gaps":{"description":"Explicit list of what is missing. A first-class citizen, not a footnote.","type":"array","items":{"type":"string"}},"quality_score":{"type":["number","null"],"minimum":0,"maximum":1,"description":"Overall data-quality / completeness score for this twin."},"connector_runs":{"description":"Last successful SCHEDULED run per connector (name -> ISO date-time). Written by the server scheduler (v0.2); the Twin-sync panel reads real dates from here instead of static labels.","type":"object","additionalProperties":{"type":"string"}}}},"Id":{"type":"string","pattern":"^[a-z][a-z0-9_-]*:[a-z0-9][a-z0-9_-]*$","description":"Namespaced, human-readable identifier: <kind>:<slug>, e.g. zone:centru-istoric, project:pietonalizare-cetate, src:osm."},"IdList":{"type":"array","items":{"$ref":"#/$defs/Id"}},"IdOrNull":{"type":["string","null"],"pattern":"^[a-z][a-z0-9_-]*:[a-z0-9][a-z0-9_-]*$","description":"Un Id, sau null când legătura nu se cunoaște încă."},"Severity":{"type":["string","null"],"enum":["low","medium","high","critical",null]},"Money":{"type":["object","null"],"required":["amount","currency"],"additionalProperties":false,"properties":{"amount":{"type":"number","minimum":0},"currency":{"type":"string","description":"ISO 4217, e.g. EUR, RON."}}},"Point":{"type":["object","null"],"required":["type","coordinates"],"additionalProperties":false,"properties":{"type":{"const":"Point"},"coordinates":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2,"description":"[longitude, latitude] (WGS84)."}}},"AreaGeometry":{"description":"Geometrie de suprafață (GeoJSON, WGS84): o parcelă sau un UTR se desenează pe hartă ca poligon, nu ca punct. null cât timp conturul nu se cunoaște.","type":["object","null"],"required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Polygon","MultiPolygon"]},"coordinates":{}}},"Geometry":{"description":"Subset of GeoJSON geometry (WGS84). null when an entity has no spatial footprint yet.","type":["object","null"],"required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point","LineString","Polygon","MultiPoint","MultiLineString","MultiPolygon"]},"coordinates":{}}}}}