@aikdna/kdna-core 0.37.0 → 0.37.1-rc.browser.1

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/README.md +12 -2
  2. package/package.json +6 -1
  3. package/src/public-contract/browser-native/generated-contract.json +3 -3
  4. package/src/public-contract/browser-native/sections/contract.json +2 -2
  5. package/src/public-contract/browser-protected/request.js +77 -0
  6. package/src/public-contract/browser-protected/state.js +200 -0
  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 +8 -8
  10. package/src/public-contract/execution06/contract.json +2 -2
  11. package/src/public-contract/execution06/generation-manifest.json +8 -8
  12. package/src/public-contract/generated-contract.json +3 -3
  13. package/src/public-contract/issuer-contract.generated.json +6 -6
  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 +8 -8
  21. package/src/public-contract/protected-browser-contract/contract.json +11824 -0
  22. package/src/public-contract/protected-browser-contract/descriptor.json +5 -0
  23. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedAdmissionResult.json +443 -0
  24. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedAuthorityContext.json +939 -0
  25. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedBinding.json +156 -0
  26. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedCallResult.json +10489 -0
  27. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedDeliveryToken.json +10 -0
  28. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedExpansionHandle.json +320 -0
  29. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedHostContext.json +677 -0
  30. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedHostObservation.json +208 -0
  31. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedReadAuthority.json +10 -0
  32. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedReadResult.json +10795 -0
  33. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedRequest.json +539 -0
  34. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedRequestAdmission.json +1016 -0
  35. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedSignaturePolicy.json +35 -0
  36. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedSnapshotData.json +8451 -0
  37. package/src/public-contract/protected-browser-contract/schemas/BrowserProtectedTransportCommitResult.json +304 -0
  38. package/src/public-contract/protected-browser-contract/schemas/TrustedBrowserProtectedHost.json +10 -0
  39. package/src/public-contract/protected-browser-contract/types.d.ts +389 -0
  40. package/src/public-contract/protected-browser-contract/validators.cjs +223756 -0
  41. package/src/public-contract/protected-sections-browser.d.ts +11 -0
  42. package/src/public-contract/protected-sections-browser.js +22 -0
  43. package/src/public-contract/protected-sections-browser.mjs +2 -0
  44. package/src/public-contract/protected-source-contract.generated.json +8 -8
  45. package/src/public-contract/protected-source-node.d.ts +1 -1
  46. package/src/public-contract/protection-admission-browser.js +21 -3
  47. package/src/public-contract/protection-contract.generated.json +9 -9
  48. package/src/public-contract/protection-envelope-codec.js +16 -12
  49. package/src/public-contract/protection-node.d.ts +2 -2
  50. package/src/public-contract/protection-validators.generated.js +5 -5
  51. package/src/public-contract/retained/contract.json +2 -2
  52. package/src/public-contract/retained/generation-manifest.json +8 -8
  53. package/src/public-contract/retained-browser06/contract.json +2 -2
  54. package/src/public-contract/sectionbytes/contract.json +2 -2
  55. package/src/public-contract/sectionbytes/generation-manifest.json +8 -8
  56. package/src/public-contract/sections/contract.json +2 -2
  57. package/src/public-contract/sections/generation-manifest.json +8 -8
  58. package/src/public-contract/source-validators.generated.js +6 -6
  59. package/src/public-contract/source06/contract.json +2 -2
