John Moehrke XACML Consent Example
0.1.0 - ci-build International flag

John Moehrke XACML Consent Example, published by John Moehrke (Moehrke Research LLC). This guide is not an authorized publication; it is the continuous build for version 0.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/JohnMoehrke/xacml-consent/ and changes regularly. See the Directory of published versions

Ab 352

let’s treat AB 352 as an organizational policy encoded as a top-level XACML PolicySet that:

  • Denies disclosure of certain sensitive data (abortion, gender‑affirming care, contraception, etc.) to out‑of‑state recipients.
  • Applies to a hospital organization in California.
  • Uses attributes to represent:
    • Data category (e.g., health:sensitivity).
    • Recipient jurisdiction (e.g., recipient:jurisdiction).
    • Purpose of use (optional, but useful).
    • Action (e.g., disclose, access, use).
graph TD
    Start((Medical Record Action)) --> Destination{Destination?}

    %% IN-STATE FLOW
    Destination -->|CA Data Exchange| InState[<b>IN-STATE</b>]
    InState --> DxFGate{Specific Consent on File?}
    
    DxFGate -->|No| AutoFilter[<b>AUTO-FILTER: ENABLED</b>]
    AutoFilter -->|Action| Scrub[Scrub Sensitive Codes]
    Scrub --> SharePartial[Share General Data Only]
    
    DxFGate -->|Yes| FilterOff[<b>Follow Consent #40;AUTO-FILTER:disabled#41;</b>]
    FilterOff --> ShareFull[Share Consent Permitted Record via DxF]

    %% OUT-OF-STATE FLOW
    Destination -->|Cross Border| OutState[<b>OUT-OF-STATE</b>]
    OutState --> ShieldGate{Specific Consent on File?}
    
    ShieldGate -->|No| Block[<b>AB 352 SHIELD: BLOCKED</b>]
    Block --> Partial[Release Non-Sensitive Data Only]
    
    ShieldGate -->|Yes| Consented[<b>Follow Consent</b>]
    Consented --> Full[Release Consent Permitted Record]

    %% Formatting
    style AutoFilter fill:#fff4dd,stroke:#d4a017,stroke-width:2px
    style FilterOff fill:#9f9,stroke:#333
    style Block fill:#f99,stroke:#333

ValueSets for AB 352

Generated by co-pilot with specific direction to use recommendations from HealthNet California AB 352 documentation.

ValueSets:

A FHIR Consent instance that is an explicit consent for AB 352 protected data, with provisions that reflect the statutory requirements, with auto-filter bypassed for in-state recipients.

  • policyRule → AB 352 statutory anchor ==> urn:law:us:ca:statute:AB352
  • policy – see note below
  • patient → the patient giving consent
  • organization → the California hospital organization
  • dateTime → when the consent was created
  • category → Release of Information Consent LOINC code
  • scope → Privacy Consent
  • provision[0] → overall provision agreement for AB 352 data segmentation for TREATMENT purpose.
    • typepermit
    • purposeTREATMENT, PAYMENT, OPERATIONS
    • provision[0] out-of-state recipients deny
      • typedeny
      • no location means everywhere (out-of-state)
      • securityLabel → three sensitivity tags from AB352 Segmentation Tags ValueSet
      • purposeTREATMENT, PAYMENT, OPERATIONS
      • provision[0] → Indicates that for in-state recipients, data tagged with specific sensitivity codes can be accessed for treatment purpose. (Auto-Filter is bypassed)
        • typepermit
        • location → organization in California
        • don't need to restate the purpose and securityLabel here since they are inherited from the parent provision.

Note that the policy element is not indicated here, as the policyRule code is sufficient to express to the recipient the statutory basis for the consent. If the Recipient does not understand the rules of AB352, then the encoded XACML PolicySet can be shared out-of-band or referenced via a URI. It is not clear what use the Recipient has for the actual XACML policy in the context of FHIR Consent, but it is included here for discussion sake. Many are arguing that the FHIR Consent must include the foundational rules in a computable form.

If the patient wants non-CA recipients to have access than provision[1] would be modified to permit instead of deny. If they want to enable only SOME out-of-state access, then multiple provisions would be needed for each authorized out-of-state organization.

PDP Evaluation

flowchart TD

    A["Request to access/disclose data"] --> B["PEP collects attributes"]
    B --> C["Attributes: action, sensitivity, recipient jurisdiction, purpose"]
    C --> D["PDP evaluates PolicySet urn:org:hospital:policyset:AB352"]

    D --> E1{"Action = disclose?"}
    E1 -- Yes --> F1{"Sensitivity in AB352 set?"}
    F1 -- Yes --> G1{"Recipient jurisdiction != CA?"}
    G1 -- Yes --> H1["Deny<br/>Obligation: log-denial"]
    G1 -- No --> I1["Continue evaluation<br/>(local org policies)"]
    F1 -- No --> I1

    E1 -- No --> E2{"Action = access/use?"}
    E2 -- Yes --> F2{"Recipient jurisdiction = CA<br/>AND purpose = TREATMENT?"}
    F2 -- Yes --> H2["Permit<br/>Obligation: segment-sensitive-data"]
    F2 -- No --> I2["NotApplicable or other org policies"]

    E2 -- No --> I2

    H2 --> J["PEP enforces segmentation<br/>(EHR/HIE data segregation)"]
    H1 --> K["PEP denies disclosure<br/>and records AuditEvent"]

XACML PolicySet for AB 352

This XACML treats AB 352 as an organizational policy implemented by a California hospital, expressed as a top‑level PolicySet with subordinate policies for:

  • Denying disclosure of AB 352‑sensitive data to out‑of‑state entities
  • Allowing in‑state treatment access
  • Enforcing segmentation obligations (modeled as XACML Obligations)
graph TD
    PS["<b>PolicySet:</b> AB352 Compliance<br/>Target: CA-HOSPITAL<br/>Combining Alg: Deny-Overrides"]
    
    PS --> P1_T
    PS --> P2_T
    PS --> P3_T

    %% Policy 1
    subgraph P1 ["Policy 1: Data Disclosure Control"]
        P1_T["Target: Action = DISCLOSE"]
        P1_R1["Rule: Deny Out-of-State"]
        P1_C{"Condition:<br/>Is Sensitive Health Data?<br/>AND Recipient != CA?"}
        P1_O["Obligation: Log Denial Reason"]
        
        P1_T --> P1_R1
        P1_R1 --> P1_C
        P1_R1 --> P1_O
    end

    %% Policy 2
    subgraph P2 ["Policy 2: In-State Clinical Use"]
        P2_T["Target: Action = ACCESS/USE"]
        P2_R1["Rule: Permit Treatment"]
        P2_C{"Condition:<br/>Recipient = CA?<br/>AND Purpose = TREATMENT?"}
        
        P2_T --> P2_R1
        P2_R1 --> P2_C
    end

    %% Policy 3
    subgraph P3 ["Policy 3: Mandatory Segmentation"]
        P3_T["Target: Any"]
        P3_R1["Rule: Permit"]
        P3_O["Obligation: Trigger Segmentation Engine<br/>for Abortion/Gender Care/Contraception"]
        
        P3_T --> P3_R1
        P3_R1 --> P3_O
    end

    %% Styling
    style PS fill:#f9f,stroke:#333,stroke-width:4px
    style P1_R1 fill:#ff9999,stroke:#c00
    style P2_R1 fill:#99ff99,stroke:#0c0
    style P3_O fill:#bbdaff,stroke:#00f

Everything is self‑contained and ready for use in an IG or PDP example. Here is the XACML PolicySet for AB 352:

<PolicySet
    xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
    PolicySetId="urn:org:hospital:policyset:AB352"
    Version="1.0"
    PolicyCombiningAlgId="urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:deny-overrides">

    <!-- Applies to this California hospital as data controller -->
    <Target>
        <AnyOf>
            <AllOf>
                <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                    <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                        CA-HOSPITAL
                    </AttributeValue>
                    <AttributeDesignator
                        AttributeId="urn:org:hospital:attribute:organization-type"
                        Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                        DataType="http://www.w3.org/2001/XMLSchema#string"/>
                </Match>
            </AllOf>
        </AnyOf>
    </Target>

    <!-- ========================================================= -->
    <!-- POLICY 1: AB352 Denial of Out-of-State Disclosure         -->
    <!-- ========================================================= -->
    <Policy
        PolicyId="urn:org:hospital:policy:AB352:deny-out-of-state-disclosure"
        RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">

        <Target>
            <AnyOf>
                <AllOf>
                    <!-- Applies to disclosure/transmission actions -->
                    <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            disclose
                        </AttributeValue>
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:action:verb"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                    </Match>
                </AllOf>
            </AnyOf>
        </Target>

        <Rule
            RuleId="urn:org:hospital:rule:AB352:deny-out-of-state"
            Effect="Deny">

            <Condition>
                <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">

                    <!-- Resource is AB352-sensitive -->
                    <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:health:sensitivity"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">ABORTION</AttributeValue>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">GENDER_AFFIRMING_CARE</AttributeValue>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CONTRACEPTION</AttributeValue>
                    </Apply>

                    <!-- Recipient jurisdiction is not California -->
                    <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-not-equal">
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:recipient:jurisdiction"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:access-subject"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CA</AttributeValue>
                    </Apply>

                </Apply>
            </Condition>

            <!-- Obligation: log denied AB352 disclosure attempt -->
            <ObligationExpressions>
                <ObligationExpression
                    ObligationId="urn:org:hospital:obligation:log-denial"
                    FulfillOn="Deny">
                    <AttributeAssignmentExpression AttributeId="urn:org:hospital:log:reason">
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            AB352 prohibited disclosure to out-of-state entity
                        </AttributeValue>
                    </AttributeAssignmentExpression>
                </ObligationExpression>
            </ObligationExpressions>

        </Rule>
    </Policy>

    <!-- ========================================================= -->
    <!-- POLICY 2: Allow In-State Treatment Access                 -->
    <!-- ========================================================= -->
    <Policy
        PolicyId="urn:org:hospital:policy:AB352:allow-in-state-treatment"
        RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides">

        <Target>
            <AnyOf>
                <AllOf>
                    <!-- Access/use actions -->
                    <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of">
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">access</AttributeValue>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">use</AttributeValue>
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:action:verb"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                    </Match>
                </AllOf>
            </AnyOf>
        </Target>

        <Rule
            RuleId="urn:org:hospital:rule:AB352:permit-in-state-treatment"
            Effect="Permit">

            <Condition>
                <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">

                    <!-- Recipient jurisdiction is California -->
                    <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:recipient:jurisdiction"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:access-subject"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">CA</AttributeValue>
                    </Apply>

                    <!-- Purpose is treatment -->
                    <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
                        <AttributeDesignator
                            AttributeId="urn:org:hospital:attribute:purpose-of-use"
                            Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
                            DataType="http://www.w3.org/2001/XMLSchema#string"/>
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">TREATMENT</AttributeValue>
                    </Apply>

                </Apply>
            </Condition>

        </Rule>
    </Policy>

    <!-- ========================================================= -->
    <!-- POLICY 3: Segmentation Requirement (Obligation)           -->
    <!-- ========================================================= -->
    <Policy
        PolicyId="urn:org:hospital:policy:AB352:segmentation"
        RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides">

        <Rule
            RuleId="urn:org:hospital:rule:AB352:segmentation-required"
            Effect="Permit">

            <!-- Always applies; obligation enforces segmentation -->
            <ObligationExpressions>
                <ObligationExpression
                    ObligationId="urn:org:hospital:obligation:segment-sensitive-data"
                    FulfillOn="Permit">
                    <AttributeAssignmentExpression AttributeId="urn:org:hospital:segmentation:categories">
                        <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">
                            ABORTION,GENDER_AFFIRMING_CARE,CONTRACEPTION
                        </AttributeValue>
                    </AttributeAssignmentExpression>
                </ObligationExpression>
            </ObligationExpressions>

        </Rule>
    </Policy>

</PolicySet>

Not just FHIR

IHE APPC / XUA mapping for AB352

  • XUA (SAML / OAuth token attributes)
    • Subject jurisdiction / location
      • XUA attribute: urn:oasis:names:tc:xspa:1.0:subject:locality (or a custom attribute)
      • Maps to XACML: urn:org:hospital:attribute:recipient:jurisdiction
  • Purpose of use
    • XUA attribute: urn:oasis:names:tc:xspa:1.0:subject:purposeofuse (e.g., TREAT)
    • Maps to XACML: urn:org:hospital:attribute:purpose-of-use
  • Role / organization
    • XUA attributes: role, organization identifiers
    • Used to distinguish in‑state vs out‑of‑state Organizations in your PDP attribute resolver.

APPC (Access Control Policy)

  • Policy artifact:
    • APPC policy references the same XACML PolicySetId: urn:org:hospital:policyset:AB352.
    • In your APPC metadata, you can declare:
      • Policy type: “regulatory‑driven organizational policy”
      • Policy reference: FHIR Consent instance Consent/consent-ab352-example
  • Enforcement points:
    • HIE edge / gateway: PEP uses XUA token + APPC policy reference to call PDP with the AB352 PolicySet.
    • EHR internal services: same XACML policy, but invoked with richer resource attributes (e.g., FHIR tags for sensitivity).

FHIR ↔ APPC ↔ XACML linkage

  • FHIR Consent.policy.uri → APPC policy identifier → XACML PolicySetId.
  • FHIR Consent.provision.class → sensitivity tags on FHIR resources (e.g., meta.security) → XACML health:sensitivity.
  • XUA attributes (purpose, locality, role) → XACML subject/environment attributes.