@parmanasystems/core 1.71.26 → 1.71.36

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/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export { RuntimeRequirements, createPolicy, generateBundle, upgradePolicy, validatePolicy } from '@parmanasystems/governance';
2
2
  export { signBundle } from '@parmanasystems/crypto';
3
+ import { Verifier } from '@parmanasystems/execution';
3
4
  export { ExecutionAttestation, ExecutionContext, ExecutionToken, INVARIANT_REGISTRY, InvariantBoundary, InvariantEntry, InvariantId, InvariantViolation, LocalSigner, LocalVerifier, ReplayStore, RuntimeManifest, Signer, Verifier, ViolationReport, executeDecision, getRuntimeManifest, hashInput, issueToken, signRuntimeManifest, verifyExecutionToken, verifyRuntimeManifest, violate } from '@parmanasystems/execution';
4
5
  export { MemoryReplayStore, RedisReplayStore, executeFromSignals } from '@parmanasystems/execution-runtime';
5
6
  export { verifyAttestation, verifyBundle, verifyExecutionRequirements, verifyRuntime, verifyRuntimeCompatibility } from '@parmanasystems/verifier';
6
7
  export { DecisionOutcome, DecisionResult } from '@parmanasystems/contracts';
7
8
  import { AuditOverride } from '@parmanasystems/audit-db';
9
+ export { canonicalize } from '@parmanasystems/bundle';
8
10
 
9
11
  interface ApproveOverrideInput {
10
12
  executionId: string;
@@ -14,15 +16,6 @@ interface ApproveOverrideInput {
14
16
  }
15
17
  declare function approveOverride(input: ApproveOverrideInput): Promise<AuditOverride>;
16
18
 
17
- /**
18
- * Serializes `value` to a stable, compact JSON string with object keys sorted
19
- * recursively. Used by the core validation pipeline for determinism checks.
20
- *
21
- * Note: unlike `@parmanasystems/bundle`'s `canonicalize`, this variant uses
22
- * compact output (`JSON.stringify` without indentation) for in-memory comparisons.
23
- */
24
- declare function canonicalize(value: unknown): string;
25
-
26
19
  /** Configuration for {@link LocalValidator}. */
27
20
  interface ValidatorConfig {
28
21
  /**
@@ -30,6 +23,13 @@ interface ValidatorConfig {
30
23
  * Defaults to {@link forbiddenDeterministicFields} when omitted.
31
24
  */
32
25
  forbiddenDeterministicFields?: readonly string[];
26
+ /**
27
+ * Optional Ed25519 verifier for the cryptographic stage.
28
+ * When provided, `stages.cryptographic` reflects the actual signature check
29
+ * and `valid` can be `true` on a fully verified envelope.
30
+ * When omitted, `stages.cryptographic` is always `false`.
31
+ */
32
+ verifier?: Verifier;
33
33
  }
34
34
 
35
35
  /**
@@ -121,9 +121,8 @@ declare class LocalValidator {
121
121
  /** Returns `true` when `payload` can be serialized through the canonical JSON pipeline without error. */
122
122
  validateCanonical(payload: unknown): boolean;
123
123
  /**
124
- * Returns `true` when the canonical form of the payload alone equals the
125
- * canonical form of `{ payload }`, confirming that no metadata fields have
126
- * leaked into the deterministic signing scope.
124
+ * Returns `true` when the payload does not contain execution metadata fields
125
+ * that must remain isolated from the deterministic signing scope.
127
126
  */
128
127
  validateMetadataIsolation(envelope: SignedEnvelope<unknown>): boolean;
129
128
  /**
@@ -226,4 +225,4 @@ interface GovernanceMetadata {
226
225
  */
227
226
  declare const forbiddenDeterministicFields: readonly ["generatedAt", "environment", "host", "runtime", "traceId"];
228
227
 
229
- export { type ApproveOverrideInput, type AttestationPayload, type GovernanceMetadata, LocalValidator, type OperationalMetadata, type ProvenanceMetadata, type ReleasePayload, type RuntimePayload, type SignedEnvelope, type ValidationResult, type ValidationStages, type ValidatorConfig, approveOverride, assertArray, assertNoOperationalMetadata, assertNonEmptyString, canonicalize, forbiddenDeterministicFields };
228
+ export { type ApproveOverrideInput, type AttestationPayload, type GovernanceMetadata, LocalValidator, type OperationalMetadata, type ProvenanceMetadata, type ReleasePayload, type RuntimePayload, type SignedEnvelope, type ValidationResult, type ValidationStages, type ValidatorConfig, approveOverride, assertArray, assertNoOperationalMetadata, assertNonEmptyString, forbiddenDeterministicFields };
package/dist/index.js CHANGED
@@ -10529,7 +10529,7 @@ async function executeFromSignals(input, signer, verifier, replayStore) {
10529
10529
  );
10530
10530
  }
