@unrdf/hooks 26.4.3 → 26.4.7

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 (59) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +566 -53
  3. package/examples/atomvm-fibo-hooks-demo.mjs +323 -0
  4. package/examples/delta-monitoring-example.mjs +213 -0
  5. package/examples/fibo-jtbd-governance.mjs +388 -0
  6. package/examples/hook-chains/node_modules/.bin/jiti +0 -0
  7. package/examples/hook-chains/node_modules/.bin/msw +0 -0
  8. package/examples/hook-chains/node_modules/.bin/terser +0 -0
  9. package/examples/hook-chains/node_modules/.bin/tsc +0 -0
  10. package/examples/hook-chains/node_modules/.bin/tsserver +0 -0
  11. package/examples/hook-chains/node_modules/.bin/tsx +0 -0
  12. package/examples/hook-chains/node_modules/.bin/validate-hooks +0 -0
  13. package/examples/hook-chains/node_modules/.bin/vite +0 -0
  14. package/examples/hook-chains/node_modules/.bin/vitest +0 -0
  15. package/examples/hook-chains/node_modules/.bin/yaml +0 -0
  16. package/examples/hook-chains/package.json +2 -2
  17. package/examples/hooks-marketplace.mjs +261 -0
  18. package/examples/n3-reasoning-example.mjs +279 -0
  19. package/examples/policy-hooks/README.md +5 -9
  20. package/examples/policy-hooks/node_modules/.bin/jiti +0 -0
  21. package/examples/policy-hooks/node_modules/.bin/msw +0 -0
  22. package/examples/policy-hooks/node_modules/.bin/terser +0 -0
  23. package/examples/policy-hooks/node_modules/.bin/tsc +0 -0
  24. package/examples/policy-hooks/node_modules/.bin/tsserver +0 -0
  25. package/examples/policy-hooks/node_modules/.bin/tsx +0 -0
  26. package/examples/policy-hooks/node_modules/.bin/validate-hooks +0 -0
  27. package/examples/policy-hooks/node_modules/.bin/vite +0 -0
  28. package/examples/policy-hooks/node_modules/.bin/vitest +0 -0
  29. package/examples/policy-hooks/node_modules/.bin/yaml +0 -0
  30. package/examples/policy-hooks/package.json +2 -2
  31. package/examples/shacl-repair-example.mjs +191 -0
  32. package/examples/window-condition-example.mjs +285 -0
  33. package/package.json +27 -23
  34. package/src/atomvm.mjs +9 -0
  35. package/src/define.mjs +114 -0
  36. package/src/executor.mjs +23 -0
  37. package/src/hooks/atomvm-bridge.mjs +332 -0
  38. package/src/hooks/builtin-hooks.mjs +17 -9
  39. package/src/hooks/condition-evaluator.mjs +681 -77
  40. package/src/hooks/define-hook.mjs +23 -23
  41. package/src/hooks/effect-executor.mjs +618 -0
  42. package/src/hooks/effect-sandbox.mjs +19 -9
  43. package/src/hooks/file-resolver.mjs +155 -1
  44. package/src/hooks/hook-chain-compiler.mjs +10 -1
  45. package/src/hooks/hook-executor.mjs +102 -73
  46. package/src/hooks/knowledge-hook-engine.mjs +133 -7
  47. package/src/hooks/ontology-learner.mjs +190 -0
  48. package/src/hooks/query.mjs +3 -3
  49. package/src/hooks/schemas.mjs +47 -3
  50. package/src/hooks/security/error-sanitizer.mjs +46 -24
  51. package/src/hooks/self-play-autonomics.mjs +464 -0
  52. package/src/hooks/telemetry.mjs +32 -9
  53. package/src/hooks/validate.mjs +100 -33
  54. package/src/index.mjs +2 -0
  55. package/src/lib/admit-hook.mjs +615 -0
  56. package/src/policy-compiler.mjs +12 -2
  57. package/dist/index.d.mts +0 -1738
  58. package/dist/index.d.ts +0 -1738
  59. package/dist/index.mjs +0 -1738