@@ -0,0 +1,11 @@
1
+ import type { CanonicalReadSnapshot } from './types.js';
2
+ import type { BrowserProtectedRequestAdmission, AdmittedBrowserProtectedRequest, BrowserProtectedRequest, BrowserProtectedAuthorityContext, BrowserProtectedReadAuthority, BrowserProtectedAdmissionResult, BrowserProtectedSnapshot, BrowserProtectedSnapshotData, BrowserProtectedOperation } from './protected-browser-contract/types.js';
3
+ export type * from './protected-browser-contract/types.js';
4
+ export declare function admitProtectedPayloadRequestJson(requestJson: string): BrowserProtectedRequestAdmission;
5
+ export declare function inspectProtectedPayloadRequest(request: AdmittedBrowserProtectedRequest): Readonly<BrowserProtectedRequest> | null;
6
+ export declare function createProtectedPayloadReadAuthorityJson(callback: (context: Readonly<BrowserProtectedAuthorityContext>) => boolean | Promise<boolean>, signaturePolicyJson?: string): BrowserProtectedReadAuthority;
7
+ // Consumes one genuine admitProtectedBrowser origin. No new decryption or physical read.
8
+ export declare function admitProtectedSectionBrowser(snapshot: CanonicalReadSnapshot, request: AdmittedBrowserProtectedRequest, authority: BrowserProtectedReadAuthority): Promise<BrowserProtectedAdmissionResult>;
9
+ export declare function inspectProtectedPayloadSnapshot(snapshot: BrowserProtectedSnapshot): Readonly<BrowserProtectedSnapshotData> | null;
10
+ export declare function bindProtectedPayloadRequest(operation: BrowserProtectedOperation, requestJson: string): BrowserProtectedRequestAdmission;
11
+ export declare function disposeProtectedSectionOperation(operation: BrowserProtectedOperation): void;
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+ const S = require('./browser-protected/state.js'), R = require('./browser-protected/request.js');
3
+ function bindProtectedPayloadRequest(operation, requestJson) {
4
+ const record = S.operation(operation);
5
+ if (!record) return R.failure(null);
6
+ const admitted = R.admit(requestJson);
7
+ if (admitted.channel !== 'admitted_request') return admitted;
8
+ try {
9
+ const token = S.normalized(S.request(admitted.request), record.view);
10
+ S.pairRequest(token, operation);
11
+ return Object.freeze({ channel: 'admitted_request', request: token });
12
+ } catch { return R.failure(S.inspectRequest(admitted.request)); }
13
+ }
14
+ module.exports = {
15
+ admitProtectedPayloadRequestJson: R.admit,
16
+ inspectProtectedPayloadRequest: S.inspectRequest,
17
+ createProtectedPayloadReadAuthorityJson: S.createAuthority,
18
+ admitProtectedSectionBrowser: S.admit,
19
+ inspectProtectedPayloadSnapshot: S.inspectSnapshot,
20
+ bindProtectedPayloadRequest,
21
+ disposeProtectedSectionOperation: S.dispose
22
+ };
@@ -0,0 +1,2 @@
1
+ import api from './protected-sections-browser.js';
2
+ export const { admitProtectedPayloadRequestJson, inspectProtectedPayloadRequest, createProtectedPayloadReadAuthorityJson, admitProtectedSectionBrowser, inspectProtectedPayloadSnapshot, bindProtectedPayloadRequest, disposeProtectedSectionOperation } = 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:612b285c79566eb308ff613fbc4fd1599ee35076efaf5c1214c271ebfa3334ab",
3
+ "definition_digest": "sha256:6a0c62e9908100fcd03b9f9b735bb0d928fa340fbe57fb894f501968aac188a8",
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.37.0",
33
- "@aikdna/kdna-read": "0.11.1"
32
+ "@aikdna/kdna-core": "0.37.1-rc.browser.1",
33
+ "@aikdna/kdna-read": "0.11.2-rc.browser.1"
34
34
  },
35
35
  "version_tuple": {
36
36
  "container": "0.5.0",
@@ -45,8 +45,8 @@
45
45
  "trace": "kdna.judgment-trace/0.3.1"
46
46
  }
47
47
  },
48
- "schema_id": "urn:kdna:schema:protected-source:1.0.0:binding:r2:7",
49
- "schema_path": "specs/protected-source-r2-binding-7.schema.json",
48
+ "schema_id": "urn:kdna:schema:protected-source:1.0.0:binding:r2:8",
49
+ "schema_path": "specs/protected-source-r2-binding-8.schema.json",
50
50
  "types": {
51
51
  "AccessMode": {
52
52
  "enum": [
@@ -9260,7 +9260,7 @@
9260
9260
  "type": "string"
9261
9261
  },
9262
9262
  "version": {
9263
- "const": "0.37.0",
9263
+ "const": "0.37.1-rc.browser.1",
9264
9264
  "type": "string"
9265
9265
  }
9266
9266
  },
@@ -10632,7 +10632,7 @@
10632
10632
  "type": "string"
10633
10633
  },
10634
10634
  "version": {
10635
- "const": "0.37.0",
10635
+ "const": "0.37.1-rc.browser.1",
10636
10636
  "type": "string"
10637
10637
  }
10638
10638
  },
@@ -13783,7 +13783,7 @@
13783
13783
  "type": "string"
13784
13784
  },
