> ## Documentation Index
> Fetch the complete documentation index at: https://docs.planeconnection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Record Integrity Anchors Reference

> Technical reference for the 5-layer tamper-evidence system: SHA-384 hash chains, Merkle trees, RFC 3161 trusted timestamping, OpenTimestamps Bitcoin anchoring, and EVM smart contract attestation (RecordAnchor V1 and UniversalAnchor V2).

PlaneConnection's record integrity system uses five independent layers to
provide cryptographically verifiable, tamper-evident records across safety,
maintenance, flight ops, and crew domains. This page documents each layer's
technical specifications, the proof lifecycle states, and the anchoring
orchestration.

For background on the trust model and regulatory motivation, see [Record
Integrity Architecture](/en/explanation/record-integrity-architecture). For
step-by-step verification procedures, see [Verify Record
Integrity](/en/how-to/ops/verify-record-integrity).

## Five-Layer Architecture Summary

| Layer                    | Technology                     | Purpose                           | Confirmation time | Cost         |
| ------------------------ | ------------------------------ | --------------------------------- | ----------------- | ------------ |
| 1. Record hashing        | SHA-384 (Web Crypto)           | Local integrity fingerprint       | Instant           | None         |
| 2. Hash chain            | Linked list with previous-hash | Sequential tamper detection       | Instant           | None         |
| 3. RFC 3161 timestamping | TSA-signed tokens              | Legal-grade temporal proof        | \< 5 seconds      | Bundled      |
| 4. OpenTimestamps        | Bitcoin blockchain anchoring   | Immutable global timestamp        | \~10 minutes      | Free         |
| 5. EVM smart contract    | UniversalAnchor on Polygon     | Programmable on-chain attestation | \~2 seconds       | \~\$0.001/tx |

## Protected Record Types

The integrity system covers 19 record types across four operational domains:

| Domain      | Record type               | Regulatory basis    |
| ----------- | ------------------------- | ------------------- |
| Safety      | Safety reports            | 14 CFR 5.21         |
| Safety      | Investigations            | 14 CFR 5.63         |
| Safety      | Corrective actions (CPAs) | 14 CFR 5.65         |
| Maintenance | Work orders               | 14 CFR 43.9         |
| Maintenance | Inspections               | 14 CFR 91.409       |
| Maintenance | AD/SB compliance          | 14 CFR 39           |
| Maintenance | Discrepancies             | 14 CFR 43.11        |
| Maintenance | MEL deferrals             | 14 CFR 91.213       |
| Maintenance | FAA Form 337              | 14 CFR 43.9(a)      |
| Maintenance | Part install/remove       | 14 CFR 91.417(a)(2) |
| Flight ops  | Flight logs               | 14 CFR 91.417       |
| Flight ops  | eAPIS filings             | 19 CFR 122.49a      |
| Flight ops  | Weight & balance          | 14 CFR 135.63       |
| Flight ops  | FRAT risk assessments     | AC 120-92D          |
| Flight ops  | Dispatch releases         | 14 CFR 135.65       |
| Crew        | Training records          | 14 CFR 135.323      |
| Crew        | Currency checks           | 14 CFR 61.57        |

## Layer 1: Record Hashing

### Algorithm

SHA-384 is the default hash algorithm, selected per CNSA 2.0 (Committee on
National Security Systems Advisory) mandate for post-quantum crypto agility.
SHA-256 is supported for backward compatibility.

| Property        | SHA-384                 | SHA-256                 |
| --------------- | ----------------------- | ----------------------- |
| Digest size     | 48 bytes (96 hex chars) | 32 bytes (64 hex chars) |
| Algorithm ID    | `sha2-384`              | `sha2-256`              |
| Web Crypto name | `SHA-384`               | `SHA-256`               |
| CNSA 2.0 status | Recommended             | Acceptable (legacy)     |

### Canonical Serialization

Before hashing, record data is serialized into a canonical form:

1. All keys are sorted alphabetically.
2. `undefined` values are omitted; `null` values are preserved.
3. The result is JSON-stringified.
4. If the record has a predecessor in the chain, the previous hash is prepended
   with a colon separator: `{previousHash}:{canonicalJSON}`.

```
Input: { technician: "John", type: "inspection", date: "2026-03-15" }
Canonical: {"date":"2026-03-15","technician":"John","type":"inspection"}
With chain: "a1b2c3...previous_hash:{"date":"2026-03-15","technician":"John","type":"inspection"}"
```

### Hash Result

Every hash computation returns both the hex digest and the algorithm identifier,
enabling future algorithm migration without breaking verification:

