@aikdna/kdna-core 0.36.0-rc.r2.7 → 0.37.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.
Files changed (45) hide show
  1. package/README.md +2 -2
  2. package/package.json +8 -2
  3. package/schema/manifest.schema.json +2 -1
  4. package/src/public-contract/browser-native/section-frame-graph.js +1 -1
  5. package/src/public-contract/browser-native/sections/contract.json +2 -2
  6. package/src/public-contract/browser-native/whole.js +1 -1
  7. package/src/public-contract/browserwhole06/contract.json +2 -2
  8. package/src/public-contract/creation06/contract.json +2 -2
  9. package/src/public-contract/creation06/generation-manifest.json +13 -13
  10. package/src/public-contract/execution-sections-node.js +1 -2
  11. package/src/public-contract/execution06/contract.json +2 -2
  12. package/src/public-contract/execution06/generation-manifest.json +13 -13
  13. package/src/public-contract/issuer-contract.generated.json +4 -4
  14. package/src/public-contract/issuer-validators.generated.js +7 -7
  15. package/src/public-contract/key-grant-issuer-node.d.ts +1 -1
  16. package/src/public-contract/package-set-contract.generated.json +5 -5
  17. package/src/public-contract/package-set-node.d.ts +1 -1
  18. package/src/public-contract/package-set-validators.generated.js +9 -9
  19. package/src/public-contract/packageset06/contract.json +2 -2
  20. package/src/public-contract/packageset06/generation-manifest.json +13 -13
  21. package/src/public-contract/protected-browser.d.ts +17 -0
  22. package/src/public-contract/protected-browser.js +4 -0
  23. package/src/public-contract/protected-browser.mjs +2 -0
  24. package/src/public-contract/protected-source-contract.generated.json +6 -6
  25. package/src/public-contract/protected-source-node.d.ts +1 -1
  26. package/src/public-contract/protection-admission-browser.js +114 -0
  27. package/src/public-contract/protection-contract.generated.json +12 -11
  28. package/src/public-contract/protection-crypto.js +7 -17
  29. package/src/public-contract/protection-envelope-codec.js +60 -1
  30. package/src/public-contract/protection-node.d.ts +2 -2
  31. package/src/public-contract/protection-validators.generated.js +5 -5
  32. package/src/public-contract/retained/contract.json +2 -2
  33. package/src/public-contract/retained/generation-manifest.json +13 -13
  34. package/src/public-contract/retained-browser06/contract.json +2 -2
  35. package/src/public-contract/section-checksums.js +1 -1
  36. package/src/public-contract/section-frame-graph.js +1 -1
  37. package/src/public-contract/section-layout.js +1 -1
  38. package/src/public-contract/sectionbytes/contract.json +2 -2
  39. package/src/public-contract/sectionbytes/generation-manifest.json +13 -13
  40. package/src/public-contract/sections/contract.json +2 -2
  41. package/src/public-contract/sections/generation-manifest.json +13 -13
  42. package/src/public-contract/sections-bytes-node.js +0 -1
  43. package/src/public-contract/source-public-pack.js +1 -1
  44. package/src/public-contract/source-validators.generated.js +6 -6
  45. package/src/public-contract/source06/contract.json +2 -2
@@ -10,7 +10,7 @@ export type IssuerIssuedObservation = { readonly "status": "issued"; readonly "g
10
10
  export type IssuerCoreRejectedObservation = { readonly "status": "core_rejected"; readonly "core": { readonly "status": "rejected"; readonly "reason": ReadDiagnosticCode; }; readonly "stage": "asset"; };
11
11
  export type IssuerFailedObservation = ({ readonly "status": "issuer_failed"; readonly "code": "ISSUER_INPUT_INVALID"; readonly "stage": "input"; } | { readonly "status": "issuer_failed"; readonly "code": "ISSUER_ASSET_PROFILE_UNSUPPORTED"; readonly "stage": "asset"; } | { readonly "status": "issuer_failed"; readonly "code": "ISSUER_ASSET_AUTHENTICATION_FAILED"; readonly "stage": "asset" | "integrity"; } | { readonly "status": "issuer_failed"; readonly "code": "ISSUER_KEY_INVALID"; readonly "stage": "issuer_key"; } | { readonly "status": "issuer_failed"; readonly "code": "ISSUER_GRANT_OPTIONS_INVALID"; readonly "stage": "input" | "grant"; } | { readonly "status": "issuer_failed"; readonly "code": "ISSUER_OUTPUT_INVALID"; readonly "stage": "input" | "asset" | "integrity" | "issuer_key" | "grant"; });
12
12
  export type IssuerResultObservation = (IssuerIssuedObservation | IssuerCoreRejectedObservation | IssuerFailedObservation);
13
- export type IssuerDescriptor = { readonly "id": "kdna.external-grant-issuer/1"; readonly "version": "1.0.0"; readonly "definition_digest": Digest; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.36.0-rc.r2.7"; }; readonly "exports": readonly ["getExternalGrantIssuerContract", "issueExternalKeyGrantForAsset"]; readonly "limits": { readonly "container_bytes": 26214400; readonly "grant_bytes": 1048576; readonly "timeout_ms_max": 60000; readonly "max_concurrent": 4; }; };
13
+ export type IssuerDescriptor = { readonly "id": "kdna.external-grant-issuer/1"; readonly "version": "1.0.0"; readonly "definition_digest": Digest; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.37.0"; }; readonly "exports": readonly ["getExternalGrantIssuerContract", "issueExternalKeyGrantForAsset"]; readonly "limits": { readonly "container_bytes": 26214400; readonly "grant_bytes": 1048576; readonly "timeout_ms_max": 60000; readonly "max_concurrent": 4; }; };
14
14
  export type IssuerSecrets = { readonly issuerRootKey: Uint8Array; readonly issuerSigningPrivateKeyPkcs8: Uint8Array; readonly signaturePolicy: IssuerSignaturePolicy };
15
15
  export type IssuanceResult = (IssuerIssuedObservation & { readonly grantBytes: Uint8Array }) | IssuerCoreRejectedObservation | IssuerFailedObservation;
16
16
  export declare function getExternalGrantIssuerContract(): IssuerDescriptor;
@@ -11,8 +11,8 @@
11
11
  "inspectAdmittedPackageSet",
12
12
  "verifyPackageSetHandoff"
13
13
  ],
14
- "core_version": "0.36.0-rc.r2.7",
15
- "definition_digest": "sha256:3b64c648ed8d2f10076ed6311f45917700df15dbc17590c1e820d64b73d83e66",
14
+ "core_version": "0.37.0",
15
+ "definition_digest": "sha256:86ceacb30be63d3b25e6cac17889ebd650fdc5cdff43340ad7d517423d2740fd",
16
16
  "limits": {
17
17
  "maxMembers": 10000,
18
18
  "maxTotalSourceBytes": 104857600
@@ -39,7 +39,7 @@
39
39
  "sealPackageSetHandoff",
40
40
  "admitPackageSetHandoff"
41
41
  ],
42
- "read_version": "0.11.0-rc.r2.7"
42
+ "read_version": "0.11.1"
43
43
  },
44
44
  "key_sets": {
45
45
  "HandoffMember": {
@@ -739,7 +739,7 @@
739
739
  "type": "array"
740
740
  },
741
741
  "core_version": {
742
- "const": "0.36.0-rc.r2.7",
742
+ "const": "0.37.0",
743
743
  "type": "string"
744
744
  },
745
745
  "definition_digest": {
@@ -769,7 +769,7 @@
769
769
  "type": "array"
770
770
  },
771
771
  "read_version": {
772
- "const": "0.11.0-rc.r2.7",
772
+ "const": "0.11.1",
773
773
  "type": "string"
774
774
  }
775
775
  },
@@ -6,7 +6,7 @@ export type PackageSetMemberObservationRequest = { readonly "set_id": Identifier
6
6
  export type PackageSetMemberObservationRow = { readonly "member_id": Identifier; readonly "asset_id": Identifier; readonly "asset_version": VersionLabel; readonly "A": Digest; readonly "decision": "allow" | "deny"; readonly "decision_id": Identifier; readonly "host_id": Identifier; readonly "host_epoch": Identifier; readonly "issued_at": UInt; readonly "expires_at": UInt; readonly "current_ms": UInt; };
7
7
  export type PackageSetMemberObservation = { readonly "decisions": ReadonlyArray<PackageSetMemberObservationRow>; };
8
8
  export type PackageSetReadObservation = { readonly "context": HostReadContextData; readonly "current_ms": UInt; };
9
- export type PackageSetNodeDescriptor = { readonly "contract": "kdna.package-set-node/0.2.1"; readonly "module_version": "0.2.0"; readonly "core_version": "0.36.0-rc.r2.7"; readonly "read_version": "0.11.0-rc.r2.7"; readonly "limits": PackageSetLimits; readonly "local_failures": ReadonlyArray<PackageSetLocalFailure>; readonly "core_callables": ReadonlyArray<Identifier>; readonly "read_callables": ReadonlyArray<Identifier>; readonly "claims": "claims_not_authenticated"; readonly "definition_digest": Digest; };
9
+ export type PackageSetNodeDescriptor = { readonly "contract": "kdna.package-set-node/0.2.1"; readonly "module_version": "0.2.0"; readonly "core_version": "0.37.0"; readonly "read_version": "0.11.1"; readonly "limits": PackageSetLimits; readonly "local_failures": ReadonlyArray<PackageSetLocalFailure>; readonly "core_callables": ReadonlyArray<Identifier>; readonly "read_callables": ReadonlyArray<Identifier>; readonly "claims": "claims_not_authenticated"; readonly "definition_digest": Digest; };
10
10
  export type PackageSetNodeSurface = (PackageSet | PackageSetHandoff | PackageSetMemberObservationRequest | PackageSetMemberObservation | PackageSetReadObservation | PackageSetNodeDescriptor);
11
11
  export type PackageSetOperation = "isolated_read" | "semantic_merge" | "cross_asset_reference";
12
12
  export type PackageSetMemberSource = { readonly "member_id": string; readonly "bytes": Uint8Array };
@@ -2324,7 +2324,7 @@ return errors === 0;
2324
2324
  }
2325
2325
  validate41.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};
