@aikdna/kdna-core 0.20.0 → 0.22.0

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,76 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.22.0 (2026-08-17)
6
+
7
+ ### Added
8
+
9
+ - RFC-0021 M1 asset signatures (`kdsig.ed25519`): sign and verify packaged
10
+ `.kdna` assets with Ed25519 signature bundles — `signKDNA`,
11
+ `verifyKDNASignature`, `composeKDNA`, signing-payload builders, key-pair
12
+ generation, key fingerprints, and signature-bundle parse/serialize —
13
+ mirrored byte-for-byte in the Python Core, with cross-language signature
14
+ conformance vectors. M1 is bound as a pre-release candidate; M2–M6 are not
15
+ implemented and remain non-binding.
16
+ - RFC-0020 minimal projection profile: a fifth load profile for small local
17
+ models, a strict subset of compact carrying the highest-question and
18
+ boundary-friendly axioms plus full boundaries (~0.8–1.1k tokens vs compact
19
+ ~5.4k on the reference assets). Availability follows the manifest
20
+ declaration; assets without a minimal declaration fail closed.
21
+
22
+ ### Fixed
23
+
24
+ - Validate decrypted external-grant and password payload plaintext against the
25
+ same declared Payload schema used for ordinary assets. Correct credentials
26
+ can no longer load schema-invalid judgment bytes.
27
+ - Close `core_structure` relation objects to the existing public relation
28
+ fields and project only that allowlist in compact Runtime Capsules, blocking
29
+ private Creation state hidden in arbitrary relation properties.
30
+ - Make the external-grant conformance golden carry one deterministic, actual
31
+ encrypted `.kdna` byte snapshot. The regression now checks the exact package
32
+ digest, Core validation, signed authorization, LoadPlan and authorized load
33
+ against that same artifact instead of deriving grant identity from
34
+ zlib-dependent repacking.
35
+ - Warn with `KDNA_DISPATCHER_DEGRADED` when the container dispatcher fails to
36
+ load for any reason other than the dispatcher file itself being absent,
37
+ instead of silently degrading to the legacy reader. The absence check now
38
+ resolves the dispatcher path up front, so a present dispatcher with a
39
+ missing internal dependency, a syntax or initialization error, or a
40
+ permission error is reported instead of being mistaken for a missing
41
+ module.
42
+ - Fail closed on hostile Argon2id parameters in untrusted password envelopes:
43
+ `memory_kib`, `iterations`, and `parallelism` must be integers within
44
+ defensive bounds (256 MiB / 16 / 8), removing a remote denial-of-service
45
+ path when loading third-party protected assets.
46
+
47
+ ## 0.21.0 (2026-07-20)
48
+
49
+ ### Changed
50
+
51
+ - Keep `planLoad` fail-closed for password-protected assets until the supplied
52
+ credential is actually verified by `load`; a mere password-present signal
53
+ no longer reports `ready` or `can_load_now: true`.
54
+ - Require at least one non-empty, author-neutral judgment unit and explicit
55
+ scope or boundary semantics while keeping optional creator provenance
56
+ separate from format validity.
57
+ - Preserve every declared pattern in compact projection instead of silently
58
+ applying a prefix budget.
59
+ - Report every non-empty payload path intentionally omitted by compact
60
+ projection, including deterministic counts, in Runtime Capsule trace and
61
+ prompt output; preserve complete axiom applicability lists and stop trimming
62
+ a full-statement fallback.
63
+ - Make `checksums.json` optional under one container authority and verify it
64
+ whenever it is present.
65
+ - Withdraw asset-signature containers from the Development Preview contract;
66
+ malformed or legacy signature declarations now fail closed. External grants
67
+ and Human Lock provenance remain separate responsibilities.
68
+ - Close licensed entitlement validation around the declared `password`,
69
+ `local_receipt`, `account`, and `org` profiles.
70
+ - Load external-grant Schemas through static package imports so bundler-based
71
+ ecosystem adapters retain the exact Core validators instead of failing at
72
+ activation time.
73
+
3
74
  ## 0.20.0 (2026-07-17)
4
75
 
5
76
  ### Changed
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @aikdna/kdna-core
2
2
 