@@ -0,0 +1,285 @@
1
+ /**
2
+ * @unrdf/hooks - Window Condition Example
3
+ *
4
+ * Demonstrates time-windowed aggregation evaluation.
5
+ * Triggers rules when aggregated metrics within time windows meet thresholds.
6
+ *
7
+ * Use cases:
8
+ * - Rate limiting: "more than 100 requests/minute"
9
+ * - Anomaly detection: "average temperature exceeds threshold"
10
+ * - Traffic analysis: "peak traffic detection"
11
+ * - Quota enforcement: "daily transaction limit"
12
+ */
13
+
14
+ import { createStore } from '@unrdf/oxigraph';
15
+ import { evaluateCondition } from '../src/hooks/condition-evaluator.mjs';
16
+ import { UnrdfDataFactory as DataFactory } from '@unrdf/core/rdf/n3-justified-only';
17
+
18
+ const { namedNode, literal, quad } = DataFactory;
19
+
20
+ console.log('=== Window Condition Example ===\n');
21
+
22
+ // Utility: create window condition
23
+ function createWindowCondition(aggregate, windowMs, query) {
24
+ return {
25
+ kind: 'window',
26
+ spec: {
27
+ size: windowMs,
28
+ aggregate: aggregate,
29
+ query: query
30
+ }
31
+ };
32
+ }
33
+
34
+ // Example 1: Count-based window
35
+ console.log('1. Count Window (Rate Limiting)\n');
36
+
37
+ const countWindowCondition = createWindowCondition(
38
+ 'count',
39
+ 60000, // 1 minute
40
+ `SELECT ?s WHERE {
41
+ ?s a ex:Request ;
42
+ ex:timestamp ?t .
43
+ FILTER (?t > NOW() - PT1M)
44
+ }`
45
+ );
46
+
47
+ console.log('Condition:');
48
+ console.log(JSON.stringify(countWindowCondition, null, 2));
49
+ console.log('');
50
+ console.log('Purpose: Count matches in last 60 seconds');
51
+ console.log('Triggers when: count >= configured threshold');
52
+ console.log('Use for: Rate limiting, quota enforcement');
53
+ console.log('');
54
+
55
+ console.log('Example usage in hook:');
56
+ console.log(`
57
+ {
58
+ condition: ${JSON.stringify(countWindowCondition, null, 4)},
59
+ effects: [{
60
+ kind: 'sparql-construct',
61
+ query: \`CONSTRUCT { ?s ex:rateLimited true } WHERE { ?s a ex:Request }\`
62
+ }]
63
+ }
64
+
65
+ Flow:
66
+ 1. Query finds all requests in last 60 seconds
67
+ 2. Count results
68
+ 3. If count > 100, hook triggers
69
+ 4. Affected requests marked as rate-limited
70
+ `);
71
+
72
+ // Example 2: Sum aggregation
73
+ console.log('\n2. Sum Window (Traffic Volume)\n');
74
+
75
+ const sumWindowCondition = createWindowCondition(
76
+ 'sum',
77
+ 300000, // 5 minutes
78
+ `SELECT ?bytes WHERE {
79
+ ?transfer ex:transferredBytes ?bytes ;
80
+ ex:timestamp ?t .
81
+ FILTER (?t > NOW() - PT5M)
82
+ }`
83
+ );
84
+
85
+ console.log('Condition:');
86
+ console.log(JSON.stringify(sumWindowCondition, null, 2));
87
+ console.log('');
88
+ console.log('Purpose: Sum bytes transferred in last 5 minutes');
89
+ console.log('Triggers when: sum > threshold (e.g., 1GB)');
90
+ console.log('Use for: Bandwidth management, peak detection\n');
91
+
92
+ // Example 3: Average aggregation
93
+ console.log('3. Average Window (Anomaly Detection)\n');
94
+
95
+ const avgWindowCondition = createWindowCondition(
96
+ 'avg',
97
+ 3600000, // 1 hour
98
+ `SELECT ?temp WHERE {
99
+ ?sensor ex:reading ?temp ;
100
+ ex:timestamp ?t .
101
+ FILTER (?t > NOW() - PT1H)
102
+ }`
103
+ );
104
+
105
+ console.log('Condition:');
106
+ console.log(JSON.stringify(avgWindowCondition, null, 2));
107
+ console.log('');
108
+ console.log('Purpose: Average temperature over last hour');
109
+ console.log('Triggers when: avg > 85 degrees (anomaly)');
110
+ console.log('Use for: Anomaly detection, SLA monitoring\n');
111
+
112
+ // Example 4: Min/Max windows
113
+ console.log('4. Min/Max Windows (Range Monitoring)\n');
114
+
115
+ const minWindowCondition = createWindowCondition(
116
+ 'min',
117
+ 86400000, // 24 hours
118
+ `SELECT ?value WHERE {
119
+ ?metric ex:dailyValue ?value ;
120
+ ex:timestamp ?t .
121
+ FILTER (?t > NOW() - P1D)
122
+ }`
123
+ );
124
+
125
+ const maxWindowCondition = createWindowCondition(
126
+ 'max',
127
+ 86400000, // 24 hours
128
+ `SELECT ?value WHERE {
129
+ ?metric ex:dailyValue ?value ;
130
+ ex:timestamp ?t .
131
+ FILTER (?t > NOW() - P1D)
132
+ }`
133
+ );
134
+
135
+ console.log('Min window (find lowest value in window):');
136
+ console.log(JSON.stringify(minWindowCondition, null, 2));
137
+ console.log('');
138
+ console.log('Max window (find highest value in window):');
139
+ console.log(JSON.stringify(maxWindowCondition, null, 2));
140
+ console.log('');
141
+ console.log('Use for: Performance tracking, threshold detection\n');
142
+
143
+ // Real-world scenarios
144
+ console.log('5. Real-World Scenarios\n');
145
+
146
+ console.log('Scenario A: API Rate Limiting');
147
+ console.log('-'.repeat(40));
148
+ console.log(`
149
+ Condition: Window count in 1 minute > 1000
150
+ {
151
+ kind: 'window',
152
+ spec: {
153
+ size: 60000,
154
+ aggregate: 'count',
155
+ query: 'SELECT ?req WHERE { ?req a ex:APICall ; ex:timestamp ?t }'
156
+ }
157
+ }
158
+
159
+ Hook flow:
160
+ 1. Client makes API requests
161
+ 2. Each request added as RDF triple with timestamp
162
+ 3. Window counts requests in last minute
163
+ 4. If > 1000, trigger rate limiting effect
164
+ 5. Mark client as throttled, return 429 Too Many Requests
165
+ `);
166
+
167
+ console.log('\nScenario B: Data Quality Monitoring');
168
+ console.log('-'.repeat(40));
169
+ console.log(`
170
+ Condition: Window average error rate in 1 hour > 5%
171
+ {
172
+ kind: 'window',
173
+ spec: {
174
+ size: 3600000,
175
+ aggregate: 'avg',
176
+ query: 'SELECT ?rate WHERE { ?batch ex:errorRate ?rate }'
177
+ }
178
+ }
179
+
180
+ Hook flow:
181
+ 1. Data processing batches complete
182
+ 2. Each batch records error rate
183
+ 3. Window averages error rates from last hour
184
+ 4. If average > 5%, alert operations
185
+ 5. Trigger investigation and mitigation effect
186
+ `);
187
+
188
+ console.log('\nScenario C: Quota Enforcement');
189
+ console.log('-'.repeat(40));
190
+ console.log(`
191
+ Condition: Window sum of usage in 24 hours > quota
192
+ {
193
+ kind: 'window',
194
+ spec: {
195
+ size: 86400000,
196
+ aggregate: 'sum',
197
+ query: 'SELECT ?usage WHERE { ?tx ex:usage ?usage }'
198
+ }
199
+ }
200
+
201
+ Hook flow:
202
+ 1. Transactions recorded with usage amount
203
+ 2. Window sums usage over rolling 24 hours
204
+ 3. If sum > daily quota, enforce limit
205
+ 4. Mark user as over-quota
206
+ 5. Require billing upgrade or wait for next period
207
+ `);
208
+
209
+ // Aggregate functions explained
210
+ console.log('\n6. Aggregate Functions Explained\n');
211
+
212
+ console.log('count - Number of matches in window');
213
+ console.log(' Example: How many API calls in last minute?');
214
+ console.log('');
215
+ console.log('sum - Total of numeric values in window');
216
+ console.log(' Example: Total bytes transferred in 5 minutes?');
217
+ console.log('');
218
+ console.log('avg - Average of numeric values in window');
219
+ console.log(' Example: Average response time over 1 hour?');
220
+ console.log('');
221
+ console.log('min - Minimum value in window');
222
+ console.log(' Example: Lowest temperature recorded today?');
223
+ console.log('');
224
+ console.log('max - Maximum value in window');
225
+ console.log(' Example: Peak memory usage in last hour?\n');
226
+
227
+ // Window sizing
228
+ console.log('7. Window Size Best Practices\n');
229
+
230
+ console.log('Use Case Window Size Frequency Aggregate');
231
+ console.log('-'.repeat(60));
232
+ console.log('API rate limiting 1 minute Per request count');
233
+ console.log('Traffic analysis 5 minutes Per measurement sum/avg');
234
+ console.log('SLA monitoring 1 hour Per measurement avg/max');
235
+ console.log('Daily quota 24 hours Per transaction sum');
236
+ console.log('Anomaly detection 1 hour Per event avg/stddev\n');
237
+
238
+ // Combining with effects
239
+ console.log('8. Full Hook Example: Rate Limiting\n');
240
+
241
+ console.log(`
242
+ const rateLimitHook = {
243
+ name: 'enforce-api-rate-limit',
244
+
245
+ condition: {
246
+ kind: 'window',
247
+ spec: {
248
+ size: 60000, // 1 minute window
249
+ aggregate: 'count',
250
+ query: \`
251
+ SELECT ?request WHERE {
252
+ ?request a ex:APIRequest ;
253
+ ex:clientId ?client ;
254
+ ex:timestamp ?t .
255
+ FILTER (?t > NOW() - PT1M)
256
+ }
257
+ \`
258
+ }
259
+ },
260
+
261
+ effects: [{
262
+ kind: 'sparql-construct',
263
+ query: \`
264
+ CONSTRUCT {
265
+ ?client ex:rateLimited true ;
266
+ ex:retryAfter "60"^^xsd:integer ;
267
+ ex:error "Rate limit exceeded" .
268
+ }
269
+ WHERE {
270
+ ?request a ex:APIRequest ;
271
+ ex:clientId ?client .
272
+ }
273
+ \`
274
+ }]
275
+ };
276
+ `);
277
+
278
+ console.log('\nExecution:');
279
+ console.log('1. Request arrives, added to store with timestamp');
280
+ console.log('2. Window condition counts requests from same client in 1min');
281
+ console.log('3. If count > 1000, condition triggers');
282
+ console.log('4. Effect adds rate limit response triples');
283
+ console.log('5. API returns 429 with retry-after header\n');
284
+
285
+ console.log('=== Example Complete ===');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unrdf/hooks",
3
- "version": "26.4.3",
3
+ "version": "26.4.7",
4
4
  "description": "UNRDF Knowledge Hooks - Policy Definition and Execution Framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,25 @@
