Rust and WASM did-method-plc tools and structures
README.md

AT Protocol PLC Command-Line Tools#

Command-line tools for working with AT Protocol PLC (Public Ledger of Credentials) DIDs.

Tools#

plc-audit: DID Audit Log Validator#

Validates the cryptographic integrity of a DID's audit log from plc.directory.

Features#

  • ๐Ÿ” Fetch Audit Logs: Retrieves complete operation history from plc.directory
  • ๐Ÿ” Cryptographic Validation: Verifies all signatures using rotation keys
  • ๐Ÿ”— Chain Verification: Validates operation chain linkage (prev references)
  • ๐Ÿ“Š Detailed Output: Shows operation history and final DID state
  • โšก Fast & Reliable: Built with Rust for performance and safety

Usage#

# Basic validation
cargo run --bin plc-audit --features cli -- did:plc:z72i7hdynmk6r22z27h6tvur

# Verbose mode (show all operations)
cargo run --bin plc-audit --features cli -- did:plc:z72i7hdynmk6r22z27h6tvur --verbose

# Quiet mode (VALID/INVALID only)
cargo run --bin plc-audit --features cli -- did:plc:z72i7hdynmk6r22z27h6tvur --quiet

# Custom PLC directory
cargo run --bin plc-audit --features cli -- did:plc:example --plc-url https://custom.plc.directory

plc-fork-viz: Fork Visualizer#

Visualizes forks in a DID's operation chain, showing which operations won/lost based on rotation key priority and the 72-hour recovery window.

Features#

  • ๐Ÿ”€ Fork Detection: Identifies competing operations in the chain
  • ๐Ÿ” Priority Analysis: Determines which rotation key signed each operation
  • โฑ๏ธ Recovery Window: Applies 72-hour recovery window rules
  • ๐Ÿ“Š Multiple Formats: Tree, JSON, and Markdown visualization
  • ๐ŸŽจ Color Coding: Green for canonical operations, red for rejected

Usage#

# Basic fork visualization
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz

# Verbose mode (detailed operation info)
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz --verbose

# Show timestamps and recovery window calculations
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz --timing

# Show full DIDs/CIDs
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz --full-ids

# Output as JSON
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz --format json

# Output as Markdown
cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz --format markdown

Output Formats#

Tree Format (default):

Fork at operation referencing bafyre...abc123
  โ”œโ”€ ๐Ÿ”ด โœ— CID: bafyre...def456
  โ”‚  Signed by: rotation_key[1]
  โ”‚  Reason: Invalidated by higher-priority key[0] within recovery window
  โ””โ”€ ๐ŸŸข โœ“ CID: bafyre...ghi789
     Signed by: rotation_key[0]
     Status: CANONICAL (winner)

JSON Format:

[
  {
    "prev_cid": "bafyre...",
    "winner_cid": "bafyre...",
    "operations": [...]
  }
]

Markdown Format:

Status CID Key Index Timestamp Reason
โœ… Winner bafyre...ghi789 0 2025-01-15 14:30:00 Canonical operation
โŒ Rejected bafyre...def456 1 2025-01-15 10:00:00 Invalidated by higher-priority key[0]

Fork Resolution Rules#

  1. Rotation Key Priority: Keys are ordered by array index (0 = highest priority)
  2. Recovery Window: 72 hours from the first operation's timestamp
  3. First-Received Default: The operation received first wins unless invalidated
  4. Higher Priority Override: A higher-priority key can invalidate if:
    • It arrives within 72 hours
    • Its key index is lower (e.g., key[0] beats key[1])

Example: No Forks#

$ cargo run --bin plc-fork-viz --features cli -- did:plc:ewvi7nxzyoun6zhxrhs64oiz

๐Ÿ” Analyzing forks in: did:plc:ewvi7nxzyoun6zhxrhs64oiz
   Source: https://plc.directory

๐Ÿ“Š Audit log contains 5 operations

โœ… No forks detected - this is a linear operation chain
   All operations form a single canonical path from genesis to tip.

Example: Fork Detected#

$ cargo run --bin plc-fork-viz --features cli -- did:plc:z7x2k3j4m5n6 --timing

๐Ÿ” Analyzing forks in: did:plc:z7x2k3j4m5n6
   Source: https://plc.directory

๐Ÿ“Š Audit log contains 8 operations
โš ๏ธ  Detected 1 fork point(s)

