rdt-model-pull
Fetches an RTiS entity model and writes a frozen JSON snapshot to models/{entity}/model.json. This is the entry point of every pipeline run — everything downstream reads from this snapshot.
| Property | Value |
|---|---|
| Binary | rdt-model-pull |
| Pipeline phase | 1 — Ingest |
| Network | RTiS REST API (or StubRTisClient in dry-run / no-credential mode) |
| Credentials | GENERIC_ID_USERNAME, GENERIC_ID_PASSWORD (Basic Auth) |
| Threading | Async — 3 concurrent RTiS API calls per entity |
| Output | models/{entity}/model.json |
Subcommands
Section titled “Subcommands”| Subcommand | Description | Implemented |
|---|---|---|
pull | Fetch entity from RTiS, write model.json | Yes |
list | List entities from the config registry | Yes |
diff | Show changes since last snapshot | Stub |
snapshot | Create a versioned snapshot | Stub |
Pull a model (dry-run — no credentials needed)
Section titled “Pull a model (dry-run — no credentials needed)”export RDT_TARGET=devrdt-model-pull --dry-run pull --entity waste-trackingDry-run mode uses StubRTisClient which returns fixture data from
cli/common/src/clients/fixtures/rtis/waste-tracking.json. No network access required.
Output:
models/waste-tracking/model.json (not written — dry-run)Pull a model (live RTiS — requires VPN + credentials)
Section titled “Pull a model (live RTiS — requires VPN + credentials)”export RDT_TARGET=devexport GENERIC_ID_USERNAME=GLOMODELexport GENERIC_ID_PASSWORD=<from .env>rdt-model-pull pull --entity waste-trackingMakes three concurrent HTTP calls to RTiS:
GET /int/refmodels/classes/{rtis_class_id}— class definition and parent edgesGET /int/refmodels/properties?domain={rtis_class_id}— OWL propertiesGET /int/refterminologies/{rtis_terminology_id}— terminology metadata
Writes the merged result to models/waste-tracking/model.json.
List registered entities
Section titled “List registered entities”rdt-model-pull --target dev listReturns entities defined in [rtis.entities.*] sections of roche-data.toml:
organization-site (vunknown)waste-tracking (vunknown)Global flags
Section titled “Global flags”| Flag | Short | Env | Description |
|---|---|---|---|
--target | -t | RDT_TARGET | Required. dev, test, or prod |
--entity | -e | — | Entity slug (required for pull, diff, snapshot) |
--dry-run | -n | — | Use stub client, skip writing files |
--quiet | -q | — | Suppress informational output |
--config | -c | — | Path to roche-data.toml (default: ./roche-data.toml) |
Configuration
Section titled “Configuration”RTiS entity identifiers are configured in roche-data.toml. The rtis_class_id and
rtis_terminology_id values are ROX-prefixed identifiers from the RTiS Reference Model.
[rtis]base_url = "https://ontology-services.roche.com/api"# timeout_seconds = 300 # default 300s; override with RTIS_TIMEOUT_SECONDS
[rtis.entities.organization-site]rtis_class_id = "ROX38275200443992329"rtis_terminology_id = "ROX38218176443982250"
[rtis.entities.waste-tracking]# Not yet registered in RTiS — file a class request with the RTiS owner.# rtis_class_id = ""# rtis_terminology_id = ""Discovering RTiS IDs: Browse all classes at
GET https://ontology-services.roche.com/api/int/refmodels/classes?page=0&size=342
with Basic Auth.
Output — model.json
Section titled “Output — model.json”A frozen RTiS snapshot. All downstream modules read from this file.
{ "id": "organization-site", "name": "organization-site", "version": "unknown", "description": "Examples: ...", "last_modified": "2023-01-26T15:14:10.796Z", "fields": [ { "name": "basal expressed in cell", "data_type": "owl:ObjectProperty", "nullable": true, "primary_key": false, "description": "" } ], "relationships": [ { "name": "is_a_formal_organization", "target_entity": "Formal organization", "relationship_type": "is-a", "foreign_key": "" } ], "terminology_mappings": [ { "field": "", "terminology_system": "master", "code": "ROX38218176443982250", "display": "Biomedical Knowledge" } ]}Field notes
Section titled “Field notes”| Field | Source | Notes |
|---|---|---|
name | Entity slug | RTiS class detail does not expose a plain-string label — the entity ID is used |
version | — | Always "unknown" — RTiS classes have no semantic version field |
description | class.comment → term.definition → term.comment | Waterfall fallback |
last_modified | class.modified → term.published | ISO-8601 |
fields | /properties?domain= | OWL properties are global — RTiS does not filter by class domain |
terminology_mappings | Terminology metadata | One entry per terminology; concept-level mappings deferred (requires elevated credentials) |
Error handling
Section titled “Error handling”rtis_class_id not set for entity
Section titled “rtis_class_id not set for entity”Error: rtis_class_id not set for entity 'waste-tracking' in roche-data.tomlThe entity exists in [rtis.entities.*] but the RTiS IDs haven’t been filled in.
Request the class from the RTiS owner and update roche-data.toml.
GENERIC_ID_USERNAME not set
Section titled “GENERIC_ID_USERNAME not set”Error: GENERIC_ID_USERNAME not set — add it to .envAdd credentials to .env at the repo root:
GENERIC_ID_USERNAME=GLOMODELGENERIC_ID_PASSWORD=<password>entity 'X' not found in roche-data.toml
Section titled “entity 'X' not found in roche-data.toml”Error: entity 'new-entity' not found in roche-data.toml — add an [rtis.entities.new-entity] sectionAdd a new [rtis.entities.*] block to roche-data.toml before running pull.
RTiS returns 401
Section titled “RTiS returns 401”Credentials are incorrect or the service account doesn’t have read access to the
target class. Verify with: curl -u $GENERIC_ID_USERNAME:$GENERIC_ID_PASSWORD https://ontology-services.roche.com/api/int/refmodels/metadata
RTiS is unreachable (no VPN)
Section titled “RTiS is unreachable (no VPN)”Error: HTTP request to RTiS refmodels/classes failedYou are not on the Roche VPN. Use --dry-run to work offline with fixture data.
Dry-run vs live mode
Section titled “Dry-run vs live mode”| Behaviour | --dry-run | Live |
|---|---|---|
| Client | StubRTisClient (fixture) | HttpRTisClient (live RTiS) |
| Network | None | RTiS REST API (VPN required) |
| Credentials | Not required | GENERIC_ID_USERNAME / GENERIC_ID_PASSWORD |
Writes model.json | No | Yes |
| Suitable for CI without VPN | Yes | No |
Troubleshooting
Section titled “Troubleshooting”Model snapshot is empty or missing fields
RTiS OWL properties are not domain-constrained — all global properties are returned
by /properties?domain=. Entity-specific fields will populate once the waste-tracking
class is registered in RTiS with explicit datatype properties.
Slow pulls (>60 s)
The default timeout is 300 s. Override with RTIS_TIMEOUT_SECONDS=60 or
timeout_seconds = 60 in [rtis] in roche-data.toml.
diff and snapshot return “not yet implemented”
These subcommands are stubbed pending RTiS change-request history API work.
Track progress on issue #64.