```typescript theme={}
interface HashResult {
  hash: string; // Lowercase hex-encoded digest
  algorithm: "sha2-384" | "sha2-256";
}
```

## Layer 2: Hash Chain

### Chain Structure

Each aircraft maintains its own hash chain -- a sequential linked list where
every record references the hash of its immediate predecessor.

```
Record 0 (genesis)        Record 1                 Record 2
┌────────────────────┐    ┌────────────────────┐    ┌────────────────────┐
│ previousHash: null │    │ previousHash: H(0) │    │ previousHash: H(1) │
│ chainSequence: 0   │    │ chainSequence: 1   │    │ chainSequence: 2   │
│ recordHash: H(0)   │    │ recordHash: H(1)   │    │ recordHash: H(2)   │
└────────────────────┘    └────────────────────┘    └────────────────────┘
```

### Chain Verification Rules

Chain verification checks three invariants:

1. **Genesis validity:** The first entry (`chainSequence: 0`) must have
   `previousHash: null`.
2. **Sequence contiguity:** Each entry's `chainSequence` must equal
   `previousEntry.chainSequence + 1`.
3. **Hash linkage:** Each entry's `previousHash` must equal the preceding
   entry's `recordHash`.

A break at any position invalidates that record and all subsequent records in
the chain.

### Full Verification

Full verification combines chain verification with individual record
re-hashing:

1. Verify chain linkage (structure).
2. For each record, re-compute the hash from source data and compare to the
   stored `recordHash`.

The result includes the chain length, count of records verified, count of
failures, and the sequence position where the chain first breaks (if any).

### Merkle Tree

For external anchoring, individual record hashes are batched into a binary
Merkle tree using SHA-384:

* Pairs of hashes are concatenated and hashed to produce parent nodes.
* If a level has an odd number of nodes, the last node is duplicated.
* The root of the tree is a single hash representing all records in the batch.

The Merkle root is what gets submitted to RFC 3161, OpenTimestamps, and EVM
anchors, allowing a single anchor transaction to cover many records.

## Layer 3: RFC 3161 Trusted Timestamping

### Protocol

RFC 3161 (IETF) defines the Time-Stamp Protocol (TSP). PlaneConnection builds
DER-encoded TimeStampReq messages and submits them to accredited TSAs over
HTTPS.

### TSA Endpoints

Hashes are submitted to three TSAs in parallel for redundancy:

| TSA      | URL                               | Operator        |
| -------- | --------------------------------- | --------------- |
| DigiCert | `http://timestamp.digicert.com`   | DigiCert Inc.   |
| Sectigo  | `http://timestamp.sectigo.com`    | Sectigo Limited |
| Apple    | `http://timestamp.apple.com/ts01` | Apple Inc.      |

Any single successful response provides sufficient temporal proof. Having
multiple TSAs protects against TSA downtime and provides independent
corroboration.

### TimeStampReq Structure

```
TimeStampReq ::= SEQUENCE {
  version        INTEGER { v1(1) },
  messageImprint SEQUENCE {
    hashAlgorithm  SEQUENCE {
      algorithm      OID (2.16.840.1.101.3.4.2.2 for SHA-384),
      parameters     NULL
    },
    hashedMessage  OCTET STRING (48 bytes for SHA-384)
  },
  certReq        BOOLEAN TRUE
}
```

### Token Structure

```
Time-Stamp Token (CMS SignedData)
├── TSTInfo
│   ├── version
│   ├── policy (TSA's timestamping policy OID)
│   ├── messageImprint
│   │   ├── hashAlgorithm: SHA-384
│   │   └── hashedMessage: <48-byte hash>
│   ├── serialNumber
│   ├── genTime: <UTC timestamp, millisecond precision>
│   ├── nonce
│   └── tsa: <TSA Distinguished Name>
└── SignerInfo (TSA signature over TSTInfo)
```

### Verification

```bash theme={}
openssl ts -verify \
  -in timestamp.tsr \
  -data record_canonical.json \
  -CAfile tsa_ca_chain.pem
```

## Layer 4: OpenTimestamps (Bitcoin Anchoring)

### Protocol

OpenTimestamps aggregates hashes into a Merkle tree and anchors the root in a
Bitcoin transaction's `OP_RETURN` output. This provides the strongest
immutability guarantee -- rewriting a Bitcoin anchor requires controlling 51%
of the Bitcoin network's hash power.

### Calendar Servers

| Calendar | URL                                        |
| -------- | ------------------------------------------ |
| Pool A   | `https://a.pool.opentimestamps.org`        |
| Pool B   | `https://b.pool.opentimestamps.org`        |
| Finney   | `https://finney.calendar.eternitywall.com` |