13785
13785
  "version": {
13786
- "const": "0.37.0",
13786
+ "const": "0.37.1-rc.browser.1",
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.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"; };
13
+ export type SourcePreviewValidation = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "name": "@aikdna/kdna-core"; readonly "version": "0.37.1-rc.browser.1"; }; 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);
@@ -30,14 +30,22 @@ function checkDeclaration(manifest) {
30
30
  }
31
31
  function inputs(value, inputProvider) {
32
32
  closed(value, ['bytes', 'plaintextPayload', 'observation'], ['signaturePolicy']);
33
- if (!(value.bytes instanceof Uint8Array) || !(value.plaintextPayload instanceof Uint8Array)) fail('INPUT_INVALID', 'input');
33
+ const containerBytes = value.bytes, suppliedPlaintext = value.plaintextPayload;
34
+ if (!(containerBytes instanceof Uint8Array) || !(suppliedPlaintext instanceof Uint8Array)) fail('INPUT_INVALID', 'input');
34
35
  const policy = value.signaturePolicy === undefined ? { requireSignature: false, expectedPublicKeyHex: null } : closed(value.signaturePolicy, ['requireSignature', 'expectedPublicKeyHex']);
35
36
  if (typeof policy.requireSignature !== 'boolean' || (policy.expectedPublicKeyHex !== null && (typeof policy.expectedPublicKeyHex !== 'string' || !/^[0-9a-f]{64}$/.test(policy.expectedPublicKeyHex)))) fail('INPUT_INVALID', 'input');
36
37
  const o = closed(value.observation, ['kind', 'proof', 'checked_at_ms', 'selection']);
37
38
  if (o.kind !== 'consumer_unlock_observation' || o.proof !== 'observation_not_authority' || !uint(o.checked_at_ms)) fail('OBSERVATION_INVALID', 'observation');
38
39
  const s = closed(o.selection, ['slotIndex', 'slot', 'kdf_profile']);
39
40
  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
+ const trustedProvider = provider(inputProvider, 'password');
42
+ // Finish every caller-owned metadata access before allocating the plaintext
43
+ // copy. The caller may still throw while a Proxy supplies a data property.
44
+ const copied = { 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 };
45
+ const observed = copied.observation, selected = observed.selection, signaturePolicy = copied.signaturePolicy;
46
+ if (observed.kind !== 'consumer_unlock_observation' || observed.proof !== 'observation_not_authority' || !uint(observed.checked_at_ms) || !uint(selected.slotIndex) || !identifier(selected.slot) || !['scrypt-sha256', 'argon2id'].includes(selected.kdf_profile)) fail('OBSERVATION_INVALID', 'observation');
47
+ if (typeof signaturePolicy.requireSignature !== 'boolean' || (signaturePolicy.expectedPublicKeyHex !== null && (typeof signaturePolicy.expectedPublicKeyHex !== 'string' || !/^[0-9a-f]{64}$/.test(signaturePolicy.expectedPublicKeyHex)))) fail('INPUT_INVALID', 'input');
48
+ return { ...copied, bytes: new Uint8Array(containerBytes), plaintext: new Uint8Array(suppliedPlaintext) };
41
49
  }