๐Ÿ“Š Fork Visualization (Tree Format)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Fork at operation referencing bafyre...abc123
  โ”œโ”€ ๐Ÿ”ด โœ— CID: bafyre...def456
     โ”‚  Signed by: rotation_key[1]
     โ”‚  Timestamp: 2025-01-15 10:00:00 UTC
     โ”‚  Reason: Invalidated by higher-priority key[0] within recovery window
     โ”‚
  โ””โ”€ ๐ŸŸข โœ“ CID: bafyre...ghi789
     โ”‚  Signed by: rotation_key[0]
     โ”‚  Timestamp: 2025-01-15 14:00:00 UTC
     โ”‚  Status: CANONICAL (winner)

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๐Ÿ“ˆ Summary:
   Total operations: 8
   Fork points: 1
   Rejected operations: 1

๐Ÿ” Fork Resolution Details:
   Fork 1: Winner is bafyre...ghi789 (signed by key[0])

Building & Installation#

Build Both Tools#

cargo build --bins --features cli --release

Install to ~/.cargo/bin#

cargo install --path . --features cli

Then use directly:

plc-audit did:plc:ewvi7nxzyoun6zhxrhs64oiz
plc-fork-viz did:plc:ewvi7nxzyoun6zhxrhs64oiz

Common Workflows#

Workflow 1: Validate and Check for Forks#

# First validate the audit log
$ plc-audit did:plc:ewvi7nxzyoun6zhxrhs64oiz
โœ… Validation successful!

# Then check for forks
$ plc-fork-viz did:plc:ewvi7nxzyoun6zhxrhs64oiz

Workflow 2: Export Fork Data#

# Export as JSON for analysis
$ plc-fork-viz did:plc:ewvi7nxzyoun6zhxrhs64oiz --format json > forks.json

# Generate Markdown report
$ plc-fork-viz did:plc:ewvi7nxzyoun6zhxrhs64oiz --format markdown > FORK_REPORT.md

Workflow 3: Monitor DIDs#

#!/bin/bash
# Monitor a DID for changes and forks
DID="did:plc:ewvi7nxzyoun6zhxrhs64oiz"

# Validate
if plc-audit $DID --quiet; then
  echo "โœ… DID is valid"

  # Check for forks
  plc-fork-viz $DID --format json > /tmp/forks.json

  if [ -s /tmp/forks.json ]; then
    echo "โš ๏ธ Forks detected!"
    plc-fork-viz $DID
  fi
else
  echo "โŒ DID validation failed!"
  exit 1
fi

Understanding Fork Visualization#

Symbols#

  • ๐ŸŒฑ Genesis operation (creates the DID)
  • ๐ŸŸข โœ“ Canonical operation (winner)
  • ๐Ÿ”ด โœ— Rejected operation (lost the fork)
  • โ”œโ”€ Fork branch (more operations follow)
  • โ””โ”€ Final fork branch

Rejection Reasons#

  1. "Invalidated by higher-priority key[N] within recovery window"

    • A higher-priority rotation key signed a competing operation within 72 hours
  2. "Higher-priority key[N] but outside 72-hour recovery window (X hours late)"

    • A higher-priority key tried to invalidate but arrived too late
  3. "Lower-priority key[N] (current winner has key[M])"

    • This operation was signed by a lower-priority key and can't override

Troubleshooting#

Error: "Invalid DID format"#

DID must follow format: did:plc:<24 lowercase base32 characters>

Error: "Failed to fetch audit log"#

  • Check internet connection
  • Verify DID exists on plc.directory
  • Try --plc-url for custom PLC directories

No forks detected but expected#

  • The DID may have a linear operation chain
  • All operations were submitted sequentially without conflicts

Technical Details#

plc-audit validates:

  1. DID format (prefix, length, base32 encoding)
  2. Chain linkage (prev references)
  3. Cryptographic signatures (ECDSA with P-256/secp256k1)
  4. State consistency

plc-fork-viz implements:

  1. Fork detection (multiple operations with same prev CID)
  2. Rotation key index resolution
  3. Priority-based fork resolution
  4. 72-hour recovery window enforcement

Both tools use:

  • reqwest for HTTP requests
  • atproto-plc library for cryptographic operations
  • clap for command-line parsing

See Also#


License#

Dual-licensed under MIT or Apache-2.0, same as the parent library.