20
20
  "README.md",
21
21
  "LICENSE"
22
22
  ],
23
+ "scripts": {
24
+ "test": "vitest run --coverage",
25
+ "test:fast": "vitest run --coverage",
26
+ "test:watch": "vitest --coverage",
27
+ "test:browser": "vitest --config vitest.browser.config.mjs",
28
+ "test:browser:chromium": "vitest --config vitest.browser.config.mjs --browser.name=chromium",
29
+ "test:browser:firefox": "vitest --config vitest.browser.config.mjs --browser.name=firefox",
30
+ "test:browser:webkit": "vitest --config vitest.browser.config.mjs --browser.name=webkit",
31
+ "test:browser:all": "vitest --workspace=vitest.browser.workspace.mjs",
32
+ "benchmark": "vitest run --coverage test/benchmarks/",
33
+ "benchmark:browser": "vitest run --config vitest.browser.config.mjs",
34
+ "build": "unbuild || true",
35
+ "lint": "eslint src/ test/ --max-warnings=0",
36
+ "lint:fix": "eslint src/ test/ --fix",
37
+ "format": "prettier --write src/",
38
+ "format:check": "prettier --check src/",
39
+ "clean": "rm -rf dist/ .nyc_output/ coverage/",
40
+ "dev": "echo 'Development mode for @unrdf/hooks'"
41
+ },
23
42
  "keywords": [
24
43
  "rdf",
25
44
  "knowledge-graph",
@@ -28,13 +47,17 @@
28
47
  "validation"
29
48
  ],
