eyeling 1.24.29 → 1.24.30

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.
@@ -0,0 +1,221 @@
1
+ # ======================================================================================
2
+ # odrl-benefits.n3
3
+ #
4
+ # A very small example showing why ODRL policies are useful.
5
+ #
6
+ # The same machine-readable policy can:
7
+ # - permit a good use case (medical research),
8
+ # - block an unwanted use case (marketing),
9
+ # - attach an operational duty (delete the data after use), and
10
+ # - produce an explainable audit trail.
11
+ # ======================================================================================
12
+
13
+ @prefix : <https://example.org/odrl-benefits#> .
14
+ @prefix odrl: <http://www.w3.org/ns/odrl/2/> .
15
+ @prefix dct: <http://purl.org/dc/terms/> .
16
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
17
+ @prefix string:<http://www.w3.org/2000/10/swap/string#> .
18
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
19
+
20
+ # -------------------
21
+ # Parties and assets
22
+ # -------------------
23
+
24
+ :ResearchLab dct:title "Example Research Lab" .
25
+ :HealthDataset dct:title "Pseudonymised health dataset" .
26
+ :MedicalResearch dct:title "medical research" .
27
+ :Marketing dct:title "marketing" .
28
+ :Allowed dct:title "Allowed" .
29
+ :Blocked dct:title "Blocked" .
30
+
31
+ # -----------------------------
32
+ # One compact ODRL policy
33
+ # -----------------------------
34
+
35
+ :Policy a odrl:Policy ;
36
+ dct:title "Health-data sharing policy" ;
37
+ odrl:permission :PermitResearchUse ;
38
+ odrl:prohibition :ProhibitMarketingUse .
39
+
40
+ :PermitResearchUse a odrl:Permission ;
41
+ odrl:assignee :ResearchLab ;
42
+ odrl:target :HealthDataset ;
43
+ odrl:action odrl:use ;
44
+ odrl:constraint [
45
+ odrl:leftOperand odrl:purpose ;
46
+ odrl:operator odrl:eq ;
47
+ odrl:rightOperand :MedicalResearch
48
+ ] ;
49
+ odrl:duty :DeleteAfterUse .
50
+
51
+ :DeleteAfterUse a odrl:Duty ;
52
+ odrl:action odrl:delete ;
53
+ odrl:target :HealthDataset ;
54
+ odrl:constraint [
55
+ odrl:leftOperand odrl:dateTime ;
56
+ odrl:operator odrl:lteq ;
57
+ odrl:rightOperand "2026-12-31"^^xsd:date
58
+ ] .
59
+
60
+ :ProhibitMarketingUse a odrl:Prohibition ;
61
+ odrl:assignee :ResearchLab ;
62
+ odrl:target :HealthDataset ;
63
+ odrl:action odrl:use ;
64
+ odrl:constraint [
65
+ odrl:leftOperand odrl:purpose ;
66
+ odrl:operator odrl:eq ;
67
+ odrl:rightOperand :Marketing
68
+ ] .
69
+
70
+ # -----------------
71
+ # Two access requests
72
+ # -----------------
73
+
74
+ :RequestResearch a :Request ;
75
+ dct:title "Use the dataset for medical research" ;
76
+ odrl:assignee :ResearchLab ;
77
+ odrl:target :HealthDataset ;
78
+ odrl:action odrl:use ;
79
+ :purpose :MedicalResearch .
80
+
81
+ :RequestMarketing a :Request ;
82
+ dct:title "Use the dataset for marketing" ;
83
+ odrl:assignee :ResearchLab ;
84
+ odrl:target :HealthDataset ;
85
+ odrl:action odrl:use ;
86
+ :purpose :Marketing .
87
+
88
+ # ---------------------------
89
+ # Minimal policy evaluation
90
+ # ---------------------------
91
+
92
+ # Benefit 1: permissions are machine-readable.
93
+ {
94
+ ?request a :Request ;
95
+ odrl:assignee ?party ;
96
+ odrl:target ?asset ;
97
+ odrl:action ?action ;
98
+ :purpose ?purpose .
99
+
100
+ :Policy odrl:permission ?permission .
101
+ ?permission odrl:assignee ?party ;
102
+ odrl:target ?asset ;
103
+ odrl:action ?action ;
104
+ odrl:constraint [
105
+ odrl:leftOperand odrl:purpose ;
106
+ odrl:operator odrl:eq ;
107
+ odrl:rightOperand ?purpose
108
+ ] .
109
+ }
110
+ =>
111
+ {
112
+ ?request :decision :Allowed ;
113
+ :benefit :MachineReadablePermission ;
114
+ :why "A matching ODRL permission grants this purpose-specific use." .
115
+ } .
116
+
117
+ # Benefit 2: prohibitions make unwanted use cases explicit.
118
+ {
119
+ ?request a :Request ;
120
+ odrl:assignee ?party ;
121
+ odrl:target ?asset ;
122
+ odrl:action ?action ;
123
+ :purpose ?purpose .
124
+
125
+ :Policy odrl:prohibition ?prohibition .
126
+ ?prohibition odrl:assignee ?party ;
127
+ odrl:target ?asset ;
128
+ odrl:action ?action ;
129
+ odrl:constraint [
130
+ odrl:leftOperand odrl:purpose ;
131
+ odrl:operator odrl:eq ;
132
+ odrl:rightOperand ?purpose
133
+ ] .
134
+ }
135
+ =>
136
+ {
137
+ ?request :decision :Blocked ;
138
+ :benefit :PurposeLimitation ;
139
+ :why "A matching ODRL prohibition blocks this purpose-specific use." .
140
+ } .
141
+
142
+ # Benefit 3: permitted use can carry operational duties.
143
+ {
144
+ ?request :decision :Allowed ;
145
+ odrl:assignee ?party ;
146
+ odrl:target ?asset ;
147
+ odrl:action ?action ;
148
+ :purpose ?purpose .
149
+
150
+ :Policy odrl:permission ?permission .
151
+ ?permission odrl:assignee ?party ;
152
+ odrl:target ?asset ;
153
+ odrl:action ?action ;
154
+ odrl:constraint [
155
+ odrl:leftOperand odrl:purpose ;
156
+ odrl:operator odrl:eq ;
157
+ odrl:rightOperand ?purpose
158
+ ] ;
159
+ odrl:duty ?duty .
160
+
161
+ ?duty odrl:action odrl:delete ;
162
+ odrl:constraint [
163
+ odrl:leftOperand odrl:dateTime ;
164
+ odrl:operator odrl:lteq ;
165
+ odrl:rightOperand ?date
166
+ ] .
167
+ }
168
+ =>
169
+ {
170
+ ?request :duty "Delete the dataset after the approved research use." ;
171
+ :deleteBy ?date ;
172
+ :benefit :OperationalDuty .
173
+ } .
174
+
175
+ # ----------------------------
176
+ # Markdown report output
177
+ # ----------------------------
178
+
179
+ :out01 log:outputString "# odrl-benefits\n\n## Source files\n\n- [N3 rules](../odrl-benefits.n3)\n\n" .
180
+ :out02 log:outputString "## Why ODRL helps\n\n" .
181
+ :out03 log:outputString "This example uses one small ODRL policy to make data-use decisions explicit, machine-checkable, and auditable.\n\n" .
182
+ :out04 log:outputString "### Policy in plain language\n\n" .
183
+ :out05 log:outputString "- The research lab **may use** the pseudonymised health dataset for **medical research**.\n" .
184
+ :out06 log:outputString "- The research lab **must delete** the dataset by `2026-12-31`.\n" .
185
+ :out07 log:outputString "- The research lab **must not use** the dataset for **marketing**.\n\n" .
186
+ :out08 log:outputString "### Evaluated requests\n\n" .
187
+ :out09 log:outputString "| Request | Decision | Explanation |\n" .
188
+ :out10 log:outputString "| --- | --- | --- |\n" .
189
+
190
+ {
191
+ :RequestResearch dct:title ?title ;
192
+ :decision ?decision ;
193
+ :why ?why ;
194
+ :deleteBy ?date .
195
+ ?decision dct:title ?decisionLabel .
196
+
197
+ ("| %s | `%s` | %s Duty: delete by `%s`. |\n" ?title ?decisionLabel ?why ?date) string:format ?line .
198
+ }
199
+ =>
200
+ {
201
+ :out11 log:outputString ?line .
202
+ } .
203
+
204
+ {
205
+ :RequestMarketing dct:title ?title ;
206
+ :decision ?decision ;
207
+ :why ?why .
208
+ ?decision dct:title ?decisionLabel .
209
+
210
+ ("| %s | `%s` | %s |\n" ?title ?decisionLabel ?why) string:format ?line .
211
+ }
212
+ =>
213
+ {
214
+ :out12 log:outputString ?line .
215
+ } .
216
+
217
+ :out13 log:outputString "\n### Benefits illustrated\n\n" .
218
+ :out14 log:outputString "1. **Clarity:** the policy says who may do what, to which asset, and for which purpose.\n" .
219
+ :out15 log:outputString "2. **Automation:** requests can be allowed or blocked by rules instead of manual reading.\n" .
220
+ :out16 log:outputString "3. **Purpose limitation:** research use and marketing use are treated differently.\n" .
221
+ :out17 log:outputString "4. **Accountability:** duties such as deletion are part of the same policy and can be audited.\n" .
@@ -0,0 +1,29 @@
1
+ # odrl-benefits
2
+
3
+ ## Source files
4
+
5
+ - [N3 rules](../odrl-benefits.n3)
6
+
7
+ ## Why ODRL helps
8
+
9
+ This example uses one small ODRL policy to make data-use decisions explicit, machine-checkable, and auditable.
10
+
11
+ ### Policy in plain language
12
+
13
+ - The research lab **may use** the pseudonymised health dataset for **medical research**.
14
+ - The research lab **must delete** the dataset by `2026-12-31`.
15
+ - The research lab **must not use** the dataset for **marketing**.
16
+
17
+ ### Evaluated requests
18
+
19
+ | Request | Decision | Explanation |
20
+ | --- | --- | --- |
21
+ | Use the dataset for medical research | `Allowed` | A matching ODRL permission grants this purpose-specific use. Duty: delete by `2026-12-31`. |
22
+ | Use the dataset for marketing | `Blocked` | A matching ODRL prohibition blocks this purpose-specific use. |
23
+
24
+ ### Benefits illustrated
25
+
26
+ 1. **Clarity:** the policy says who may do what, to which asset, and for which purpose.
27
+ 2. **Automation:** requests can be allowed or blocked by rules instead of manual reading.
28
+ 3. **Purpose limitation:** research use and marketing use are treated differently.
29
+ 4. **Accountability:** duties such as deletion are part of the same policy and can be audited.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.24.29",
3
+ "version": "1.24.30",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -873,6 +873,10 @@ ${JSON.stringify(last, null, 2)}`);
873
873
  const outputStringProgram = `@prefix : <#> .
