# PolitiMind Transparency Log — Encoding Rule

**Version:** `pm-tlog@1.0.0`  
**Status:** Normative  
**Canonical URL:** `https://politimind.com/transparency/rule/v1`  
**Audience:** Anyone who wants to check our work without trusting us.

---

## Why this document exists

A transparency log that only its operator can interpret is not a transparency log. It is a claim with extra steps.

This rule defines the byte-level procedure required to independently recompute PolitiMind transparency-log leaf preimages, RFC 6962 Merkle roots, inclusion proofs, and the versioned commitment expected in an on-chain epoch anchor. It is intentionally public and implementation-independent.

**This document is immutable for version `pm-tlog@1.0.0`.** Any change to canonicalization, leaf encoding, tree construction, proof semantics, or the anchor-commitment binding requires a new version and a new public document. Historical epochs remain bound to the rule version recorded when they were produced.

---

## 1. What may be committed

Four claim families share one transparency tree:

| Leaf type | Commitment purpose |
|---|---|
| `identity_commitment` | commit to a privacy-preserving uniqueness/verification artifact |
| `poll_preregistration` | commit to a poll design/methodology artifact before fielding |
| `response_receipt` | commit to a privacy-preserving response receipt artifact |
| `result_run` | commit to a specific result-run artifact and its lineage |

**Never place PII in a leaf preimage.** Personal information, biometric data or templates, email addresses, IP addresses, raw identity-provider identifiers, raw response text, and other directly identifying material must remain outside the public transparency log. Leaves carry content hashes/commitments and public verification metadata only.

The presence of a leaf proves only that the encoded commitment was included in the tree represented by a verified root. The meaning of that commitment depends on the separately published schema for that leaf type.

---

## 2. Canonical JSON serialization

Payload hashes are SHA-256 over a deterministic JSON serialization produced by the following rules:

1. Object keys are sorted lexicographically by UTF-16 code unit at every depth.
2. Array order is preserved exactly.
3. `undefined` object properties are omitted.
4. `undefined` array elements become `null`, preserving array length.
5. Numbers use `JSON.stringify` semantics, except `-0` is normalized to `0`.
6. `NaN`, positive infinity, and negative infinity are rejected.
7. No insignificant whitespace is emitted.
8. The resulting string is encoded as UTF-8.
9. Payload hash = SHA-256 of those UTF-8 bytes, encoded as lowercase hexadecimal.

Reference implementation: `src/lib/transparency/canonicalize.ts`.

---

## 3. Leaf preimage and domain separation

The exact leaf preimage is:

```text
RULE_VERSION ‖ US ‖ leafType ‖ US ‖ vrfIndex ‖ US ‖ revision ‖ US ‖ leafState ‖ US ‖ payloadHash
```

where:

- `RULE_VERSION` = `pm-tlog@1.0.0`
- `US` = U+001F (ASCII Unit Separator, byte `0x1f` in UTF-8)
- `leafType` is one of:
  - `identity_commitment`
  - `poll_preregistration`
  - `response_receipt`
  - `result_run`
- `vrfIndex` = lowercase hexadecimal VRF output associated with the logical label
- `revision` = non-negative base-10 integer
- `leafState` = `active` or `obsolete`
- `payloadHash` = lowercase hexadecimal SHA-256 payload hash

The complete preimage is UTF-8 encoded before RFC 6962 leaf hashing.

`leafType` is inside the committed preimage. This domain separation prevents a valid inclusion proof for one claim family from being reinterpreted as a different claim family.

---

## 4. RFC 6962 Merkle tree

PolitiMind uses the Certificate Transparency Merkle Tree Hash construction rather than duplicate-last-node tree logic.

```text
MTH({})     = SHA-256("")
MTH({d0})   = SHA-256(0x00 ‖ d0)
MTH(D[n])   = SHA-256(0x01 ‖ MTH(D[0:k]) ‖ MTH(D[k:n]))
```

For `n > 1`, `k` is the largest power of two strictly less than `n`.

- Leaf hash prefix: `0x00`
- Internal node prefix: `0x01`

These prefixes separate leaf and internal-node hash domains. The RFC 6962 split rule also avoids the duplicate-last-node ambiguity in which distinct leaf sets can otherwise share a root.

Reference implementation: `src/lib/transparency/merkle.ts`.

---

## 5. Inclusion proofs

An inclusion proof is an ordered bottom-up audit path. Each entry contains:

- `hash`: lowercase 32-byte hexadecimal sibling hash
- `isLeft`: boolean indicating whether the sibling is left of the running accumulator

Verification begins with `SHA-256(0x00 ‖ leafPreimageBytes)` and applies each proof step using `SHA-256(0x01 ‖ left ‖ right)`. Verification succeeds only when the final accumulator equals the published epoch root exactly.

A proof that succeeds against one root says nothing about another root, another leaf type, or another rule version.

---

## 6. Revisions and obsolescence

The transparency log is append-only. Existing committed leaves are not edited in place.

When a logical commitment is superseded, a later revision is appended. Where an artifact must be retired, a later revision may use `leafState = "obsolete"`. The historical commitment remains part of the historical tree; the newer revision communicates current state without rewriting prior roots.

Obsolescence is not a substitute for deletion of underlying private data. Private-data deletion/retention is governed separately by PolitiMind privacy controls.

---

## 7. VRF indexing