42
50
  function assertObservationBinding(observation, envelope) {
43
51
  const slots = envelope.key_slots;
@@ -63,7 +71,7 @@ function parseKdsigBundle(raw) {
63
71
  return value;
64
72
  }
65
73
  async function verifyIntegrityBrowser(entries, manifest, E, policy) {
66
- const integrity = { checksums: 'absent', signature: 'absent', signature_content_digest: null };
74
+ const integrity = { checksums: 'absent', signature: 'absent', signature_content_digest: null, public_key: null };
67
75
  if (Object.hasOwn(entries, 'checksums.json')) {
68
76
  const raw = entries['checksums.json']; let value;
69
77
  try { if (raw.length > 1048576) throw Error(); value = parseJson(raw); } catch { fail('CHECKSUMS_INVALID', 'integrity'); }
@@ -85,6 +93,7 @@ async function verifyIntegrityBrowser(entries, manifest, E, policy) {
85
93
  } catch (error) { if (isFailure(error)) throw error; throw Object.assign(new Error('WebCrypto Ed25519 failed'), { reason: 'READ_CORE_CAPABILITY_UNAVAILABLE' }); }
86
94
  integrity.signature = policy.expectedPublicKeyHex === null ? 'verified_self_key' : 'verified_pinned_key';
87
95
  integrity.signature_content_digest = signatureDigest;
96
+ integrity.public_key = bundle.public_key;
88
97
  } else if (policy.requireSignature || policy.expectedPublicKeyHex !== null) fail('SIGNATURE_INVALID', 'integrity');
89
98
  return integrity;
90
99
  }
@@ -103,6 +112,15 @@ async function admitProtectedBrowser(input, inputProvider) {
103
112
  stage = 'payload'; const payload = decodeValidatedPayload(manifest, plaintext);
104
113
  stage = 'interpretation'; const result = finishAdmission(manifest, payload, entries, digests, integrity.checksums === 'verified_document_1' ? digests.E : null);
105
114
  const disclosure = freeze({ slot_selection: { ...copied.observation.selection }, observation_not_authority: true, provenance: 'host_supplied_triple' });
115
+ if (result.status === 'accepted') {
116
+ const view = require('./brand.js').inspectSnapshot(result.snapshot);
117
+ require('./browser-protected/state.js').register(result.snapshot, {
118
+ provider: copied.trustedProvider, integrity, disclosure,
119
+ observation: { snapshot_id: view.snapshot_id, tuple: view.tuple, asset: view.asset,
120
+ ...digests, ir_digest: view.ir_digest, integrity, unlock_observation: copied.observation,
121
+ disclosure, physical_reads: 'none', new_decryption: false }
122
+ });
123
+ }
106
124
  return freeze(result.status === 'accepted' ? { status: 'accepted', snapshot: result.snapshot, disclosure } : { status: 'catalog_only', catalog: result, disclosure });
107
125
  } catch (error) {
108
126
  if (isFailure(error) || stage === 'input') return failure(error);
@@ -14,7 +14,7 @@
14
14
  "schema_path": "specs/checksums-document-1.schema.json",
15
15
  "version": "1.0.0"
16
16
  },
17
- "definition_digest": "sha256:c88dfae7dc756d00fad579b02c7ea0f14b21f3d1ca3edecbf2fad8f4c5fd9e4a",
17
+ "definition_digest": "sha256:7257adf964aadbce546b1403a059852b72f5df269503d6b58445d1f549e2252d",
18
18
  "delivery_history": {
19
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.",
20
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.",
@@ -802,8 +802,8 @@
802
802
  "runtime_not_implemented": [],
803
803
  "schema_binding": {
804
804
  "package_versions": {
805
- "@aikdna/kdna-core": "0.37.0",
806
- "@aikdna/kdna-read": "0.11.1"
805
+ "@aikdna/kdna-core": "0.37.1-rc.browser.1",
806
+ "@aikdna/kdna-read": "0.11.2-rc.browser.1"
807
807
  },
808
808
  "version_tuple": {
809
809
  "container": "0.5.0",
@@ -818,12 +818,12 @@
818
818
  "trace": "kdna.judgment-trace/0.3.1"
819
819
  }
820
820
  },
821
- "schema_id": "urn:kdna:schema:protection-admission:1.0.0:binding:r2:7",
822
- "schema_path": "specs/protection-admission-r2-binding-7.schema.json",
821
+ "schema_id": "urn:kdna:schema:protection-admission:1.0.0:binding:r2:8",
822
+ "schema_path": "specs/protection-admission-r2-binding-8.schema.json",
823
823
  "specification": {
824
- "bytes": 37902,
824
+ "bytes": 38180,
825
825
  "path": "specs/protection-admission.md",
826
- "sha256": "7dbc85924d7c0a1d0d4556aeac92de8ac91d331185b4a65d066c0d165c3fadcc"
826
+ "sha256": "35180f6583ac97302096a8e2ff786f1c7a9a0c10caabc3a4fa627affd1640bef"
827
827
  },
828
828
  "types": {
829
829
  "ChecksumsDocument1": {
@@ -1060,7 +1060,7 @@
1060
1060
  "type": "string"
1061
1061
  },
1062
1062
  "version": {
1063
- "const": "0.37.0",
1063
+ "const": "0.37.1-rc.browser.1",
1064
1064
  "type": "string"
1065
1065
  }
1066
1066
  },
@@ -2295,7 +2295,7 @@
2295
2295
  "type": "string"
2296
2296
  },
2297
2297
  "version": {
2298
- "const": "0.37.0",
2298
+ "const": "0.37.1-rc.browser.1",
2299
2299
  "type": "string"
2300
2300
  }
2301
2301
  },
@@ -1,30 +1,34 @@
1
1
  'use strict';
2
2
  const fail = (code, stage) => require('./protection-declaration.js').fail(code, stage);