2326
2326
 
2327
- const schema87 = {"additionalProperties":false,"properties":{"claims":{"const":"claims_not_authenticated","type":"string"},"contract":{"const":"kdna.package-set-node/0.2.1","type":"string"},"core_callables":{"items":{"$ref":"#/$defs/Identifier"},"maxItems":7,"minItems":7,"type":"array"},"core_version":{"const":"0.36.0-rc.r2.7","type":"string"},"definition_digest":{"$ref":"#/$defs/Digest"},"limits":{"$ref":"#/$defs/PackageSetLimits"},"local_failures":{"items":{"$ref":"#/$defs/PackageSetLocalFailure"},"maxItems":12,"minItems":12,"type":"array"},"module_version":{"const":"0.2.0","type":"string"},"read_callables":{"items":{"$ref":"#/$defs/Identifier"},"maxItems":5,"minItems":5,"type":"array"},"read_version":{"const":"0.11.0-rc.r2.7","type":"string"}},"required":["contract","module_version","core_version","read_version","limits","local_failures","core_callables","read_callables","claims","definition_digest"],"type":"object"};
2327
+ const schema87 = {"additionalProperties":false,"properties":{"claims":{"const":"claims_not_authenticated","type":"string"},"contract":{"const":"kdna.package-set-node/0.2.1","type":"string"},"core_callables":{"items":{"$ref":"#/$defs/Identifier"},"maxItems":7,"minItems":7,"type":"array"},"core_version":{"const":"0.37.0","type":"string"},"definition_digest":{"$ref":"#/$defs/Digest"},"limits":{"$ref":"#/$defs/PackageSetLimits"},"local_failures":{"items":{"$ref":"#/$defs/PackageSetLocalFailure"},"maxItems":12,"minItems":12,"type":"array"},"module_version":{"const":"0.2.0","type":"string"},"read_callables":{"items":{"$ref":"#/$defs/Identifier"},"maxItems":5,"minItems":5,"type":"array"},"read_version":{"const":"0.11.1","type":"string"}},"required":["contract","module_version","core_version","read_version","limits","local_failures","core_callables","read_callables","claims","definition_digest"],"type":"object"};
2328
2328
  const schema90 = {"additionalProperties":false,"properties":{"maxMembers":{"const":10000,"type":"integer"},"maxTotalSourceBytes":{"const":104857600,"type":"integer"}},"required":["maxMembers","maxTotalSourceBytes"],"type":"object"};
2329
2329
  const schema91 = {"enum":["invalid_limits","member_limit_exceeded","source_bytes_limit_exceeded","invalid_member_source","invalid_read_request","provider_invalid","provider_failed","provider_observation_invalid","cancelled","core_unavailable","delivery_unconfirmed","handoff_invalid"],"type":"string"};
2330
2330
 
@@ -2460,8 +2460,8 @@ if(typeof data4 !== "string"){
2460
2460
  validate45.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/type",keyword:"type",params:{type: "string"},message:"must be string"}];
2461
2461
  return false;
2462
2462
  }