### Digest Requirements

OTS calendars require exactly 32-byte (SHA-256) digests. When the record
uses SHA-384, the hex string is first re-hashed with SHA-256 to produce
the required 32 bytes before submission.

### Proof Lifecycle

1. **Submission:** Digest bytes are POSTed to `/digest` on the calendar server.
2. **Pending proof:** The calendar returns an incomplete proof file containing
   the calendar commitment. Stored with status `pending`.
3. **Upgrade:** A background process polls the calendar server to upgrade
   pending proofs once the Bitcoin block is confirmed (typically 10--60 minutes).
4. **Complete proof:** The upgraded proof contains the full Merkle path from
   the record hash to the Bitcoin block header. Status becomes `confirmed`.

### Verification

```bash theme={}
pip install opentimestamps-client
ots verify record_canonical.json.ots -f record_canonical.json
```

Or verify online at [opentimestamps.org](https://opentimestamps.org).

## Layer 5: EVM Smart Contract

PlaneConnection has deployed two generations of anchor contracts. Both are live
and referenced by existing proofs.

### RecordAnchor V1

The original anchor contract -- a minimal Solidity contract that stores bytes32
Merkle roots with timestamps. No access control; gas cost is the economic gate.

```solidity theme={}
contract RecordAnchor {
  struct Anchor {
    bytes32 merkleRoot;
    uint256 timestamp;
    address sender;
  }

  mapping(bytes32 => Anchor) public anchors;

  event Anchored(
    bytes32 indexed merkleRoot,
    address indexed sender,
    uint256 timestamp
  );

  function anchor(bytes32 merkleRoot) external {
    anchors[merkleRoot] = Anchor(merkleRoot, block.timestamp, msg.sender);
    emit Anchored(merkleRoot, msg.sender, block.timestamp);
  }

  function getAnchor(bytes32 merkleRoot)
    external view returns (Anchor memory)
  {
    return anchors[merkleRoot];
  }
}
```

### UniversalAnchor V2

The current-generation anchor contract extends V1 with batch anchoring,
workspace and record-type scoping, access control, and an emergency pause
mechanism.

**Key features:**

* **Batch anchoring.** Anchor hundreds of Merkle roots in a single transaction,
  dramatically reducing gas costs for high-volume operators.
* **Workspace scoping.** Each anchor is associated with a workspace identifier,
  enabling efficient per-operator querying and audit filtering.
* **Record-type classification.** Anchors carry a record-type tag (e.g.,
  `safety_report`, `work_order`, `flight_log`), enabling domain-specific
  verification queries.
* **Ownable access control.** Only authorized addresses can submit anchors,
  preventing unauthorized writes.
* **Pausable emergency stop.** The contract owner can pause anchoring in an
  emergency without redeploying, then resume when the issue is resolved.

### Gas Cost Comparison

| Operation          | Approximate cost | Records covered |
| ------------------ | ---------------- | --------------- |
| Single anchor (V1) | \~\$0.001        | 1               |
| Single anchor (V2) | \~\$0.001        | 1               |
| Batch of 10 (V2)   | \~\$0.008        | 10              |
| Batch of 100 (V2)  | \~\$0.075        | 100             |

<Tip>
  Batch anchoring means a busy Part 135 operation generating dozens of records per day can anchor
  them all for less than a penny per record. The per-record cost decreases as batch size increases.
</Tip>

### Deployed Addresses

| Contract           | Network                | Chain ID | Address                                      | Explorer                                                                                       |
| ------------------ | ---------------------- | -------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| RecordAnchor V1    | Polygon Amoy (testnet) | 80002    | `0x86007a431A521792D4Bf459B81E85a2a85Dad627` | [PolygonScan](https://amoy.polygonscan.com/address/0x86007a431A521792D4Bf459B81E85a2a85Dad627) |
| UniversalAnchor V2 | Polygon Amoy (testnet) | 80002    | `0xcE42455d789624d509206FF844Ef3afCD8Ef34b8` | [PolygonScan](https://amoy.polygonscan.com/address/0xcE42455d789624d509206FF844Ef3afCD8Ef34b8) |
| UniversalAnchor V2 | Ethereum Sepolia       | --       | Planned                                      | --                                                                                             |
| UniversalAnchor V2 | Polygon mainnet        | 137      | Planned                                      | --                                                                                             |

### Transaction Flow

1. Record hashes are batched into a Merkle tree and the root is computed.
2. For V1: the root (padded to bytes32) is submitted as a single anchor call.
3. For V2: one or more roots are submitted in a batch call with workspace and
   record-type metadata.
4. The transaction is confirmed with 1 block confirmation (60-second timeout).
5. The transaction hash, block number, and gas used are stored alongside the
   records.

### Verification

**Block explorer:** Search the transaction hash on
[PolygonScan (Amoy)](https://amoy.polygonscan.com). The `Anchored` event log
shows the Merkle root, sender, and block timestamp. For V2 batch transactions,
each root in the batch emits a separate event with its workspace and record-type
tags.

**Programmatic:** Query the contract's `getAnchor` function (V1) or
`getAnchor` with workspace filtering (V2) using any Ethereum-compatible client
library. The returned struct contains the Merkle root, timestamp, and sender
address.

## Anchor Orchestrator

The anchor orchestrator coordinates all three external layers in parallel.
A failure in one layer does not block the others.

### Strategies

| Strategy       | Layers activated                          |
| -------------- | ----------------------------------------- |
| `full`         | RFC 3161 + OpenTimestamps + EVM (default) |
| `rfc3161-only` | RFC 3161 only                             |
| `ots-only`     | OpenTimestamps only                       |
| `evm-only`     | EVM only                                  |

Individual layers can also be skipped regardless of strategy.

### Result

The orchestrator returns a result containing:

* The Merkle root that was anchored.
* The hash algorithm used.
* An array of layer results (one per activated layer), each with
  success/failure status and layer-specific tokens, proofs, or transaction data.
* The `anchoredAt` timestamp.
* A flag indicating whether every activated layer succeeded.

## Proof Lifecycle States

| State         | Description                                                                                                |
| ------------- | ---------------------------------------------------------------------------------------------------------- |
| **Pending**   | Anchor request submitted but confirmation not yet received.                                                |
| **Anchored**  | Anchor accepted by external system (TSA signed, OTS calendar committed, EVM tx submitted).                 |
| **Confirmed** | Sufficient confirmations received (RFC 3161: immediate; OTS: Bitcoin block mined; EVM: 1 block).           |
| **Verified**  | Independently verified by PlaneConnection's cross-layer verification service.                              |
| **Expired**   | Anchor no longer actively verifiable (e.g., TSA certificate chain expired). Historical validity preserved. |
| **Failed**    | Anchor submission failed and could not be retried. Record is still protected by other layers.              |

### State Transitions

```
              ┌──────────┐
  [Record     │          │
   saved]────►│ Pending  │
              │          │
              └─────┬────┘
                    │ anchor accepted
                    ▼
              ┌──────────┐
              │ Anchored │
              └─────┬────┘
                    │ confirmations received
                    ▼
              ┌──────────┐
              │Confirmed │
              └─────┬────┘
                    │ verification service confirms
                    ▼
              ┌──────────┐         ┌─────────┐
              │ Verified │────────►│ Expired │
              └──────────┘  cert   └─────────┘
                            expiry
```

## Cross-Layer Verification

A periodic verification process compares the canonical record hash against
hashes stored in each anchor layer. If any layer's hash disagrees with the
base hash, the record is flagged as inconsistent and a tamper alert is
generated.

The check processes up to 500 anchored records per run. Records without any
anchor layers are skipped. The result includes counts of checked, consistent,
and inconsistent records, plus human-readable alerts for each discrepancy.

## Proof Bundle Contents

When you export a proof bundle from PlaneConnection, it contains the following
for each included record:

| Component                | RFC 3161 | OTS | EVM |
| ------------------------ | :------: | :-: | :-: |
| Record canonical JSON    |    Yes   | Yes | Yes |
| SHA-384 hash             |    Yes   | Yes | Yes |
| Hash chain position      |    Yes   | Yes | Yes |
| RFC 3161 TST (DER bytes) |    Yes   |  No |  No |
| TSA certificate chain    |    Yes   |  No |  No |
| OTS proof file           |    No    | Yes |  No |
| Bitcoin block header     |    No    | Yes |  No |
| EVM transaction hash     |    No    |  No | Yes |
| Contract address         |    No    |  No | Yes |

## Related

<CardGroup cols={2}>
  <Card title="Record Integrity Architecture" href="/explanation/record-integrity-architecture">
    Why five layers, regulatory context, and trust model design.
  </Card>

  <Card title="Verify Record Integrity" href="/how-to/ops/verify-record-integrity">
    Step-by-step verification and proof bundle export guide.
  </Card>

  <Card title="Manage Work Orders" href="/how-to/ops/manage-work-orders">
    Work orders that generate records added to the hash chain.
  </Card>

  <Card title="Notification Channels" href="/reference/notification-channels">
    Alert configuration for hash chain break notifications.
  </Card>
</CardGroup>