3
+ const { utf8, equal, concat } = require('./browser-native/bytes.js');
3
4
  const LIMIT = 8 * 1024 * 1024;
4
5
  function invalid() { fail('ENVELOPE_INVALID','envelope'); }
5
6
  function head(major, n) {
6
7
  if (!Number.isSafeInteger(n) || n < 0) invalid();
7
- if (n < 24) return Buffer.from([(major << 5) | n]);
8
+ if (n < 24) return Uint8Array.of((major << 5) | n);
8
9
  const width = n <= 255 ? 1 : n <= 65535 ? 2 : n <= 4294967295 ? 4 : 8;
9
- const out = Buffer.alloc(width + 1); out[0] = (major << 5) | ({1:24,2:25,4:26,8:27})[width];
10
- if (width === 8) out.writeBigUInt64BE(BigInt(n),1); else out.writeUIntBE(n,1,width);
10
+ const out = new Uint8Array(width + 1), view = new DataView(out.buffer); out[0] = (major << 5) | ({1:24,2:25,4:26,8:27})[width];
11
+ if (width === 8) view.setBigUint64(1,BigInt(n),false);
12
+ else if (width === 4) view.setUint32(1,n,false);
13
+ else if (width === 2) view.setUint16(1,n,false);
14
+ else out[1]=n;
11
15
  return out;
12
16
  }