3
+ > **Status:** Pre-release. This source tree contains unreleased work beyond
4
+ > the published incumbent `0.22.0` (RFC-0021 M1 asset signatures and the
5
+ > RFC-0020 minimal projection profile); the next release coordinate is not
6
+ > finalized. The older `0.21.0` line predates the signature track. Candidate
7
+ > source, APIs, and evidence must not be described as already published.
8
+
3
9
  Core library for packaged `.kdna` judgment assets. It implements one current
4
10
  container contract, authorization planning, integrity evidence, Runtime Capsule
5
11
  projection, and the correlated Agent Host execution boundary.
@@ -7,9 +13,13 @@ projection, and the correlated Agent Host execution boundary.
7
13
  ## Install
8
14
 
9
15
  ```bash
10
- npm install @aikdna/kdna-core
16
+ npm install @aikdna/kdna-core@0.22.0
11
17
  ```
12
18
 
19
+ That command installs the published incumbent. Use its release notes for the
20
+ exact `0.22.0` contract. The examples below describe the current source
21
+ candidate and require its final release coordinate before registry use.
22
+
13
23
  ## Pack, validate, plan, and load
14
24
 
15
25
  Use the package root. Version-qualified entry points and parallel generation
@@ -58,7 +68,7 @@ separate from loadability: `planLoad` and every load path block a valid asset
58
68
  that requires a newer loader with `KDNA_LOADER_VERSION_UNSUPPORTED` before
59
69
  projection.
60
70
 
61
- ## Stable Runtime contracts
71
+ ## Current candidate Runtime contracts
62
72
 
63
73
  There is one current responsibility chain:
64
74
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikdna/kdna-core",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "KDNA Core library for validating, planning, and loading local .kdna judgment assets.",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@noble/hashes": "^1.8.0",
67
- "cbor-x": "^1.6.4",
67
+ "cbor-x": "^1.6.5",
68
68
  "ajv": "^8.20.0",
69
69
  "ajv-formats": "^3.0.1"
70
70
  }
@@ -9,7 +9,7 @@
9
9
  "properties": {
10
10
  "default_profile": {
11
11
  "type": "string",
12
- "enum": ["index", "compact", "scenario", "full"]
12
+ "enum": ["index", "compact", "scenario", "full", "minimal"]
13
13
  },
14
14
  "profiles": {
15
15
  "type": "object",
@@ -19,7 +19,8 @@
19
19
  "index": { "$ref": "#/$defs/profile" },
20
20
  "compact": { "$ref": "#/$defs/profile" },
21
21
  "scenario": { "$ref": "#/$defs/profile" },
22
- "full": { "$ref": "#/$defs/profile" }
22
+ "full": { "$ref": "#/$defs/profile" },
23
+ "minimal": { "$ref": "#/$defs/profile" }
23
24
  }
24
25
  }
25
26
  },
@@ -15,6 +15,7 @@
15
15
  "can_load_now",
16
16
  "projection_policy",
17
17
  "checks",
18
+ "signature_state",
18
19
  "issues",
19
20
  "source",
20
21
  "input_fingerprint"
@@ -87,6 +88,7 @@
87
88
  "schema_valid",
88
89
  "payload_valid",
89
90
  "checksums_valid",
91
+ "signature_valid",
90
92
  "load_contract_valid",
91
93
  "overall_valid"
92
94
  ],
@@ -96,10 +98,15 @@
96
98
  "schema_valid": { "type": "boolean" },
97
99
  "payload_valid": { "type": "boolean" },
98
100
  "checksums_valid": { "type": "boolean" },
101
+ "signature_valid": { "type": "boolean" },
99
102
  "load_contract_valid": { "type": "boolean" },
100
103
  "overall_valid": { "type": "boolean" }
101
104
  }
102
105
  },
106
+ "signature_state": {
107
+ "description": "RFC-0021 M1 signature evidence state: absent (unsigned), verified (signature.kdsig verified), or invalid (present but rejected).",
108
+ "enum": ["absent", "verified", "invalid"]
109
+ },
103
110
  "issues": {
104
111
  "type": "array",
105
112
  "items": {
@@ -40,6 +40,14 @@
40
40
  }
41
41
  }
42
42
  }