2463
- if("0.36.0-rc.r2.7" !== data4){
2464
- validate45.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/const",keyword:"const",params:{allowedValue: "0.36.0-rc.r2.7"},message:"must be equal to constant"}];
2463
+ if("0.37.0" !== data4){
2464
+ validate45.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/const",keyword:"const",params:{allowedValue: "0.37.0"},message:"must be equal to constant"}];
2465
2465
  return false;
2466
2466
  }
2467
2467
  var valid0 = _errs11 === errors;
@@ -2696,8 +2696,8 @@ if(typeof data14 !== "string"){
2696
2696
  validate45.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/type",keyword:"type",params:{type: "string"},message:"must be string"}];
2697
2697
  return false;
2698
2698
  }
2699
- if("0.11.0-rc.r2.7" !== data14){
2700
- validate45.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/const",keyword:"const",params:{allowedValue: "0.11.0-rc.r2.7"},message:"must be equal to constant"}];
2699
+ if("0.11.1" !== data14){
2700
+ validate45.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/const",keyword:"const",params:{allowedValue: "0.11.1"},message:"must be equal to constant"}];
2701
2701
  return false;
2702
2702
  }
2703
2703
  var valid0 = _errs36 === errors;
@@ -2973,8 +2973,8 @@ if(typeof data4 !== "string"){
2973
2973
  validate55.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/type",keyword:"type",params:{type: "string"},message:"must be string"}];
2974
2974
  return false;
2975
2975
  }
2976
- if("0.36.0-rc.r2.7" !== data4){
2977
- validate55.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/const",keyword:"const",params:{allowedValue: "0.36.0-rc.r2.7"},message:"must be equal to constant"}];
2976
+ if("0.37.0" !== data4){
2977
+ validate55.errors = [{instancePath:instancePath+"/core_version",schemaPath:"#/properties/core_version/const",keyword:"const",params:{allowedValue: "0.37.0"},message:"must be equal to constant"}];
2978
2978
  return false;
2979
2979
  }
2980
2980
  var valid0 = _errs11 === errors;
@@ -3209,8 +3209,8 @@ if(typeof data14 !== "string"){
3209
3209
  validate55.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/type",keyword:"type",params:{type: "string"},message:"must be string"}];
3210
3210
  return false;
3211
3211
  }
3212
- if("0.11.0-rc.r2.7" !== data14){
3213
- validate55.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/const",keyword:"const",params:{allowedValue: "0.11.0-rc.r2.7"},message:"must be equal to constant"}];
3212
+ if("0.11.1" !== data14){
3213
+ validate55.errors = [{instancePath:instancePath+"/read_version",schemaPath:"#/properties/read_version/const",keyword:"const",params:{allowedValue: "0.11.1"},message:"must be equal to constant"}];
3214
3214
  return false;
3215
3215
  }
3216
3216
  var valid0 = _errs36 === errors;
@@ -2,8 +2,8 @@
2
2
  "candidate_only": true,
3
3
  "source": {
4
4
  "path": "specs/public-semantic-source.json",
5
- "bytes": 1435436,
6
- "sha256": "4b39c37c7a6f18ade567fb6248e6488af94737c0f4a08f25ef4751399e5315ec"
5
+ "bytes": 1438087,
6
+ "sha256": "5ae686be4e7a7d7abcc88967ac3fc67cbbcc7e5f60d8379cc109edd7a581598a"
7
7
  },
8
8
  "historical_original_source": {
9
9
  "scope": "historical_original_contract_source_identity_not_current_generator_input",
@@ -3,35 +3,35 @@
3
3
  "candidate_only": true,
4
4
  "source": {
5
5
  "path": "specs/public-semantic-source.json",
6
- "bytes": 1435436,
7
- "sha256": "4b39c37c7a6f18ade567fb6248e6488af94737c0f4a08f25ef4751399e5315ec"
6
+ "bytes": 1438087,
7
+ "sha256": "5ae686be4e7a7d7abcc88967ac3fc67cbbcc7e5f60d8379cc109edd7a581598a"
8
8
  },
9
9
  "producer": {
10
10
  "recipe": {
11
11
  "path": "scripts/public-contract/native-output-recipe.json",
12
- "bytes": 155955,
13
- "sha256": "b0cbd0e1f84ff66a777ec355b3247a7291db5464f315dc816a490161ff041ff0"
12
+ "bytes": 155707,
13
+ "sha256": "2cf31e27fdd1d8264b41fc7355a5c767c4a28f5cec01a7930f5c8a6851c36c29"
14
14
  },
15
15
  "scripts": [
16
16
  {
17
17
  "path": "scripts/public-contract/generate-native.mjs",
18
- "bytes": 6022,
19
- "sha256": "43795046b00966c27a2db591d0792c370bc956bf7f2268b9d8646f7a2b3715f3"
18
+ "bytes": 6966,
19
+ "sha256": "2385330076357ac83182d77e0a1f7bf683003aaae276103919862811db36da3d"
20
20
  },
21
21
  {
22
22
  "path": "scripts/public-contract/native-renderer.mjs",
23
- "bytes": 15777,
24
- "sha256": "0c5a8a5d10e96d9842325a9180b8112e4c9c760bae49979f67e4691df4b5c5cf"
23
+ "bytes": 19534,
24
+ "sha256": "05a359837c3c61d18ecc3fe109387ade921daf25eb12a8530e7a5b7550dfe1c7"
25
25
  },
26
26
  {
27
27
  "path": "scripts/public-contract/generation-writer.mjs",
28
- "bytes": 4940,
29
- "sha256": "2ec51fda7f38c4d35d915ef0bf4e75d34a33c65ca7cc8ad6648b062d065d4bdc"
28
+ "bytes": 5909,
29
+ "sha256": "5f2b95585cfb99084af9ad03a2e95926d7a445c12f25ed29ede05aa6d17bac98"
30
30
  },
31
31
  {
32
32
  "path": "scripts/public-contract/generate.mjs",
33
- "bytes": 72318,
34
- "sha256": "cd1914a7fd684fc033f635bd331bb5491446222352097fec72dc05982e0e4661"
33
+ "bytes": 73563,
34
+ "sha256": "9ed819f22c943fcda69a8df10ea1d49439255fee0fb72f81a8e5a6d5c1a4dd26"
35
35
  }
36
36
  ]
37
37
  },
@@ -586,7 +586,7 @@
586
586
  {
587
587
  "path": "packages/kdna-core/src/public-contract/packageset06/contract.json",
588
588
  "bytes": 307339,
589
- "sha256": "51100a21485fb629b4f6a642c61e8bd2710f37a5062e7d106d79e15e5392a389"
589
+ "sha256": "bd01b6f179b096cb0e0e65ebe3ff42322401e9920ef78220347dc0d8662a48fd"
590
590
  },
591
591
  {
592
592
  "path": "packages/kdna-core/src/public-contract/packageset06/api.d.ts",
@@ -0,0 +1,17 @@
1
+ // Generated protected-browser definitions; schema validity is not authority.
2
+ import type { CanonicalReadSnapshot, CoreAdmissionCatalogOnly, CoreAdmissionRejected } from './types.js';
3
+ import type { ProtectionDiagnostic, ProtectionRuntimeDescriptor, ProtectedSignaturePolicy, TrustedProtectionProvider } from './protection-node.js';
4
+ export type ConsumerUnlockSelection = { readonly "slotIndex": number; readonly "slot": string; readonly "kdf_profile": "scrypt-sha256" | "argon2id"; };
5
+ export type ConsumerUnlockObservation = { readonly "kind": "consumer_unlock_observation"; readonly "proof": "observation_not_authority"; readonly "checked_at_ms": number; readonly "selection": ConsumerUnlockSelection; };
6
+ export type ProtectedBrowserInput = { readonly "bytes": Uint8Array; readonly "plaintextPayload": Uint8Array; readonly "observation": ConsumerUnlockObservation; readonly "signaturePolicy"?: ProtectedSignaturePolicy; };
7
+ export type ProtectedBrowserDisclosure = { readonly "slot_selection": ConsumerUnlockSelection; readonly "observation_not_authority": true; readonly "provenance": "host_supplied_triple"; };
8
+ export type ProtectedBrowserAccepted = { readonly "status": "accepted"; readonly "snapshot": CanonicalReadSnapshot; readonly "disclosure": ProtectedBrowserDisclosure; };
9
+ export type ProtectedBrowserCatalogOnly = { readonly "status": "catalog_only"; readonly "catalog": CoreAdmissionCatalogOnly; readonly "disclosure": ProtectedBrowserDisclosure; };
10
+ export type ProtectedBrowserCoreRejected = { readonly "status": "core_rejected"; readonly "stage": "container" | "manifest" | "payload" | "interpretation"; readonly "core": CoreAdmissionRejected; };
11
+ export type ProtectedBrowserFailed = { readonly "status": "protection_failed"; readonly "diagnostic": ProtectedBrowserDiagnostic; };
12
+ // The observation-phase codes are the reviewed family extension settled under
13
+ // D-CBPA-IMPL-3 (2026-10-06); the shared node codes keep their stages.
14
+ export type ProtectedBrowserDiagnostic = (ProtectionDiagnostic | { readonly "code": "PROTECTION_OBSERVATION_INVALID"; readonly "stage": "observation"; } | { readonly "code": "PROTECTION_OBSERVATION_BINDING_INVALID"; readonly "stage": "binding"; } | { readonly "code": "PROTECTION_NOT_DECLARED"; readonly "stage": "declaration"; });
15
+ export type ProtectedBrowserAdmissionResult = (ProtectedBrowserAccepted | ProtectedBrowserCatalogOnly | ProtectedBrowserCoreRejected | ProtectedBrowserFailed);
16
+ export declare function getProtectionContract(): ProtectionRuntimeDescriptor;
17
+ export declare function admitProtectedBrowser(input: ProtectedBrowserInput, provider: TrustedProtectionProvider): Promise<ProtectedBrowserAdmissionResult>;
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+ const { getProtectionContract } = require('./protection-declaration.js');
3
+ const { admitProtectedBrowser } = require('./protection-admission-browser.js');
4
+ module.exports = { getProtectionContract, admitProtectedBrowser };
@@ -0,0 +1,2 @@
1
+ import api from './protected-browser.js';
2
+ export const { getProtectionContract, admitProtectedBrowser } = api;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "api_typescript": "export type ProtectedSourceContractIdentity = { readonly id: 'kdna.protected-source/1'; readonly version: '1.0.0'; readonly definition_digest: import('./types.js').Digest };\nexport type ProtectedSourceRuntimeDescriptor = { readonly contract: ProtectedSourceContractIdentity; readonly implementation: { readonly package: '@aikdna/kdna-core'; readonly version: string }; readonly profiles: ReadonlyArray<'kdna.envelope.aead/0.1.0' | 'kdna.envelope.external-grant/0.1.0'>; readonly callables: ReadonlyArray<'getProtectedSourceContract' | 'createTrustedProtectedSourceHost' | 'withProtectedSourceNode' | 'commitProtectedSourceTransport' | 'previewProtectedSourceRevision' | 'produceProtectedSourceRevision'>; readonly limits: { readonly container_bytes: 26214400; readonly entries: 128; readonly entry_bytes: 8388608; readonly total_uncompressed_bytes: 12582912; readonly delivered_plaintext_bytes: 8388608; readonly documented_raw_byte_bound: 20971520; readonly timeout_ms_max: 60000 }; readonly proof_limits: ReadonlyArray<string> };\nexport type SourceHostObservationContext = { readonly context_id: string | null; readonly epoch: string | null; readonly asset_digest: string; readonly scope: 'complete_source'; readonly purpose: string; readonly requested_at_ms: number };\nexport type ProtectedSourceMember = { readonly name: string; readonly type: 'file'; readonly mode: number; readonly bytes: Uint8Array };\nexport type ProtectedSourceInventoryEntry = { readonly name: string; readonly type: 'file'; readonly mode: number; readonly size: number; readonly sha256: string };\nexport type ProtectedSourceBundle = { readonly identity: { readonly A: string; readonly C: string; readonly E: string }; readonly manifest: unknown; readonly payload: unknown; readonly original_members: ReadonlyArray<ProtectedSourceMember>; readonly original_inventory: ReadonlyArray<ProtectedSourceInventoryEntry>; readonly plaintext_payload: { readonly entry: 'payload.kdnab'; readonly bytes: Uint8Array; readonly sha256: string }; readonly prior_snapshot: unknown; readonly host_observation: unknown; readonly proof_limits: ReadonlyArray<string> };\nexport type ProtectedSourceRevisionContext = { readonly [brand: symbol]: true };\nexport type ProtectedSourcePreparedDelivery = { readonly [brand: symbol]: true };\nexport type ProtectedSourceHostCallbacks = { readonly observe: (context: SourceHostObservationContext) => SourceHostObservation | Promise<SourceHostObservation>; readonly deliver: (bundle: ProtectedSourceBundle, prepared: ProtectedSourcePreparedDelivery, context: ProtectedSourceRevisionContext) => boolean | Promise<boolean> };\nexport type TrustedProtectedSourceHost = { readonly [brand: symbol]: true };\nexport type ProtectedSourceRevisionOptions = { readonly admission: import('./protection-node.js').ProtectedAdmissionOptions; readonly expected_A: string; readonly timeout_ms: number };\nexport type TrustedProtectedSourceTransport = { readonly observeScope: () => SourceHostObservation | Promise<SourceHostObservation>; readonly commit: (bundle: ProtectedSourceBundle | null) => boolean };\nexport type ProtectedSourceCommitResult = { readonly status: 'source_committed'; readonly disclosure: import('./protection-node.js').ProtectionDisclosure; readonly body: null; readonly body_bytes: 0 } | SourceFailed;\nexport type ProtectedSourcePolicy = ({ readonly kind: 'password'; readonly asset_uid: string; readonly entitlement: { readonly profile: 'password'; readonly offline?: boolean; readonly revocable?: boolean }; readonly slots: ReadonlyArray<{ readonly slot: string; readonly kdf_profile: 'scrypt-sha256' | 'argon2id' }> } | { readonly kind: 'external-grant'; readonly asset_uid: string; readonly entitlement: { readonly profile: 'account' | 'org'; readonly offline?: boolean; readonly revocable?: boolean }; readonly key_ref: string; readonly issuer_key_id: string }) & { readonly checksums: boolean; readonly signature: 'none' | 'ed25519' };\nexport type ProtectedSourceEdits = { readonly manifest?: unknown; readonly payload?: unknown };\nexport type ProtectedSourceProviderRequest = { readonly source_A: string; readonly edits_digest: string; readonly policy_digest: string; readonly kind: 'password' | 'external-grant'; readonly signature: 'none' | 'ed25519' };\nexport type ProtectedSourceOutputSecrets = { readonly passwords?: ReadonlyArray<{ readonly slot: string; readonly password: Uint8Array }>; readonly signingSeed?: Uint8Array; readonly issuerRootKey?: Uint8Array };\nexport type SourceRevisionEvidence = { readonly contract: ProtectedSourceContractIdentity; readonly implementation: { readonly package: '@aikdna/kdna-core'; readonly version: string }; readonly source_A: string; readonly output: { readonly A: string; readonly C: string; readonly E: string }; readonly profile: { readonly id: string; readonly version: string }; readonly entry: 'payload.kdnab'; readonly member_actions: { readonly [name: string]: 'added' | 'replaced' | 'removed' }; readonly integrity: unknown; readonly payload_source: 'explicit_edit' | 'original_decrypted_cbor'; readonly proof: 'producer_observation_not_consumer_admission'; readonly output_delivery: 'not_published' | 'trusted_host'; readonly output_A: string | null };\nexport type ProtectedSourceRevisionResult = { readonly status: 'revision_produced'; readonly bytes: Uint8Array; readonly evidence: SourceRevisionEvidence; readonly body_bytes: number } | { readonly status: 'revision_rejected'; readonly diagnostic: SourceDiagnostic; readonly body: null; readonly body_bytes: 0 };\nexport declare function getProtectedSourceContract(): ProtectedSourceRuntimeDescriptor;\nexport declare function createTrustedProtectedSourceHost(callbacks: ProtectedSourceHostCallbacks): TrustedProtectedSourceHost;\nexport declare function withProtectedSourceNode(input: string | Uint8Array, options: ProtectedSourceRevisionOptions, protectionProvider: import('./protection-node.js').TrustedProtectionProvider, sourceHost: TrustedProtectedSourceHost): Promise<ProtectedSourceObservation>;\nexport declare function commitProtectedSourceTransport(prepared: ProtectedSourcePreparedDelivery, transport: TrustedProtectedSourceTransport): Promise<ProtectedSourceCommitResult>;\nexport declare function previewProtectedSourceRevision(context: ProtectedSourceRevisionContext, edits: ProtectedSourceEdits, policy: ProtectedSourcePolicy): Promise<ProtectedSourceRevisionPreviewResult>;\nexport declare function produceProtectedSourceRevision(context: ProtectedSourceRevisionContext, edits: ProtectedSourceEdits, policy: ProtectedSourcePolicy, outputSecretProvider: (request: ProtectedSourceProviderRequest) => ProtectedSourceOutputSecrets | Promise<ProtectedSourceOutputSecrets>): Promise<ProtectedSourceRevisionResult>;\n",
3
- "definition_digest": "sha256:848d4afbb80130e12217c0d86ef5d6a21e5e032687d47c3837dc8341f25981fe",
3
+ "definition_digest": "sha256:612b285c79566eb308ff613fbc4fd1599ee35076efaf5c1214c271ebfa3334ab",
4
4
  "id": "kdna.protected-source/1",
5
5
  "limits": {
6
6
  "container_bytes": 26214400,
@@ -29,8 +29,8 @@
29
29
  ],
30
30
  "schema_binding": {
31
31
  "package_versions": {
32
- "@aikdna/kdna-core": "0.36.0-rc.r2.7",
33
- "@aikdna/kdna-read": "0.11.0-rc.r2.7"
32
+ "@aikdna/kdna-core": "0.37.0",
33
+ "@aikdna/kdna-read": "0.11.1"
34
34
  },
35
35
  "version_tuple": {
36
36
  "container": "0.5.0",
@@ -9260,7 +9260,7 @@
9260
9260
  "type": "string"
9261
9261
  },
9262
9262
  "version": {
9263
- "const": "0.36.0-rc.r2.7",
9263
+ "const": "0.37.0",
9264
9264
  "type": "string"
9265
9265
  }
9266
9266
  },
@@ -10632,7 +10632,7 @@
10632
10632
  "type": "string"
10633
10633
  },
10634
10634
  "version": {
10635
- "const": "0.36.0-rc.r2.7",
10635
+ "const": "0.37.0",
10636
10636
  "type": "string"
10637
10637
  }
10638
10638
  },
@@ -13783,7 +13783,7 @@
13783
13783
  "type": "string"
13784
13784
  },
13785
13785
  "version": {
13786
- "const": "0.36.0-rc.r2.7",
13786
+ "const": "0.37.0",
13787
13787
  "type": "string"
13788
13788
  }
13789
13789
  },
@@ -10,7 +10,7 @@ export type ProtectedSourceCatalog = { readonly "status": "catalog_only"; readon
10
10
  export type SourceCoreRejected = { readonly "status": "core_rejected"; readonly "stage": "admission"; readonly "core": CoreAdmissionRejected; readonly "disclosure": ProtectionDisclosure; readonly "body": null; readonly "body_bytes": 0; };
11
11
  export type ProtectedSourceObservation = (ProtectedSourceDelivered | ProtectedSourceCatalog | SourceCoreRejected | SourceFailed);
12
12
  export type SourceHostObservation = { readonly "context_id": Identifier; readonly "epoch": Identifier; readonly "asset_digest": Digest; readonly "permission": "allowed" | "denied"; readonly "scope": "complete_source"; readonly "current_ms": UInt; readonly "expires_at_ms": UInt; readonly "revoked": boolean; };
13
- export type SourcePreviewValidation = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "name": "@aikdna/kdna-core"; readonly "version": "0.36.0-rc.r2.7"; }; readonly "source_A": Digest; readonly "original_payload_digest": Digest; readonly "edits_digest": Digest; readonly "policy_digest": Digest; readonly "semantic_status": "valid"; readonly "proof": "semantic_validation_not_ciphertext_admission"; };
13
+ export type SourcePreviewValidation = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "name": "@aikdna/kdna-core"; readonly "version": "0.37.0"; }; readonly "source_A": Digest; readonly "original_payload_digest": Digest; readonly "edits_digest": Digest; readonly "policy_digest": Digest; readonly "semantic_status": "valid"; readonly "proof": "semantic_validation_not_ciphertext_admission"; };
14
14
  export type SourcePreviewValid = { readonly "status": "preview_valid"; readonly "validation": SourcePreviewValidation; readonly "body": null; readonly "body_bytes": 0; };