30
49
  "dependencies": {
31
- "@unrdf/core": "26.4.3",
32
- "@unrdf/oxigraph": "26.4.3",
50
+ "@noble/hashes": "^1.4.0",
51
+ "@unrdf/core": "26.4.4",
52
+ "@unrdf/oxigraph": "26.4.4",
33
53
  "citty": "^0.1.6",
54
+ "eyereasoner": "^10",
55
+ "sparqljs": "^3.7.3",
34
56
  "zod": "^4.1.13"
35
57
  },
36
58
  "devDependencies": {
37
59
  "@types/node": "^24.10.1",
60
+ "@unrdf/test-utils": "workspace:*",
38
61
  "vitest": "^4.0.15"
39
62
  },
40
63
  "engines": {
@@ -52,24 +75,5 @@
52
75
  "license": "MIT",
53
76
  "publishConfig": {
54
77
  "access": "public"
55
- },
56
- "scripts": {
57
- "test": "vitest run --coverage",
58
- "test:fast": "vitest run --coverage",
59
- "test:watch": "vitest --coverage",
60
- "test:browser": "vitest --config vitest.browser.config.mjs",
61
- "test:browser:chromium": "vitest --config vitest.browser.config.mjs --browser.name=chromium",
62
- "test:browser:firefox": "vitest --config vitest.browser.config.mjs --browser.name=firefox",
63
- "test:browser:webkit": "vitest --config vitest.browser.config.mjs --browser.name=webkit",
64
- "test:browser:all": "vitest --workspace=vitest.browser.workspace.mjs",
65
- "benchmark": "vitest run --coverage test/benchmarks/",
66
- "benchmark:browser": "vitest run --config vitest.browser.config.mjs",
67
- "build": "unbuild || true",
68
- "lint": "eslint src/ test/ --max-warnings=0",
69
- "lint:fix": "eslint src/ test/ --fix",
70
- "format": "prettier --write src/",
71
- "format:check": "prettier --check src/",
72
- "clean": "rm -rf dist/ .nyc_output/ coverage/",
73
- "dev": "echo 'Development mode for @unrdf/hooks'"
74
78
  }
75
- }
79
+ }
package/src/atomvm.mjs ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @unrdf/hooks/atomvm
3
+ *
4
+ * AtomVM/Erlang integration for Knowledge Hooks
5
+ *
6
+ * @module @unrdf/hooks/atomvm
7
+ */
8
+
9
+ export { HooksBridge, createHooksBridge } from './hooks/atomvm-bridge.mjs';
package/src/define.mjs ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @unrdf/hooks/define
3
+ *
4
+ * Hook Definition API - Define, validate, and build knowledge hooks.
5
+ *
6
+ * @module @unrdf/hooks/define
7
+ */
8
+
9
+ // ── Core hook definition ────────────────────────────────────────────────────
10
+ export {
11
+ defineHook,
12
+ isValidHook,
13
+ getHookMetadata,
14
+ hasValidation,
15
+ hasTransformation,
16
+ HookTriggerSchema,
17
+ HookConfigSchema,
18
+ HookSchema,
19
+ } from './hooks/define-hook.mjs';
20
+
21
+ // ── Knowledge hook schemas ──────────────────────────────────────────────────
22
+ export {
23
+ KnowledgeHookSchema,
24
+ HookMetaSchema,
25
+ HookConditionSchema,
26
+ HookEffectSchema,
27
+ createKnowledgeHook,
28
+ validateKnowledgeHook,
29
+ } from './hooks/schemas.mjs';
30
+
31
+ // ── Condition kind enums ────────────────────────────────────────────────────
32
+
33
+ /** @type {'sparql-ask'} SPARQL ASK boolean query */
34
+ export const SPARQL_ASK = 'sparql-ask';
35
+
36
+ /** @type {'sparql-select'} SPARQL SELECT tabular query */
37
+ export const SPARQL_SELECT = 'sparql-select';
38
+
39
+ /** @type {'shacl'} SHACL shapes validation */
40
+ export const SHACL = 'shacl';
41
+
42
+ /** @type {'delta'} Delta change detection */
43
+ export const DELTA = 'delta';
44
+
45
+ /** @type {'threshold'} Numeric threshold evaluation */
46
+ export const THRESHOLD = 'threshold';
47
+
48
+ /** @type {'count'} Count-based condition */
49
+ export const COUNT = 'count';
50
+
51
+ /** @type {'window'} Sliding window temporal condition */
52
+ export const WINDOW = 'window';
53
+
54
+ /** @type {'n3'} N3 forward-chaining reasoning */
55
+ export const N3 = 'n3';
56
+
57
+ /**
58
+ * All condition kinds as a frozen object.
59
+ * @type {Readonly<Record<string, string>>}
60
+ */
61
+ export const ConditionKind = Object.freeze({
62
+ SPARQL_ASK,
63
+ SPARQL_SELECT,
64
+ SHACL,
65
+ DELTA,
66
+ THRESHOLD,
67
+ COUNT,
68
+ WINDOW,
69
+ N3,
70
+ });
71
+
72
+ // ── Hook definition builders ────────────────────────────────────────────────
73
+
74
+ import { defineHook as _defineHook } from './hooks/define-hook.mjs';
75
+
76
+ /**
77
+ * Define a validation-only hook.
78
+ *
79
+ * @param {string} name - Hook name
80
+ * @param {string} trigger - Hook trigger
81
+ * @param {Function} validate - Validation function (quad) => boolean
82
+ * @param {Record<string, any>} [metadata] - Optional metadata
83
+ * @returns {object} Defined hook
84
+ */
85
+ export function defineValidationHook(name, trigger, validate, metadata) {
86
+ return _defineHook({ name, trigger, validate, metadata });
87
+ }
88
+
89
+ /**
90
+ * Define a transformation-only hook.
91
+ *
92
+ * @param {string} name - Hook name
93
+ * @param {string} trigger - Hook trigger
94
+ * @param {Function} transform - Transform function (quad) => quad
95
+ * @param {Record<string, any>} [metadata] - Optional metadata
96
+ * @returns {object} Defined hook
97
+ */
98
+ export function defineTransformHook(name, trigger, transform, metadata) {
99
+ return _defineHook({ name, trigger, transform, metadata });
100
+ }
101
+
102
+ /**
103
+ * Define a hook with both validation and transformation.
104
+ *
105
+ * @param {string} name - Hook name
106
+ * @param {string} trigger - Hook trigger
107
+ * @param {Function} validate - Validation function (quad) => boolean
108
+ * @param {Function} transform - Transform function (quad) => quad
109
+ * @param {Record<string, any>} [metadata] - Optional metadata
110
+ * @returns {object} Defined hook
111
+ */
112
+ export function defineValidateAndTransformHook(name, trigger, validate, transform, metadata) {
113
+ return _defineHook({ name, trigger, validate, transform, metadata });
114
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview Hook Execution API - Entry point for @unrdf/hooks/executor
3
+ *
4
+ * Provides the primary execution interface:
5
+ * - HookExecutor (KnowledgeHookEngine) for high-performance hook execution
6
+ * - executeHook() for single hook execution
7
+ * - batchExecute() for bulk operations
8
+ * - Result schemas and types
9
+ *
10
+ * @module @unrdf/hooks/executor
11
+ */
12
+
13
+ // Main execution engine (aliased as HookExecutor for public API)
14
+ export { KnowledgeHookEngine as HookExecutor } from './hooks/knowledge-hook-engine.mjs';
15
+
16
+ // Single hook execution
17
+ export { executeHook } from './hooks/hook-executor.mjs';
18
+
19
+ // Batch execution (aliased as batchExecute for public API)
20
+ export { executeBatch as batchExecute } from './hooks/hook-executor.mjs';
21
+
22
+ // Result types / schemas
23
+ export { HookResultSchema, ChainResultSchema } from './hooks/hook-executor.mjs';