@aikdna/kdna-core 0.15.10 → 0.15.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.15.11 (2026-07-03)
4
+
5
+ **Fix**: repair Core v1 container dispatcher module resolution in the
6
+ published package layout.
7
+
8
+ - Corrects internal `src/container-dispatcher.js` imports so the dispatcher can
9
+ load sibling `asset-reader` and `v1` modules after npm packaging.
10
+ - Loads v1 JSON schemas through package-relative static imports before falling
11
+ back to disk discovery, so bundled server environments do not look for
12
+ KDNA schemas in the host application directory.
13
+ - Adds regression coverage for loading a v1 source asset through the dispatcher
14
+ from the package `src/` layout and for validating from a non-repository cwd.
15
+ - Fix webpack bundler warning: use `eval('require')` for ajv meta-schema import
16
+ so webpack does not try to statically resolve the JSON file at build time.
17
+
18
+ No public API changes.
3
19
 
4
20
  ## v0.15.10 (2026-06-30)
5
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-core",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
4
4
  "description": "KDNA Core library for validating, planning, and loading local .kdna judgment assets.",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -47,7 +47,7 @@ function parseJson(buf, entryName) {
47
47
  try {
48
48
  return JSON.parse(Buffer.isBuffer(buf) ? buf.toString('utf8') : String(buf));
49
49
  } catch (e) {
50
- throw new Error(`${entryName}: invalid JSON: ${e.message}`);
50
+ throw new Error(`${entryName}: invalid JSON: ${e.message}`, { cause: e });
51
51
  }
52
52
  }
53
53
 
@@ -325,7 +325,7 @@ function verifyHumanLockSignatures(coreData, manifest, errors, warnings) {
325
325
  ];
326
326
 
327
327
  let verified = 0, missing = 0, invalid = 0;