874
874
  @prefix log: <http://www.w3.org/2000/10/swap/log#> .
875
875
  :report log:outputString "## Hello from output string\n\nLine 2 with **bold** and [Eyeling](https://example.org/eyeling)\n" .
876
+ `;
877
+ const riskMarkdownOutputStringProgram = `@prefix : <#> .
878
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
879
+ :report log:outputString "# Risk report\n\n### Clause H1 — score 100\n\nRisk: secondary use is permitted without a safeguard. Clause H1: Hospital may provide electronic health data for secondary use.\n\n- **Mitigation for clause H1:** Require a permit before secondary use.\n" .
876
880
  `;
877
881
  const baseOnlyMarkdownProgram = `@base <https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/smoke-arithmetic.n3> .
878
882
  @prefix : <#> .
@@ -977,6 +981,25 @@ ${JSON.stringify(last, null, 2)}`);
977
981
  assert.equal(renderedAgain.renderedTabSelected, true, 'Expected Rendered tab to be selectable again');
978
982
  endTest();
979
983
 
984
+ beginTest('playground renders Markdown reports with colon-led prose lines');
985
+ await setProgram(riskMarkdownOutputStringProgram);
986
+ await clickRun();
987
+ const riskMarkdown = await waitForState(
988
+ 'risk Markdown rendering',
989
+ (st) =>
990
+ String(st.status || '')
991
+ .trim()
992
+ .startsWith('Done') && /Risk report/.test(String(st.output || '')),
993
+ 20000,
994
+ );
995
+ assert.equal(riskMarkdown.outputTabsHidden, false, 'Expected risk-report Markdown tabs to be visible');
996
+ assert.equal(riskMarkdown.renderedHidden, false, 'Expected risk-report Markdown to render by default');
997
+ assert.equal(riskMarkdown.sourceHidden, true, 'Expected risk-report Markdown source to be hidden by default');
998
+ assert.match(riskMarkdown.renderedHtml, /<h1>Risk report<\/h1>/i, 'Expected risk-report heading rendering');
999
+ assert.match(riskMarkdown.renderedHtml, /<h3>Clause H1 — score 100<\/h3>/i, 'Expected risk-report clause heading rendering');
1000
+ assert.match(riskMarkdown.renderedHtml, /<strong>Mitigation for clause H1:<\/strong>/i, 'Expected risk-report mitigation bold rendering');
1001
+ endTest();
1002
+
980
1003
  // 5) Shared state files may only restore editor text. If that text came from a repository
981
1004
  // example, the injected @base line should still give Markdown links the static output-page base.
982
1005
  beginTest('playground resolves Markdown links from restored example base directives');