@o-lang/olang 1.2.19 → 1.2.20
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/package.json +1 -1
- package/src/runtime/index.js +45 -42
package/package.json
CHANGED
package/src/runtime/index.js
CHANGED
|
@@ -1,89 +1,91 @@
|
|
|
1
1
|
// src/runtime/index.js
|
|
2
2
|
const { RuntimeAPI } = require('./RuntimeAPI');
|
|
3
|
-
const { parse }
|
|
4
|
-
const crypto
|
|
5
|
-
const fs
|
|
6
|
-
const path
|
|
3
|
+
const { parse } = require('../parser');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// ── Load kernel private key (cached) ─────────────────────────────────────────
|
|
9
9
|
let KERNEL_PRIVATE_KEY = null;
|
|
10
|
+
|
|
10
11
|
function getKernelPrivateKey() {
|
|
11
12
|
if (KERNEL_PRIVATE_KEY) return KERNEL_PRIVATE_KEY;
|
|
12
|
-
|
|
13
|
-
const keyPath
|
|
14
|
-
const absolutePath = path.isAbsolute(keyPath)
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
const keyPath = process.env.KERNEL_PRIVATE_KEY_PATH || './kernel-keys/kernel-private.pem';
|
|
15
|
+
const absolutePath = path.isAbsolute(keyPath)
|
|
16
|
+
? keyPath
|
|
17
|
+
: path.join(process.cwd(), keyPath);
|
|
18
|
+
|
|
16
19
|
if (!fs.existsSync(absolutePath)) {
|
|
17
20
|
console.warn('[kernel] Warning: Private key not found at', absolutePath);
|
|
18
21
|
console.warn('[kernel] Audit entries will NOT be signed');
|
|
19
22
|
return null;
|
|
20
23
|
}
|
|
21
|
-
|
|
24
|
+
|
|
22
25
|
KERNEL_PRIVATE_KEY = fs.readFileSync(absolutePath, 'utf8');
|
|
23
26
|
console.log('[kernel] ✅ Private key loaded for signing');
|
|
24
27
|
return KERNEL_PRIVATE_KEY;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
//
|
|
30
|
+
// ── Sign audit data with RSA-SHA256 ──────────────────────────────────────────
|
|
31
|
+
// Uses RSA-SHA256 to match the RSA key generated by crypto.generateKeyPairSync.
|
|
32
|
+
// The same sorted JSON serialization is used during verification.
|
|
33
|
+
|
|
28
34
|
function signAuditData(auditData, privateKeyPem) {
|
|
29
35
|
if (!privateKeyPem) return null;
|
|
30
|
-
|
|
36
|
+
|
|
31
37
|
try {
|
|
32
|
-
// Serialize
|
|
38
|
+
// Serialize with sorted keys — must match verifySignature() in server.js
|
|
33
39
|
const serialized = JSON.stringify(auditData, Object.keys(auditData).sort());
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
key: privateKeyPem,
|
|
41
|
-
dsaEncoding: 'ieee-p1363', // Required for ED25519
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return signature.toString('hex');
|
|
40
|
+
|
|
41
|
+
const sign = crypto.createSign('SHA256');
|
|
42
|
+
sign.update(serialized);
|
|
43
|
+
sign.end();
|
|
44
|
+
|
|
45
|
+
return sign.sign(privateKeyPem, 'hex');
|
|
46
46
|
} catch (err) {
|
|
47
47
|
console.error('[kernel] Signature error:', err.message);
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// ── Main execute function ─────────────────────────────────────────────────────
|
|
53
|
+
|
|
52
54
|
async function execute(workflow, inputs, agentResolver, verbose = false) {
|
|
53
55
|
const rt = new RuntimeAPI({ verbose });
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
+
|
|
57
|
+
// Run the workflow — result contains only Return values
|
|
56
58
|
const result = await rt.executeWorkflow(workflow, inputs, agentResolver);
|
|
57
59
|
|
|
58
|
-
//
|
|
60
|
+
// Grab audit data while RuntimeAPI instance is still alive
|
|
59
61
|
const lastEntry = rt.auditLog.at(-1);
|
|
60
62
|
const firstEntry = rt.auditLog.at(0);
|
|
61
63
|
|
|
62
|
-
// Build audit object BEFORE signing
|
|
64
|
+
// Build audit object BEFORE signing — must match verifySignature() structure
|
|
63
65
|
const auditData = {
|
|
64
|
-
execution_hash: lastEntry?.hash
|
|
65
|
-
previous_hash: firstEntry?.hash
|
|
66
|
+
execution_hash: lastEntry?.hash ?? null,
|
|
67
|
+
previous_hash: firstEntry?.hash ?? 'GENESIS',
|
|
66
68
|
merkle_root: rt._calculateMerkleRoot(),
|
|
67
|
-
kernel_version: lastEntry?.details?.kernel_version
|
|
69
|
+
kernel_version: lastEntry?.details?.kernel_version ?? null,
|
|
68
70
|
governance_profile_hash: lastEntry?.details?.governance_profile_hash ?? null,
|
|
69
71
|
integrity: rt.verifyAuditLogIntegrity(),
|
|
70
72
|
chain: rt.auditLog,
|
|
71
73
|
};
|
|
72
74
|
|
|
73
|
-
//
|
|
75
|
+
// Sign the audit data with the kernel private key
|
|
74
76
|
const privateKey = getKernelPrivateKey();
|
|
75
|
-
const signature
|
|
76
|
-
|
|
77
|
-
// Load public key for verification (
|
|
77
|
+
const signature = signAuditData(auditData, privateKey);
|
|
78
|
+
|
|
79
|
+
// Load public key for client-side verification (stripped PEM)
|
|
78
80
|
let publicKey = null;
|
|
79
81
|
if (privateKey) {
|
|
80
82
|
try {
|
|
81
|
-
const pubKeyPath
|
|
82
|
-
const absolutePubPath = path.isAbsolute(pubKeyPath)
|
|
83
|
-
? pubKeyPath
|
|
83
|
+
const pubKeyPath = process.env.KERNEL_PUBLIC_KEY_PATH || './kernel-keys/kernel-public.pem';
|
|
84
|
+
const absolutePubPath = path.isAbsolute(pubKeyPath)
|
|
85
|
+
? pubKeyPath
|
|
84
86
|
: path.join(process.cwd(), pubKeyPath);
|
|
87
|
+
|
|
85
88
|
if (fs.existsSync(absolutePubPath)) {
|
|
86
|
-
// Read and clean PEM for storage
|
|
87
89
|
publicKey = fs.readFileSync(absolutePubPath, 'utf8')
|
|
88
90
|
.replace('-----BEGIN PUBLIC KEY-----', '')
|
|
89
91
|
.replace('-----END PUBLIC KEY-----', '')
|
|
@@ -94,10 +96,11 @@ async function execute(workflow, inputs, agentResolver, verbose = false) {
|
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
// Attach audit to result — server.js detaches it before sending to client
|
|
97
100
|
result.__audit = {
|
|
98
101
|
...auditData,
|
|
99
|
-
signature,
|
|
100
|
-
publicKey,
|
|
102
|
+
signature, // RSA-SHA256 hex signature
|
|
103
|
+
publicKey, // Stripped PEM for client verification
|
|
101
104
|
};
|
|
102
105
|
|
|
103
106
|
return result;
|