15
15
  export type SourcePreviewRejected = { readonly "status": "preview_rejected"; readonly "diagnostic": SourceDiagnostic; readonly "body": null; readonly "body_bytes": 0; };
16
16
  export type ProtectedSourceRevisionPreviewResult = (SourcePreviewValid | SourcePreviewRejected);
@@ -0,0 +1,114 @@
1
+ 'use strict';
2
+ // Browser protected admission core (case A: an independent browser entry).
3
+ //
4
+ // The host supplies the container bytes, the payload plaintext bytes and the
5
+ // unlock observation; nothing here decrypts, and the observation is never
6
+ // authority (its provenance limit is named in the disclosure). The five-step
7
+ // admission mirrors the retained node entry's structure and codes; the kdsig
8
+ // face follows the browser family route (globalThis.crypto subtle, same
9
+ // kdsig.ed25519:0.1.0 framing as the node helper), and the checksums document
10
+ // is verified against a verbatim local port of protection-integrity.makeChecksums
11
+ // (that module is node-bound by its kdsig helper import).
12
+ const { parseJson, canonicalJson, freeze, uint, identifier } = require('./strict-input.js');
13
+ const { parseContainer } = require('./container.js');
14
+ const { inflate } = require('./browser-native/portable-inflate.js');
15
+ const { utf8, fromHex } = require('./browser-native/bytes.js');
16
+ const { digest, contentTreePreimage, runtimeEntryPreimage, runtimeEntryNames } = require('./digests.js');
17
+ const { validate } = require('./validate.js');
18
+ const { rejected } = require('./admit.js');
19
+ const { decodeValidatedPayload, assertContentBindings, finishAdmission } = require('./semantic-admission.js');
20
+ const { fail, failure, isFailure, closed, provider, assetProtectionDeclaration } = require('./protection-declaration.js');
21
+ const { decodeEnvelope, validateEnvelopeShape } = require('./protection-envelope-codec.js');
22
+ const { signatureContentPreimage } = require('./browser-native/signature-domain.js');
23
+ const { ChecksumsDocument1: checksumsShape } = require('./protection-validators.generated.js');
24
+ function checkDeclaration(manifest) {
25
+ const profile = assetProtectionDeclaration(manifest);
26
+ if (!profile) fail('NOT_DECLARED', 'declaration');
27
+ if (profile.id !== 'kdna.envelope.aead') fail('PROFILE_UNSUPPORTED', 'declaration');
28
+ if (manifest.entitlement.offline === false || manifest.entitlement.revocable === true) fail('DECLARATION_CONFLICT', 'authorization');
29
+ return profile;
30
+ }
31
+ function inputs(value, inputProvider) {
32
+ closed(value, ['bytes', 'plaintextPayload', 'observation'], ['signaturePolicy']);
33
+ if (!(value.bytes instanceof Uint8Array) || !(value.plaintextPayload instanceof Uint8Array)) fail('INPUT_INVALID', 'input');
34
+ const policy = value.signaturePolicy === undefined ? { requireSignature: false, expectedPublicKeyHex: null } : closed(value.signaturePolicy, ['requireSignature', 'expectedPublicKeyHex']);
35
+ if (typeof policy.requireSignature !== 'boolean' || (policy.expectedPublicKeyHex !== null && (typeof policy.expectedPublicKeyHex !== 'string' || !/^[0-9a-f]{64}$/.test(policy.expectedPublicKeyHex)))) fail('INPUT_INVALID', 'input');
36
+ const o = closed(value.observation, ['kind', 'proof', 'checked_at_ms', 'selection']);
37
+ if (o.kind !== 'consumer_unlock_observation' || o.proof !== 'observation_not_authority' || !uint(o.checked_at_ms)) fail('OBSERVATION_INVALID', 'observation');
38
+ const s = closed(o.selection, ['slotIndex', 'slot', 'kdf_profile']);
39
+ if (!uint(s.slotIndex) || !identifier(s.slot) || !['scrypt-sha256', 'argon2id'].includes(s.kdf_profile)) fail('OBSERVATION_INVALID', 'observation');
40
+ return { bytes: new Uint8Array(value.bytes), plaintext: new Uint8Array(value.plaintextPayload), observation: { kind: o.kind, proof: o.proof, checked_at_ms: o.checked_at_ms, selection: { slotIndex: s.slotIndex, slot: s.slot, kdf_profile: s.kdf_profile } }, signaturePolicy: { ...policy }, trustedProvider: provider(inputProvider, 'password') };
41
+ }
42
+ function assertObservationBinding(observation, envelope) {
43
+ const slots = envelope.key_slots;
44
+ if (observation.selection.slotIndex >= slots.length) fail('OBSERVATION_BINDING_INVALID', 'binding');
45
+ const slot = slots[observation.selection.slotIndex];
46
+ if (slot.slot !== observation.selection.slot || slot.kdf_profile !== observation.selection.kdf_profile) fail('OBSERVATION_BINDING_INVALID', 'binding');
47
+ }
48
+ // Verbatim port of protection-integrity.makeChecksums (node-bound there).
49
+ function makeChecksums(entries, manifest, E) {
50
+ const names = runtimeEntryNames(entries, manifest);
51
+ return { profile: 'kdna.checksums.document/1', profile_version: '1.0.0', algorithm: 'sha256', digest_profile: 'kdna.digest-basis.runtime-entry-set', digest_profile_version: '0.2.0', covered_entries: names, entries: names.map(name => ({ name, bytes: entries[name].length, digest: digest(entries[name]) })), entry_set_digest: E };
52
+ }
53
+ function parseKdsigBundle(raw) {
54
+ // The same bundle domain the node helper and the browser section verifier accept.
55
+ if (raw.length < 3 || raw.length > 1048576) fail('SIGNATURE_INVALID', 'integrity');
56
+ if (raw[0] === 0xef && raw[1] === 0xbb && raw[2] === 0xbf) fail('SIGNATURE_INVALID', 'integrity');
57
+ let value;
58
+ try { value = parseJson(raw); } catch { fail('SIGNATURE_INVALID', 'integrity'); }
59
+ const fields = ['algorithm', 'content_digest', 'profile', 'profile_version', 'public_key', 'signature'];
60
+ if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).length !== fields.length || !fields.every(k => Object.hasOwn(value, k) && typeof value[k] === 'string')) fail('SIGNATURE_INVALID', 'integrity');
61
+ if (!/^sha256:[0-9a-f]{64}$/.test(value.content_digest) || !/^[0-9a-f]{64}$/.test(value.public_key) || !/^[0-9a-f]{128}$/.test(value.signature)) fail('SIGNATURE_INVALID', 'integrity');
62
+ if (value.profile !== 'kdsig.ed25519' || value.profile_version !== '0.1.0' || value.algorithm !== 'ed25519') fail('PROFILE_UNSUPPORTED', 'integrity');
63
+ return value;
64
+ }
65
+ async function verifyIntegrityBrowser(entries, manifest, E, policy) {
66
+ const integrity = { checksums: 'absent', signature: 'absent', signature_content_digest: null };
67
+ if (Object.hasOwn(entries, 'checksums.json')) {
68
+ const raw = entries['checksums.json']; let value;
69
+ try { if (raw.length > 1048576) throw Error(); value = parseJson(raw); } catch { fail('CHECKSUMS_INVALID', 'integrity'); }
70
+ if (value?.profile !== 'kdna.checksums.document/1' || value?.profile_version !== '1.0.0') fail('PROFILE_UNSUPPORTED', 'integrity');
71
+ if (!checksumsShape(value) || canonicalJson(value) !== canonicalJson(makeChecksums(entries, manifest, E))) fail('CHECKSUMS_INVALID', 'integrity');
72
+ integrity.checksums = 'verified_document_1';
73
+ }
74
+ if (Object.hasOwn(entries, 'signature.kdsig')) {
75
+ const bundle = parseKdsigBundle(entries['signature.kdsig']);
76
+ if (policy.expectedPublicKeyHex !== null && bundle.public_key !== policy.expectedPublicKeyHex) fail('SIGNATURE_PIN_MISMATCH', 'integrity');
77
+ const signatureDigest = digest(signatureContentPreimage(entries));
78
+ if (bundle.content_digest !== signatureDigest) fail('SIGNATURE_INVALID', 'integrity');
79
+ const subtle = globalThis.crypto?.subtle;
80
+ if (!subtle || typeof subtle.importKey !== 'function' || typeof subtle.verify !== 'function') throw Object.assign(new Error('WebCrypto Ed25519 unavailable'), { reason: 'READ_CORE_CAPABILITY_UNAVAILABLE' });
81
+ try {
82
+ const key = await subtle.importKey('raw', fromHex(bundle.public_key), 'Ed25519', false, ['verify']);
83
+ const ok = await subtle.verify('Ed25519', key, fromHex(bundle.signature), utf8('kdsig.ed25519:0.1.0:' + signatureDigest));
84
+ if (ok !== true) fail('SIGNATURE_INVALID', 'integrity');
85
+ } catch (error) { if (isFailure(error)) throw error; throw Object.assign(new Error('WebCrypto Ed25519 failed'), { reason: 'READ_CORE_CAPABILITY_UNAVAILABLE' }); }
86
+ integrity.signature = policy.expectedPublicKeyHex === null ? 'verified_self_key' : 'verified_pinned_key';
87
+ integrity.signature_content_digest = signatureDigest;
88
+ } else if (policy.requireSignature || policy.expectedPublicKeyHex !== null) fail('SIGNATURE_INVALID', 'integrity');
89
+ return integrity;
90
+ }
91
+ async function admitProtectedBrowser(input, inputProvider) {
92
+ let copied, plaintext, stage = 'input';
93
+ try {
94
+ copied = inputs(input, inputProvider); plaintext = copied.plaintext; const bytes = copied.bytes;
95
+ stage = 'container'; const entries = parseContainer(bytes, inflate);
96
+ stage = 'manifest'; const manifest = validate('Manifest', parseJson(entries['kdna.json']));
97
+ const profile = checkDeclaration(manifest);
98
+ const digests = { A: digest(bytes), C: digest(contentTreePreimage(entries)), E: digest(runtimeEntryPreimage(entries, manifest)) };
99
+ assertContentBindings(manifest, digests.C);
100
+ const integrity = await verifyIntegrityBrowser(entries, manifest, digests.E, copied.signaturePolicy);
101
+ const envelope = validateEnvelopeShape(decodeEnvelope(entries['payload.kdnab']), profile);
102
+ assertObservationBinding(copied.observation, envelope);
103
+ stage = 'payload'; const payload = decodeValidatedPayload(manifest, plaintext);
104
+ stage = 'interpretation'; const result = finishAdmission(manifest, payload, entries, digests, integrity.checksums === 'verified_document_1' ? digests.E : null);
105
+ const disclosure = freeze({ slot_selection: { ...copied.observation.selection }, observation_not_authority: true, provenance: 'host_supplied_triple' });
106
+ return freeze(result.status === 'accepted' ? { status: 'accepted', snapshot: result.snapshot, disclosure } : { status: 'catalog_only', catalog: result, disclosure });
107
+ } catch (error) {
108
+ if (isFailure(error) || stage === 'input') return failure(error);
109
+ return freeze({ status: 'core_rejected', stage, core: rejected(error?.code === 'MODULE_NOT_FOUND' ? 'READ_CORE_CAPABILITY_UNAVAILABLE' : error?.reason ?? 'READ_CORE_INVALID', error.component_failure ?? null, error.diagnostic ?? null) });
110
+ } finally {
111
+ plaintext?.fill(0);
112
+ }
113
+ }
114
+ module.exports = { admitProtectedBrowser };
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "api_typescript": "export type ProtectedSignaturePolicy = { readonly requireSignature: boolean; readonly expectedPublicKeyHex: string | null };\nexport type ProtectionGrantExpectations = { readonly issuer: string; readonly signing_key_id: string; readonly issuer_public_key: string; readonly account_id: string; readonly entitlement_id: string; readonly entitlement_profile: 'account' | 'org'; readonly device_id: string; readonly device_agreement_public_key: string; readonly device_signing_public_key: string };\nexport type ProtectedCredential = { readonly kind: 'none' } | { readonly kind: 'password'; readonly password: Uint8Array; readonly slotIndex?: number } | { readonly kind: 'external-grant'; readonly grantBytes: Uint8Array; readonly deviceAgreementPrivateKeyPkcs8: Uint8Array; readonly mode: 'online' | 'offline'; readonly expected: ProtectionGrantExpectations };\nexport type ProtectedAdmissionOptions = { readonly credential: ProtectedCredential; readonly signaturePolicy: ProtectedSignaturePolicy };\nexport type ProtectionStateScope = { readonly issuer: string; readonly account_id: string; readonly entitlement_id: string };\nexport type ProtectionHighWater = { readonly scope: ProtectionStateScope; readonly highest_status_version: number; readonly status: 'active' | 'revoked' | 'expired'; readonly last_trusted_time_ms: number; readonly revision: number };\nexport type ProtectionStateAdvance = { readonly scope: ProtectionStateScope; readonly device_id: string; readonly verified: { readonly grant_digest: string; readonly status_version: number; readonly status: 'active' | 'revoked' | 'expired'; readonly observed_at_ms: number } };\nexport type ProtectionRefreshContext = ProtectionStateScope & { readonly device_id: string; readonly A: string; readonly grant_id: string; readonly status_version: number; readonly purpose: 'authorization' | 'projection' | 'host_handoff' | 'transport_commit' };\nexport type TrustedProtectionProvider = { readonly kind: 'local'; readonly clock: () => number } | { readonly kind: 'external'; readonly clock: () => number; readonly capabilities: { readonly offline: boolean; readonly status_refresh: boolean; readonly revocation: boolean }; readonly readAdvance: (input: ProtectionStateAdvance) => Promise<ProtectionHighWater>; readonly refresh?: (context: ProtectionRefreshContext) => Promise<Uint8Array> };\nexport type ProtectionPhase = 'projection' | 'host_observation' | 'host_handoff' | 'read_return' | 'transport_commit' | 'execution';\nexport type ProtectionCurrent = { readonly status: 'current'; readonly receipt: ProtectionReceipt };\nexport type ProtectionObserved = ProtectionCurrent & { readonly checkpoint: ProtectionCheckpoint };\nexport type ProtectionSource = { readonly kind: 'snapshot'; readonly snapshot: CanonicalReadSnapshot } | { readonly kind: 'catalog'; readonly catalog: CoreAdmissionCatalogOnly };\nexport type ProtectionBindingResult = { readonly status: 'bound'; readonly binding: ProtectionBinding } | ProtectedAdmissionFailed;\nexport type ProtectedExportOptions = ({ readonly kind: 'integrity' } | { readonly kind: 'password'; readonly asset_uid: string; readonly entitlement: { readonly profile: 'password'; readonly offline?: boolean; readonly revocable?: boolean }; readonly slots: ReadonlyArray<{ readonly slot: string; readonly kdf_profile: 'scrypt-sha256' | 'argon2id' }> } | { readonly kind: 'external-grant'; readonly asset_uid: string; readonly entitlement: { readonly profile: 'account' | 'org'; readonly offline?: boolean; readonly revocable?: boolean }; readonly key_ref: string; readonly issuer_key_id: string }) & { readonly checksums: boolean; readonly signature: 'none' | 'ed25519' };\nexport type ProtectedProducerSecrets = { readonly passwords: ReadonlyArray<{ readonly slot: string; readonly password: Uint8Array }>; readonly signingSeed?: Uint8Array; readonly issuerRootKey?: never } | { readonly issuerRootKey: Uint8Array; readonly signingSeed?: Uint8Array; readonly passwords?: never } | { readonly signingSeed?: Uint8Array; readonly issuerRootKey?: never; readonly passwords?: never };\nexport type ProtectedExportResult = { readonly status: 'produced'; readonly bytes: Uint8Array; readonly evidence: ProtectedExportEvidence } | ProtectedCoreRejected | ProtectedAdmissionFailed;\nexport declare function getProtectionContract(): ProtectionRuntimeDescriptor;\nexport declare function admitProtectedNode(input: string | Uint8Array, options: ProtectedAdmissionOptions, provider: TrustedProtectionProvider): Promise<ProtectedAdmissionResult>;\nexport declare function bindProtectionOperation(operation: ProtectionOperation): ProtectionBindingResult;\nexport declare function disposeProtectionOperation(operation: ProtectionOperation): void;\nexport declare function protectSourceBytes(input: Uint8Array, options: ProtectedExportOptions, secrets: ProtectedProducerSecrets): Promise<ProtectedExportResult>;\n",
3
+ "browser_api_typescript": "import type { CanonicalReadSnapshot, CoreAdmissionCatalogOnly, CoreAdmissionRejected } from './types.js';\nimport type { ProtectionDiagnostic, ProtectionRuntimeDescriptor, ProtectedSignaturePolicy, TrustedProtectionProvider } from './protection-node.js';\nexport type ConsumerUnlockSelection = { readonly \"slotIndex\": number; readonly \"slot\": string; readonly \"kdf_profile\": \"scrypt-sha256\" | \"argon2id\"; };\nexport type ConsumerUnlockObservation = { readonly \"kind\": \"consumer_unlock_observation\"; readonly \"proof\": \"observation_not_authority\"; readonly \"checked_at_ms\": number; readonly \"selection\": ConsumerUnlockSelection; };\nexport type ProtectedBrowserInput = { readonly \"bytes\": Uint8Array; readonly \"plaintextPayload\": Uint8Array; readonly \"observation\": ConsumerUnlockObservation; readonly \"signaturePolicy\"?: ProtectedSignaturePolicy; };\nexport type ProtectedBrowserDisclosure = { readonly \"slot_selection\": ConsumerUnlockSelection; readonly \"observation_not_authority\": true; readonly \"provenance\": \"host_supplied_triple\"; };\nexport type ProtectedBrowserAccepted = { readonly \"status\": \"accepted\"; readonly \"snapshot\": CanonicalReadSnapshot; readonly \"disclosure\": ProtectedBrowserDisclosure; };\nexport type ProtectedBrowserCatalogOnly = { readonly \"status\": \"catalog_only\"; readonly \"catalog\": CoreAdmissionCatalogOnly; readonly \"disclosure\": ProtectedBrowserDisclosure; };\nexport type ProtectedBrowserCoreRejected = { readonly \"status\": \"core_rejected\"; readonly \"stage\": \"container\" | \"manifest\" | \"payload\" | \"interpretation\"; readonly \"core\": CoreAdmissionRejected; };\nexport type ProtectedBrowserFailed = { readonly \"status\": \"protection_failed\"; readonly \"diagnostic\": ProtectedBrowserDiagnostic; };\n// The observation-phase codes are the reviewed family extension settled under\n// D-CBPA-IMPL-3 (2026-10-06); the shared node codes keep their stages.\nexport type ProtectedBrowserDiagnostic = (ProtectionDiagnostic | { readonly \"code\": \"PROTECTION_OBSERVATION_INVALID\"; readonly \"stage\": \"observation\"; } | { readonly \"code\": \"PROTECTION_OBSERVATION_BINDING_INVALID\"; readonly \"stage\": \"binding\"; } | { readonly \"code\": \"PROTECTION_NOT_DECLARED\"; readonly \"stage\": \"declaration\"; });\nexport type ProtectedBrowserAdmissionResult = (ProtectedBrowserAccepted | ProtectedBrowserCatalogOnly | ProtectedBrowserCoreRejected | ProtectedBrowserFailed);\nexport declare function getProtectionContract(): ProtectionRuntimeDescriptor;\nexport declare function admitProtectedBrowser(input: ProtectedBrowserInput, provider: TrustedProtectionProvider): Promise<ProtectedBrowserAdmissionResult>;",
3
4
  "capability_shapes": {
4
5
  "ProtectionBinding": "{ readonly source: () => ProtectionSource | ProtectedAdmissionFailed; readonly observe: (phase: ProtectionPhase) => Promise<ProtectionObserved | ProtectionCurrentFailure>; readonly assertCurrent: (checkpoint: ProtectionCheckpoint) => ProtectionCurrent | ProtectionCurrentFailure }"
5
6
  },