43
+ },
44
+ {
45
+ "if": { "properties": { "access": { "const": "licensed" } }, "required": ["access"] },
46
+ "then": { "required": ["entitlement"] }
47
+ },
48
+ {
49
+ "if": { "required": ["entitlement"] },
50
+ "then": { "properties": { "access": { "const": "licensed" } }, "required": ["access"] }
43
51
  }
44
52
  ],
45
53
  "properties": {
@@ -139,6 +147,19 @@
139
147
  "enum": ["public", "licensed", "remote"],
140
148
  "description": "Stable delivery and authorization mode for the asset."
141
149
  },
150
+ "entitlement": {
151
+ "type": "object",
152
+ "required": ["profile"],
153
+ "additionalProperties": true,
154
+ "properties": {
155
+ "profile": {
156
+ "type": "string",
157
+ "enum": ["password", "local_receipt", "account", "org"]
158
+ },
159
+ "offline": { "type": "boolean" },
160
+ "revocable": { "type": "boolean" }
161
+ }
162
+ },
142
163
  "summary": { "type": "string" },
143
164
  "description": { "type": "string" },
144
165
  "language": { "type": "string" },
@@ -223,19 +244,8 @@
223
244
  }
224
245
  }
225
246
  },
226
- "signatures": {
227
- "type": "array",
228
- "items": {
229
- "type": "object",
230
- "required": ["role", "path", "algorithm"],
231
- "properties": {
232
- "role": { "type": "string" },
233
- "path": { "type": "string" },
234
- "algorithm": { "type": "string" },
235
- "key_id": { "type": "string" }
236
- }
237
- }
238
- },
247
+ "signature": false,
248
+ "signatures": false,
239
249
  "dependencies": {
240
250
  "type": "object",
241
251
  "additionalProperties": {
@@ -243,7 +253,7 @@
243
253
  }
244
254
  },
