eyeprolog 1.3.99 → 1.3.100
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.
- package/README.md +4 -1
- package/examples/cross-organization-data-sharing.pl +121 -0
- package/examples/data/README.md +15 -0
- package/examples/data/cross-organization-data-sharing-input.nq +40 -0
- package/examples/data/cross-organization-data-sharing-output.nq +5 -0
- package/examples/data/cross-organization-data-sharing-output.pl +3 -0
- package/examples/data/cross-organization-data-sharing-rules.pl +77 -0
- package/examples/data/explainable-ev-depot-configuration-input.nq +22 -0
- package/examples/data/explainable-ev-depot-configuration-output.nq +4 -0
- package/examples/data/explainable-ev-depot-configuration-output.pl +2 -0
- package/examples/data/explainable-ev-depot-configuration-rules.pl +52 -0
- package/examples/data/operational-incident-response-input.nq +17 -0
- package/examples/data/operational-incident-response-output.nq +9 -0
- package/examples/data/operational-incident-response-output.pl +7 -0
- package/examples/data/operational-incident-response-rules.pl +68 -0
- package/examples/data/sbom-vulnerability-response-input.nq +19 -0
- package/examples/data/sbom-vulnerability-response-output.nq +5 -0
- package/examples/data/sbom-vulnerability-response-output.pl +3 -0
- package/examples/data/sbom-vulnerability-response-rules.pl +85 -0
- package/examples/data/scientific-evidence-graph-input.nq +32 -0
- package/examples/data/scientific-evidence-graph-output.nq +4 -0
- package/examples/data/scientific-evidence-graph-output.pl +2 -0
- package/examples/data/scientific-evidence-graph-rules.pl +54 -0
- package/examples/deck/README.md +5 -0
- package/examples/deck/cross-organization-data-sharing.md +35 -0
- package/examples/deck/explainable-ev-depot-configuration.md +38 -0
- package/examples/deck/operational-incident-response.md +35 -0
- package/examples/deck/sbom-vulnerability-response.md +42 -0
- package/examples/deck/scientific-evidence-graph.md +40 -0
- package/examples/explainable-ev-depot-configuration.pl +78 -0
- package/examples/operational-incident-response.pl +89 -0
- package/examples/output/cross-organization-data-sharing.pl +8 -0
- package/examples/output/explainable-ev-depot-configuration.pl +8 -0
- package/examples/output/operational-incident-response.pl +8 -0
- package/examples/output/sbom-vulnerability-response.pl +4 -0
- package/examples/output/scientific-evidence-graph.pl +9 -0
- package/examples/sbom-vulnerability-response.pl +108 -0
- package/examples/scientific-evidence-graph.pl +90 -0
- package/package.json +1 -1
- package/playground.html +8 -3
- package/src/lib/freeze.pl +23 -14
- package/test/run-playground.mjs +12 -0
- package/test/run-regression.mjs +17 -0
- package/the-art-of-eyeprolog.md +11 -4
- package/why-eyeprolog.md +2 -0
package/README.md
CHANGED
|
@@ -64,8 +64,9 @@ printf 'human(socrates).\nmortal(X) :- human(X).\n' |
|
|
|
64
64
|
- [Why EyeProlog?](https://eyereasoner.github.io/eyeprolog/why-eyeprolog) — project scope and design
|
|
65
65
|
- [Playground](https://eyereasoner.github.io/eyeprolog/playground) — run EyeProlog in a browser
|
|
66
66
|
- [Examples](examples) — runnable programs and checked output
|
|
67
|
+
- [Example decks](examples/deck/README.md) — explainable RDF/Prolog scenarios with reproducible roundtrips
|
|
67
68
|
- [Symbiotic Knowledge Graphs](examples/deck/symbiotic-knowledge-graphs.md) — RDF ↔ Prolog heatwave-response demo for human/AI/KG co-evolution
|
|
68
|
-
- [rdf-prolog-roundtrip](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the
|
|
69
|
+
- [rdf-prolog-roundtrip](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the RDF examples
|
|
69
70
|
- [ISO conformance audit](test/conformance/ISO-COMPLIANCE.md) — supported Part 1 profile
|
|
70
71
|
- [Conformance report](conformance-report.md) — generated public corpus summary
|
|
71
72
|
- [OpenRuleBench](openrulebench/README.md) — portable benchmark profile
|
|
@@ -76,6 +77,8 @@ EyeProlog can sit behind an RDF knowledge graph without inventing a private grap
|
|
|
76
77
|
|
|
77
78
|
The checked [Symbiotic Knowledge Graphs example](examples/symbiotic-knowledge-graph.pl) uses named graphs and RDF 1.2 triple terms to distinguish trusted knowledge, AI-proposed statements, and human review. Its [wide-audience companion](examples/deck/symbiotic-knowledge-graphs.md) explains why this is a useful present-day software model for human/AI/KG co-evolution: RDF supplies shared semantic memory, Prolog supplies explicit deliberation, AI supplies new hypotheses, and people remain participants in meaning and judgment.
|
|
78
79
|
|
|
80
|
+
The same RDF → Prolog → RDF boundary is exercised by five additional checked scenarios: [cross-organization data sharing](examples/deck/cross-organization-data-sharing.md), [explainable EV-depot configuration](examples/deck/explainable-ev-depot-configuration.md), [operational incident response](examples/deck/operational-incident-response.md), [software supply-chain vulnerability response](examples/deck/sbom-vulnerability-response.md), and a [scientific evidence graph](examples/deck/scientific-evidence-graph.md). Together they cover policy decisions, reversible configuration reasoning, dependency-graph diagnosis, transitive SBOM exposure, and evidence aggregation with explicit disagreement.
|
|
81
|
+
|
|
79
82
|
## Development
|
|
80
83
|
|
|
81
84
|
```sh
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
% Generated by rdf-prolog-roundtrip.
|
|
2
|
+
|
|
3
|
+
% RDF terms use rdf(Subject, Predicate, Object, Graph).
|
|
4
|
+
|
|
5
|
+
rdf(iri('https://example.org/data-sharing/policy/main'), iri('http://www.w3.org/ns/odrl/2/permission'), iri('https://example.org/data-sharing/policy/research-permission'), iri('https://example.org/data-sharing/graph/policy')).
|
|
6
|
+
rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/policy')).
|
|
7
|
+
rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/policy')).
|
|
8
|
+
rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/policy')).
|
|
9
|
+
rdf(iri('https://example.org/data-sharing/policy/research-permission'), iri('https://example.org/vocab/maxRetentionDays'), literal('180', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/policy')).
|
|
10
|
+
rdf(iri('https://example.org/data-sharing/policy/main'), iri('http://www.w3.org/ns/odrl/2/prohibition'), iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('https://example.org/data-sharing/graph/policy')).
|
|
11
|
+
rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/target'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/policy')).
|
|
12
|
+
rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/action'), iri('http://www.w3.org/ns/odrl/2/distribute'), iri('https://example.org/data-sharing/graph/policy')).
|
|
13
|
+
rdf(iri('https://example.org/data-sharing/policy/marketing-prohibition'), iri('http://www.w3.org/ns/odrl/2/purpose'), iri('https://w3id.org/dpv#Marketing'), iri('https://example.org/data-sharing/graph/policy')).
|
|
14
|
+
rdf(iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/eu'), iri('https://example.org/data-sharing/graph/organizations')).
|
|
15
|
+
rdf(iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/vocab/certifiedResearchOrg'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/organizations')).
|
|
16
|
+
rdf(iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/us'), iri('https://example.org/data-sharing/graph/organizations')).
|
|
17
|
+
rdf(iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/vocab/certifiedResearchOrg'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/organizations')).
|
|
18
|
+
rdf(iri('https://example.org/data-sharing/org/ad-network'), iri('https://example.org/vocab/region'), iri('https://example.org/data-sharing/region/eu'), iri('https://example.org/data-sharing/graph/organizations')).
|
|
19
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
|
|
20
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/university-eu'), iri('https://example.org/data-sharing/graph/requests')).
|
|
21
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/requests')).
|
|
22
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/requests')).
|
|
23
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/retentionDays'), literal('120', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
|
|
24
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
|
|
25
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
|
|
26
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
|
|
27
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
|
|
28
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/ad-network'), iri('https://example.org/data-sharing/graph/requests')).
|
|
29
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/distribute'), iri('https://example.org/data-sharing/graph/requests')).
|
|
30
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#Marketing'), iri('https://example.org/data-sharing/graph/requests')).
|
|
31
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/retentionDays'), literal('30', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
|
|
32
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/no'), iri('https://example.org/data-sharing/graph/requests')).
|
|
33
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
|
|
34
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
|
|
35
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/dataset'), iri('https://example.org/data-sharing/dataset/cohort-a'), iri('https://example.org/data-sharing/graph/requests')).
|
|
36
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/recipient'), iri('https://example.org/data-sharing/org/university-us'), iri('https://example.org/data-sharing/graph/requests')).
|
|
37
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/action'), iri('http://www.w3.org/ns/odrl/2/use'), iri('https://example.org/data-sharing/graph/requests')).
|
|
38
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/purpose'), iri('https://w3id.org/dpv#ScientificResearch'), iri('https://example.org/data-sharing/graph/requests')).
|
|
39
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/retentionDays'), literal('90', datatype('http://www.w3.org/2001/XMLSchema#integer')), iri('https://example.org/data-sharing/graph/requests')).
|
|
40
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/pseudonymized'), iri('https://example.org/data-sharing/value/yes'), iri('https://example.org/data-sharing/graph/requests')).
|
|
41
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/legalBasis'), iri('https://w3id.org/dpv#Consent'), iri('https://example.org/data-sharing/graph/requests')).
|
|
42
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'), iri('https://example.org/vocab/standardContractualClauses'), iri('https://example.org/data-sharing/value/no'), iri('https://example.org/data-sharing/graph/requests')).
|
|
43
|
+
|
|
44
|
+
% Rules
|
|
45
|
+
% Flagship example: cross-organization data-sharing decisions using RDF,
|
|
46
|
+
% W3C ODRL vocabulary, DPV terms, and portable ISO Prolog policy rules.
|
|
47
|
+
|
|
48
|
+
%% goal: sharing_decision(X0, X1)
|
|
49
|
+
%% goal: obligation(X0, X1)
|
|
50
|
+
%% goal: decision_reason(X0, X1)
|
|
51
|
+
|
|
52
|
+
v(dataset, iri('https://example.org/vocab/dataset')).
|
|
53
|
+
v(recipient, iri('https://example.org/vocab/recipient')).
|
|
54
|
+
v(action, iri('https://example.org/vocab/action')).
|
|
55
|
+
v(purpose, iri('https://example.org/vocab/purpose')).
|
|
56
|
+
v(retention_days, iri('https://example.org/vocab/retentionDays')).
|
|
57
|
+
v(pseudonymized, iri('https://example.org/vocab/pseudonymized')).
|
|
58
|
+
v(legal_basis, iri('https://example.org/vocab/legalBasis')).
|
|
59
|
+
v(scc, iri('https://example.org/vocab/standardContractualClauses')).
|
|
60
|
+
v(region, iri('https://example.org/vocab/region')).
|
|
61
|
+
v(certified, iri('https://example.org/vocab/certifiedResearchOrg')).
|
|
62
|
+
v(max_retention, iri('https://example.org/vocab/maxRetentionDays')).
|
|
63
|
+
|
|
64
|
+
g(requests, iri('https://example.org/data-sharing/graph/requests')).
|
|
65
|
+
g(policy, iri('https://example.org/data-sharing/graph/policy')).
|
|
66
|
+
g(orgs, iri('https://example.org/data-sharing/graph/organizations')).
|
|
67
|
+
|
|
68
|
+
yes(iri('https://example.org/data-sharing/value/yes')).
|
|
69
|
+
no(iri('https://example.org/data-sharing/value/no')).
|
|
70
|
+
eu(iri('https://example.org/data-sharing/region/eu')).
|
|
71
|
+
consent_basis(iri('https://w3id.org/dpv#Consent')).
|
|
72
|
+
|
|
73
|
+
request(research_eu, iri('https://example.org/data-sharing/request/research-eu')).
|
|
74
|
+
request(marketing, iri('https://example.org/data-sharing/request/marketing')).
|
|
75
|
+
request(research_us, iri('https://example.org/data-sharing/request/research-us')).
|
|
76
|
+
|
|
77
|
+
integer_literal(literal(Text, datatype('http://www.w3.org/2001/XMLSchema#integer')), N) :- atom_chars(Text,Cs), number_chars(N,Cs).
|
|
78
|
+
|
|
79
|
+
request_data(Id,R,D,Recipient,Action,Purpose,Retention,Pseudo,Basis,Scc) :-
|
|
80
|
+
request(Id,R), g(requests,G), v(dataset,PD),v(recipient,PR),v(action,PA),v(purpose,PP),v(retention_days,PT),v(pseudonymized,PPs),v(legal_basis,PL),v(scc,PS),
|
|
81
|
+
rdf(R,PD,D,G),rdf(R,PR,Recipient,G),rdf(R,PA,Action,G),rdf(R,PP,Purpose,G),rdf(R,PT,L,G),integer_literal(L,Retention),rdf(R,PPs,Pseudo,G),rdf(R,PL,Basis,G),rdf(R,PS,Scc,G).
|
|
82
|
+
|
|
83
|
+
policy_permission(D,Action,Purpose,MaxRetention) :-
|
|
84
|
+
g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/permission'),Rule,G),
|
|
85
|
+
rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G),
|
|
86
|
+
v(max_retention,PM), rdf(Rule,PM,L,G), integer_literal(L,MaxRetention).
|
|
87
|
+
|
|
88
|
+
policy_prohibition(D,Action,Purpose) :-
|
|
89
|
+
g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/prohibition'),Rule,G),
|
|
90
|
+
rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G).
|
|
91
|
+
|
|
92
|
+
recipient_region(Recipient,Region) :- g(orgs,G),v(region,P),rdf(Recipient,P,Region,G).
|
|
93
|
+
certified(Recipient) :- g(orgs,G),v(certified,P),yes(Y),rdf(Recipient,P,Y,G).
|
|
94
|
+
|
|
95
|
+
sharing_decision(Id, deny) :- request_data(Id,_R,D,_Recip,Action,Purpose,_Ret,_Ps,_B,_S), policy_prohibition(D,Action,Purpose).
|
|
96
|
+
sharing_decision(Id, review) :-
|
|
97
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
98
|
+
recipient_region(Recip,Region), eu(EU), Region \= EU, no(N), Scc=N.
|
|
99
|
+
sharing_decision(Id, permit) :-
|
|
100
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,_Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
101
|
+
recipient_region(Recip,Region), eu(EU), Region=EU.
|
|
102
|
+
sharing_decision(Id, permit) :-
|
|
103
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
104
|
+
recipient_region(Recip,Region), eu(EU), Region \= EU, Scc=Y.
|
|
105
|
+
|
|
106
|
+
obligation(research_eu, delete_after_days(120)) :- sharing_decision(research_eu,permit).
|
|
107
|
+
obligation(research_eu, retain_audit_log) :- sharing_decision(research_eu,permit).
|
|
108
|
+
|
|
109
|
+
decision_reason(research_eu, "ODRL permission matches; recipient is certified, data is pseudonymized, retention is within 180 days, and the transfer stays in-region.") :- sharing_decision(research_eu,permit).
|
|
110
|
+
decision_reason(marketing, "The requested marketing distribution matches an explicit ODRL prohibition.") :- sharing_decision(marketing,deny).
|
|
111
|
+
decision_reason(research_us, "The research purpose is permitted, but the out-of-region transfer lacks the required contractual safeguard and must be reviewed.") :- sharing_decision(research_us,review).
|
|
112
|
+
|
|
113
|
+
result_rdf(R, iri('https://example.org/vocab/sharingDecision'), D, iri('https://example.org/data-sharing/graph/derived')) :-
|
|
114
|
+
sharing_decision(Id,Decision), request(Id,R), decision_iri(Decision,D).
|
|
115
|
+
decision_iri(permit,iri('https://example.org/data-sharing/decision/permit')).
|
|
116
|
+
decision_iri(deny,iri('https://example.org/data-sharing/decision/deny')).
|
|
117
|
+
decision_iri(review,iri('https://example.org/data-sharing/decision/review')).
|
|
118
|
+
|
|
119
|
+
write_results :- result_rdf(S,P,O,G), write_term(rdf(S,P,O,G),[quoted(true)]), write('.'), nl, fail.
|
|
120
|
+
write_results.
|
|
121
|
+
:- set_prolog_flag(unknown, fail).
|
package/examples/data/README.md
CHANGED
|
@@ -19,3 +19,18 @@ symbiotic-knowledge-graph-input.nq
|
|
|
19
19
|
The input uses named graphs for source boundaries and RDF 1.2 triple terms for AI-proposed statements. A proposed triple is therefore metadata until governance rules accept it; it does not become an operational assertion merely because an AI produced it.
|
|
20
20
|
|
|
21
21
|
See [the wide-audience deck](../deck/symbiotic-knowledge-graphs.md) for the scenario and architecture.
|
|
22
|
+
|
|
23
|
+
## Additional decision and evidence roundtrips
|
|
24
|
+
|
|
25
|
+
Five further examples use the same explicit boundary: source RDF is converted to `rdf/4` facts, portable rules are appended for EyeProlog, checked conclusions are emitted as Prolog, and ground result facts are converted back to RDF.
|
|
26
|
+
|
|
27
|
+
| Scenario | Source and rules | Materialized result | Companion |
|
|
28
|
+
| --- | --- | --- | --- |
|
|
29
|
+
| Cross-organization data sharing | [`cross-organization-data-sharing-input.nq`](cross-organization-data-sharing-input.nq) · [`cross-organization-data-sharing-rules.pl`](cross-organization-data-sharing-rules.pl) | [`cross-organization-data-sharing-output.nq`](cross-organization-data-sharing-output.nq) | [deck](../deck/cross-organization-data-sharing.md) |
|
|
30
|
+
| Explainable EV-depot configuration | [`explainable-ev-depot-configuration-input.nq`](explainable-ev-depot-configuration-input.nq) · [`explainable-ev-depot-configuration-rules.pl`](explainable-ev-depot-configuration-rules.pl) | [`explainable-ev-depot-configuration-output.nq`](explainable-ev-depot-configuration-output.nq) | [deck](../deck/explainable-ev-depot-configuration.md) |
|
|
31
|
+
| Operational incident response | [`operational-incident-response-input.nq`](operational-incident-response-input.nq) · [`operational-incident-response-rules.pl`](operational-incident-response-rules.pl) | [`operational-incident-response-output.nq`](operational-incident-response-output.nq) | [deck](../deck/operational-incident-response.md) |
|
|
32
|
+
| SBOM vulnerability response | [`sbom-vulnerability-response-input.nq`](sbom-vulnerability-response-input.nq) · [`sbom-vulnerability-response-rules.pl`](sbom-vulnerability-response-rules.pl) | [`sbom-vulnerability-response-output.nq`](sbom-vulnerability-response-output.nq) | [deck](../deck/sbom-vulnerability-response.md) |
|
|
33
|
+
| Scientific evidence graph | [`scientific-evidence-graph-input.nq`](scientific-evidence-graph-input.nq) · [`scientific-evidence-graph-rules.pl`](scientific-evidence-graph-rules.pl) | [`scientific-evidence-graph-output.nq`](scientific-evidence-graph-output.nq) | [deck](../deck/scientific-evidence-graph.md) |
|
|
34
|
+
|
|
35
|
+
Each scenario also has a generated runnable program one directory up and a checked stdout file in `../output/`. The corresponding deck contains the exact reproduction commands for the RDF roundtrip.
|
|
36
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/data-sharing/policy/main> <http://www.w3.org/ns/odrl/2/permission> <https://example.org/data-sharing/policy/research-permission> <https://example.org/data-sharing/graph/policy> .
|
|
4
|
+
<https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/target> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/policy> .
|
|
5
|
+
<https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/policy> .
|
|
6
|
+
<https://example.org/data-sharing/policy/research-permission> <http://www.w3.org/ns/odrl/2/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/policy> .
|
|
7
|
+
<https://example.org/data-sharing/policy/research-permission> <https://example.org/vocab/maxRetentionDays> "180"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/policy> .
|
|
8
|
+
<https://example.org/data-sharing/policy/main> <http://www.w3.org/ns/odrl/2/prohibition> <https://example.org/data-sharing/policy/marketing-prohibition> <https://example.org/data-sharing/graph/policy> .
|
|
9
|
+
<https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/target> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/policy> .
|
|
10
|
+
<https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/action> <http://www.w3.org/ns/odrl/2/distribute> <https://example.org/data-sharing/graph/policy> .
|
|
11
|
+
<https://example.org/data-sharing/policy/marketing-prohibition> <http://www.w3.org/ns/odrl/2/purpose> <https://w3id.org/dpv#Marketing> <https://example.org/data-sharing/graph/policy> .
|
|
12
|
+
<https://example.org/data-sharing/org/university-eu> <https://example.org/vocab/region> <https://example.org/data-sharing/region/eu> <https://example.org/data-sharing/graph/organizations> .
|
|
13
|
+
<https://example.org/data-sharing/org/university-eu> <https://example.org/vocab/certifiedResearchOrg> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/organizations> .
|
|
14
|
+
<https://example.org/data-sharing/org/university-us> <https://example.org/vocab/region> <https://example.org/data-sharing/region/us> <https://example.org/data-sharing/graph/organizations> .
|
|
15
|
+
<https://example.org/data-sharing/org/university-us> <https://example.org/vocab/certifiedResearchOrg> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/organizations> .
|
|
16
|
+
<https://example.org/data-sharing/org/ad-network> <https://example.org/vocab/region> <https://example.org/data-sharing/region/eu> <https://example.org/data-sharing/graph/organizations> .
|
|
17
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
|
|
18
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/university-eu> <https://example.org/data-sharing/graph/requests> .
|
|
19
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/requests> .
|
|
20
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/requests> .
|
|
21
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/retentionDays> "120"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
|
|
22
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
|
|
23
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
|
|
24
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
|
|
25
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
|
|
26
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/ad-network> <https://example.org/data-sharing/graph/requests> .
|
|
27
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/distribute> <https://example.org/data-sharing/graph/requests> .
|
|
28
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/purpose> <https://w3id.org/dpv#Marketing> <https://example.org/data-sharing/graph/requests> .
|
|
29
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/retentionDays> "30"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
|
|
30
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/no> <https://example.org/data-sharing/graph/requests> .
|
|
31
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
|
|
32
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
|
|
33
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/dataset> <https://example.org/data-sharing/dataset/cohort-a> <https://example.org/data-sharing/graph/requests> .
|
|
34
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/recipient> <https://example.org/data-sharing/org/university-us> <https://example.org/data-sharing/graph/requests> .
|
|
35
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/action> <http://www.w3.org/ns/odrl/2/use> <https://example.org/data-sharing/graph/requests> .
|
|
36
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/purpose> <https://w3id.org/dpv#ScientificResearch> <https://example.org/data-sharing/graph/requests> .
|
|
37
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/retentionDays> "90"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/data-sharing/graph/requests> .
|
|
38
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/pseudonymized> <https://example.org/data-sharing/value/yes> <https://example.org/data-sharing/graph/requests> .
|
|
39
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/legalBasis> <https://w3id.org/dpv#Consent> <https://example.org/data-sharing/graph/requests> .
|
|
40
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/standardContractualClauses> <https://example.org/data-sharing/value/no> <https://example.org/data-sharing/graph/requests> .
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/data-sharing/request/marketing> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/deny> <https://example.org/data-sharing/graph/derived> .
|
|
4
|
+
<https://example.org/data-sharing/request/research-us> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/review> <https://example.org/data-sharing/graph/derived> .
|
|
5
|
+
<https://example.org/data-sharing/request/research-eu> <https://example.org/vocab/sharingDecision> <https://example.org/data-sharing/decision/permit> <https://example.org/data-sharing/graph/derived> .
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
rdf(iri('https://example.org/data-sharing/request/marketing'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/deny'),iri('https://example.org/data-sharing/graph/derived')).
|
|
2
|
+
rdf(iri('https://example.org/data-sharing/request/research-us'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/review'),iri('https://example.org/data-sharing/graph/derived')).
|
|
3
|
+
rdf(iri('https://example.org/data-sharing/request/research-eu'),iri('https://example.org/vocab/sharingDecision'),iri('https://example.org/data-sharing/decision/permit'),iri('https://example.org/data-sharing/graph/derived')).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
% Flagship example: cross-organization data-sharing decisions using RDF,
|
|
2
|
+
% W3C ODRL vocabulary, DPV terms, and portable ISO Prolog policy rules.
|
|
3
|
+
|
|
4
|
+
%% goal: sharing_decision(X0, X1)
|
|
5
|
+
%% goal: obligation(X0, X1)
|
|
6
|
+
%% goal: decision_reason(X0, X1)
|
|
7
|
+
|
|
8
|
+
v(dataset, iri('https://example.org/vocab/dataset')).
|
|
9
|
+
v(recipient, iri('https://example.org/vocab/recipient')).
|
|
10
|
+
v(action, iri('https://example.org/vocab/action')).
|
|
11
|
+
v(purpose, iri('https://example.org/vocab/purpose')).
|
|
12
|
+
v(retention_days, iri('https://example.org/vocab/retentionDays')).
|
|
13
|
+
v(pseudonymized, iri('https://example.org/vocab/pseudonymized')).
|
|
14
|
+
v(legal_basis, iri('https://example.org/vocab/legalBasis')).
|
|
15
|
+
v(scc, iri('https://example.org/vocab/standardContractualClauses')).
|
|
16
|
+
v(region, iri('https://example.org/vocab/region')).
|
|
17
|
+
v(certified, iri('https://example.org/vocab/certifiedResearchOrg')).
|
|
18
|
+
v(max_retention, iri('https://example.org/vocab/maxRetentionDays')).
|
|
19
|
+
|
|
20
|
+
g(requests, iri('https://example.org/data-sharing/graph/requests')).
|
|
21
|
+
g(policy, iri('https://example.org/data-sharing/graph/policy')).
|
|
22
|
+
g(orgs, iri('https://example.org/data-sharing/graph/organizations')).
|
|
23
|
+
|
|
24
|
+
yes(iri('https://example.org/data-sharing/value/yes')).
|
|
25
|
+
no(iri('https://example.org/data-sharing/value/no')).
|
|
26
|
+
eu(iri('https://example.org/data-sharing/region/eu')).
|
|
27
|
+
consent_basis(iri('https://w3id.org/dpv#Consent')).
|
|
28
|
+
|
|
29
|
+
request(research_eu, iri('https://example.org/data-sharing/request/research-eu')).
|
|
30
|
+
request(marketing, iri('https://example.org/data-sharing/request/marketing')).
|
|
31
|
+
request(research_us, iri('https://example.org/data-sharing/request/research-us')).
|
|
32
|
+
|
|
33
|
+
integer_literal(literal(Text, datatype('http://www.w3.org/2001/XMLSchema#integer')), N) :- atom_chars(Text,Cs), number_chars(N,Cs).
|
|
34
|
+
|
|
35
|
+
request_data(Id,R,D,Recipient,Action,Purpose,Retention,Pseudo,Basis,Scc) :-
|
|
36
|
+
request(Id,R), g(requests,G), v(dataset,PD),v(recipient,PR),v(action,PA),v(purpose,PP),v(retention_days,PT),v(pseudonymized,PPs),v(legal_basis,PL),v(scc,PS),
|
|
37
|
+
rdf(R,PD,D,G),rdf(R,PR,Recipient,G),rdf(R,PA,Action,G),rdf(R,PP,Purpose,G),rdf(R,PT,L,G),integer_literal(L,Retention),rdf(R,PPs,Pseudo,G),rdf(R,PL,Basis,G),rdf(R,PS,Scc,G).
|
|
38
|
+
|
|
39
|
+
policy_permission(D,Action,Purpose,MaxRetention) :-
|
|
40
|
+
g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/permission'),Rule,G),
|
|
41
|
+
rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G),
|
|
42
|
+
v(max_retention,PM), rdf(Rule,PM,L,G), integer_literal(L,MaxRetention).
|
|
43
|
+
|
|
44
|
+
policy_prohibition(D,Action,Purpose) :-
|
|
45
|
+
g(policy,G), rdf(_,iri('http://www.w3.org/ns/odrl/2/prohibition'),Rule,G),
|
|
46
|
+
rdf(Rule,iri('http://www.w3.org/ns/odrl/2/target'),D,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/action'),Action,G), rdf(Rule,iri('http://www.w3.org/ns/odrl/2/purpose'),Purpose,G).
|
|
47
|
+
|
|
48
|
+
recipient_region(Recipient,Region) :- g(orgs,G),v(region,P),rdf(Recipient,P,Region,G).
|
|
49
|
+
certified(Recipient) :- g(orgs,G),v(certified,P),yes(Y),rdf(Recipient,P,Y,G).
|
|
50
|
+
|
|
51
|
+
sharing_decision(Id, deny) :- request_data(Id,_R,D,_Recip,Action,Purpose,_Ret,_Ps,_B,_S), policy_prohibition(D,Action,Purpose).
|
|
52
|
+
sharing_decision(Id, review) :-
|
|
53
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
54
|
+
recipient_region(Recip,Region), eu(EU), Region \= EU, no(N), Scc=N.
|
|
55
|
+
sharing_decision(Id, permit) :-
|
|
56
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,_Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
57
|
+
recipient_region(Recip,Region), eu(EU), Region=EU.
|
|
58
|
+
sharing_decision(Id, permit) :-
|
|
59
|
+
request_data(Id,_R,D,Recip,Action,Purpose,Retention,Pseudo,Basis,Scc), consent_basis(Basis), policy_permission(D,Action,Purpose,Max), certified(Recip), Retention =< Max, yes(Y), Pseudo=Y,
|
|
60
|
+
recipient_region(Recip,Region), eu(EU), Region \= EU, Scc=Y.
|
|
61
|
+
|
|
62
|
+
obligation(research_eu, delete_after_days(120)) :- sharing_decision(research_eu,permit).
|
|
63
|
+
obligation(research_eu, retain_audit_log) :- sharing_decision(research_eu,permit).
|
|
64
|
+
|
|
65
|
+
decision_reason(research_eu, "ODRL permission matches; recipient is certified, data is pseudonymized, retention is within 180 days, and the transfer stays in-region.") :- sharing_decision(research_eu,permit).
|
|
66
|
+
decision_reason(marketing, "The requested marketing distribution matches an explicit ODRL prohibition.") :- sharing_decision(marketing,deny).
|
|
67
|
+
decision_reason(research_us, "The research purpose is permitted, but the out-of-region transfer lacks the required contractual safeguard and must be reviewed.") :- sharing_decision(research_us,review).
|
|
68
|
+
|
|
69
|
+
result_rdf(R, iri('https://example.org/vocab/sharingDecision'), D, iri('https://example.org/data-sharing/graph/derived')) :-
|
|
70
|
+
sharing_decision(Id,Decision), request(Id,R), decision_iri(Decision,D).
|
|
71
|
+
decision_iri(permit,iri('https://example.org/data-sharing/decision/permit')).
|
|
72
|
+
decision_iri(deny,iri('https://example.org/data-sharing/decision/deny')).
|
|
73
|
+
decision_iri(review,iri('https://example.org/data-sharing/decision/review')).
|
|
74
|
+
|
|
75
|
+
write_results :- result_rdf(S,P,O,G), write_term(rdf(S,P,O,G),[quoted(true)]), write('.'), nl, fail.
|
|
76
|
+
write_results.
|
|
77
|
+
:- set_prolog_flag(unknown, fail).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/availablePowerKw> "60"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/site> .
|
|
4
|
+
<https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/requiredChargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/site> .
|
|
5
|
+
<https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/requiredConnector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/site> .
|
|
6
|
+
<https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/site> .
|
|
7
|
+
<https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/chargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
8
|
+
<https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/sitePowerRequirementKw> "45"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
9
|
+
<https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
|
|
10
|
+
<https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
|
|
11
|
+
<https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/chargeKw> "50"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
12
|
+
<https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/sitePowerRequirementKw> "80"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
13
|
+
<https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
|
|
14
|
+
<https://example.org/ev-depot/charger/rapid50> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
|
|
15
|
+
<https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/chargeKw> "11"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
16
|
+
<https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/sitePowerRequirementKw> "25"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
17
|
+
<https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/ccs2> <https://example.org/ev-depot/graph/catalog> .
|
|
18
|
+
<https://example.org/ev-depot/charger/budget11> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
|
|
19
|
+
<https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/chargeKw> "22"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
20
|
+
<https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/sitePowerRequirementKw> "45"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/ev-depot/graph/catalog> .
|
|
21
|
+
<https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/connector> <https://example.org/ev-depot/connector/type2> <https://example.org/ev-depot/graph/catalog> .
|
|
22
|
+
<https://example.org/ev-depot/charger/legacy22> <https://example.org/vocab/supply> <https://example.org/ev-depot/supply/three-phase> <https://example.org/ev-depot/graph/catalog> .
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/ev-depot/site/depot-a> <https://example.org/vocab/recommendedCharger> <https://example.org/ev-depot/charger/fleet22> <https://example.org/ev-depot/graph/derived> .
|
|
4
|
+
<https://example.org/ev-depot/charger/fleet22> <https://example.org/vocab/configurationStatus> <https://example.org/ev-depot/state/compatible> <https://example.org/ev-depot/graph/derived> .
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
rdf(iri('https://example.org/ev-depot/site/depot-a'),iri('https://example.org/vocab/recommendedCharger'),iri('https://example.org/ev-depot/charger/fleet22'),iri('https://example.org/ev-depot/graph/derived')).
|
|
2
|
+
rdf(iri('https://example.org/ev-depot/charger/fleet22'),iri('https://example.org/vocab/configurationStatus'),iri('https://example.org/ev-depot/state/compatible'),iri('https://example.org/ev-depot/graph/derived')).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
% Flagship example: explainable configuration rather than opaque filtering.
|
|
2
|
+
% The same relational model answers: what fits, why does an option fail, and
|
|
3
|
+
% what would have to change to make a rejected option viable?
|
|
4
|
+
|
|
5
|
+
%% goal: compatible(X0, X1)
|
|
6
|
+
%% goal: recommendation(X0, X1)
|
|
7
|
+
%% goal: blocker(X0, X1, X2)
|
|
8
|
+
%% goal: required_change(X0, X1, X2)
|
|
9
|
+
|
|
10
|
+
v(available_power,iri('https://example.org/vocab/availablePowerKw')).
|
|
11
|
+
v(required_charge,iri('https://example.org/vocab/requiredChargeKw')).
|
|
12
|
+
v(required_connector,iri('https://example.org/vocab/requiredConnector')).
|
|
13
|
+
v(supply,iri('https://example.org/vocab/supply')).
|
|
14
|
+
v(charge_kw,iri('https://example.org/vocab/chargeKw')).
|
|
15
|
+
v(site_power_requirement,iri('https://example.org/vocab/sitePowerRequirementKw')).
|
|
16
|
+
v(connector,iri('https://example.org/vocab/connector')).
|
|
17
|
+
|
|
18
|
+
g(site,iri('https://example.org/ev-depot/graph/site')). g(catalog,iri('https://example.org/ev-depot/graph/catalog')).
|
|
19
|
+
resource(depot_a,iri('https://example.org/ev-depot/site/depot-a')).
|
|
20
|
+
resource(fleet22,iri('https://example.org/ev-depot/charger/fleet22')).
|
|
21
|
+
resource(rapid50,iri('https://example.org/ev-depot/charger/rapid50')).
|
|
22
|
+
resource(budget11,iri('https://example.org/ev-depot/charger/budget11')).
|
|
23
|
+
resource(legacy22,iri('https://example.org/ev-depot/charger/legacy22')).
|
|
24
|
+
product(fleet22). product(rapid50). product(budget11). product(legacy22).
|
|
25
|
+
integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
|
|
26
|
+
|
|
27
|
+
site_number(Key,N):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,L,G),integer_literal(L,N).
|
|
28
|
+
site_term(Key,V):-resource(depot_a,S),v(Key,P),g(site,G),rdf(S,P,V,G).
|
|
29
|
+
product_number(Product,Key,N):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,L,G),integer_literal(L,N).
|
|
30
|
+
product_term(Product,Key,V):-resource(Product,R),v(Key,P),g(catalog,G),rdf(R,P,V,G).
|
|
31
|
+
|
|
32
|
+
blocker(depot_a,Product,insufficient_site_power(Available,Needed)):-product(Product),site_number(available_power,Available),product_number(Product,site_power_requirement,Needed),Available < Needed.
|
|
33
|
+
blocker(depot_a,Product,insufficient_charge_rate(Offered,Required)):-product(Product),product_number(Product,charge_kw,Offered),site_number(required_charge,Required),Offered < Required.
|
|
34
|
+
blocker(depot_a,Product,connector_mismatch(Offered,Required)):-product(Product),product_term(Product,connector,OfferedIri),site_term(required_connector,RequiredIri),OfferedIri \= RequiredIri,connector_name(OfferedIri,Offered),connector_name(RequiredIri,Required).
|
|
35
|
+
blocker(depot_a,Product,supply_mismatch):-product(Product),product_term(Product,supply,S),site_term(supply,SiteS),S \= SiteS.
|
|
36
|
+
|
|
37
|
+
connector_name(iri('https://example.org/ev-depot/connector/ccs2'),ccs2).
|
|
38
|
+
connector_name(iri('https://example.org/ev-depot/connector/type2'),type2).
|
|
39
|
+
|
|
40
|
+
compatible(depot_a,Product):-product(Product),\+ blocker(depot_a,Product,_).
|
|
41
|
+
recommendation(depot_a,fleet22):-compatible(depot_a,fleet22).
|
|
42
|
+
|
|
43
|
+
required_change(depot_a,Product,increase_site_power_to(Needed)):-blocker(depot_a,Product,insufficient_site_power(_,Needed)).
|
|
44
|
+
required_change(depot_a,Product,choose_charger_at_least_kw(Required)):-blocker(depot_a,Product,insufficient_charge_rate(_,Required)).
|
|
45
|
+
required_change(depot_a,Product,use_connector(Required)):-blocker(depot_a,Product,connector_mismatch(_,Required)).
|
|
46
|
+
|
|
47
|
+
result_rdf(S,iri('https://example.org/vocab/recommendedCharger'),C,iri('https://example.org/ev-depot/graph/derived')):-recommendation(depot_a,Product),resource(depot_a,S),resource(Product,C).
|
|
48
|
+
result_rdf(C,iri('https://example.org/vocab/configurationStatus'),iri('https://example.org/ev-depot/state/compatible'),iri('https://example.org/ev-depot/graph/derived')):-compatible(depot_a,Product),resource(Product,C).
|
|
49
|
+
|
|
50
|
+
write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
|
|
51
|
+
write_results.
|
|
52
|
+
:- set_prolog_flag(unknown, fail).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/operations/service/storefront> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/topology> .
|
|
4
|
+
<https://example.org/operations/service/mobile-app> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/topology> .
|
|
5
|
+
<https://example.org/operations/service/checkout-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/topology> .
|
|
6
|
+
<https://example.org/operations/service/payment-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/db/primary> <https://example.org/operations/graph/topology> .
|
|
7
|
+
<https://example.org/operations/service/payment-api> <https://example.org/vocab/dependsOn> <https://example.org/operations/service/auth-service> <https://example.org/operations/graph/topology> .
|
|
8
|
+
<https://example.org/operations/service/auth-service> <https://example.org/vocab/dependsOn> <https://example.org/operations/db/identity> <https://example.org/operations/graph/topology> .
|
|
9
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/symptom> <https://example.org/operations/symptom/db-timeout> <https://example.org/operations/graph/incident> .
|
|
10
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/observedOn> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/incident> .
|
|
11
|
+
<https://example.org/operations/db/primary> <https://example.org/vocab/status> <https://example.org/operations/state/unhealthy> <https://example.org/operations/graph/telemetry> .
|
|
12
|
+
<https://example.org/operations/db/primary> <https://example.org/vocab/diskUsagePercent> "100"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/operations/graph/telemetry> .
|
|
13
|
+
<https://example.org/operations/db/replica> <https://example.org/vocab/status> <https://example.org/operations/state/healthy> <https://example.org/operations/graph/telemetry> .
|
|
14
|
+
<https://example.org/operations/service/auth-service> <https://example.org/vocab/status> <https://example.org/operations/state/healthy> <https://example.org/operations/graph/telemetry> .
|
|
15
|
+
<https://example.org/operations/service/payment-api> <https://example.org/vocab/errorRatePercent> "72"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/operations/graph/telemetry> .
|
|
16
|
+
<https://example.org/operations/runbook/db-failover> <https://example.org/vocab/whenCause> <https://example.org/operations/cause/disk-full> <https://example.org/operations/graph/runbook> .
|
|
17
|
+
<https://example.org/operations/runbook/db-failover> <https://example.org/vocab/action> <https://example.org/operations/action/failover-to-replica> <https://example.org/operations/graph/runbook> .
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/rootCause> <https://example.org/operations/db/primary> <https://example.org/operations/graph/derived> .
|
|
4
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/recommendedAction> <https://example.org/operations/action/failover-to-replica> <https://example.org/operations/graph/derived> .
|
|
5
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/db/primary> <https://example.org/operations/graph/derived> .
|
|
6
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/payment-api> <https://example.org/operations/graph/derived> .
|
|
7
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/storefront> <https://example.org/operations/graph/derived> .
|
|
8
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/mobile-app> <https://example.org/operations/graph/derived> .
|
|
9
|
+
<https://example.org/operations/incident/inc-900> <https://example.org/vocab/impacts> <https://example.org/operations/service/checkout-api> <https://example.org/operations/graph/derived> .
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/rootCause'),iri('https://example.org/operations/db/primary'),iri('https://example.org/operations/graph/derived')).
|
|
2
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/recommendedAction'),iri('https://example.org/operations/action/failover-to-replica'),iri('https://example.org/operations/graph/derived')).
|
|
3
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/db/primary'),iri('https://example.org/operations/graph/derived')).
|
|
4
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/payment-api'),iri('https://example.org/operations/graph/derived')).
|
|
5
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/storefront'),iri('https://example.org/operations/graph/derived')).
|
|
6
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/mobile-app'),iri('https://example.org/operations/graph/derived')).
|
|
7
|
+
rdf(iri('https://example.org/operations/incident/inc-900'),iri('https://example.org/vocab/impacts'),iri('https://example.org/operations/service/checkout-api'),iri('https://example.org/operations/graph/derived')).
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
% Flagship example: operational incident diagnosis and response.
|
|
2
|
+
% The topology, incident observations, telemetry, and runbook are RDF data.
|
|
3
|
+
% Prolog correlates evidence, traverses service dependencies, and recommends a
|
|
4
|
+
% bounded mitigation with an inspectable evidence chain.
|
|
5
|
+
|
|
6
|
+
%% goal: root_cause(X0, X1, X2)
|
|
7
|
+
%% goal: impacted_service(X0, X1)
|
|
8
|
+
%% goal: recommended_action(X0, X1)
|
|
9
|
+
%% goal: evidence_chain(X0, X1)
|
|
10
|
+
|
|
11
|
+
v(depends_on,iri('https://example.org/vocab/dependsOn')).
|
|
12
|
+
v(symptom,iri('https://example.org/vocab/symptom')).
|
|
13
|
+
v(observed_on,iri('https://example.org/vocab/observedOn')).
|
|
14
|
+
v(status,iri('https://example.org/vocab/status')).
|
|
15
|
+
v(disk_usage,iri('https://example.org/vocab/diskUsagePercent')).
|
|
16
|
+
v(error_rate,iri('https://example.org/vocab/errorRatePercent')).
|
|
17
|
+
v(when_cause,iri('https://example.org/vocab/whenCause')).
|
|
18
|
+
v(action,iri('https://example.org/vocab/action')).
|
|
19
|
+
|
|
20
|
+
g(topology,iri('https://example.org/operations/graph/topology')).
|
|
21
|
+
g(telemetry,iri('https://example.org/operations/graph/telemetry')).
|
|
22
|
+
g(incident,iri('https://example.org/operations/graph/incident')).
|
|
23
|
+
g(runbook,iri('https://example.org/operations/graph/runbook')).
|
|
24
|
+
|
|
25
|
+
resource(inc900,iri('https://example.org/operations/incident/inc-900')).
|
|
26
|
+
resource(storefront,iri('https://example.org/operations/service/storefront')).
|
|
27
|
+
resource(mobile_app,iri('https://example.org/operations/service/mobile-app')).
|
|
28
|
+
resource(checkout_api,iri('https://example.org/operations/service/checkout-api')).
|
|
29
|
+
resource(payment_api,iri('https://example.org/operations/service/payment-api')).
|
|
30
|
+
resource(auth_service,iri('https://example.org/operations/service/auth-service')).
|
|
31
|
+
resource(primary_db,iri('https://example.org/operations/db/primary')).
|
|
32
|
+
resource(replica_db,iri('https://example.org/operations/db/replica')).
|
|
33
|
+
|
|
34
|
+
integer_literal(literal(Text,datatype('http://www.w3.org/2001/XMLSchema#integer')),N):-atom_chars(Text,Cs),number_chars(N,Cs).
|
|
35
|
+
|
|
36
|
+
depends(A,B):-resource(A,RA),resource(B,RB),v(depends_on,P),g(topology,G),rdf(RA,P,RB,G).
|
|
37
|
+
transitively_depends(A,B):-depends(A,B).
|
|
38
|
+
transitively_depends(A,B):-depends(A,C),transitively_depends(C,B).
|
|
39
|
+
|
|
40
|
+
telemetry(Resource,Key,Value):-resource(Resource,R),v(Key,P),g(telemetry,G),rdf(R,P,Value,G).
|
|
41
|
+
incident_fact(Key,Value):-resource(inc900,I),v(Key,P),g(incident,G),rdf(I,P,Value,G).
|
|
42
|
+
|
|
43
|
+
root_cause(inc900,primary_db,disk_full):-
|
|
44
|
+
incident_fact(symptom,iri('https://example.org/operations/symptom/db-timeout')),
|
|
45
|
+
telemetry(primary_db,status,iri('https://example.org/operations/state/unhealthy')),
|
|
46
|
+
telemetry(primary_db,disk_usage,L),integer_literal(L,100),
|
|
47
|
+
telemetry(payment_api,error_rate,E),integer_literal(E,Rate),Rate >= 50,
|
|
48
|
+
telemetry(auth_service,status,iri('https://example.org/operations/state/healthy')).
|
|
49
|
+
|
|
50
|
+
impacted_service(inc900,primary_db):-root_cause(inc900,primary_db,_).
|
|
51
|
+
impacted_service(inc900,Service):-root_cause(inc900,primary_db,_),transitively_depends(Service,primary_db).
|
|
52
|
+
|
|
53
|
+
cause_iri(disk_full,iri('https://example.org/operations/cause/disk-full')).
|
|
54
|
+
action_iri(failover_to_replica,iri('https://example.org/operations/action/failover-to-replica')).
|
|
55
|
+
runbook_action(Cause,Action):-g(runbook,G),v(when_cause,PC),v(action,PA),cause_iri(Cause,C),action_iri(Action,A),rdf(Rule,PC,C,G),rdf(Rule,PA,A,G).
|
|
56
|
+
|
|
57
|
+
recommended_action(inc900,failover(primary_db,replica_db)):-
|
|
58
|
+
root_cause(inc900,primary_db,disk_full),runbook_action(disk_full,failover_to_replica),telemetry(replica_db,status,iri('https://example.org/operations/state/healthy')).
|
|
59
|
+
|
|
60
|
+
evidence_chain(inc900,[payment_api_db_timeout,primary_db_unhealthy,primary_db_disk_100_percent,auth_service_healthy,replica_db_healthy]):-recommended_action(inc900,_).
|
|
61
|
+
|
|
62
|
+
result_rdf(I,iri('https://example.org/vocab/rootCause'),C,iri('https://example.org/operations/graph/derived')):-root_cause(inc900,primary_db,disk_full),resource(inc900,I),resource(primary_db,C).
|
|
63
|
+
result_rdf(I,iri('https://example.org/vocab/recommendedAction'),ActionIri,iri('https://example.org/operations/graph/derived')):-recommended_action(inc900,_),runbook_action(disk_full,failover_to_replica),action_iri(failover_to_replica,ActionIri),resource(inc900,I).
|
|
64
|
+
result_rdf(I,iri('https://example.org/vocab/impacts'),S,iri('https://example.org/operations/graph/derived')):-impacted_service(inc900,Service),resource(inc900,I),resource(Service,S).
|
|
65
|
+
|
|
66
|
+
write_results:-result_rdf(S,P,O,G),write_term(rdf(S,P,O,G),[quoted(true)]),write('.'),nl,fail.
|
|
67
|
+
write_results.
|
|
68
|
+
:- set_prolog_flag(unknown, fail).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/rootComponent> <https://example.org/supply-chain/component/shop-app> <https://example.org/supply-chain/graph/sbom> .
|
|
4
|
+
<https://example.org/supply-chain/component/shop-app> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/payments-sdk> <https://example.org/supply-chain/graph/sbom> .
|
|
5
|
+
<https://example.org/supply-chain/component/payments-sdk> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/crypto-wrapper> <https://example.org/supply-chain/graph/sbom> .
|
|
6
|
+
<https://example.org/supply-chain/component/crypto-wrapper> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/supply-chain/graph/sbom> .
|
|
7
|
+
<https://example.org/supply-chain/component/shop-app> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/log-agent> <https://example.org/supply-chain/graph/sbom> .
|
|
8
|
+
<https://example.org/supply-chain/component/log-agent> <https://example.org/vocab/dependsOn> <https://example.org/supply-chain/component/log-core-2.1> <https://example.org/supply-chain/graph/sbom> .
|
|
9
|
+
<https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/vocab/affectedBy> <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
10
|
+
<https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/vocab/severityScore> "98"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
11
|
+
<https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/vocab/fixedComponent> <https://example.org/supply-chain/component/openssl-3.0.14> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
12
|
+
<https://example.org/supply-chain/component/log-core-2.1> <https://example.org/vocab/affectedBy> <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
13
|
+
<https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/vocab/severityScore> "54"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
14
|
+
<https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/vocab/fixedComponent> <https://example.org/supply-chain/component/log-core-2.2> <https://example.org/supply-chain/graph/vulnerabilities> .
|
|
15
|
+
<https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/criticalService> <https://example.org/supply-chain/value/yes> <https://example.org/supply-chain/graph/policy> .
|
|
16
|
+
<https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/currentDate> "20260828"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/policy> .
|
|
17
|
+
<https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/waivesForService> <https://example.org/supply-chain/service/checkout-prod> <https://example.org/supply-chain/graph/policy> .
|
|
18
|
+
<https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/waivesVulnerability> <https://example.org/supply-chain/cve/CVE-2026-2222> <https://example.org/supply-chain/graph/policy> .
|
|
19
|
+
<https://example.org/supply-chain/waiver/logging> <https://example.org/vocab/expiresOn> "20261231"^^<http://www.w3.org/2001/XMLSchema#integer> <https://example.org/supply-chain/graph/policy> .
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
VERSION "1.2"
|
|
2
|
+
|
|
3
|
+
<https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/deploymentDecision> <https://example.org/supply-chain/decision/block> <https://example.org/supply-chain/graph/derived> .
|
|
4
|
+
<https://example.org/supply-chain/service/checkout-prod> <https://example.org/vocab/exposedTo> <https://example.org/supply-chain/cve/CVE-2026-7777> <https://example.org/supply-chain/graph/derived> .
|
|
5
|
+
<https://example.org/supply-chain/component/openssl-3.0.12> <https://example.org/vocab/upgradeTo> <https://example.org/supply-chain/component/openssl-3.0.14> <https://example.org/supply-chain/graph/derived> .
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
rdf(iri('https://example.org/supply-chain/service/checkout-prod'),iri('https://example.org/vocab/deploymentDecision'),iri('https://example.org/supply-chain/decision/block'),iri('https://example.org/supply-chain/graph/derived')).
|
|
2
|
+
rdf(iri('https://example.org/supply-chain/service/checkout-prod'),iri('https://example.org/vocab/exposedTo'),iri('https://example.org/supply-chain/cve/CVE-2026-7777'),iri('https://example.org/supply-chain/graph/derived')).
|
|
3
|
+
rdf(iri('https://example.org/supply-chain/component/openssl-3.0.12'),iri('https://example.org/vocab/upgradeTo'),iri('https://example.org/supply-chain/component/openssl-3.0.14'),iri('https://example.org/supply-chain/graph/derived')).
|