@@ -13,7 +14,7 @@
13
14
  "schema_path": "specs/checksums-document-1.schema.json",
14
15
  "version": "1.0.0"
15
16
  },
16
- "definition_digest": "sha256:0c84c6fb73b3f6fbb453a7b7494baba81249814d6a9a6f72719ce219392751ab",
17
+ "definition_digest": "sha256:c88dfae7dc756d00fad579b02c7ea0f14b21f3d1ca3edecbf2fad8f4c5fd9e4a",
17
18
  "delivery_history": {
18
19
  "acknowledgement": "Only literal synchronous true confirms the configured trusted transport handoff. False/throw/thenable/invalid return leaves outcome_unknown. Never await or execute an untrusted then method to improve the result. Callback itself may already have sent data.",
19
20
  "disposal": "Disposal closes authority and clears secrets best effort but retains the redacted per-token delivery history while its token/owning Read remains reachable, so a later failure cannot erase past attempts.",
@@ -177,8 +178,8 @@
177
178
  "packages/kdna-core/src/public-contract/protection-declaration.js:1-75",
178
179
  "packages/kdna-core/src/public-contract/protection-admission.js:1-94",
179
180
  "packages/kdna-core/src/public-contract/protection-producer.js:1-75",
180
- "packages/kdna-core/src/public-contract/protection-crypto.js:1-91",
181
- "packages/kdna-core/src/public-contract/protection-envelope-codec.js:1-78"
181
+ "packages/kdna-core/src/public-contract/protection-crypto.js:1-82",
182
+ "packages/kdna-core/src/public-contract/protection-envelope-codec.js:1-138"
182
183
  ],