245
255
  "extends": {
246
- "description": "Asset inheritance declaration (Story 12). This asset inherits judgment content from the named base asset. Distinct from 'dependencies' (peer composition): 'extends' creates a single-inheritance hierarchy where the child specialises the parent. The child's cards override the parent's cards with the same ID; parent cards not overridden are inherited. Format: '@scope/name@semver-range' string, or an object with 'name' and optional 'version' fields.",
256
+ "description": "Asset inheritance declaration. This asset inherits judgment content from the named base asset. Distinct from 'dependencies' (peer composition): 'extends' creates a single-inheritance hierarchy where the child specialises the parent. The child's cards override the parent's cards with the same ID; parent cards not overridden are inherited. Format: '@scope/name@semver-range' string, or an object with 'name' and optional 'version' fields.",
247
257
  "oneOf": [
248
258
  {
249
259
  "type": "string",
@@ -18,11 +18,63 @@
18
18
  },
19
19
  "core": {
20
20
  "type": "object",
21
- "required": ["highest_question", "axioms"],
21
+ "required": ["axioms"],
22
22
  "additionalProperties": true,
23
+ "anyOf": [
24
+ { "required": ["highest_question"] },
25
+ {
26
+ "required": ["judgment_role"],
27
+ "properties": {
28
+ "judgment_role": {
29
+ "anyOf": [
30
+ { "required": ["acts_as"] },
31
+ { "required": ["does_not_act_as"] },
32
+ { "required": ["responsibility"] }
33
+ ]
34
+ }
35
+ }
36
+ },
37
+ {
38
+ "required": ["boundaries"],
39
+ "properties": { "boundaries": { "minItems": 1 } }
40
+ },
41
+ {
42
+ "properties": {
43
+ "axioms": {
44
+ "contains": {
45
+ "type": "object",
46
+ "anyOf": [
47
+ {
48
+ "required": ["applies_when"],
49
+ "properties": {
50
+ "applies_when": {
51
+ "type": "array",
52
+ "minItems": 1,
53
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
54
+ }
55
+ }
56
+ },
57
+ {
58
+ "required": ["does_not_apply_when"],
59
+ "properties": {
60
+ "does_not_apply_when": {
61
+ "type": "array",
62
+ "minItems": 1,
63
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
64
+ }
65
+ }
66
+ }
67
+ ]
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ],
23
73
  "properties": {
24
74
  "highest_question": {
25
75
  "type": "string",
76
+ "minLength": 1,
77
+ "pattern": "\\S",
26
78
  "description": "The single most important question this judgment system answers."
27
79
  },
28
80
  "worldview": {
@@ -39,23 +91,121 @@
39
91
  "type": "object",
40
92
  "additionalProperties": true,
41
93
  "properties": {
42
- "acts_as": { "type": "string" },
94
+ "acts_as": { "type": "string", "minLength": 1, "pattern": "\\S" },
43
95
  "does_not_act_as": {
44
96
  "oneOf": [
45
- { "type": "string" },
46
- { "type": "array", "items": { "type": "string" } }
97
+ { "type": "string", "minLength": 1, "pattern": "\\S" },
98
+ {
99
+ "type": "array",
100
+ "minItems": 1,
101
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
102
+ }
47
103
  ]
48
104
  },
49
- "responsibility": { "type": "string" }
105
+ "responsibility": { "type": "string", "minLength": 1, "pattern": "\\S" }
50
106
  },
51
107
  "description": "The authority this asset exercises and the responsibilities explicitly outside it."
52
108
  },
109
+ "core_structure": {
110
+ "type": "array",
111
+ "items": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "required": ["from", "to", "via"],
115
+ "properties": {
116
+ "from": { "type": "string", "minLength": 1, "pattern": "\\S" },
117
+ "to": { "type": "string", "minLength": 1, "pattern": "\\S" },
118
+ "via": { "type": "string", "enum": ["priority", "exception"] },
119
+ "applies_when": {
120
+ "type": "array",
121
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
122
+ },
123
+ "does_not_apply_when": {
124
+ "type": "array",
125
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
126
+ }
127
+ }
128
+ },
129
+ "description": "Ordered public judgment relations. Relation objects are closed so private authoring state cannot enter Runtime projection."
130
+ },
53
131
  "axioms": {
54
132
  "type": "array",
55
- "description": "The list of axioms. Phase 1 accepts an empty array."
133
+ "minItems": 1,
134
+ "items": {
135
+ "oneOf": [
136
+ { "type": "string", "minLength": 1, "pattern": "\\S" },
137
+ {
138
+ "type": "object",
139
+ "minProperties": 1,
140
+ "properties": {
141
+ "applies_when": {
142
+ "type": "array",
143
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
144
+ },
145
+ "does_not_apply_when": {
146
+ "type": "array",
147
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
148
+ }
149
+ },
150
+ "anyOf": [
151
+ {
152
+ "required": ["statement"],
153
+ "properties": { "statement": { "type": "string", "minLength": 1, "pattern": "\\S" } }
154
+ },
155
+ {
156
+ "required": ["one_sentence"],
157
+ "properties": { "one_sentence": { "type": "string", "minLength": 1, "pattern": "\\S" } }
158
+ },
159
+ {
160
+ "required": ["full_statement"],
161
+ "properties": { "full_statement": { "type": "string", "minLength": 1, "pattern": "\\S" } }
162
+ }
163
+ ]
164
+ }
165
+ ]
166
+ },
167
+ "description": "At least one non-empty judgment statement with an actual selection meaning."
56
168
  },
57
169
  "boundaries": {
58
170
  "type": "array",
171
+ "items": {
172
+ "oneOf": [
173
+ { "type": "string", "minLength": 1, "pattern": "\\S" },
174
+ {
175
+ "type": "object",
176
+ "minProperties": 1,
177
+ "anyOf": [
178
+ { "required": ["scope"], "properties": { "scope": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
179
+ { "required": ["out_of_scope"], "properties": { "out_of_scope": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
180
+ { "required": ["text"], "properties": { "text": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
181
+ { "required": ["statement"], "properties": { "statement": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
182
+ { "required": ["one_sentence"], "properties": { "one_sentence": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
183
+ { "required": ["boundary"], "properties": { "boundary": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
184
+ { "required": ["stance"], "properties": { "stance": { "type": "string", "minLength": 1, "pattern": "\\S" } } },
185
+ {
186
+ "required": ["applies_when"],
187
+ "properties": {
188
+ "applies_when": {
189
+ "type": "array",
190
+ "minItems": 1,
191
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
192
+ }
193
+ }
194
+ },
195
+ {
196
+ "required": ["does_not_apply_when"],
197
+ "properties": {
198
+ "does_not_apply_when": {
199
+ "type": "array",
200
+ "minItems": 1,
201
+ "items": { "type": "string", "minLength": 1, "pattern": "\\S" }
202
+ }
203
+ }
204
+ }
205
+ ]
206
+ }
207
+ ]
208
+ },
59
209
  "description": "Explicit out-of-scope statements."
60
210
  },
61
211
  "risk_model": {
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "signature": { "$ref": "#/$defs/signature" },
38
38
  "access": { "enum": ["public", "licensed", "remote"] },
39
- "profile": { "enum": ["index", "compact", "scenario", "full"] },
39
+ "profile": { "enum": ["index", "compact", "scenario", "full", "minimal"] },
40
40
  "context": { "type": "object" },
41
41
  "trace": { "$ref": "#/$defs/trace" }
42
42
  },
@@ -78,13 +78,28 @@
78
78
  }
79
79
  },
80
80
  "signature": {
81
- "type": "object",
82
- "required": ["state"],
83
- "additionalProperties": false,
84
- "properties": {
85
- "state": { "enum": ["verified", "not_checked", "absent"] },
86
- "issuer": { "type": "string", "minLength": 1 }
87
- }
81
+ "oneOf": [
82
+ {
83
+ "type": "object",
84
+ "required": ["state"],
85
+ "additionalProperties": false,
86
+ "properties": {
87
+ "state": { "const": "absent" }
88
+ }
89
+ },
90
+ {
91
+ "type": "object",
92
+ "required": ["state", "profile", "profile_version", "key_fingerprint", "content_digest"],
93
+ "additionalProperties": false,
94
+ "properties": {
95
+ "state": { "const": "verified" },
96
+ "profile": { "const": "kdsig.ed25519" },
97
+ "profile_version": { "const": "0.1.0" },
98
+ "key_fingerprint": { "$ref": "#/$defs/sha256" },
99
+ "content_digest": { "$ref": "#/$defs/sha256" }
100
+ }
101
+ }
102
+ ]
88
103
  },
89
104
  "trace": {
90
105
  "type": "object",
@@ -106,9 +121,51 @@
106
121
  "input_kind": { "enum": ["packaged_file", "packaged_bytes"] },
107
122
  "runtime_eligible": { "const": true },
108
123
  "schema_valid": { "const": true },
109
- "signature_state": { "enum": ["verified", "not_checked", "absent"] },
110
- "profile": { "enum": ["index", "compact", "scenario", "full"] }
124
+ "signature_state": { "enum": ["absent", "verified"] },
125
+ "profile": { "enum": ["index", "compact", "scenario", "full", "minimal"] },
126
+ "projection_report": { "$ref": "#/$defs/projectionReport" }
111
127
  }
128
+ },
129
+ "projectionReport": {
130
+ "type": "object",
131
+ "required": ["status", "omitted", "omitted_total"],
132
+ "additionalProperties": false,
133
+ "properties": {
134
+ "status": { "enum": ["complete", "partial"] },
135
+ "omitted": {
136
+ "type": "array",
137
+ "items": {
138
+ "type": "object",
139
+ "required": ["path", "count"],
140
+ "additionalProperties": false,
141
+ "properties": {
142
+ "path": { "type": "string", "pattern": "^/" },
143
+ "count": { "type": "integer", "minimum": 1 }
144
+ }
145
+ }
146
+ },
147
+ "omitted_total": { "type": "integer", "minimum": 0 }
148
+ },
149
+ "allOf": [
150
+ {
151
+ "if": { "properties": { "status": { "const": "complete" } } },
152
+ "then": {
153
+ "properties": {
154
+ "omitted": { "maxItems": 0 },
155
+ "omitted_total": { "const": 0 }
156
+ }
157
+ }
158
+ },
159
+ {
160
+ "if": { "properties": { "status": { "const": "partial" } } },
161
+ "then": {
162
+ "properties": {
163
+ "omitted": { "minItems": 1 },
164
+ "omitted_total": { "minimum": 1 }
165
+ }
166
+ }
167
+ }
168
+ ]
112
169
  }
113
170
  }
114
171
  }