328
- for (const [arrayName, _cardType] of CORE_CARD_ARRAYS) {
328
+ for (const [arrayName] of CORE_CARD_ARRAYS) {
329
329
  const cards = coreData?.[arrayName];
330
330
  if (!Array.isArray(cards) || cards.length === 0) continue;
331
331
 
@@ -4,7 +4,7 @@ const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
  const crypto = require('node:crypto');
6
6
 
7
- const { createKdnaAssetReader } = require('../asset-reader.js');
7
+ const { createKdnaAssetReader } = require('./asset-reader.js');
8
8
 
9
9
  const MIMETYPE_V1 = 'application/vnd.kdna.asset';
10
10
  const MIMETYPE_V2 = 'application/vnd.aikdna.kdna+zip';
@@ -220,7 +220,7 @@ function readSourceDirectory(absPath, _opts) {
220
220
  */
221
221
  function readV1Container(absPath, _opts) {
222
222
  // Delegate to the existing v1 layout reader for validation
223
- const v1Layout = require('../v1/index.js').readV1Layout(absPath);
223
+ const v1Layout = require('./v1/index.js').readV1Layout(absPath);
224
224
 
225
225
  const containerBuf = fs.readFileSync(absPath);
226
226
  const assetDigest = crypto.createHash('sha256').update(containerBuf).digest();
@@ -102,7 +102,6 @@ function hkdfSha256(ikm, salt = null, info = '', length = 32) {
102
102
 
103
103
  // ── AES-256-KW (RFC 3394) ─────────────────────────────────────────
104
104
 
105
- const AES_BLOCK = 16;
106
105
  const KW_IV = Buffer.from('a6a6a6a6a6a6a6a6', 'hex'); // RFC 3394 default IV
107
106
 
108
107
  function aesWrap(key, plaintext) {
package/src/public-api.js CHANGED
@@ -110,7 +110,7 @@ async function validateKDNA(input, options = {}) {
110
110
  const reader = readerFrom(options);
111
111
  const asset = await asAsset(input, { ...options, reader });
112
112
  const assetResult = await reader.verify(asset, options);
113
- let dataMap = null;
113
+ let dataMap;
114
114
  let lintResult = { errors: [], warnings: [] };
115
115
  let schemaResult = { errors: [], warnings: [] };
116
116
  let crossFileResult = { errors: [], warnings: [] };
package/src/v1/index.js CHANGED
@@ -91,6 +91,16 @@ const FORBIDDEN_OUTPUT_TERMS = Object.freeze([
91
91
  let _ajv = null;
92
92
  let _validators = null;
93
93
 
94
+ function loadPackagedSchemas() {
95
+ return {
96
+ manifestSchema: require('../../schema/manifest.schema.json'),
97
+ payloadSchema: require('../../schema/payload-profile-v1.schema.json'),
98
+ bundlePayloadSchema: require('../../schema/bundle-profile-v1.schema.json'),
99
+ checksumsSchema: require('../../schema/checksums.schema.json'),
100
+ loadContractSchema: require('../../schema/load-contract.schema.json'),
101
+ };
102
+ }
103
+
94
104
  function getRepoRoot() {
95
105
  // Walk up from this file to find the repo root (where schema/ lives).
96
106
  // Works whether this module is loaded from packages/kdna/src/ or
@@ -106,6 +116,26 @@ function getRepoRoot() {
106
116
  return process.cwd();
107
117
  }
108
118
 
119
+ function loadSchemasFromDisk() {
120
+ const repoRoot = getRepoRoot();
121
+ const schemaDir = path.join(repoRoot, 'schema');
122
+ return {
123
+ manifestSchema: JSON.parse(fs.readFileSync(path.join(schemaDir, 'manifest.schema.json'), 'utf8')),
124
+ payloadSchema: JSON.parse(
125
+ fs.readFileSync(path.join(schemaDir, 'payload-profile-v1.schema.json'), 'utf8'),
126
+ ),
127
+ bundlePayloadSchema: JSON.parse(
128
+ fs.readFileSync(path.join(schemaDir, 'bundle-profile-v1.schema.json'), 'utf8'),
129
+ ),
130
+ checksumsSchema: JSON.parse(
131
+ fs.readFileSync(path.join(schemaDir, 'checksums.schema.json'), 'utf8'),
132
+ ),
133
+ loadContractSchema: JSON.parse(
134
+ fs.readFileSync(path.join(schemaDir, 'load-contract.schema.json'), 'utf8'),
135
+ ),
136
+ };
137
+ }
138
+
109
139
  function loadSchemas() {
110
140
  if (_validators) return _validators;
111
141
  let Ajv;
@@ -119,21 +149,13 @@ function loadSchemas() {
119
149
  // to structural checks (no JSON-schema enforcement).
120
150
  return null;
121
151
  }
122
- const repoRoot = getRepoRoot();
123
- const schemaDir = path.join(repoRoot, 'schema');
124
- const manifestSchema = JSON.parse(fs.readFileSync(path.join(schemaDir, 'manifest.schema.json'), 'utf8'));
125
- const payloadSchema = JSON.parse(
126
- fs.readFileSync(path.join(schemaDir, 'payload-profile-v1.schema.json'), 'utf8'),
127
- );
128
- const bundlePayloadSchema = JSON.parse(
129
- fs.readFileSync(path.join(schemaDir, 'bundle-profile-v1.schema.json'), 'utf8'),
130
- );
131
- const checksumsSchema = JSON.parse(
132
- fs.readFileSync(path.join(schemaDir, 'checksums.schema.json'), 'utf8'),
133
- );
134
- const loadContractSchema = JSON.parse(
135
- fs.readFileSync(path.join(schemaDir, 'load-contract.schema.json'), 'utf8'),
136
- );
152
+ let schemas;
153
+ try {
154
+ schemas = loadPackagedSchemas();
155
+ } catch {
156
+ schemas = loadSchemasFromDisk();
157
+ }
158
+ const { manifestSchema, payloadSchema, bundlePayloadSchema, checksumsSchema, loadContractSchema } = schemas;
137
159
  const ajv = new Ajv({ allErrors: true, strict: false });
138
160
  addFormats(ajv);
139
161
  ajv.addSchema(loadContractSchema, 'load-contract.schema.json');
@@ -521,7 +543,7 @@ function readV1Layout(absPath) {
521
543
 
522
544
  const map = {};
523
545
  let entries = null; // ZIP entries if container
524
- let kind = null; // 'dir' | 'file'
546
+ let kind; // 'dir' | 'file'
525
547
 
526
548
  if (stat.isDirectory()) {
527
549
  kind = 'dir';
@@ -589,7 +611,7 @@ function readV1Layout(absPath) {
589
611
  try {
590
612
  manifest = parseJsonEntry('kdna.json', map['kdna.json']);
591
613
  } catch (e) {
592
- throw new Error(`kdna.json is not valid JSON: ${e.message}`);
614
+ throw new Error(`kdna.json is not valid JSON: ${e.message}`, { cause: e });
593
615
  }
594
616
  if (manifest.lineage !== undefined && Array.isArray(manifest.lineage)) {
595
617
  throw new Error('kdna.json.lineage must be an object, not an array');
@@ -1773,7 +1795,7 @@ function loadV1Unsafe(inputPath, opts = {}) {
1773
1795
  const rawPayload = v1.map['payload.kdnab'];
1774
1796
  payload = parseJsonEntry('payload.kdnab', rawPayload);
1775
1797
  } catch (e) {
1776
- throw new Error(`payload.kdnab is not valid JSON: ${e.message}`);
1798
+ throw new Error(`payload.kdnab is not valid JSON: ${e.message}`, { cause: e });
1777
1799
  }
1778
1800
 
1779
1801
  if (payload.profile && payload.ciphertext && (m.payload?.encrypted || m.encryption?.encrypted_entries?.includes('payload.kdnab'))) {
@@ -1946,7 +1968,7 @@ function loadV1Unsafe(inputPath, opts = {}) {
1946
1968
  }));
1947
1969
  result.inheritance_applied = true;
1948
1970
  }
1949
- } catch (_) {
1971
+ } catch {
1950
1972
  // extends merge is best-effort — never block load
1951
1973
  result.inheritance_applied = false;
1952
1974
  }
@@ -59,7 +59,10 @@ function validateDomainSchema(dataMap, schemaMap) {
59
59
  const ajvInstance = new ajv({ allErrors: true, strict: false });
60
60
  if (addFormats) addFormats(ajvInstance);
61
61
  try {
62
- ajvInstance.addMetaSchema(require('ajv/dist/refs/json-schema-2020-12.json'));
62
+ // Use eval('require') to avoid webpack static analysis trying to
63
+ // resolve this JSON file at build time (it is only needed at runtime).
64
+ const _require = eval('require');
65
+ ajvInstance.addMetaSchema(_require('ajv/dist/refs/json-schema-2020-12.json'));
63
66
  } catch {
64
67
  /* meta-schema already available or not needed */
65
68
  }
@@ -169,9 +169,6 @@ function checkWorkPackStructure(manifest, rootDir) {
169
169
  */
170
170
  function inspectWorkPack(manifest, rootDir) {
171
171
  const kdnaMode = manifest.kdna?.mode || 'unknown';
172
- const kdnaCount =
173
- kdnaMode === 'single' ? 1 : (manifest.kdna?.assets || []).length;
174
-
175
172
  const structure = checkWorkPackStructure(manifest, rootDir);
176
173
 
177
174
  return {
@@ -240,7 +237,8 @@ function _lazyAjv() {
240
237
  return _ajvInstance;
241
238
  } catch (e) {
242
239
  throw new Error(
243
- 'ajv is required for Work Pack validation. Install: npm install ajv ajv-formats'
240
+ 'ajv is required for Work Pack validation. Install: npm install ajv ajv-formats',
241
+ { cause: e },
244
242
  );
245
243
  }
246
244
  }