183
184
  "proof": [
184
185
  {
@@ -707,8 +708,8 @@
707
708
  "packages/kdna-core/src/public-contract/protection-declaration.js:1-75",
708
709
  "packages/kdna-core/src/public-contract/protection-admission.js:1-94",
709
710
  "packages/kdna-core/src/public-contract/protection-producer.js:1-75",
710
- "packages/kdna-core/src/public-contract/protection-crypto.js:1-91",
711
- "packages/kdna-core/src/public-contract/protection-envelope-codec.js:1-78"
711
+ "packages/kdna-core/src/public-contract/protection-crypto.js:1-82",
712
+ "packages/kdna-core/src/public-contract/protection-envelope-codec.js:1-138"
712
713
  ]
713
714
  },
714
715
  "PROTECTION-RESULTS": {
@@ -801,8 +802,8 @@
801
802
  "runtime_not_implemented": [],
802
803
  "schema_binding": {
803
804
  "package_versions": {
804
- "@aikdna/kdna-core": "0.36.0-rc.r2.7",
805
- "@aikdna/kdna-read": "0.11.0-rc.r2.7"
805
+ "@aikdna/kdna-core": "0.37.0",
806
+ "@aikdna/kdna-read": "0.11.1"
806
807
  },
807
808
  "version_tuple": {
808
809
  "container": "0.5.0",
@@ -820,9 +821,9 @@
820
821
  "schema_id": "urn:kdna:schema:protection-admission:1.0.0:binding:r2:7",
821
822
  "schema_path": "specs/protection-admission-r2-binding-7.schema.json",
822
823
  "specification": {
823
- "bytes": 37918,
824
+ "bytes": 37902,
824
825
  "path": "specs/protection-admission.md",
825
- "sha256": "995681e3836abc3087c98adfd5d18bba59de3d6ee31d3a351438bd43b8c732ba"
826
+ "sha256": "7dbc85924d7c0a1d0d4556aeac92de8ac91d331185b4a65d066c0d165c3fadcc"
826
827
  },
827
828
  "types": {
828
829
  "ChecksumsDocument1": {
@@ -1059,7 +1060,7 @@
1059
1060
  "type": "string"
1060
1061
  },
1061
1062
  "version": {
1062
- "const": "0.36.0-rc.r2.7",
1063
+ "const": "0.37.0",
1063
1064
  "type": "string"
1064
1065
  }
1065
1066
  },
@@ -2294,7 +2295,7 @@
2294
2295
  "type": "string"
2295
2296
  },
2296
2297
  "version": {
2297
- "const": "0.36.0-rc.r2.7",
2298
+ "const": "0.37.0",
2298
2299
  "type": "string"
2299
2300
  }
2300
2301
  },
@@ -4,28 +4,18 @@ const { fail } = require('./protection-declaration.js');
4
4
  const { aesWrap, aesUnwrap } = require('../crypto-profile.js');
5
5
  const { externalEnvelopeAad, deriveExternalAssetCek } = require('../external-key-grant.js');
6
6
  const { digest } = require('./digests.js');
7
- const { PasswordEnvelope: passwordShape, ExternalEnvelope: externalShape } = require('./protection-validators.generated.js');
7
+ const { decode64Bytes, validateEnvelopeShape, passwordAadBytes } = require('./protection-envelope-codec.js');
8
+ // The pure shapes live in the codec module (browser-reusable); these wrappers keep the
9
+ // retained result identities (Buffer outputs, same verdicts, same codes) so every existing
10
+ // caller in this package stays unchanged.
8
11
  function decode64(value, length = null, url = false) {
9
- const encoding = url ? 'base64url' : 'base64';
10
- if (typeof value !== 'string') fail('ENVELOPE_INVALID','envelope');
11
- const decoded = Buffer.from(value,encoding);
12
- if (decoded.toString(encoding) !== value || (length !== null && decoded.length !== length)) fail('ENVELOPE_INVALID','envelope');
13
- return decoded;
12
+ return Buffer.from(decode64Bytes(value, length, url));
14
13
  }
15
14
  function validateEnvelope(value, profile) {
16
- if (value?.profile !== profile.id || (value.profile_version ?? value.contract_version) !== profile.version) fail('PROFILE_UNSUPPORTED','envelope');
17
- if (profile.id === 'kdna.envelope.aead') {
18
- if (!passwordShape(value) || value.kdf_profile !== value.key_slots[0].kdf_profile) fail('ENVELOPE_INVALID','envelope');
19
- for (const slot of value.key_slots) { decode64(slot.kdf_params.salt,16); decode64(slot.wrapped_key,40); }
20
- decode64(value.iv,12); decode64(value.tag,16); decode64(value.ciphertext);
21
- } else {
22
- if (!externalShape(value) || value.entry_path !== 'payload.kdnab') fail('ENVELOPE_INVALID','envelope');
23
- decode64(value.iv,12,true); decode64(value.tag,16,true); decode64(value.ciphertext,null,true);
24
- }
25
- return value;
15
+ return validateEnvelopeShape(value, profile);
26
16
  }
27
17
  function passwordAad(manifest) {
28
- return Buffer.from(['kdna.envelope.aead','0.1.0',manifest.asset_uid,manifest.asset_id,manifest.version,'payload.kdnab',manifest.access,manifest.entitlement.profile].join('\n'));
18
+ return Buffer.from(passwordAadBytes(manifest));
29
19
  }
30
20
  function deriveKek(password, slot) {
31
21
  const salt = decode64(slot.kdf_params.salt,16);