🗂️ Schema Management

RelataDB is ontology-driven: types are data, not DDL. Register them at runtime, evolve them online, branch them.

client.register_type(
    "Person",
    description="A natural person under investigation",
    owner="fraud-team",
    properties={
        "id":      {"type": "text"},
        "name":    {"type": "text"},
        "email":   {"type": "text"},
        "phone":   {"type": "text"},
        "role":    {"type": "text"},
        "company": {"type": "text"},
        "risk":    {"type": "text"},
    },
)
# {"created": True, "name": "Person"}

List and inspect what you registered:

client.list_types()
# {"types": [{"name": "Person", "rows": 0}, {"name": "Transaction", "rows": 0}, ...]}
 
client.type_detail("Person")
# {"name": "Person", "owner": "fraud-team", "rows": 4,
#  "properties": {"id": {...}, "name": {...}, ...}}

Evolve the schema without downtime — add / drop / rename / retype:

# Add a `sanctions_status` column to every existing Person row.
client.schema_alter("Person", "add", "sanctions_status", col_type="text")
 
# Rename `risk` → `risk_band`.
client.schema_alter("Person", "rename", "risk", new_column="risk_band")
 
# Retype a column.
client.schema_alter("Person", "retype", "phone", col_type="text")

Register a typed edge for graph traversal (ADR-007):

client.register_edge_type("Person", "Transaction", "AUTHORIZED")
# {"from_type": "Person", "to_type": "Transaction", "label": "AUTHORIZED"}
 
client.list_edge_types()
# {"edges": [{"from_type": "Person", "to_type": "Transaction",
#             "label": "AUTHORIZED"}, ...]}

Remove a type when it's no longer needed (admin token required):

client.deregister_type("ExperimentalType")
# {"deleted": True, "name": "ExperimentalType"}
Migrate a whole ontology in one governed call

ontology_migrate registers type specs, link types, and property constraints together so a SHACL-consistent ontology lands atomically:

client.ontology_migrate({
    "types": [
        {"name": "Person",       "properties": {"name": {"type": "text"}}},
        {"name": "Transaction",  "properties": {"amount": {"type": "float"}}},
    ],
    "links": [
        {"from": "Person", "to": "Transaction", "label": "AUTHORIZED"},
    ],
})

And register SmartIngest enrichment rules so custom identifiers get auto-detected alongside the 76 built-in canonical types:

client.enrichment_rules({
    "rules": [
        {"name": "internal_acct", "pattern": r"ACME-\d{6}",
         "canonical_kind": "account_number"},
    ],
})

Next: Ingest Data — load the four suspects, the wire transfers, and the case documents that the Shadow Ledger investigation is built on.