All walkthroughs / Health organisation
A researcher in a hospital group is stopped at the table of admissions that a data engineer brought in. The researcher asks for access, and the custodian of the department that owns the table decides. Python and the console show the same story from two sides.
me is the client library signed in as the person named on the label, and custodian is the client library signed in as the custodian.The Cardiology department of a hospital group owns a table of hospital admissions that a data engineer, Devi, brought in and sealed, and nobody can read it yet. A researcher wants to study it. This part shows the researcher being stopped, asking for access, and being answered by a different person.
Sam is a researcher in the Health organisation and wants to study readmissions, which are patients who come back to hospital soon after leaving. To start, Sam asks Munitas for a token, which is a short-lived password that also says why Sam wants to read, here a readmission study. Sam then connects DuckDB, a free tool for analysing tables, to the list of tables that Munitas offers, called the catalog, and asks what is in it. DuckDB runs inside Sam's own Python session and reads the tables from Munitas.
me is the Munitas client library, a small Python package that asks Munitas for things on the person’s behalf, signed in as Sam. DuckDB runs in this Python session. It asks Munitas for the table. If Munitas allows it, DuckDB receives a short-lived key and reads the table directly.token = me.catalog_token(purpose="readmission study") # shown once, never printed
import duckdb
con = duckdb.connect()
con.execute("INSTALL iceberg; LOAD iceberg;")
con.execute(f"ATTACH 'health' AS lake (TYPE ICEBERG, ENDPOINT 'http://localhost:8000/iceberg', TOKEN '{token}')")
print(con.sql("SELECT schema AS dataset, name AS version FROM (SHOW ALL TABLES) ORDER BY 1"))What came back┌─────────────────┬─────────┐ │ dataset │ version │ │ varchar │ varchar │ ├─────────────────┼─────────┤ │ diagnosis_codes │ v1 │ └─────────────────┴─────────┘
diagnosis_codes, the public lookup that Devi brought in and Hartley agreed to open. The admissions dataset does not appear at all, because Sam may not read it.In the console, the Munitas web page for people, Sam searches the datasets list for the lookup. The list shows the dataset that Devi brought in and that the Cardiology department owns.
The admissions dataset is at the Raw access level, the most restricted one. Nobody may read it without a lease, which is permission from the owning department's custodian to read it for one stated purpose and for a limited time. Sam tries to read it anyway.
con was set in step 1.try:
print(con.sql('SELECT count(*) FROM lake."admissions".v1'))
except Exception as exc:
print("Refused:", exc)What came backRefused: HTTP Error: GetTableInformation endpoint returned response code Forbidden_403 with message "no role reaches class RAW"
no role reaches class RAW. Sam's role, researcher, reaches the Published level and nothing above it. Munitas gives the reason instead of a bare error.The same datasets list in the console now shows the admissions dataset, which the Cardiology department owns.
On the page of the dataset version, Sam writes what the data will be used for, why something less sensitive would not do, and for how long access is needed. The request goes to Hartley, the custodian of the Cardiology department, because Cardiology owns the data.
Hartley's home page lists the requests to read Cardiology's data. Only an approver of Cardiology can decide this one, and Sam cannot approve a request made under Sam's own name.
Hartley chooses Grant access. The request leaves the queue, and a lease now exists that lets Sam read this one dataset for the stated purpose.
Back in Sam's Python session, the kind of question that was refused a moment ago now works. Storage takes a few seconds to learn of new access, so the first box asks again until it is answered. The second box looks at three rows.
me is the Munitas client library, a small Python package that asks Munitas for things on the person’s behalf, signed in as Sam. DuckDB runs in this Python session. It asks Munitas for the table. If Munitas allows it, DuckDB receives a short-lived key and reads the table directly.Names used here that are not defined in this box: con was set in step 1; time is Python’s standard time module.for _ in range(20): # storage takes a few seconds to learn of new access
try:
print(con.sql('SELECT count(*) AS admissions FROM lake."admissions".v1'))
break
except Exception:
time.sleep(3)What came back┌────────────┐ │ admissions │ │ int64 │ ├────────────┤ │ 400 │ └────────────┘
con was set in step 1.print(con.sql("""SELECT admission_id, age, diagnosis_code, length_of_stay_days FROM lake."admissions".v1 LIMIT 3"""))What came back┌──────────────┬───────┬────────────────┬─────────────────────┐ │ admission_id │ age │ diagnosis_code │ length_of_stay_days │ │ varchar │ int64 │ varchar │ int64 │ ├──────────────┼───────┼────────────────┼─────────────────────┤ │ ADM-0001 │ 68 │ I47.1 │ 5 │ │ ADM-0002 │ 59 │ I42.0 │ 4 │ │ ADM-0003 │ 40 │ I48.91 │ 1 │ └──────────────┴───────┴────────────────┴─────────────────────┘