10531
10531
  const execution_fingerprint = crypto.createHash("sha256").update(
10532
- JSON.stringify({
10532
+ canonicalizeForSigning({
10533
10533
  policyId: input.policyId,
10534
10534
  policyVersion: input.policyVersion,
10535
10535
  signals: input.signals
@@ -10554,7 +10554,7 @@ async function executeFromSignals(input, signer, verifier, replayStore) {
10554
10554
  }
10555
10555
  const runtimeManifest = getRuntimeManifest();
10556
10556
  const token = issueToken({
10557
- executionId: execution_fingerprint,
10557
+ executionId: crypto.randomUUID(),
10558
10558
  policyId: input.policyId,
10559
10559
  policyVersion: input.policyVersion,
10560
10560
  schemaVersion: policy.schemaVersion,
@@ -10740,17 +10740,17 @@ import {
10740
10740
 
10741
10741
  // src/override.ts
10742
10742
  import crypto2 from "crypto";
10743
+ import { canonicalize } from "@parmanasystems/bundle";
10743
10744
  async function approveOverride(input) {
10744
10745
  const override_id = crypto2.randomUUID();
10745
10746
  const approved_at = /* @__PURE__ */ new Date();
10746
10747
  const override_signature = crypto2.createHash("sha256").update(
10747
- JSON.stringify({
10748
+ canonicalize({
10748
10749
  override_id,
10749
10750
  executionId: input.executionId,
10750
10751
  approved_by: input.approved_by,
10751
10752
  approver_role: input.approver_role,
10752
- reason: input.reason,
10753
- approved_at
10753
+ reason: input.reason
10754
10754
  })
10755
10755
  ).digest("hex");
10756
10756
  const override = {
@@ -10768,21 +10768,7 @@ async function approveOverride(input) {
10768
10768
  }
10769
10769
 
10770
10770
  // src/canonicalize.ts
10771
- function sortKeys(value) {
10772
- if (Array.isArray(value)) {
10773
- return value.map(sortKeys);
10774
- }
10775
- if (value && typeof value === "object") {
10776
- return Object.keys(value).sort().reduce((acc, key) => {
10777
- acc[key] = sortKeys(value[key]);
10778
- return acc;
10779
- }, {});
10780
- }
10781
- return value;
10782
- }
10783
- function canonicalize(value) {
10784
- return JSON.stringify(sortKeys(value));
10785
- }
10771
+ import { canonicalize as canonicalize2 } from "@parmanasystems/bundle";
10786
10772
 
10787
10773
  // src/invariants.ts
10788
10774
  function assertNonEmptyString(value) {
@@ -10857,30 +10843,35 @@ var LocalValidator = class {
10857
10843
  /** Returns `true` when `payload` can be serialized through the canonical JSON pipeline without error. */
10858
10844
  validateCanonical(payload) {
10859
10845
  try {
10860
- canonicalize(payload);
10846
+ canonicalize2(payload);
10861
10847
  return true;
10862
10848
  } catch {
10863
10849
  return false;
10864
10850
  }
10865
10851
  }
10866
10852
  /**
10867
- * Returns `true` when the canonical form of the payload alone equals the
10868
- * canonical form of `{ payload }`, confirming that no metadata fields have
10869
- * leaked into the deterministic signing scope.
10853
+ * Returns `true` when the payload does not contain execution metadata fields
10854
+ * that must remain isolated from the deterministic signing scope.
10870
10855
  */
10871
10856
  validateMetadataIsolation(envelope) {
10872
10857
  try {
10873
- const canonicalPayload = canonicalize(
10874
- this.extractDeterministicPayload(
10875
- envelope
10876
- )
10858
+ const payload = this.extractDeterministicPayload(
10859
+ envelope
10860
+ );
10861
+ const metadataFields = [
10862
+ "executionId",
10863
+ "policyId",
10864
+ "policyVersion",
10865
+ "execution_fingerprint",
10866
+ "execution_state",
10867
+ "runtime_manifest"
10868
+ ];
10869
+ const payloadKeys = Object.keys(
10870
+ payload || {}
10871
+ );
10872
+ return !metadataFields.some(
10873
+ (f) => payloadKeys.includes(f)
10877
10874
  );
10878
- const canonicalEnvelope = canonicalize({
10879
- payload: this.extractDeterministicPayload(
10880
- envelope
10881
- )
10882
- });
10883
- return canonicalPayload === canonicalEnvelope;
10884
10875
  } catch {
10885
10876
  return false;
10886
10877
  }
@@ -10903,7 +10894,10 @@ var LocalValidator = class {
10903
10894
  const metadataIsolation = structure && this.validateMetadataIsolation(
10904
10895
  envelope
10905
10896
  );
10906
- const cryptographic = false;
10897
+ const cryptographic = structure && !!this.config.verifier && this.config.verifier.verify(
10898
+ canonicalize2(envelope.payload),
10899
+ envelope.signature
10900
+ );
10907
10901
  const errors = [];
10908
10902
  if (!structure) {
10909
10903
  errors.push(
@@ -10951,7 +10945,7 @@ export {
10951
10945
  assertArray,
10952
10946
  assertNoOperationalMetadata,
10953
10947
  assertNonEmptyString,
10954
- canonicalize,
10948
+ canonicalize2 as canonicalize,
10955
10949
  createPolicy,
10956
10950
  executeDecision3 as executeDecision,
10957
10951
  executeFromSignals,