Site is where trials operate. The Site entity in TOP captures the physical/operational research site as a study-independent operational and feasibility entity — staff, equipment, IRB-of-record default, SFQ feasibility profile, infrastructure. The StudySite entity captures Site's role on a specific Study — the per-Study lifecycle, the per-Study Principal Investigator, the per-Study Delegation of Authority Log, the per-Study IRB approval, the per-Study contracts, and the entry point for Participants and Visit-occurrences at this Site for this Study. The operational chain is Site → StudySite → Study → Protocol → SOA → Visit → Activity. Site has very few direct edges; everything operational is reached via StudySite.
The shape lets a Site Coordinator query "show me my Site's open queries on Study ONCO-423" via Site → StudySite → Study traversal without polluting the Site entity with thousands of per-Study CRF/Visit/Query references. It lets a Sponsor PM query "across all my StudySites, where is enrollment behind target" with one StudySite-level scan. It lets the SFQ projection ("Site X's feasibility for Study Y") run directly off the Site's stable feasibility attributes. It anchors GCP discipline cleanly: R3 Section 2 obligations (qualification, delegation, IP management, records) live on StudySite where they're per-Study real; R3 Section 4.3 computerised-system obligations live on the linked System; Equipment carries calibration and qualification independent of any computerised layer.
Site spec extends the Sponsor spec template with five additions: an architectural-anchor section (the operational hierarchy), R3 alignment as a first-class section (Section 2 / 3 / 4 / Appendix C / Annex 2), an ISF alignment table mapping all 23 sections to TOP entities, a lifecycle state machine (separate for Site and StudySite), a persona-to-Site-view matrix covering ten roles, an SFQ projection as a named query template, and a delegation matrix. Site is the most operationally consequential top-level in the trials commons; the spec depth reflects that.
The operational chain runs from Site at the top of operations through StudySite (the per-Study pivot) down to Activity-occurrences during Visits:
Two sides, meeting at Visit. The definition side is top-down from Protocol: Protocol → SOA → Visit-template → Activity defines what is supposed to happen. The operational side is top-down from Site: Site → StudySite → Participant → Visit-occurrence → Activity-occurrence captures what actually happened at a specific Site for a specific Study.
This anchors three model decisions:
| Attribute | Type | Lens | Doc |
|---|---|---|---|
| siteId | ngsi-ld:URI | identity | Globally unique NGSI-LD identifier. |
| siteName | xsd:string | identity | Display name. |
| siteType | enum | identity | HOSPITAL · CLINIC · ACADEMIC_MEDICAL_CENTER · RESEARCH_CENTER · COMMUNITY_PRACTICE · DECENTRALIZED_HUB · VIRTUAL. |
| address, city, country, … | xsd:string | contact | Primary site address. 0..N for DECENTRALIZED_HUB; 1 for fixed-location. |
| gcpQualified | xsd:boolean | qualification | Site holds current GCP qualification (R3 Section 2.1). |
| therapeuticAreasExperienced | xsd:string | feasibility | Comma-separated TA experience array (oncology, cardiology, …). SFQ matching key. |
| indicationExperience | xsd:object | feasibility | Array of {indication, totalTrials, totalPatientsEnrolled} structured records. |
| averageEnrollmentRate | xsd:decimal | feasibility | Patients/month average across past trials. SFQ benchmark. |
| freezerCapacity | xsd:object | feasibility | Array of {tempRange, volume, units}. Sample-storage feasibility. |
| imagingCapabilities | enum array | feasibility | XRAY, CT, MRI, ULTRASOUND, PET, SPECT, ECHO, NUCLEAR_MEDICINE, MAMMOGRAPHY. |
| labCapabilities | enum array | feasibility | CLIA, CAP, CENTRAL, POINT_OF_CARE, SPECIALTY. |
| pharmacyOnSite, dctCapable, econsentCapable, eproCapable | xsd:boolean | feasibility | Capability booleans for SFQ matching. |
| edcVendorExperience | xsd:string | feasibility | Comma-separated array of EDC vendors the Site has experience with. Technology-readiness signal. |
| irbType | enum | regulatory default | CENTRAL · LOCAL · HYBRID. Per-Study IRB-of-record assignment lives on StudySite.hasIRB. |
| insuranceCarrier, insuranceCoverageAmount, insuranceCurrency, insuranceExpiry | mixed | insurance | Site-level professional liability / clinical-trial insurance. |
| subInvestigatorCount, coordinatorCount, studyNurseCount, labTechCount | xsd:integer | staff capacity | Aggregate counts. The actual roster lives on hasStaff. |
| languagesSupported | xsd:string | staff capacity | Comma-separated ISO 639-1 codes. |
| gcpTrainingCurrencyRate | xsd:decimal | staff capacity | 0.0–1.0 percentage of staff with current GCP training. SFQ signal. |
| Predicate | Target | Cardinality | Operational meaning |
|---|---|---|---|
| belongsToOrganization | Organization | 1..1 | Legal Organization that owns or operates this Site (e.g., MSKCC's Organization for the MSKCC main-campus Site). USDM Organization.managedSites is the inverse. |
| partOfSiteNetwork | Organization | 0..1 | SMO/network membership. Organization with organizationType=SITE_NETWORK or SMO. Site-network membership is study-independent. |
| parentSite | Site | 0..1 | Self-reference for satellite-of-main-site. Different from network membership. |
| hasStaff | Person | 0..N | Persons employed/affiliated at this Site, study-independent. Per-Study delegation lives on StudySite.delegatesAuthorityTo. |
| hostsEquipment | Equipment | 0..N | Site-bound equipment (Equipment.equipmentBinding=SITE_BOUND). |
| hasStorageLocation | StorageLocation | 0..N | Freezer slots, refrigerator shelves, cabinet drawers, ambient pharmacy shelves. |
| usesSystem | System | 0..N | Site-operational Systems (Site's EMR, source-document repository, local pharmacy system) that exist regardless of Study. |
| hasInstitutionalDocument | Document | 0..N | Site-level study-independent essential records: licenses, CLIA certifications, accreditations, institutional SOPs. |
| hasInstitutionalCredential | Credential | 0..N | Site-level credentials (CLIA, JCAHO, ISO 9001, lab accreditations). |
| Attribute | Type | Doc |
|---|---|---|
| studySiteId | ngsi-ld:URI | Globally unique identifier for this Site-Study pair. |
| siteNumber | xsd:string | Site number assigned by Sponsor for this Study. |
| studySiteStatus | enum | PLANNED · IN_QUALIFICATION · ACTIVE · ON_HOLD · CLOSED. Per-Study lifecycle. |
| activationDate, deactivationDate | xsd:date | Activation = SIV completed, FPI possible. Deactivation = close-out done. |
| enrollmentTarget, actualEnrollment | xsd:integer | Per-Study targets and actuals. Aggregate (could be SPARQL-derived) but stored for view speed. |
| oversightTier | enum | LOW · MEDIUM · HIGH. R3 Section 3.10 risk-based monitoring tier per StudySite. Same Site can be HIGH on a complex oncology trial and LOW on a simple registry. |
| recruitmentPotential | xsd:integer | Per-protocol recruitment estimate. R3 Section 2.2. |
| staffingAdequate | xsd:boolean | Per-protocol staffing adequacy. R3 Section 2.2. |
| irbApprovalStatus, irbApprovalDate | enum, xsd:date | PENDING · APPROVED · WITH_CONDITIONS · EXPIRED · WITHDRAWN · DENIED. |
| regulatoryAuthorizationStatus | enum | NOT_REQUIRED · PENDING · APPROVED · EXPIRED · WITHDRAWN · DENIED. Per-jurisdiction. |
| essentialRecordsRetentionUntil | xsd:date | R3 Appendix C retention; per-Study because retention requirements vary by jurisdiction × Study type. |
| validFrom, validUntil | xsd:dateTime | NGSI-LD temporal: PI handoff, SoR transfer, etc. |
| Predicate | Target | Cardinality | Operational meaning |
|---|---|---|---|
| forSite | Site | 1..1 | The Site this StudySite participation belongs to. |
| forStudy | Study | 1..1 | The Study this Site is participating in. |
| hasPrincipalInvestigator | Person | 1..1 | Per-Study PI. R3 Section 2.1 GCP-required. Drawn from forSite.hasStaff. |
| delegatesAuthorityTo | Person | 1..N | Per-Study Delegation of Authority Log. R3 Section 2.3.3 GCP-required. |
| hasIRB | OversightBody | 1..N | Per-Study IRB(s)/IEC(s) of record. 1..N for multi-IRB cases. |
| submitsTo | RegulatoryAuthority | 0..N | Per-jurisdiction regulatory authorities. R3 Section 2.3.5 inspection right. |
| hasContract | Contract | 0..N | Site-level contracts: CTA, CDA, MTA, DTA. |
| hostsVisit | Visit | 0..N | Visit-occurrences at this Site for this Study (when Visit lifts; OOUX Visit→Site is a tracked correction). |
| hasParticipant | Participant | 0..N | Participants enrolled at this Site for this Study. |
| hasMonitoringVisit | MonitoringVisit | 0..N | Per-Study monitoring visits. |
| hasAudit | Audit | 0..N | Per-Study audits at this Site. |
| engagesVendor | Organization | 0..N | Per-Study Site-engaged vendors (R3 Section 2.3.4 documented agreements). Distinct from Sponsor-engaged vendors. |
| usesLaboratory | Organization | 0..N | Per-Study Site-engaged laboratories (Organization with organizationType=LABORATORY). |
| usesSystem | System | 0..N | Per-Study Systems (Sponsor-provisioned EDC, per-Study IRT, etc.). |
| reportsTo | Sponsor | 0..N | Per-Study reporting (R3 Sections 2.7, 2.13: safety, data, noncompliance). |
| hasEssentialRecord | Document | 0..N | Per-Study essential records (Document.essentialRecordPurpose set per R3 Appendix C). |
Five decisions shape the Site model. Each made in dialogue with the OOUX, USDM, ICH E6(R3), and ISF anchors; reversible if downstream evidence argues against.
The OOUX Site object listed both study-independent attributes (siteName, siteType, address, contact info, equipment, staff) and per-Study attributes (siteNumber, enrollmentTarget, IRB approval status, last monitoring visit date) on a single entity. This conflates two lenses. The Sponsor v0.1.4 closure resolved an analogous tension by making Sponsor per-Org-per-Study and pushing corporate-scope facts onto Organization. Site needs the same treatment: per-Study facts move to a new StudySite horizontal that captures the (Site, Study) pair, and Site itself stays as the stable operational and feasibility entity. Why two entities and not one: a Site exists with its staff, equipment, IRB-of-record default, qualifications, and infrastructure regardless of which Studies are active. Site selection (the SFQ feasibility lens) operates on Site facts; per-Study operational management operates on StudySite facts. Conflating them forces every per-Study record to denormalize Site facts and every Site record to denormalize per-Study facts — a maintenance and consistency disaster.
Trade-off: TOP carries one more entity than USDM (which has Organization + StudySite without a middle Site). The crosswalk is two-way: Site → usdm:Organization (with type=Code(Site)); StudySite → usdm:StudySite. Verified against the actual USDM v3 schema (cdisc-org/usdm src/usdm_model/study_site.py + organization.py): USDM's StudySite is minimal (id + name + label + description + country) and most operational facts live on Organization with type Code. TOP's three-tier (Organization + Site + StudySite) projects to USDM's two-tier cleanly and carries the operational richness USDM doesn't model.
The OOUX inverse view shows 36+ relationships pointing at Site from other objects (Visit → Site, Participant → Site, CRF → Site, Adverse Event → Site, etc.). Putting all 36+ as direct edges on Site would denormalize the schema and force every Site read to traverse a vast object graph. The Sponsor v0.1.1 cardinality realism pass made the analogous decision: keep direct relationships only for things that are Sponsor-scoped (Contracts, Budgets, Submissions, Audits at sponsor level); traverse via Study for things that are Study-scoped.
For Site, the discipline is: Site keeps direct edges only to study-independent facts (Organization, network, staff roster, equipment, storage, institutional documents/credentials, Site-operational Systems). Everything per-Study reaches through StudySite (Visit-occurrences, Participants, CRFs, Adverse Events, Samples, IP dispensations, monitoring visits, audits, contracts, IRB, regulatory authority, vendors, per-Study Systems). The OOUX Visit→Site and Participant→Site direct edges are flagged as corrections for when those top-levels lift; they should point at StudySite, not Site.
Trade-off: query authors writing "show me all queries on Site X" need to traverse Site → StudySite → … which is one more hop than a direct edge would be. Acceptable: the ergonomic cost is small (named query templates, see §11) and the schema compactness is large.
The original framing of "Site uses System X, Sponsor uses System Y" treated System as a two-layer (ownership / use) concept. Bo's eTMF insight sharpened it: a System has a third axis — what each role can see — even when ownership and use are resolved. The Sponsor genuinely may not know the URL of the Site's local source-document repository, even though they monitor data captured at the Site.
Initial framing treated visibility as a presentation-layer projection concern. ICH E6(R3) Section 3.9 (Sponsor oversight obligations under documented agreements) and Section 2.12 (Investigator/institution records responsibilities) reframed it as oversight, not visibility. The third axis is GCP-mandated responsibility allocation, which is a schema-level fact: Sponsor sees what Sponsor has agreement-grounded oversight over (R3 3.6, 3.9); Site sees what Site is GCP-responsible for (R3 2.12, 2.13). The schema captures who is responsible; presentation filters are a thin layer on top.
The three-relationship pattern on the System horizontal:
The Site-owned source-document repository case where Sponsor doesn't know the URL is correctly modeled as "no Sponsor-System triple" — there is no usedBy or oversightHeldBy from Sponsor's Organization. Schema-level truth, not presentation filter. This is much cleaner than the original "Sponsor's projection filters out the URL" framing.
In an investigator-initiated trial (IIT), the Investigator is the Sponsor. Memorial Sloan Kettering as both Site and Sponsor for a single-PI academic study is the canonical case. Two ways to model this: (a) introduce a special "isAlsoSponsor" relationship on Site, or (b) let the existing relationships handle it via the same Organization playing both roles.
Decision: (b). MSKCC's Organization plays both managesSite → Site:mskcc AND playsSponsorRole → Sponsor:mskcc-iit-onco-001-fda. The same Person is Site.hasStaff AND Sponsor.primaryContactId. Sponsor.sponsorType=ACADEMIC and Sponsor.isInitiator=true flag the academic IIT. No new schema relationship required: the role conflation is captured by entity reuse rather than special-cased predicates.
Critical: R3 Sponsor obligations under Section 3 do not relax in IITs. Section 3.10 quality management, Section 3.11 monitoring, Section 3.13 safety reporting, Section 3.14 insurance, Section 3.6 documented agreements with service providers — all still apply when the Investigator is the Sponsor. Keeping the Sponsor entity present (rather than collapsing it into Site) preserves auditability of these obligations. Underrepresentation of these obligations in IITs is a known regulatory risk; the schema makes them visible.
SHACL invariant 9 (System sponsor-critical oversight) carries an IIT exception: when the SITE-type Organization that holds oversight on a sponsor-critical System also plays a Sponsor role on a Study using that System (via playsSponsorRole + matching Study), the violation does not fire. Encoded as FILTER NOT EXISTS in the SPARQL constraint.
Modern Equipment (refrigerators, freezers, centrifuges) often contains a computerised System component (IoT temperature monitors, audit-trail-enabled firmware). Three options were considered: (a) collapse Equipment into System; (b) collapse System into Equipment; (c) keep them distinct and link via a relationship.
Decision: (c). Equipment is the physical asset under R3 qualification/calibration/maintenance discipline; System is the computerised layer under R3 Section 4.3 validation/audit-trail/security/access-control discipline. They link via Equipment.monitoredBySystem → System. The temperature log itself is a third entity: Log{logType=IP_STORAGE_TEMPERATURE, forEquipment=freezer, forSystem=monitor, forStudySite=…}. Three entities working together rather than two conflated.
Trade-off: a simple lab fridge with no monitoring is just Equipment (no System triple, no Log triple). An IoT-monitored freezer is Equipment + System + Log. Operators don't pay for the System/Log discipline when they don't need it; they get it cleanly when they do.
ICH E6(R3) Step 4 Final (January 2025) supersedes R2 and is the current GCP standard. The Site model anchors to R3 throughout: Section 2 (Investigator responsibilities) defines what a Site IS; Section 3 (Sponsor responsibilities) grounds the System three-axis decision; Section 4 (Data Governance) shapes the System horizontal's attribute set; Appendix C (Essential Records) drives the Document.essentialRecordPurpose taxonomy; Annex 2 frames decentralized modalities.
| R3 § | Topic | How TOP encodes it |
|---|---|---|
| 2.1 | Qualifications and training | StudySite.hasPrincipalInvestigator → Person (1..1, GCP-required). Person.gcpTrainingStatus + Person.hasCredential. Site.gcpQualified for institution-level qualification. |
| 2.2 | Resources (recruitment, staff, facilities) | Site.facilitiesAdequate, Site.subInvestigatorCount, Site.coordinatorCount, etc. Per-protocol adequacy lives on StudySite.staffingAdequate and StudySite.recruitmentPotential. |
| 2.3.1–2.3.2 | Delegation oversight | StudySite.delegatesAuthorityTo → Person (1..N, GCP-required). Investigator retains ultimate responsibility (modeled by hasPrincipalInvestigator's mandatory cardinality). |
| 2.3.3 | Delegation record | StudySite.delegatesAuthorityTo carries role/scope/dates. SHACL invariant 8: ACTIVE StudySite must have ≥1 delegation entry. |
| 2.3.4 | Service-provider agreements | StudySite.engagesVendor → Organization (R3 2.3.4 documented agreements), StudySite.usesLaboratory → Organization (Lab agreements). StudySite.hasContract → Contract (CTA, CDA). |
| 2.3.5 | Permit monitoring/audit/inspection | StudySite.hasMonitoringVisit, StudySite.hasAudit, StudySite.submitsTo → RegulatoryAuthority (inspection right anchored here). |
| 2.4 | IRB/IEC communication | StudySite.hasIRB → OversightBody (1..N). Per-Study, multi-IRB cases supported. |
| 2.5 | Protocol compliance | StudySite.forStudy → Study → hasProtocol → Protocol. Implicit through participation. |
| 2.6 | Premature termination | StudySite.studySiteStatus enum (PLANNED → IN_QUALIFICATION → ACTIVE → ON_HOLD → CLOSED). StudySite.deactivationDate. |
| 2.7 | Participant care + safety reporting | StudySite.reportsTo → Sponsor (safety, data, noncompliance). StudySite.hasParticipant traversal for participant-level data. |
| 2.8 | Informed consent | StudySite.hasParticipant → Participant → InformedConsent (when those lift; flagged-missing today). |
| 2.9 | End of participation | Through StudySite traversal to Participant lifecycle (when Participant lifts). |
| 2.10 | IP management | StudySite usesSystem traversal to IRT; Equipment for storage; Log{logType=IP_DISPENSING, IP_ACCOUNTABILITY}; StorageLocation for IP storage. |
| 2.11 | Randomization/unblinding | StudySite.usesSystem (per-Study IRT). Document{documentType=BLINDING_PROCEDURES}. |
| 2.12 | Records (essential) | StudySite.hasEssentialRecord → Document (with essentialRecordPurpose + responsibleParty=INVESTIGATOR_INSTITUTION). |
| 2.13 | Reports | StudySite.reportsTo → Sponsor; Document{documentType=MONITORING_REPORT, AUDIT_REPORT, etc.}. |
R3 Section 3 grounds the Sponsor side of the Site relationship. Key touchpoints:
R3 Section 4 maps directly onto the System horizontal:
| R3 § | Topic | System attribute / relationship |
|---|---|---|
| 4.1 | Blinding safeguards | System.systemType=IRT carries blinding-procedures aspects; Document{documentType=BLINDING_PROCEDURES}. |
| 4.2.1–4.2.8 | Data lifecycle (capture → destruction) | Log entries record the lifecycle stages; System.auditTrailEnabled flags audit-trail capability per R3 4.2.2. |
| 4.3.1 | Procedures | System.proceduresDocumentRef → Document. |
| 4.3.2 | Training | Person.hasTrainingRecord → TrainingRecord (when TrainingRecord lifts; flagged-missing today). |
| 4.3.3 | Security | System.securityAssessmentRef → Document. |
| 4.3.4 | Validation (risk-based) | System.validationStatus (NOT_VALIDATED · IN_VALIDATION · VALIDATED · REVALIDATING · RETIRED), System.validationApproach (RISK_BASED · FULL_VALIDATION · VENDOR_QUALIFICATION_ONLY), System.lastValidationDate. |
| 4.3.5 | System release | System.releaseStatus (DEVELOPMENT · UAT · PRODUCTION · REVALIDATING · RETIRED). |
| 4.3.6 | Failure contingencies | System.contingencyPlanRef → Document. |
| 4.3.7 | Technical support | System.supportContact → Person. |
| 4.3.8 | User management / access controls | System.accessControlPolicyRef → Document. |
R3 Appendix C is the canonical record taxonomy, replacing R2's Section 8 prescriptive document list. Records are categorized by two axes:
The legacy ISF section taxonomy is captured in Document.isfSection as a free-text mapping; the operational continuity is preserved without making ISF the canonical primary axis.
R3 doesn't enumerate DCT modalities formally; it places decentralized aspects within the principles and Annex 1 applicability with proportionate/risk-based approaches. TOP's existing siteType enum (HOSPITAL, CLINIC, ACADEMIC_MEDICAL_CENTER, RESEARCH_CENTER, COMMUNITY_PRACTICE, DECENTRALIZED_HUB, VIRTUAL) is sufficient. The flexibility lives in how existing relationships are populated (a VIRTUAL Site has no fixed address; a DECENTRALIZED_HUB has 0..N addresses) rather than in a new enum.
The ISF section taxonomy is the legacy operational view that maps onto R3 Appendix C. Maintaining the alignment is operationally valuable — sponsors, CROs, and sites organize day-to-day artifacts against the ISF — but the canonical anchor is R3 Appendix C; ISF mappings are secondary.
The ISF reference used here is a 23-section TOC (sourced from a Singapore HSA-flavored ISF that mirrors the international ICH E6 essential-documents structure). Re-validate against the actual CDISC ISF Provisional v1 PDF when accessible — section names and counts may differ.
| ISF § | Artifact | TOP Path | Coverage |
|---|---|---|---|
| 1.1 | Site staff contact details | Site.hasStaff → Person | FULL |
| 1.2 | External vendor contact details | StudySite.engagesVendor → Organization | FULL |
| 2 | Investigator's Brochure (current + prior) | Document(documentType=INVESTIGATOR_BROCHURE) | FULL |
| 3.1, 3.2 | Protocol (current + prior) | Study → Protocol + Document versions | PARTIAL — Protocol horizontal not fully fleshed |
| 3.3 | Protocol Signature Page | Document(documentType=SIGNATURE_SHEET) | FULL |
| 4.1, 4.2 | ICF current + prior (with translations) | Document(documentType=ICF) + language attribute | FULL |
| 4.3 | Translation Certificates | Document(documentType=TRANSLATION_CERTIFICATE) | FULL |
| 4.4 | Signed ICFs (per Participant) | Traversal: StudySite.hasParticipant → Participant → InformedConsent | TRAVERSAL |
| 4.5 | Signed ICF Tracking Log | Aggregate query over Participant ICFs at this StudySite | TRAVERSAL |
| 5.1 | Patient Card / Diary / Questionnaires | Document(documentType=...) + Questionnaire (when lifts) | PARTIAL |
| 6 | Recruitment advertisement | Document(documentType=RECRUITMENT_AD) | FULL |
| 7.1, 7.2 | Blank CRF (current + prior) | CRF horizontal (not yet lifted) | GAP |
| 7.3 | CRF Completion Guidelines | Document | FULL |
| 7.4, 7.5 | Signed/completed CRFs + corrections | Traversal via Participant + Visit | TRAVERSAL |
| 8 | Source Documents | Document(documentType=SOURCE_DOCUMENT) | FULL |
| 9.1 | IRB Submission and Approval Documents | StudySite.hasIRB + Document(documentType=IRB_APPROVAL_LETTER) | FULL |
| 9.2–9.6 | IRB progress reports, composition, safety/non-compliance notifications, correspondences | Document for reports/letters; Log(logType=COMMUNICATION, correspondent → IRB Org) for correspondences; OversightBody.members for composition (when OversightBody lifts) | PARTIAL |
| 10.1–10.6 | Regulatory Authority (HSA/FDA/EMA/etc.) submissions, status reports, import permits, safety notifications, correspondences | StudySite.submitsTo → RegulatoryAuthority (when RegulatoryAuthority lifts) + Document + Log{COMMUNICATION} | PARTIAL — RegulatoryAuthority flagged-missing |
| 11.1 | Signature Sheet (Delegation of Authority) | StudySite.delegatesAuthorityTo → Person | FULL |
| 11.2 | CV of Study Personnel | Person.hasCredential → Credential(credentialType=CV) | FULL |
| 11.3 | Training Log | Log(logType=TRAINING) + Person.hasTrainingRecord (TrainingRecord flagged-missing) | PARTIAL |
| 12.1 | Confidentiality Agreement | Document(documentType=CDA) | FULL |
| 12.2 | Clinical Trial Agreement | Document(documentType=CTA) + StudySite.hasContract | FULL |
| 12.4 | Insurance Certificate | Document(documentType=INSURANCE_CERTIFICATE) + Site insurance attrs | FULL |
| 13.1–13.4 | Subject Logs (screening, enrolment, identification, visit tracking) | Either Log entries or aggregate queries over Participant + Enrollment | TRAVERSAL |
| 14.1 | IP Handling Instructions | Document(documentType=IP_HANDLING_INSTRUCTIONS) | FULL |
| 14.2 | IP Shipping/Receipt Records | Shipment horizontal (not yet lifted) | GAP |
| 14.3 | IP Dispensing/Accountability Logs | Log(logType=IP_DISPENSING, IP_ACCOUNTABILITY) | FULL |
| 14.4 | IP Destruction Documentation | Document(documentType=IP_DESTRUCTION_RECORD) | FULL |
| 14.5 | IP Storage Temperature Logs | Log(logType=IP_STORAGE_TEMPERATURE) + forEquipment + forSystem (the freezer-with-IoT-monitor pattern) | FULL |
| 15.1 | Decoding Procedures (blinded) | Document(documentType=BLINDING_PROCEDURES) | FULL |
| 16.1 | Site Visit Log (monitoring) | StudySite.hasMonitoringVisit → MonitoringVisit (flagged-missing) + Log(logType=MONITORING_VISIT) | PARTIAL |
| 16.2 | Visit Correspondences | Log(logType=COMMUNICATION) | FULL |
| 17.1 | Lab normal values/ranges | Document(documentType=LAB_NORMAL_RANGES) + StudySite.usesLaboratory | FULL |
| 17.2 | Lab Certification/Accreditation | Lab Org → hasInstitutionalCredential → Credential(credentialType=CLIA_CERTIFICATION, etc.) | FULL |
| 18.1 | Biological Sample Handling Log | Log(logType=SAMPLE_HANDLING) | FULL |
| 18.2 | Sample Handling Manual | Document(documentType=SAMPLE_HANDLING_MANUAL) | FULL |
| 18.3 | Sample Shipping Records | Log(logType=SAMPLE_SHIPPING) + Shipment (when lifts) | PARTIAL |
| 19.1 | SAE Tracking Log | Log(logType=SAE_TRACKING) + Participant traversal (when Participant lifts) | TRAVERSAL |
| 19.2, 19.3 | SAE Reports + Expedited Safety Reports | Document + RegulatorySubmission (already in source) | FULL |
| 20 | Study Reports / Publications | Document(documentType=MONITORING_REPORT, AUDIT_REPORT) + Sponsor.publishesPublication | FULL |
| 21.1, 21.2, 21.3 | Investigator/SIV/Other Meeting documentation | Investigator Meeting needs Meeting horizontal (gap); SIV maps to MonitoringVisit{visitType=SITE_INITIATION} (when MonitoringVisit lifts). | PARTIAL |
| 22.1–22.4 | Correspondences (Sponsor, Site Staff, Lab/Vendors, Other) | Log(logType=COMMUNICATION, correspondent → Org) | FULL |
| 23 | Miscellaneous | Document (catchall) | FULL |
Coverage summary: ~28 ISF subsections fully covered, ~9 partial (mostly waiting for flagged-missing horizontals: MonitoringVisit, RegulatoryAuthority, TrainingRecord, OversightBody, Shipment), ~2 explicit gaps (CRF horizontal, Meeting horizontal — neither lifts in v0.2.0; tracked).
The Site itself doesn't really have a strong lifecycle — it's a research facility that exists across studies. Site.status is a coarse-grained ACTIVE / INACTIVE / RETIRED enum. The interesting lifecycle is StudySite (per-Study).
| Transition | Trigger | SHACL guards |
|---|---|---|
| PLANNED → IN_QUALIFICATION | Site selected; SIV scheduled | StudySite must have forSite + forStudy populated. |
| IN_QUALIFICATION → ACTIVE | Site Initiation Visit completed; IRB approval; first patient possible | SHACL invariant 7: ACTIVE requires hasPrincipalInvestigator. SHACL invariant 8: ACTIVE requires ≥1 delegatesAuthorityTo entry. (Implicit: irbApprovalStatus should be APPROVED before ACTIVE — recommended SHACL addition in v0.3.) |
| ACTIVE ↔ ON_HOLD | Sponsor or Site initiates pause (safety hold, IRB suspension, recruitment pause) | Bidirectional. ON_HOLD must retain hasPrincipalInvestigator; staffing requirements relax. |
| ACTIVE / ON_HOLD → CLOSED | Close-out visit completed; all participants discontinued; essential records archived | deactivationDate must be populated. essentialRecordsRetentionUntil must be populated. |
| CLOSED → (any) | Disallowed. | Once a StudySite closes, it stays closed. Re-opening creates a new StudySite with new identifiers. |
Memorial Sloan Kettering runs Pfizer's ONCO-423 trial. MSKCC is a single Site (HOSPITAL type) with one PI, one IRB of record, one CTA.
Elevate Research is an SMO with three locations (Boston, Phoenix, Miami), all participating in the same Pfizer ONCO-423 trial. Three Sites under one Organization.
Dr. Kim at MSKCC runs IIT-ONCO-001 with departmental funds. MSKCC is both Site and Sponsor; Dr. Kim is both PI on Site and primary contact on Sponsor.
Curebase operates a virtual decentralized hub (siteType=DECENTRALIZED_HUB) for a multi-region asthma trial. No fixed address; participants in three US states are managed remotely.
Site-X's original PI Dr. Adams retires on 2026-04-01; Dr. Brown takes over. The same StudySite continues, with two hasPrincipalInvestigator triples bracketed by validFrom / validUntil.
MSKCC running Pfizer's ONCO-423 uses two eTMF-class systems: Pfizer's Veeva Vault (Sponsor-operated) for the central eTMF, and MSKCC's local Iron Mountain repository for the institutional ISF.
MSKCC's pharmacy-grade -80°C freezer F-12 is cloud-monitored by SaaS provider StratoMon. Continuous temperature readings are appended to a Log entity tied to both the Equipment and the System.
Site-Y closes its participation on Study X (low enrollment, sponsor cuts). studySiteStatus moves ACTIVE → CLOSED with a deactivationDate. essentialRecordsRetentionUntil populated.
Reads: StudySite for current participation status; hostsVisit for today's visits; hasParticipant for enrolled participants; delegatesAuthorityTo to confirm own role/scope. Writes: visit completion, CRF entries (per Visit), Discrepancy responses.
Reads: full StudySite scope including Adverse Event traversal, Audit findings, Monitoring visit outcomes, Delegation Log. Signs: protocol signature page (FORM_1572), CRFs (verification), AE assessments, ICFs (witness).
Reads: scope-restricted StudySite view per Delegation Log entry; read-write access to assigned Participant subset.
Reads: Site.hasStorageLocation (pharmacy storage), Equipment(equipmentClass=FREEZER, REFRIGERATOR), Log(logType=IP_DISPENSING, IP_ACCOUNTABILITY, IP_STORAGE_TEMPERATURE). Writes: IP Dispensing Log entries, IP Accountability Log entries.
Reads: StudySite.hostsVisit for sample collection schedule; Site.hasStorageLocation + Equipment(CENTRIFUGE, etc.). Writes: Sample Handling Log, Sample Shipping Log entries.
Reads: StudySite for sites I monitor (filter by Sponsor.engages and own assignment); hasMonitoringVisit; hasParticipant traversal for SDV; Discrepancy aggregates per StudySite. Writes: MonitoringVisit findings, Action Items.
Reads: aggregated StudySite.actualEnrollment / enrollmentTarget, studySiteStatus distribution, last MonitoringVisit dates. Site-level rollup via forSite + partOfSiteNetwork.
Reads: All StudySites where forSite → Site → partOfSiteNetwork → Organization:my-smo. Group by Sponsor.belongsToOrganization for sponsor-portfolio map; group by therapeutic area for indication-portfolio map.
Reads: StudySite.delegatesAuthorityTo (Delegation Log), hasPrincipalInvestigator + Person.hasCredential, hasEssentialRecord → Document(essentialRecordPurpose=...). Plus per-System validation status. R3 Section 2.3.5 grounds the inspection right; SHACL invariants 7+8 enforce the data shape.
Reads: scope per Audit assignment; full StudySite visibility plus traversal to Participant-level data. Writes: Audit findings, CAPA requests.
GET /entities?type=Discrepancy &q=relatedStudy=="urn:ngsi-ld:Study:ONCO-423" &q=relatedSite=="urn:ngsi-ld:Site:mskcc-main" &q=queryStatus=="OPEN" &options=keyValues
GET /entities?type=StudySite &q=forStudy=="urn:ngsi-ld:Study:ONCO-423" &q=studySiteStatus=="ACTIVE" &options=keyValues # Then client-side filter: actualEnrollment / enrollmentTarget < 0.7
GET /entities?type=StudySite &q=forStudy=="urn:ngsi-ld:Study:ONCO-423" &q=oversightTier=="HIGH" &q=lastMonitoringVisitDate<"2026-02-08" &options=keyValues
GET /entities?type=StudySite &q=studySiteStatus=="ACTIVE" &q=forSite.partOfSiteNetwork=="urn:ngsi-ld:Organization:elevate-research" &options=keyValues # Client-side: traverse forStudy → engages_inverse → Sponsor
GET /entities?type=StudySite &q=forSite=="urn:ngsi-ld:Site:mskcc-main" &q=forStudy=="urn:ngsi-ld:Study:ONCO-423" &options=sysAttrs # Then for each Person in delegatesAuthorityTo: GET /entities?type=Person&id=<personId>&options=keyValues GET /entities?type=Credential&q=forPerson==<personId>
GET /entities?type=Document &q=hasEssentialRecord_inverse=="urn:ngsi-ld:StudySite:mskcc-onco423" &options=keyValues # Group by essentialRecordPurpose
The Site Feasibility Questionnaire (SFQ) is the canonical sponsor-selection artifact. Sponsor portfolio teams use SFQs to qualify Sites for upcoming Studies. The SFQ projection is a named query template that runs against the Site's stable feasibility attributes — no per-Study data needed.
QUERY SiteFeasibilityProjection(siteId) RETURNS FROM Site WHERE Site.siteId = $siteId: -- Identity siteId, siteName, siteType, address, country -- Therapeutic / population fit therapeuticAreasExperienced, indicationExperience, patientPopulationAccess -- Past trial experience (benchmarks) totalTrialsConducted, trialsByPhase, averageEnrollmentRate, firstPatientInToActivationDays, queryResponseTimeHours, sponsorRetentionRate -- Infrastructure freezerCapacity, imagingCapabilities, labCapabilities, pharmacyOnSite, dctCapable, econsentCapable, eproCapable, edcVendorExperience -- Regulatory / ethics defaults irbType, typicalIrbApprovalDays, regulatoryAuthorityExperience, sopsAvailable, sopLibrarySize -- Insurance insuranceCarrier, insuranceCoverageAmount, insuranceCurrency, insuranceExpiry -- Staff capacity subInvestigatorCount, coordinatorCount, regulatoryCoordinatorCount, studyNurseCount, labTechCount, languagesSupported, gcpTrainingCurrencyRate -- Network membership (for SMO sites) partOfSiteNetwork → Organization (organizationName, organizationType) -- Equipment summary (for infrastructure verification) hostsEquipment[equipmentClass IN (FREEZER, CENTRIFUGE, ECG_MACHINE, MRI, ...)] RETURN AS JSON-LD with @context: top-clinical-trials
The projection contains zero per-Study data. A Sponsor portfolio team can score the Site for fit without entering a CTA, signing CDAs, or escalating engagement — the SFQ projection IS the qualification surface. Once the Site qualifies, a StudySite is created with the per-Study scope and engagement begins. Versioning the SFQ projection (capturing the exact attribute values at SFQ submission time) is a v0.3 enhancement; the projection runs on current Site state for v0.2.0.
R3 Section 2.3.3 GCP-requires a Delegation of Authority Log: "the investigator should ensure a record is maintained of the persons and parties to whom the investigator has delegated trial-related activities." TOP encodes this as StudySite.delegatesAuthorityTo → Person with role/scope/temporal attributes carried on the relationship.
| Role | Typical scope | R3 grounding | Common scope restrictions |
|---|---|---|---|
| PRINCIPAL_INVESTIGATOR | Full GCP responsibility | R3 2.1, 2.3.1 | None (PI retains ultimate responsibility) |
| SUB_INVESTIGATOR | Medical decisions, AE assessment | R3 2.3.1, 2.3.2 | Cannot sign 1572 (PI only); cannot delegate further |
| STUDY_COORDINATOR | Operational management, Visit scheduling, ICF administration | R3 2.3.1 | No medical decisions; no IP dispensing without separate delegation |
| REGULATORY_COORDINATOR | IRB submissions, regulatory authority correspondences | R3 2.4 | Limited to administrative regulatory activities |
| PHARMACIST | IP dispensing, accountability, storage, destruction | R3 2.10 | Restricted to IP-related activities |
| STUDY_NURSE | Visit conduct, sample collection, vital signs, participant care | R3 2.7 | Per nursing scope of practice |
| LAB_TECH | Sample processing, lab tests, shipping | R3 2.10 (samples) | Lab activities only |
| DATA_ENTRY | CRF entry from source documents | R3 4.2.1 | Restricted to administrative data entry; cannot SDV |
| SOURCE_DATA_VERIFIER | SDV against source documents | R3 4.2.3 | Restricted to verification; cannot enter or correct data |
Each delegatesAuthorityTo triple carries a role enum (one of the above), a validFrom/validUntil temporal pair, and an optional scope restriction (free-text or structured). When Person, PersonRole, or DelegationRecord lift to richer entities in v0.3, the role can move from a relationship attribute to a structured PersonRole entity with full audit trail.
| Operator phrasing | Translated query shape | Discriminating predicate |
|---|---|---|
| "Show me Site X's profile" | type=Site & siteId==X | Site identity |
| "Is Site X currently active on Study Y?" | type=StudySite & forSite==X & forStudy==Y & studySiteStatus=="ACTIVE" | studySiteStatus |
| "Who's the PI at Site X for Study Y?" | type=StudySite & forSite==X & forStudy==Y → hasPrincipalInvestigator | StudySite.hasPrincipalInvestigator |
| "Where is enrollment behind target?" | type=StudySite & studySiteStatus=="ACTIVE" & ratio of actualEnrollment/enrollmentTarget < threshold | StudySite enrollment attrs |
| "Which sites have done oncology trials?" | type=Site & therapeuticAreasExperienced contains "ONCOLOGY" | Site.therapeuticAreasExperienced |
| "Sites in the Elevate Research network" | type=Site & partOfSiteNetwork=="urn:ngsi-ld:Organization:elevate-research" | Site.partOfSiteNetwork |
| "Where can we run a -80°C freezer trial?" | type=Site & freezerCapacity contains tempRange="-80C" | Site.freezerCapacity |
| "Sites that have used Veeva Vault" | type=Site & edcVendorExperience contains "Veeva" | Site.edcVendorExperience |
| "Active sites with HIGH oversight tier" | type=StudySite & studySiteStatus=="ACTIVE" & oversightTier=="HIGH" | StudySite.oversightTier |
| "Sites without a current PI" | type=StudySite & studySiteStatus=="ACTIVE" & NOT EXISTS hasPrincipalInvestigator (SHACL violation) | SHACL invariant 7 |
| "Show me the Delegation Log for Site X on Study Y" | type=StudySite & forSite==X & forStudy==Y → delegatesAuthorityTo | StudySite.delegatesAuthorityTo |
| "Who's monitoring this site?" | type=MonitoringVisit (when lifts) & forStudySite==SS-X-Y; or traverse Sponsor.engages_inverse | MonitoringVisit (lift pending) |
| "What freezer is sample S in?" | type=Sample (when lifts) & sampleId==S → atStorageLocation → inEquipment | StorageLocation.inEquipment chain |
| "Site's calibration status on freezer F-12" | type=Equipment & equipmentId==F-12 → hasCredential & credentialType=="CALIBRATION_CERTIFICATE" | Equipment.hasCredential |
The pattern that earns its keep: operator questions about Site decompose to either Site (study-independent) or StudySite (per-Study) plus one or two attribute or relationship constraints. Site-level questions about feasibility/capability never need to traverse to per-Study data; per-Study questions never need to reach back into Site-level feasibility. The split is paying for itself in NLP tractability.
The SHACL shapes in shapes/clinical-trials-shapes.ttl are emitted from the source intermediate by tools/build_shacl.py. The full graph (Sponsor + Study + Site + 9 horizontals) emits 14 NodeShapes and 290 property shapes. Domain invariants are encoded as sh:SPARQLConstraint shapes (validated by pyshacl in --advanced mode).
| # | Invariant | Severity |
|---|---|---|
| 1 | Sponsor: isSponsorOfRecord=true should imply hasRegulatoryResponsibility=true (21 CFR 312.52 transfer-of-obligations exception permitted). | sh:Warning |
| 2 | Sponsor: every Study must have ≥1 Sponsor with isSponsorOfRecord=true. | sh:Violation |
| 3 | Sponsor: at most one Sponsor with isSponsorOfRecord=true per (Study × jurisdiction). | sh:Violation |
| 4 | Sponsor: every Study must have ≥1 Sponsor with hasOperationalResponsibility=true. | sh:Violation |
| 5 | Site: siteType=DECENTRALIZED_HUB requires belongsToOrganization populated. A decentralized hub still needs a legal Organization to anchor regulatory and contractual responsibility. | sh:Violation |
| 6 | Site: partOfSiteNetwork target Organization must have organizationType ∈ {SITE_NETWORK, SMO}. Catches modeling errors where partOfSiteNetwork points at a SPONSOR or VENDOR. | sh:Violation |
| 7 | StudySite: studySiteStatus=ACTIVE requires hasPrincipalInvestigator. R3 Section 2.1 GCP-required. | sh:Violation |
| 8 | StudySite: studySiteStatus=ACTIVE requires ≥1 delegatesAuthorityTo entry. R3 Section 2.3.3 GCP-requires the Delegation of Authority Log. | sh:Violation |
| 9 | System: sponsor-critical (EDC/CTMS/IRT/SAFETY_DB) cannot have SITE-type Organization as oversightHeldBy under R3 Section 3.9. IIT exception: encoded as FILTER NOT EXISTS over the Site=Sponsor case (same Org plays both managesSite and playsSponsorRole on a Study using this System). | sh:Violation |
| 10 | Credential: exactly one of forPerson, forSite, forEquipment must be populated. Polymorphic-target discipline; no multi-target bindings. | sh:Violation |
| Invariant | Status |
|---|---|
| StudySite: hasPrincipalInvestigator must be drawn from forSite.hasStaff. Requires cross-entity traversal in SPARQL. | v0.3 |
| StudySite: delegatesAuthorityTo Persons must each be drawn from forSite.hasStaff. Requires cross-entity traversal. | v0.3 |
| StudySite: irbApprovalStatus should be APPROVED before studySiteStatus moves to ACTIVE. | v0.3 (lifecycle guard) |
| StudySite: deactivationDate must be populated when studySiteStatus=CLOSED. | v0.3 |
| Site: parentSite must not form a cycle (transitive). Hard to express in SPARQL. | Optional, low priority |
| Sponsor-engaged service provider: when Sponsor engages a vendor (via CRO or Service relationships) AND the StudySite uses that vendor, a Site-side documented agreement should exist (R3 2.3.4). Cross-entity invariant; SPARQL complex. | v0.3 |
| Standard | Site | StudySite | Notes |
|---|---|---|---|
| FHIR R5 | fhir:Organization | fhir:ResearchStudy.site | FHIR collapses Site into Organization with no separate per-Study site entity. Projection: TOP Site → FHIR Organization (with type code); TOP StudySite → FHIR ResearchStudy.site (a CodeableReference). |
| USDM v3 | usdm:Organization (with type=Code(Site)) | usdm:StudySite | USDM has no operational-Site entity; StudySite is minimal (id+name+description+country). TOP carries substantially more on both Site and StudySite. Verified against cdisc-org/usdm study_site.py + organization.py. |
| CDISC CDASH v2.1 | cdash:DM.SITEID | (traversed via Participant) | CDASH is participant/visit-form-level; Site appears as a SITEID variable on demographics CRF. |
| ICH E6(R3) | Annex 1 §2 (Investigator/Institution) | Annex 1 §2.3 (per-Study delegation), Appendix C (Essential Records, INVESTIGATOR_INSTITUTION-owned) | R3 doesn't have a Site entity per se; the Investigator/Institution is the GCP-responsible party. TOP's Site/StudySite split honors R3's responsibility allocation cleanly. |
| ICH/GCP Investigator Site File | (institutional records: §1.1, §11.2, §17.2, §18.2) | (per-Study records: §1.2, §3.3, §4.1, §11.1, §12, §13, §14, §16, §19, §22) | ISF section taxonomy maps onto TOP via Document.isfSection (legacy operational view) and Document.essentialRecordPurpose (R3 canonical). Full alignment table in §6. |
| W3C PROV | prov:Agent / prov:Location | prov:Activity with role bindings | PROV models Site as either a Location-class Agent or as Organization-class Agent. StudySite participation is a PROV Activity with the Investigator as prov:Agent. |
| NCIt | NCIT:C16696 (Clinical Site) | NCIT:C42850 (Clinical Trial Site) | NCIt distinguishes the institutional clinical site from the per-trial role; matches TOP's Site/StudySite split semantically. |
Items called out for resolution before v0.1 of the clinical-research reference graph publishes. Each is tracked; none block the architectural decisions in §4.
| Issue | Status | Owner |
|---|---|---|
| OOUX Visit→Site direct edge correction. OOUX has Visit pointing at 1 Site; should be 1 StudySite. Surfaces when Visit lifts. | Tracked | Visit lift |
| OOUX Participant→Site direct edge correction. Same pattern as Visit. | Tracked | Participant lift |
| Visit template-vs-occurrence split. OOUX Visit conflates the protocol-defined visit template (SOA Item) with the participant-realized visit occurrence. Either two entities or a discriminator on Visit is required. | Tracked | Visit lift |
| OversightBody horizontal not yet in TOP source. StudySite.hasIRB target is flagged-missing; SHACL minCount relaxes to 0 until lift. | v0.3 | Working group |
| RegulatoryAuthority horizontal not yet in TOP source. StudySite.submitsTo, Sponsor.regulatoryAuthorityScope target flagged-missing. | v0.3 | Working group |
| Contract horizontal not yet in TOP source. StudySite.hasContract flagged-missing. | v0.3 | Working group |
| MonitoringVisit horizontal not yet in TOP source. StudySite.hasMonitoringVisit flagged-missing. | v0.3 | Working group |
| Audit horizontal not yet in TOP source. StudySite.hasAudit flagged-missing. | v0.3 | Working group |
| TrainingRecord horizontal not yet in TOP source. Person.hasTrainingRecord flagged-missing. | v0.3 | Working group |
| Enrollment horizontal not yet in TOP source. | v0.3 | Working group |
| StudyStartupPackage horizontal not yet in TOP source. | v0.3 | Working group |
| Document.essentialRecordPurpose enum is currently a 7-value placeholder. Full R3 Appendix C purpose taxonomy requires PDF transcription. | Pending | Outreach |
| SiteFeasibilityProjection versioning. Today the projection runs on current Site state; SFQ-time snapshots (versioned feasibility profiles tied to Sponsor SFQ submissions) is a v0.3 enhancement. | v0.3 | Bo |
| Site Performance Metric sub-object. Parked in v0.2.0 because metric definitions are role-specific and belong with reference-pattern projections (v0.3 reference-architecture roadmap item). | Parked | Bo |
| System horizontal earns a dedicated v0.3 spec doc. R3 Section 4.3 alone gives System ~10 attributes; a dedicated spec is warranted as the System surface area accumulates. | v0.3 | Working group |
| SHACL pending invariants (cross-entity Person-must-be-from-Site.hasStaff; lifecycle pre-ACTIVE IRB-approval check; Sponsor-engaged-vendor → Site-side-agreement). Listed in §14. | v0.3 | Translator scaffold v3 |
| USDM parentOrganization equivalent verification with David Iverson Hurst (CDISC USDM working group). | Outreach pending | Bo |
| CDISC ISF Provisional v1 PDF re-validation. Section 6 alignment table is grounded in a Singapore HSA-flavored TOC; need to confirm against the actual CDISC Provisional document. | Outreach pending | Bo |
| Person/PersonRole structure: PersonRole as a separate sub-object vs. role enum on relationships. v0.2.0 keeps role as a relationship attribute; v0.3 may lift PersonRole if the role taxonomy outgrows the enum. | v0.3 | Working group |