File size: 4,995 Bytes
518343a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// SPDX-License-Identifier: Apache-2.0
// © 2026 Lutar, Stephen P. — SZL Holdings
// ORCID: 0009-0001-0110-4173
//
// Layer 6 — a11oy policy gate for BekensteinBound (A7)
//
// *** STAGED — ADVISORY ONLY ***
// Lean status: conjectured (formal proof pending lutar-lean Paper R2)
// This gate issues warnings but does NOT block production by default.
//
// Policy rationale:
//   Receipt chain entropy H(R_n) is bounded by the information-theoretic
//   limit from registry area: H(R_n) ≤ 8·sizeBytes bits. This is an advisory
//   check — chains exceeding the bound indicate anomalous entropy generation
//   that may signal state corruption or replay attacks.
//
//   Lean axiom cited: `bekensteinBound` (A7)
//   Lean file: Lutar/Gate/BekensteinBound.lean (pending — conjectured)
//   Lean commit SHA: 1dca00032dfc9aa8559cc6c2e4b63192fcf52371
//
//   Policy: advisory (severity: 'warning') — entropy > 8*sizeBytes → warn
//
// References:
//   Zenodo: https://doi.org/10.5281/zenodo.19944926
//   Thesis §4.5: bekensteinBound axiom; TH6 DPI proof discharges this

export interface BekensteinBoundGateConfig {
  /** Bits-per-byte multiplier. Default: 8 (maximum information density). */
  bitsPerByte?: number;
  /**
   * If true, deny on bound violation. Default: false (advisory / warning only).
   * STAGED: set to false until TH6 formal proof lands on lutar-lean.
   */
  enforced?: boolean;
}

export interface BekensteinBoundGateOpts {
  /** Measured chain entropy in bits (Shannon estimator). */
  chainEntropyBits: number;
  /** Registry size in bytes. */
  registrySizeBytes: number;
}

export interface BekensteinBoundDecision {
  allow:             boolean;
  rationale:         string;
  formula:           string;
  leanTheorem:       string;
  leanFile:          string;
  leanCommitSha:     string;
  severity:          'warning' | 'error';
  staged:            boolean;
  chainEntropyBits:  number;
  boundBits:         number;
  withinBound:       boolean;
  lambdaScore:       number;
}

const LEAN_THEOREM   = "bekensteinBound";
const LEAN_FILE      = "Lutar/Gate/BekensteinBound.lean";
const LEAN_COMMIT    = "1dca00032dfc9aa8559cc6c2e4b63192fcf52371";
const DEFAULT_BPB    = 8;

// ── Inline formula ────────────────────────────────────────────────────────────
// A7 (conjectured): H(R_n) ≤ 8·sizeBytes bits (advisory; TH6 DPI discharges formally)

/**
 * BekensteinBound (A7) policy gate — STAGED ADVISORY.
 *
 * Checks receipt chain entropy against the information-theoretic registry bound.
 * Issues a warning by default; can be made enforcing once TH6 is formally proved.
 *
 * Lean axiom: `bekensteinBound` (A7) — conjectured; TH6 provides elementary proof
 * Lean file: Lutar/Gate/BekensteinBound.lean (pending; commit 1dca00032dfc9aa8559cc6c2e4b63192fcf52371)
 * Zenodo: https://doi.org/10.5281/zenodo.19944926
 */
export function bekensteinBoundGate(
  config: BekensteinBoundGateConfig = {}
): (opts: BekensteinBoundGateOpts) => BekensteinBoundDecision {
  const bitsPerByte = config.bitsPerByte ?? DEFAULT_BPB;
  const enforced    = config.enforced ?? false;
  if (!Number.isFinite(bitsPerByte) || bitsPerByte <= 0) {
    throw new Error(`BekensteinBoundGate: bitsPerByte must be > 0; got ${bitsPerByte}`);
  }

  return function gate(opts: BekensteinBoundGateOpts): BekensteinBoundDecision {
    const { chainEntropyBits, registrySizeBytes } = opts;
    if (!Number.isFinite(chainEntropyBits) || chainEntropyBits < 0) {
      throw new Error(`BekensteinBoundGate: chainEntropyBits must be ≥ 0; got ${chainEntropyBits}`);
    }
    if (!Number.isFinite(registrySizeBytes) || registrySizeBytes <= 0) {
      throw new Error(`BekensteinBoundGate: registrySizeBytes must be > 0; got ${registrySizeBytes}`);
    }

    const boundBits    = bitsPerByte * registrySizeBytes;
    const withinBound  = chainEntropyBits <= boundBits;
    const severity     = enforced ? 'error' as const : 'warning' as const;
    const allow        = withinBound || !enforced;
    const lambdaScore  = withinBound ? 1.0 : boundBits / chainEntropyBits;

    const stagedNote   = enforced ? '' : ' [STAGED-ADVISORY: not blocking]';
    const rationale = withinBound
      ? `BekensteinBound (A7): H(chain)=${chainEntropyBits.toFixed(2)} bits ≤ bound=${boundBits.toFixed(2)} bits (${registrySizeBytes} bytes × ${bitsPerByte}). Within bound.${stagedNote} Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`
      : `BekensteinBound (A7): H(chain)=${chainEntropyBits.toFixed(2)} bits > bound=${boundBits.toFixed(2)} bits — anomalous entropy.${stagedNote} Lean: ${LEAN_THEOREM} @${LEAN_COMMIT.slice(0, 12)}`;

    return { allow, rationale, formula: "BekensteinBound", leanTheorem: LEAN_THEOREM, leanFile: LEAN_FILE, leanCommitSha: LEAN_COMMIT, severity, staged: !enforced, chainEntropyBits, boundBits, withinBound, lambdaScore };
  };
}