For AI agents: the documentation index is at /docs/aidbox/llms.txt. A Markdown version of this page is available at /docs/aidbox/notebooks.md or by requesting it with the Accept: text/markdown header.
Aidbox Docs
All notebooks

LBAC reference

Security label options and a live look at which records actually carry them

7 cells · updated Aug 28, 2026

This is a read-only view. Responses shown were saved when the notebook was published — open it in your own Aidbox to run the cells against live data.

Label-Based Access Control (LBAC)

Live on both serenity-local and wzrd-lab since 2026-08-28 — see docs/admin-guide/aidbox-console.md's "Label-Based Access Control (LBAC)" section and memory project_aidbox_lbac_backlog for the full story.

The one rule that matters: a resource with no meta.security label is inaccessible to everyone — admin, root, any role. Every query below runs through this notebook's own SQL engine, which (like $psql) bypasses LBAC's read gate — this is the normal way to inspect labeled data as an admin, not a workaround.

Confidentiality codes (http://terminology.hl7.org/CodeSystem/v3-Confidentiality)

Hierarchical — a request's confidentiality level expands downward to everything less restrictive. Confirmed live against this exact Aidbox version (aidbox-docs's own worked LBAC example): a request carrying R is granted R, N, M, L, and U. V sits above this chain — an R-level request does not see V-labeled resources.

CodeMeaningGranted by a request holding...
VVery restrictedV only — does not expand down automatically per the accessibility matrix example
RRestrictedR (expands to grant N, M, L, U too)
NNormalN, M, L, U
MModerateM, L, U
LLowL, U
UUnrestrictedU only

What this stack actually uses: every Keycloak-issued token for serenity-chart-viewer/practitioner-app carries a baseline U (unrestricted) — see the role-to-smart-scope script mapper in scripts/register-keycloak-sso.sh. Nothing in this stack currently issues a request with any other confidentiality level — the label options above are all available, just unused beyond the baseline so far.

Sensitivity / compartment codes (http://terminology.hl7.org/CodeSystem/v3-ActCode)

A second, independent code system LBAC also checks for overlap — not hierarchical the way Confidentiality is; a request needs the specific code a resource is labeled with (no automatic expansion). Only used in this stack so far in the demo/tutorial data actually seeded here:

CodeMeaning
PSYPsychiatry
HIVHIV/AIDS information
ETHSubstance abuse related information
CTCOMPTCare team compartment
FMCOMPTFinancial management compartment
RESCOMPTResearch project compartment
PROCESSINLINELABELMarker telling Aidbox to also apply element-level masking (meta.security, not a sensitivity label itself)

See aidbox-docs/docs/access-control/authorization/label-based-access-control.md for the full masking mechanics (this is what makes Patient.identifier/Patient.name maskable per-field, independent of whether the whole resource is readable).

SQL Send Cells run only inside Aidbox. Use Run in Aidbox above to open this notebook in your own instance.
SELECT 'Patient' AS resource_type, sec->>'code' AS code, sec->>'system' AS system, count(*)
FROM patient, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Encounter', sec->>'code', sec->>'system', count(*)
FROM encounter, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Observation', sec->>'code', sec->>'system', count(*)
FROM observation, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Condition', sec->>'code', sec->>'system', count(*)
FROM condition, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Questionnaire', sec->>'code', sec->>'system', count(*)
FROM questionnaire, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'QuestionnaireResponse', sec->>'code', sec->>'system', count(*)
FROM questionnaireresponse, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Organization', sec->>'code', sec->>'system', count(*)
FROM organization, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'Practitioner', sec->>'code', sec->>'system', count(*)
FROM practitioner, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'PractitionerRole', sec->>'code', sec->>'system', count(*)
FROM practitionerrole, jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
UNION ALL
SELECT 'User', sec->>'code', sec->>'system', count(*)
FROM "user", jsonb_array_elements(resource#>'{meta,security}') sec
GROUP BY 1,2,3
ORDER BY 1, 4 DESC;
SQL Send Cells run only inside Aidbox. Use Run in Aidbox above to open this notebook in your own instance.
SELECT 'Patient' AS resource_type, count(*) AS missing_label FROM patient WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Encounter', count(*) FROM encounter WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Observation', count(*) FROM observation WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Condition', count(*) FROM condition WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Questionnaire', count(*) FROM questionnaire WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'QuestionnaireResponse', count(*) FROM questionnaireresponse WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Organization', count(*) FROM organization WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'Practitioner', count(*) FROM practitioner WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'PractitionerRole', count(*) FROM practitionerrole WHERE resource#>'{meta,security}' IS NULL
UNION ALL SELECT 'User', count(*) FROM "user" WHERE resource#>'{meta,security}' IS NULL
ORDER BY 2 DESC;

Anything showing up in the query above needs scripts/lbac-backfill-default-label.sh re-run (it's idempotent — only touches resources actually missing a label). This happens whenever new data is bulk-loaded or written by something other than practitioner-app (which labels its own writes at creation time, see apps/practitioner-app/lib/aidbox/security-label.ts) or a Keycloak-fronted app's own creates.

SQL Send Cells run only inside Aidbox. Use Run in Aidbox above to open this notebook in your own instance.
SELECT id, resource#>'{meta,security}' AS security_labels
FROM patient
ORDER BY id
LIMIT 50;