eyeprolog 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/examples/dpv-odrl-purpose-mapping.pl +124 -0
  2. package/examples/odrl-dpv-fpv-trust-flow.pl +154 -0
  3. package/examples/odrl-dpv-healthcare-risk-ranked.pl +177 -0
  4. package/examples/odrl-dpv-risk-ranked.pl +201 -0
  5. package/examples/odrl-policy-advanced.pl +140 -0
  6. package/examples/odrl-policy.pl +80 -0
  7. package/examples/output/dpv-odrl-purpose-mapping.pl +18 -0
  8. package/examples/output/odrl-dpv-fpv-trust-flow.pl +9 -0
  9. package/examples/output/odrl-dpv-healthcare-risk-ranked.pl +15 -0
  10. package/examples/output/odrl-dpv-risk-ranked.pl +20 -0
  11. package/examples/output/odrl-policy-advanced.pl +6 -0
  12. package/examples/output/odrl-policy.pl +4 -0
  13. package/examples/output/rdf12-annotated-claims.pl +9 -0
  14. package/examples/output/rdf12-annotation.pl +4 -0
  15. package/examples/output/rdf12-directional-language.pl +2 -0
  16. package/examples/output/rdf12-nested-triple-term.pl +1 -0
  17. package/examples/output/rdf12-trig-graph-join.pl +1 -0
  18. package/examples/output/rdf12-trig-named-graph.pl +3 -0
  19. package/examples/output/rdf12-trig-triple-term.pl +1 -0
  20. package/examples/output/rdf12-triple-term.pl +1 -0
  21. package/examples/output/snaf.pl +1 -0
  22. package/examples/proof/snaf.pl +20 -0
  23. package/examples/rdf12-annotated-claims.pl +151 -0
  24. package/examples/rdf12-annotation.pl +54 -0
  25. package/examples/rdf12-directional-language.pl +24 -0
  26. package/examples/rdf12-nested-triple-term.pl +31 -0
  27. package/examples/rdf12-trig-graph-join.pl +34 -0
  28. package/examples/rdf12-trig-named-graph.pl +27 -0
  29. package/examples/rdf12-trig-triple-term.pl +27 -0
  30. package/examples/rdf12-triple-term.pl +27 -0
  31. package/examples/snaf.pl +12 -0
  32. package/package.json +1 -1
  33. package/playground.html +15 -0
  34. package/test/run-examples.mjs +1 -0
  35. package/the-art-of-eyeprolog.md +26 -2