13
- function compare(a,b) { return a.length - b.length || Buffer.compare(a,b); }
17
+ function compare(a,b) { if(a.length!==b.length)return a.length-b.length;for(let i=0;i<a.length;i++)if(a[i]!==b[i])return a[i]-b[i];return 0; }
14
18
  function encodeEnvelope(value) {
15
19
  let count = 0;
16
20
  function encode(v, depth) {
17
21
  if (++count > 100000 || depth > 16) invalid();
18
22
  if (typeof v === 'string') {
19
23
  if (!v.isWellFormed()) invalid();
20
- const bytes = Buffer.from(v); if (bytes.length > LIMIT) invalid();
21
- return Buffer.concat([head(3,bytes.length),bytes]);
24
+ const bytes = utf8(v); if (bytes.length > LIMIT) invalid();
25
+ return concat([head(3,bytes.length),bytes]);
22
26
  }
23
27
  if (Number.isSafeInteger(v) && v >= 0) return head(0,v);
24
- if (Array.isArray(v)) return Buffer.concat([head(4,v.length), ...v.map(x=>encode(x,depth+1))]);
28
+ if (Array.isArray(v)) return concat([head(4,v.length), ...v.map(x=>encode(x,depth+1))]);
25
29
  if (v && typeof v === 'object' && [Object.prototype,null].includes(Object.getPrototypeOf(v))) {
26
30
  const members = Object.keys(v).map(k => [encode(k,depth+1), encode(v[k],depth+1)]).sort((a,b)=>compare(a[0],b[0]));
27
- return Buffer.concat([head(5,members.length), ...members.flat()]);
31
+ return concat([head(5,members.length), ...members.flat()]);
28
32
  }
29
33
  invalid();
30
34
  }
@@ -34,7 +38,7 @@ function encodeEnvelope(value) {
34
38
  // It never decodes Payload: authenticated plaintext goes to the sole Payload codec.
35
39
  function decodeEnvelope(input) {
36
40
  if (!(input instanceof Uint8Array) || !input.length || input.length > LIMIT) invalid();
37
- const bytes = Buffer.from(input); let offset = 0, count = 0;
41
+ const bytes = new Uint8Array(input), view = new DataView(bytes.buffer); let offset = 0, count = 0;
38
42
  const decoder = new TextDecoder('utf-8',{fatal:true});
39
43
  function read(depth) {
40
44
  if (++count > 100000 || depth > 16 || offset >= bytes.length) invalid();
@@ -43,7 +47,7 @@ function decodeEnvelope(input) {
43
47
  let n = add;
44
48
  if (add >= 24) {
45
49
  const width = 2 ** (add - 24); if (offset + width > bytes.length) invalid();
46
- n = width === 8 ? Number(bytes.readBigUInt64BE(offset)) : bytes.readUIntBE(offset,width); offset += width;
50
+ n = width === 8 ? Number(view.getBigUint64(offset,false)) : width === 4 ? view.getUint32(offset,false) : width === 2 ? view.getUint16(offset,false) : bytes[offset]; offset += width;
47
51
  if (!Number.isSafeInteger(n) || n < (width === 1 ? 24 : 2 ** (8 * width / 2))) invalid();
48
52
  }
49
53
  if (major === 0) return n;
@@ -63,7 +67,7 @@ function decodeEnvelope(input) {
63
67
  }
64
68
  return value;
65
69
  }
66
- const value = read(0); if (offset !== bytes.length || !encodeEnvelope(value).equals(bytes)) invalid(); return value;
70
+ const value = read(0); if (offset !== bytes.length || !equal(encodeEnvelope(value),bytes)) invalid(); return value;
67
71
  }
68
72
  // The frozen RFC18 ciphertext pattern is strict canonical padded base64. Native
69
73
  // RegExp's repeated four-character group can exhaust the VM stack on an otherwise
@@ -71,7 +75,7 @@ function decodeEnvelope(input) {
71
75
  // (including padding bits) in bounded linear memory; all other patterns stay native.
72
76
  const CIPHERTEXT_PATTERN = '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?$';
73
77
  function envelopeRegExp(pattern, flags) {
74
- if(pattern===CIPHERTEXT_PATTERN)return {test:value=>typeof value==='string'&&Buffer.from(value,'base64').toString('base64')===value};
78
+ if(pattern===CIPHERTEXT_PATTERN)return {test:value=>{try {decode64Bytes(value);return true;}catch{return false;}}};
75
79
  return new RegExp(pattern,flags);
76
80
  }
77
81
  envelopeRegExp.code = "require('./protection-envelope-codec.js').envelopeRegExp";
@@ -39,8 +39,8 @@ declare const ProtectionCheckpointBrand: unique symbol;
39
39
  export type ProtectionCheckpoint = { readonly [ProtectionCheckpointBrand]: true };
40
40
  declare const ProtectedHostReadProviderBrand: unique symbol;
41
41
  export type ProtectedHostReadProvider = { readonly [ProtectedHostReadProviderBrand]: true };
42
- export type ProtectionRuntimeDescriptor = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.37.0"; }; readonly "profiles": ReadonlyArray<"kdna.envelope.aead/0.1.0" | "kdna.envelope.external-grant/0.1.0" | "kdna.checksums.document/1@1.0.0" | "kdsig.ed25519/0.1.0">; readonly "kdfs": ReadonlyArray<"scrypt-sha256" | "argon2id">; readonly "capabilities": ReadonlyArray<"protected_admission" | "protected_operation" | "protected_production">; };
43
- export type ProtectedExportEvidence = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.37.0"; }; readonly "source_A": Digest; readonly "output": { readonly "A": Digest; readonly "C": Digest; readonly "E": Digest; }; readonly "profile": (ProtectionProfile | null); readonly "entry": "payload.kdnab"; readonly "integrity": ProtectionIntegrity; readonly "proof": "producer_observation_not_consumer_admission"; };
42
+ export type ProtectionRuntimeDescriptor = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.37.1-rc.browser.1"; }; readonly "profiles": ReadonlyArray<"kdna.envelope.aead/0.1.0" | "kdna.envelope.external-grant/0.1.0" | "kdna.checksums.document/1@1.0.0" | "kdsig.ed25519/0.1.0">; readonly "kdfs": ReadonlyArray<"scrypt-sha256" | "argon2id">; readonly "capabilities": ReadonlyArray<"protected_admission" | "protected_operation" | "protected_production">; };
43
+ export type ProtectedExportEvidence = { readonly "contract": ProtectionContractIdentity; readonly "implementation": { readonly "package": "@aikdna/kdna-core"; readonly "version": "0.37.1-rc.browser.1"; }; readonly "source_A": Digest; readonly "output": { readonly "A": Digest; readonly "C": Digest; readonly "E": Digest; }; readonly "profile": (ProtectionProfile | null); readonly "entry": "payload.kdnab"; readonly "integrity": ProtectionIntegrity; readonly "proof": "producer_observation_not_consumer_admission"; };
44
44
  export type ProtectedRequestVersionRejected = { readonly "channel": "read_envelope"; readonly "envelope": ReadEnvelopeRejected; readonly "admission_rejection": null; readonly "control": null; readonly "transport_failure": null; };
45
45
  export type ProtectionCurrentFailure = { readonly "status": "protection_failed"; readonly "diagnostic": ProtectionDiagnostic; readonly "checked_at_ms": (UInt | null); };
46
46
  export type ProtectedSignaturePolicy = { readonly requireSignature: boolean; readonly expectedPublicKeyHex: string | null };