`vrfIndex` provides a deterministic, cryptographically derived index for a logical label without exposing the underlying private identifier in the public leaf preimage.

VRF-based placement can make placement rules independently auditable when the corresponding VRF proof and public key are published. **VRF indexing does not by itself prove that every eligible record was submitted to the log.** Completeness requires the separately defined production ingestion, result-run, and publication controls.

---

## 8. Epochs

An epoch groups a finite ordered set of encoded leaves into one RFC 6962 root.

Public epoch metadata must include at minimum:

- epoch number
- Merkle root
- tree size
- encoding rule version
- previous epoch root, or a genesis marker for the first epoch
- anchor-interface version when an on-chain anchor is attempted
- transaction/chain metadata once an anchor is confirmed

Every epoch must record the exact `encoding_rule_version` that generated it. An implementation must refuse to create a production anchor for an encoding-rule version that is not publicly available at its stable versioned URL.

---

## 9. On-chain anchor commitment — `pm-anchor@1.0.0`

The v1 verifier binds an epoch to a precise 32-byte on-chain commitment. The anchor preimage is:

```text
ANCHOR_INTERFACE_VERSION ‖ US ‖ epochNumber ‖ US ‖ merkleRoot ‖ US ‖ encodingRuleVersion ‖ US ‖ previousEpochRoot
```

where:

- `ANCHOR_INTERFACE_VERSION` = `pm-anchor@1.0.0`
- `US` = U+001F
- `epochNumber` = non-negative base-10 integer
- `merkleRoot` = lowercase 32-byte hex without `0x`
- `encodingRuleVersion` = `pm-tlog@1.0.0`
- `previousEpochRoot` = lowercase 32-byte hex without `0x`, or literal `genesis` for the first epoch

The bytes are UTF-8 encoded and SHA-256 hashed:

```text
anchorCommitment = SHA-256(anchorPreimageBytes)
```

The expected EVM call is the standard `commit(bytes32)` interface:

```text
function signature: commit(bytes32)
function selector:  0xf14fcbc8
calldata:           0xf14fcbc8 ‖ anchorCommitment
```

A production verifier must require the transaction input to equal that exact selector plus that exact 32-byte argument. Merely finding the Merkle root or commitment as a substring in unrelated calldata is not a valid anchor proof.

Full chain verification additionally requires:

1. expected Base chain ID matches the RPC chain ID;
2. transaction exists;
3. receipt exists and reports success;
4. transaction destination equals the independently configured/versioned PolitiMind anchor contract;
5. the anchor block has the configured minimum confirmation depth;
6. the exact `commit(bytes32)` argument equals the recomputed epoch anchor commitment;
7. epoch metadata uses the expected encoding-rule and anchor-interface versions.

The actual PolitiMind anchor contract address, deployment environment, review record, and upgrade history are versioned release metadata and are not invented by this encoding rule.

---

## 10. Independent verifier

Reference distribution artifact:

```text
verifier/politimind-verify.mjs
```

Supported commands:

```bash
node verifier/politimind-verify.mjs receipt <receiptHash>
node verifier/politimind-verify.mjs poll <pollId>
node verifier/politimind-verify.mjs epoch <epochNumber>
node verifier/politimind-verify.mjs selftest
```

Full chain verification additionally accepts independently supplied RPC/contract configuration:

```bash
--rpc <base-rpc-url>
--contract <expected-anchor-contract>
--chainId <decimal-chain-id>
--confirmations <minimum-confirmations>
```

Verifier status semantics are:

- `PASS` / exit `0`: requested proof, including every required layer for that invocation, verified.
- `FAIL` / exit `1`: a cryptographic, metadata, contract, chain, or confirmation check failed.
- `PARTIAL` / exit `2`: inclusion may be valid, but required independent chain/anchor inputs or published metadata are unavailable; no full anchor claim is made.

Usage error is exit `64`; unexpected verifier software failure is exit `70`.

---

## 11. What this does and does not prove

Honesty about limits is part of the protocol.

### When the corresponding artifacts exist and verification succeeds, this protocol can prove

- that a specific encoded commitment was included in a specific epoch tree;
- that a published epoch root is consistent with the supplied leaf and inclusion proof;
- that two independently implemented encoders/tree verifiers agree on the same deterministic rule;
- that an on-chain transaction to the expected anchor contract committed the exact versioned epoch commitment, when full anchor verification returns `PASS`;
- that later publication of a different artifact cannot silently change the bytes committed by an earlier verified root.

### This protocol does not prove

- that a participant answered honestly;
- that a participant is representative of a target population;
- that every eligible record was submitted to the log;
- that a sampling or weighting methodology is statistically correct;
- that a factual premise in a poll question is true;
- that identity verification itself was error-free;
- that PolitiMind is trustworthy in general.

Those are separate identity, methodology, completeness, governance, and operational claims. Cryptography can make specific commitments checkable; it cannot turn an unsupported claim into a true one.

---

## 12. Versioning and publication rule

`pm-tlog@1.0.0` is immutable once published at its canonical URL. A breaking change requires a new rule identifier and a new stable URL. Historical verifier releases must remain capable of applying the historical rule to historical epochs.

**No production epoch may be anchored under `pm-tlog@1.0.0` until this exact normative artifact is publicly fetchable at `https://politimind.com/transparency/rule/v1`.**