@@ -0,0 +1,124 @@
1
+ % Adapted from rdf-prolog-roundtrip.
2
+ % This standalone program combines generated RDF input with its ISO Prolog rules.
3
+
4
+ % Generated by rdf-prolog-roundtrip.
5
+
6
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
+
8
+ rdf(iri('https://example.org/alpha_care_process'), iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), iri('https://w3id.org/dpv#Process'), default_graph).
9
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasDataController'), iri('https://example.org/hospital_a'), default_graph).
10
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasRecipient'), iri('https://example.org/research_partner'), default_graph).
11
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasPersonalData'), iri('https://example.org/lab_result'), default_graph).
12
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasProcessing'), iri('https://w3id.org/dpv#Use'), default_graph).
13
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasPurpose'), iri('https://w3id.org/dpv#Healthcare'), default_graph).
14
+ rdf(iri('https://example.org/alpha_care_process'), iri('https://w3id.org/dpv#hasLegalBasis'), iri('https://w3id.org/dpv#Consent'), default_graph).
15
+ rdf(iri('https://example.org/alpha_policy'), iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), iri('http://www.w3.org/ns/odrl/2/Policy'), default_graph).
16
+ rdf(iri('https://example.org/alpha_policy'), iri('https://example.org/representsProcess'), iri('https://example.org/alpha_care_process'), default_graph).
17
+ rdf(iri('https://example.org/alpha_policy'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/alpha_permission'), default_graph).
18
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), iri('http://www.w3.org/ns/odrl/2/Permission'), default_graph).
19
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/assigner'), iri('https://example.org/hospital_a'), default_graph).
20
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/assignee'), iri('https://example.org/research_partner'), default_graph).
21
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/lab_result'), default_graph).
22
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/use'), default_graph).
23
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/constraint'), iri('https://example.org/alpha_purpose_constraint'), default_graph).
24
+ rdf(iri('https://example.org/alpha_permission'), iri('http://www.w3.org/ns/odrl/2/constraint'), iri('https://example.org/alpha_basis_constraint'), default_graph).
25
+ rdf(iri('https://example.org/alpha_purpose_constraint'), iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), iri('http://www.w3.org/ns/odrl/2/Constraint'), default_graph).
26
+ rdf(iri('https://example.org/alpha_purpose_constraint'), iri('http://www.w3.org/ns/odrl/2/leftOperand'), iri('http://www.w3.org/ns/odrl/2/purpose'), default_graph).
27
+ rdf(iri('https://example.org/alpha_purpose_constraint'), iri('http://www.w3.org/ns/odrl/2/operator'), iri('http://www.w3.org/ns/odrl/2/isA'), default_graph).
28
+ rdf(iri('https://example.org/alpha_purpose_constraint'), iri('http://www.w3.org/ns/odrl/2/rightOperand'), iri('https://w3id.org/dpv#Healthcare'), default_graph).
29
+ rdf(iri('https://example.org/alpha_basis_constraint'), iri('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), iri('http://www.w3.org/ns/odrl/2/Constraint'), default_graph).
30
+ rdf(iri('https://example.org/alpha_basis_constraint'), iri('http://www.w3.org/ns/odrl/2/leftOperand'), iri('https://example.org/legalBasis'), default_graph).
31
+ rdf(iri('https://example.org/alpha_basis_constraint'), iri('http://www.w3.org/ns/odrl/2/operator'), iri('http://www.w3.org/ns/odrl/2/isA'), default_graph).
32
+ rdf(iri('https://example.org/alpha_basis_constraint'), iri('http://www.w3.org/ns/odrl/2/rightOperand'), iri('https://w3id.org/dpv#Consent'), default_graph).
33
+
34
+ % The DPV process and ODRL policy are RDF data. The rules verify the six
35
+ % correspondences and return one deterministic mapping report.
36
+ %% goal: result_rdf(_, _, _, _)
37
+
38
+ dpv_odrl_purpose_mapping(Mappings) :-
39
+ findall(
40
+ mapping(SourceRole, Value, TargetRole),
41
+ mapped_role(SourceRole, Value, TargetRole),
42
+ Mappings
43
+ ).
44
+
45
+ mapped_role(data_controller, Controller, assigner) :-
46
+ rdf_link(ex(alpha_care_process), dpv(hasDataController), ex(Controller)),
47
+ rdf_link(ex(alpha_permission), odrl(assigner), ex(Controller)).
48
+
49
+ mapped_role(recipient, Recipient, assignee) :-
50
+ rdf_link(ex(alpha_care_process), dpv(hasRecipient), ex(Recipient)),
51
+ rdf_link(ex(alpha_permission), odrl(assignee), ex(Recipient)).
52
+
53
+ mapped_role(personal_data, Data, target) :-
54
+ rdf_link(ex(alpha_care_process), dpv(hasPersonalData), ex(Data)),
55
+ rdf_link(ex(alpha_permission), odrl(target), ex(Data)).
56
+
57
+ mapped_role(processing, dpv_use, action) :-
58
+ rdf_link(ex(alpha_care_process), dpv(hasProcessing), dpv('Use')),
59
+ rdf_link(ex(alpha_permission), odrl(action), odrl(use)).
60
+
61
+ mapped_role(purpose, dpv_healthcare, constraint(alpha_purpose_constraint)) :-
62
+ rdf_link(ex(alpha_care_process), dpv(hasPurpose), dpv('Healthcare')),
63
+ odrl_constraint(alpha_purpose_constraint, odrl(purpose), dpv('Healthcare')).
64
+
65
+ mapped_role(legal_basis, dpv_consent, constraint(alpha_basis_constraint)) :-
66
+ rdf_link(ex(alpha_care_process), dpv(hasLegalBasis), dpv('Consent')),
67
+ odrl_constraint(alpha_basis_constraint, ex(legalBasis), dpv('Consent')).
68
+
69
+ odrl_constraint(Name, LeftOperand, RightOperand) :-
70
+ rdf_link(ex(alpha_permission), odrl(constraint), ex(Name)),
71
+ rdf_link(ex(Name), odrl('leftOperand'), LeftOperand),
72
+ rdf_link(ex(Name), odrl(operator), odrl('isA')),
73
+ rdf_link(ex(Name), odrl('rightOperand'), RightOperand).
74
+
75
+ rdf_link(Subject, Predicate, Object) :-
76
+ iri_term(Subject, SubjectIri),
77
+ iri_term(Predicate, PredicateIri),
78
+ rdf(iri(SubjectIri), iri(PredicateIri), iri(ObjectIri), default_graph),
79
+ iri_term(Object, ObjectIri).
80
+
81
+ iri_term(ex(Name), Iri) :- namespace_iri('https://example.org/', Name, Iri).
82
+ iri_term(dpv(Name), Iri) :- namespace_iri('https://w3id.org/dpv#', Name, Iri).
83
+ iri_term(odrl(Name), Iri) :- namespace_iri('http://www.w3.org/ns/odrl/2/', Name, Iri).
84
+
85
+ namespace_iri(Prefix, Name, Iri) :- atom_concat(Prefix, Name, Iri).
86
+
87
+ % RDF form of every verified DPV -> ODRL mapping.
88
+ result_rdf(iri(Node), iri('https://example.org/sourceRole'), iri(RoleIri), default_graph) :-
89
+ mapped_role(Role, _Value, _Target),
90
+ mapping_node(Role, Node),
91
+ mapping_role_iri(Role, RoleIri).
92
+ result_rdf(iri(Node), iri('https://example.org/value'), iri(ValueIri), default_graph) :-
93
+ mapped_role(Role, Value, _Target),
94
+ mapping_node(Role, Node),
95
+ mapping_value_iri(Role, Value, ValueIri).
96
+ result_rdf(iri(Node), iri('https://example.org/mappingTarget'), iri(TargetIri), default_graph) :-
97
+ mapped_role(Role, _Value, Target),
98
+ mapping_node(Role, Node),
99
+ mapping_target_iri(Target, TargetIri).
100
+
101
+ mapping_node(Role, Iri) :- atom_concat('https://example.org/result/mapping/', Role, Iri).
102
+ mapping_role_iri(Role, Iri) :- atom_concat('https://example.org/role/', Role, Iri).
103
+
104
+ mapping_value_iri(data_controller, Value, Iri) :- iri_term(ex(Value), Iri).
105
+ mapping_value_iri(recipient, Value, Iri) :- iri_term(ex(Value), Iri).
106
+ mapping_value_iri(personal_data, Value, Iri) :- iri_term(ex(Value), Iri).
107
+ mapping_value_iri(processing, dpv_use, Iri) :- iri_term(dpv('Use'), Iri).
108
+ mapping_value_iri(purpose, dpv_healthcare, Iri) :- iri_term(dpv('Healthcare'), Iri).
109
+ mapping_value_iri(legal_basis, dpv_consent, Iri) :- iri_term(dpv('Consent'), Iri).
110
+
111
+ mapping_target_iri(assigner, Iri) :- iri_term(odrl(assigner), Iri).
112
+ mapping_target_iri(assignee, Iri) :- iri_term(odrl(assignee), Iri).
113
+ mapping_target_iri(target, Iri) :- iri_term(odrl(target), Iri).
114
+ mapping_target_iri(action, Iri) :- iri_term(odrl(action), Iri).
115
+ mapping_target_iri(constraint(Name), Iri) :- iri_term(ex(Name), Iri).
116
+
117
+ % ISO Prolog helper: print the complete test result as rdf/4 facts.
118
+ write_results :-
119
+ result_rdf(S, P, O, G),
120
+ write_term(rdf(S, P, O, G), [quoted(true)]),
121
+ write('.'),
122
+ nl,
123
+ fail.
124
+ write_results.
@@ -0,0 +1,154 @@
1
+ % Adapted from rdf-prolog-roundtrip.
2
+ % This standalone program combines generated RDF input with its ISO Prolog rules.
3
+
4
+ % Generated by rdf-prolog-roundtrip.
5
+
6
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
+
8
+ rdf(iri('https://example.org/trust-policy'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/healthcare-permission'), default_graph).
9
+ rdf(iri('https://example.org/trust-policy'), iri('http://www.w3.org/ns/odrl/2/prohibition'), iri('https://example.org/marketing-prohibition'), default_graph).
10
+ rdf(iri('https://example.org/healthcare-permission'), iri('http://www.w3.org/ns/odrl/2/assignee'), iri('https://example.org/research-partner'), default_graph).
11
+ rdf(iri('https://example.org/healthcare-permission'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/lab-result'), default_graph).
12
+ rdf(iri('https://example.org/healthcare-permission'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/use'), default_graph).
13
+ rdf(iri('https://example.org/healthcare-permission'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://example.org/healthcare'), default_graph).
14
+ rdf(iri('https://example.org/healthcare-permission'), iri('https://example.org/minTrust'), literal('0.80', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
15
+ rdf(iri('https://example.org/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/assignee'), iri('https://example.org/ad-network'), default_graph).
16
+ rdf(iri('https://example.org/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/lab-result'), default_graph).
17
+ rdf(iri('https://example.org/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/distribute'), default_graph).
18
+ rdf(iri('https://example.org/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://example.org/marketing'), default_graph).
19
+ rdf(iri('https://example.org/hospital-a'), iri('https://example.org/trustScore'), literal('0.92', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
20
+ rdf(iri('https://example.org/small-clinic'), iri('https://example.org/trustScore'), literal('0.63', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
21
+ rdf(iri('https://example.org/ad-network'), iri('https://example.org/trustScore'), literal('0.28', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
22
+ rdf(iri('https://example.org/flow-care'), iri('https://example.org/source'), iri('https://example.org/hospital-a'), default_graph).
23
+ rdf(iri('https://example.org/flow-care'), iri('https://example.org/recipient'), iri('https://example.org/research-partner'), default_graph).
24
+ rdf(iri('https://example.org/flow-care'), iri('https://example.org/data'), iri('https://example.org/lab-result'), default_graph).
25
+ rdf(iri('https://example.org/flow-care'), iri('https://example.org/requestedAction'), iri('http://www.w3.org/ns/odrl/2/use'), default_graph).
26
+ rdf(iri('https://example.org/flow-care'), iri('https://example.org/requestedPurpose'), iri('https://example.org/healthcare'), default_graph).
27
+ rdf(iri('https://example.org/flow-clinic'), iri('https://example.org/source'), iri('https://example.org/small-clinic'), default_graph).
28
+ rdf(iri('https://example.org/flow-clinic'), iri('https://example.org/recipient'), iri('https://example.org/research-partner'), default_graph).
29
+ rdf(iri('https://example.org/flow-clinic'), iri('https://example.org/data'), iri('https://example.org/lab-result'), default_graph).
30
+ rdf(iri('https://example.org/flow-clinic'), iri('https://example.org/requestedAction'), iri('http://www.w3.org/ns/odrl/2/use'), default_graph).
31
+ rdf(iri('https://example.org/flow-clinic'), iri('https://example.org/requestedPurpose'), iri('https://example.org/healthcare'), default_graph).
32
+ rdf(iri('https://example.org/flow-ads'), iri('https://example.org/source'), iri('https://example.org/hospital-a'), default_graph).
33
+ rdf(iri('https://example.org/flow-ads'), iri('https://example.org/recipient'), iri('https://example.org/ad-network'), default_graph).
34
+ rdf(iri('https://example.org/flow-ads'), iri('https://example.org/data'), iri('https://example.org/lab-result'), default_graph).
35
+ rdf(iri('https://example.org/flow-ads'), iri('https://example.org/requestedAction'), iri('http://www.w3.org/ns/odrl/2/distribute'), default_graph).
36
+ rdf(iri('https://example.org/flow-ads'), iri('https://example.org/requestedPurpose'), iri('https://example.org/marketing'), default_graph).
37
+
38
+ % ODRL policy rules, trust scores, and requested flows are RDF data. The rules
39
+ % produce one deterministic FPV-style decision report.
40
+ %% goal: result_rdf(_, _, _, _)
41
+
42
+ trust_flow_report([Care, Clinic, Ads]) :-
43
+ flow_decision(flow_care, Care),
44
+ flow_decision(flow_clinic, Clinic),
45
+ flow_decision(flow_ads, Ads).
46
+
47
+ flow_decision(Flow, decision(Flow, permit, confidence(Score), status(executable_flow))) :-
48
+ permitted_flow(Flow, Score).
49
+ flow_decision(Flow, decision(Flow, review, confidence(Score), risk(trustworthiness_risk))) :-
50
+ review_flow(Flow, Score).
51
+ flow_decision(Flow, decision(Flow, deny, status(blocked_flow), risk(unwanted_disclosure))) :-
52
+ prohibited_flow(Flow).
53
+
54
+ permitted_flow(Flow, Score) :-
55
+ flow_request(Flow, Source, Recipient, Data, Action, Purpose),
56
+ policy_rule(odrl(permission), Rule, Recipient, Data, Action, Purpose),
57
+ rdf_number(Rule, ex(minTrust), Minimum),
58
+ rdf_number(Source, ex(trustScore), Score),
59
+ Score >= Minimum.
60
+
61
+ review_flow(Flow, Score) :-
62
+ flow_request(Flow, Source, Recipient, Data, Action, Purpose),
63
+ policy_rule(odrl(permission), Rule, Recipient, Data, Action, Purpose),
64
+ rdf_number(Rule, ex(minTrust), Minimum),
65
+ rdf_number(Source, ex(trustScore), Score),
66
+ Score < Minimum.
67
+
68
+ prohibited_flow(Flow) :-
69
+ flow_request(Flow, _Source, Recipient, Data, Action, Purpose),
70
+ policy_rule(odrl(prohibition), _Rule, Recipient, Data, Action, Purpose).
71
+
72
+ flow_request(Flow, Source, Recipient, Data, Action, Purpose) :-
73
+ flow_resource(Flow, Resource),
74
+ rdf_link(Resource, ex(source), Source),
75
+ rdf_link(Resource, ex(recipient), Recipient),
76
+ rdf_link(Resource, ex(data), Data),
77
+ rdf_link(Resource, ex(requestedAction), Action),
78
+ rdf_link(Resource, ex(requestedPurpose), Purpose).
79
+
80
+ policy_rule(Type, Rule, Recipient, Data, Action, Purpose) :-
81
+ rdf_link(ex('trust-policy'), Type, Rule),
82
+ rdf_link(Rule, odrl(assignee), Recipient),
83
+ rdf_link(Rule, odrl(target), Data),
84
+ rdf_link(Rule, odrl(action), Action),
85
+ rdf_link(Rule, odrl(purpose), Purpose).
86
+
87
+ flow_resource(flow_care, ex('flow-care')).
88
+ flow_resource(flow_clinic, ex('flow-clinic')).
89
+ flow_resource(flow_ads, ex('flow-ads')).
90
+
91
+ rdf_link(Subject, Predicate, Object) :-
92
+ iri_term(Subject, SubjectIri),
93
+ iri_term(Predicate, PredicateIri),
94
+ rdf(iri(SubjectIri), iri(PredicateIri), iri(ObjectIri), default_graph),
95
+ iri_term(Object, ObjectIri).
96
+
97
+ rdf_number(Subject, Predicate, Number) :-
98
+ iri_term(Subject, SubjectIri),
99
+ iri_term(Predicate, PredicateIri),
100
+ rdf(iri(SubjectIri), iri(PredicateIri), literal(Text, datatype(_Datatype)), default_graph),
101
+ atom_chars(Text, Chars),
102
+ number_chars(Number, Chars).
103
+
104
+ iri_term(ex(Name), Iri) :- namespace_iri('https://example.org/', Name, Iri).
105
+ iri_term(odrl(Name), Iri) :- namespace_iri('http://www.w3.org/ns/odrl/2/', Name, Iri).
106
+
107
+ namespace_iri(Prefix, Name, Iri) :- atom_concat(Prefix, Name, Iri).
108
+
109
+ % RDF form of each flow decision.
110
+ result_rdf(iri(FlowIri), iri('https://example.org/decision'), iri(DecisionIri), default_graph) :-
111
+ flow_decision(Flow, DecisionTerm),
112
+ decision_name(DecisionTerm, Decision),
113
+ flow_resource(Flow, FlowResource),
114
+ iri_term(FlowResource, FlowIri),
115
+ atom_concat('https://example.org/', Decision, DecisionIri).
116
+ result_rdf(iri(FlowIri), iri('https://example.org/confidence'), literal(Text, datatype('http://www.w3.org/2001/XMLSchema#decimal')), default_graph) :-
117
+ flow_decision(Flow, DecisionTerm),
118
+ decision_has_confidence(DecisionTerm),
119
+ flow_resource(Flow, FlowResource),
120
+ iri_term(FlowResource, FlowIri),
121
+ flow_request(Flow, Source, _Recipient, _Data, _Action, _Purpose),
122
+ iri_term(Source, SourceIri),
123
+ rdf(iri(SourceIri), iri('https://example.org/trustScore'), literal(Text, datatype(_)), default_graph).
124
+ result_rdf(iri(FlowIri), iri('https://example.org/status'), iri(StatusIri), default_graph) :-
125
+ flow_decision(Flow, DecisionTerm),
126
+ decision_status(DecisionTerm, Status),
127
+ flow_resource(Flow, FlowResource),
128
+ iri_term(FlowResource, FlowIri),
129
+ atom_concat('https://example.org/', Status, StatusIri).
130
+ result_rdf(iri(FlowIri), iri('https://example.org/risk'), iri(RiskIri), default_graph) :-
131
+ flow_decision(Flow, DecisionTerm),
132
+ decision_risk(DecisionTerm, Risk),
133
+ flow_resource(Flow, FlowResource),
134
+ iri_term(FlowResource, FlowIri),
135
+ atom_concat('https://example.org/', Risk, RiskIri).
136
+
137
+ decision_name(decision(_, permit, _, _), permit).
138
+ decision_name(decision(_, review, _, _), review).
139
+ decision_name(decision(_, deny, _, _), deny).
140
+ decision_has_confidence(decision(_, permit, confidence(_), _)).
141
+ decision_has_confidence(decision(_, review, confidence(_), _)).
142
+ decision_status(decision(_, permit, _, status(Status)), Status).
143
+ decision_status(decision(_, deny, status(Status), _), Status).
144
+ decision_risk(decision(_, review, _, risk(Risk)), Risk).
145
+ decision_risk(decision(_, deny, _, risk(Risk)), Risk).
146
+
147
+ % ISO Prolog helper: print the complete test result as rdf/4 facts.
148
+ write_results :-
149
+ result_rdf(S, P, O, G),
150
+ write_term(rdf(S, P, O, G), [quoted(true)]),
151
+ write('.'),
152
+ nl,
153
+ fail.
154
+ write_results.
@@ -0,0 +1,177 @@
1
+ % Adapted from rdf-prolog-roundtrip.
2
+ % This standalone program combines generated RDF input with its ISO Prolog rules.
3
+
4
+ % Generated by rdf-prolog-roundtrip.
5
+
6
+ % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
+
8
+ rdf(iri('https://example.org/healthcare-policy'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/research-use'), default_graph).
9
+ rdf(iri('https://example.org/healthcare-policy'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/genomic-sharing'), default_graph).
10
+ rdf(iri('https://example.org/healthcare-policy'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/record-retention'), default_graph).
11
+ rdf(iri('https://example.org/healthcare-policy'), iri('https://example.org/riskProfile'), iri('https://example.org/consent-profile'), default_graph).
12
+ rdf(iri('https://example.org/healthcare-policy'), iri('https://example.org/riskProfile'), iri('https://example.org/sharing-profile'), default_graph).
13
+ rdf(iri('https://example.org/healthcare-policy'), iri('https://example.org/riskProfile'), iri('https://example.org/retention-profile'), default_graph).
14
+ rdf(iri('https://example.org/research-use'), iri('https://example.org/clause'), literal('h1', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
15
+ rdf(iri('https://example.org/research-use'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/use'), default_graph).
16
+ rdf(iri('https://example.org/genomic-sharing'), iri('https://example.org/clause'), literal('h2', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
17
+ rdf(iri('https://example.org/genomic-sharing'), iri('http://www.w3.org/ns/odrl/2/action'), iri('https://example.org/disclose'), default_graph).
18
+ rdf(iri('https://example.org/genomic-sharing'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/genomic-data'), default_graph).
19
+ rdf(iri('https://example.org/record-retention'), iri('https://example.org/clause'), literal('h4', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
20
+ rdf(iri('https://example.org/record-retention'), iri('http://www.w3.org/ns/odrl/2/constraint'), iri('https://example.org/retention-constraint'), default_graph).
21
+ rdf(iri('https://example.org/retention-constraint'), iri('http://www.w3.org/ns/odrl/2/leftOperand'), iri('https://example.org/retentionDays'), default_graph).
22
+ rdf(iri('https://example.org/retention-constraint'), iri('http://www.w3.org/ns/odrl/2/operator'), iri('http://www.w3.org/ns/odrl/2/eq'), default_graph).
23
+ rdf(iri('https://example.org/retention-constraint'), iri('http://www.w3.org/ns/odrl/2/rightOperand'), literal('3650', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
24
+ rdf(iri('https://example.org/consent-profile'), iri('https://example.org/risk'), iri('https://example.org/consent-risk'), default_graph).
25
+ rdf(iri('https://example.org/consent-profile'), iri('https://example.org/policyRule'), iri('https://example.org/research-use'), default_graph).
26
+ rdf(iri('https://example.org/consent-profile'), iri('https://example.org/need'), iri('https://example.org/explicit-consent-for-research'), default_graph).
27
+ rdf(iri('https://example.org/consent-profile'), iri('https://example.org/baseScore'), literal('85', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
28
+ rdf(iri('https://example.org/consent-profile'), iri('https://example.org/mitigation'), iri('https://example.org/require-explicit-consent'), default_graph).
29
+ rdf(iri('https://example.org/sharing-profile'), iri('https://example.org/risk'), iri('https://example.org/sharing-risk'), default_graph).
30
+ rdf(iri('https://example.org/sharing-profile'), iri('https://example.org/policyRule'), iri('https://example.org/genomic-sharing'), default_graph).
31
+ rdf(iri('https://example.org/sharing-profile'), iri('https://example.org/need'), iri('https://example.org/deidentify-before-sharing'), default_graph).
32
+ rdf(iri('https://example.org/sharing-profile'), iri('https://example.org/baseScore'), literal('90', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
33
+ rdf(iri('https://example.org/sharing-profile'), iri('https://example.org/mitigation'), iri('https://example.org/require-deidentification'), default_graph).
34
+ rdf(iri('https://example.org/retention-profile'), iri('https://example.org/risk'), iri('https://example.org/retention-risk'), default_graph).
35
+ rdf(iri('https://example.org/retention-profile'), iri('https://example.org/policyRule'), iri('https://example.org/record-retention'), default_graph).
36
+ rdf(iri('https://example.org/retention-profile'), iri('https://example.org/need'), iri('https://example.org/retention-limit-3-years'), default_graph).
37
+ rdf(iri('https://example.org/retention-profile'), iri('https://example.org/baseScore'), literal('55', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
38
+ rdf(iri('https://example.org/retention-profile'), iri('https://example.org/mitigation'), iri('https://example.org/limit-retention-to-1095-days'), default_graph).
39
+ rdf(iri('https://example.org/explicit-consent-for-research'), iri('https://example.org/importance'), literal('35', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
40
+ rdf(iri('https://example.org/deidentify-before-sharing'), iri('https://example.org/importance'), literal('35', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
41
+ rdf(iri('https://example.org/retention-limit-3-years'), iri('https://example.org/importance'), literal('15', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
42
+ rdf(iri('https://example.org/retention-limit-3-years'), iri('https://example.org/maximumDays'), literal('1095', datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph).
43
+
44
+ % ODRL permissions and DPV-style risk profiles are RDF data. The rules detect
45
+ % missing safeguards, score the risks, and return one deterministic ranking.
46
+ %% goal: result_rdf(_, _, _, _)
47
+
48
+ healthcare_risk_report(Ranked) :-
49
+ findall(
50
+ key(InverseScore, Clause)-dpv_risk(Risk, Score, Level, Clause, Mitigation),
51
+ (
52
+ risk_report(Risk, Score, Level, Clause, Mitigation),
53
+ InverseScore is 1000 - Score
54
+ ),
55
+ Unsorted
56
+ ),
57
+ sort(Unsorted, Sorted),
58
+ ranked_values(Sorted, 1, Ranked).
59
+
60
+ risk_report(Risk, Score, Level, Clause, Mitigation) :-
61
+ risk_profile(_Profile, Risk, Rule, Need, Base, Mitigation),
62
+ risk_triggered(Risk, Rule, Need),
63
+ rdf_text(Rule, ex(clause), ClauseText),
64
+ Clause = ClauseText,
65
+ rdf_number(Need, ex(importance), Importance),
66
+ Raw is Base + Importance,
67
+ (Raw > 100 -> Score = 100 ; Score = Raw),
68
+ risk_level(Score, Level).
69
+
70
+ risk_profile(Profile, Risk, Rule, Need, Base, Mitigation) :-
71
+ rdf_link(ex('healthcare-policy'), ex(riskProfile), Profile),
72
+ rdf_link(Profile, ex(risk), RiskResource),
73
+ risk_resource(Risk, RiskResource),
74
+ rdf_link(Profile, ex(policyRule), Rule),
75
+ rdf_link(Profile, ex(need), Need),
76
+ rdf_number(Profile, ex(baseScore), Base),
77
+ rdf_link(Profile, ex(mitigation), MitigationResource),
78
+ mitigation_resource(Mitigation, MitigationResource).
79
+
80
+ risk_triggered(consent_risk, Rule, _Need) :-
81
+ rdf_link(ex('healthcare-policy'), odrl(permission), Rule),
82
+ rdf_link(Rule, odrl(action), odrl(use)),
83
+ \+ constraint_text(Rule, ex(explicitConsent), 'true').
84
+
85
+ risk_triggered(sharing_risk, Rule, _Need) :-
86
+ rdf_link(ex('healthcare-policy'), odrl(permission), Rule),
87
+ rdf_link(Rule, odrl(action), ex(disclose)),
88
+ rdf_link(Rule, odrl(target), ex('genomic-data')),
89
+ \+ constraint_text(Rule, ex(deidentified), 'true').
90
+
91
+ risk_triggered(retention_risk, Rule, Need) :-
92
+ rdf_link(ex('healthcare-policy'), odrl(permission), Rule),
93
+ constraint_number(Rule, ex(retentionDays), Days),
94
+ rdf_number(Need, ex(maximumDays), Maximum),
95
+ Days > Maximum.
96
+
97
+ constraint_text(Rule, LeftOperand, Value) :-
98
+ rdf_link(Rule, odrl(constraint), Constraint),
99
+ rdf_link(Constraint, odrl('leftOperand'), LeftOperand),
100
+ rdf_link(Constraint, odrl(operator), odrl(eq)),
101
+ rdf_text(Constraint, odrl('rightOperand'), Value).
102
+
103
+ constraint_number(Rule, LeftOperand, Number) :-
104
+ constraint_text(Rule, LeftOperand, Text),
105
+ atom_chars(Text, Chars),
106
+ number_chars(Number, Chars).
107
+
108
+ risk_level(Score, high) :- Score > 79.
109
+ risk_level(Score, moderate) :- Score > 49, Score < 80.
110
+
111
+ ranked_values([], _Rank, []).
112
+ ranked_values([_Key-Risk|Rest], Rank, [rank(Rank, Risk)|Ranked]) :-
113
+ NextRank is Rank + 1,
114
+ ranked_values(Rest, NextRank, Ranked).
115
+
116
+ risk_resource(consent_risk, ex('consent-risk')).
117
+ risk_resource(sharing_risk, ex('sharing-risk')).
118
+ risk_resource(retention_risk, ex('retention-risk')).
119
+
120
+ mitigation_resource(require_explicit_consent, ex('require-explicit-consent')).
121
+ mitigation_resource(require_deidentification, ex('require-deidentification')).
122
+ mitigation_resource(limit_retention_to_1095_days, ex('limit-retention-to-1095-days')).
123
+
124
+ rdf_link(Subject, Predicate, Object) :-
125
+ iri_term(Subject, SubjectIri),
126
+ iri_term(Predicate, PredicateIri),
127
+ rdf(iri(SubjectIri), iri(PredicateIri), iri(ObjectIri), default_graph),
128
+ iri_term(Object, ObjectIri).
129
+
130
+ rdf_text(Subject, Predicate, Text) :-
131
+ iri_term(Subject, SubjectIri),
132
+ iri_term(Predicate, PredicateIri),
133
+ rdf(iri(SubjectIri), iri(PredicateIri), literal(Text, datatype(_Datatype)), default_graph).
134
+
135
+ rdf_number(Subject, Predicate, Number) :-
136
+ rdf_text(Subject, Predicate, Text),
137
+ atom_chars(Text, Chars),
138
+ number_chars(Number, Chars).
139
+
140
+ iri_term(ex(Name), Iri) :- namespace_iri('https://example.org/', Name, Iri).
141
+ iri_term(odrl(Name), Iri) :- namespace_iri('http://www.w3.org/ns/odrl/2/', Name, Iri).
142
+
143
+ namespace_iri(Prefix, Name, Iri) :- atom_concat(Prefix, Name, Iri).
144
+
145
+ % RDF form of the ranked healthcare risks.
146
+ result_rdf(iri(RiskIri), iri('https://example.org/rank'), literal(RankText, datatype('http://www.w3.org/2001/XMLSchema#integer')), default_graph) :-
147
+ healthcare_ranked_item(Rank, Risk, _Score, _Level, _Clause, _Mitigation),
148
+ risk_resource(Risk, RiskTerm), iri_term(RiskTerm, RiskIri), number_atom(Rank, RankText).
149
+ result_rdf(iri(RiskIri), iri('https://example.org/score'), literal(ScoreText, datatype('http://www.w3.org/2001/XMLSchema#integer')), default_graph) :-
150
+ healthcare_ranked_item(_Rank, Risk, Score, _Level, _Clause, _Mitigation),
151
+ risk_resource(Risk, RiskTerm), iri_term(RiskTerm, RiskIri), number_atom(Score, ScoreText).
152
+ result_rdf(iri(RiskIri), iri('https://example.org/level'), iri(LevelIri), default_graph) :-
153
+ healthcare_ranked_item(_Rank, Risk, _Score, Level, _Clause, _Mitigation),
154
+ risk_resource(Risk, RiskTerm), iri_term(RiskTerm, RiskIri), atom_concat('https://example.org/', Level, LevelIri).
155
+ result_rdf(iri(RiskIri), iri('https://example.org/clause'), literal(Clause, datatype('http://www.w3.org/2001/XMLSchema#string')), default_graph) :-
156
+ healthcare_ranked_item(_Rank, Risk, _Score, _Level, Clause, _Mitigation),
157
+ risk_resource(Risk, RiskTerm), iri_term(RiskTerm, RiskIri).
158
+ result_rdf(iri(RiskIri), iri('https://example.org/mitigation'), iri(MitigationIri), default_graph) :-
159
+ healthcare_ranked_item(_Rank, Risk, _Score, _Level, _Clause, Mitigation),
160
+ risk_resource(Risk, RiskTerm), iri_term(RiskTerm, RiskIri),
161
+ mitigation_resource(Mitigation, MitigationTerm), iri_term(MitigationTerm, MitigationIri).
162
+
163
+ healthcare_ranked_item(Rank, Risk, Score, Level, Clause, Mitigation) :-
164
+ healthcare_risk_report(Ranked),
165
+ list_member(rank(Rank, dpv_risk(Risk, Score, Level, Clause, Mitigation)), Ranked).
166
+ list_member(X, [X|_]).
167
+ list_member(X, [_|Xs]) :- list_member(X, Xs).
168
+ number_atom(Number, Atom) :- number_chars(Number, Chars), atom_chars(Atom, Chars).
169
+
170
+ % ISO Prolog helper: print the complete test result as rdf/4 facts.
171
+ write_results :-
172
+ result_rdf(S, P, O, G),
173
+ write_term(rdf(S, P, O, G), [quoted(true)]),
174
+ write('.'),
175
+ nl,
176
+ fail.
177
+ write_results.