localgreenchain/docs/architecture/transport-tracking.md
Claude 4111c3acf1
Add complete documentation suite for LocalGreenChain
- Add guides: quick-start, installation, configuration, grower, consumer, transport, vertical-farm
- Add API references: REST, demand, vertical-farming
- Add concepts: blockchain, seasonal-planning, carbon-footprint
- Add architecture: data-flow, transport-tracking
- Add vertical-farming: environmental-control, automation, integration
- Add examples: seed-to-harvest, demand-driven-planting, vertical-farm-setup

Completes Agent_5 documentation tasks from AGENT_REPORT.md
2025-11-22 18:48:42 +00:00

15 KiB
Raw Permalink Blame History

Transport Tracking Architecture

Deep dive into the seed-to-seed transport tracking system.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                    TRANSPORT TRACKING SYSTEM                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                      TRANSPORT CHAIN                         │   │
│  │                                                               │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐        │   │
│  │  │Genesis  │→ │ Block 1 │→ │ Block 2 │→ │ Block N │        │   │
│  │  │         │  │ Seed    │  │ Plant   │  │ Harvest │        │   │
│  │  │         │  │ Acquire │  │         │  │         │        │   │
│  │  └─────────┘  └─────────┘  └─────────┘  └─────────┘        │   │
│  │                                                               │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│           ┌──────────────────┼──────────────────┐                   │
│           ▼                  ▼                  ▼                   │
│  ┌────────────────┐  ┌──────────────┐  ┌───────────────┐           │
│  │  Event Index   │  │ Plant Index  │  │  Batch Index  │           │
│  │  (by event ID) │  │ (by plant ID)│  │ (by batch ID) │           │
│  └────────────────┘  └──────────────┘  └───────────────┘           │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                      SERVICES                                 │   │
│  │                                                               │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐         │   │
│  │  │Distance │  │ Carbon  │  │   QR    │  │ Journey │         │   │
│  │  │Calculator│  │Calculator│  │Generator│  │ Builder │         │   │
│  │  └─────────┘  └─────────┘  └─────────┘  └─────────┘         │   │
│  │                                                               │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

TransportChain Class

Core Structure

class TransportChain {
  // Blockchain data
  public chain: TransportBlock[];
  public difficulty: number;

  // Indexes for fast lookups
  private eventIndex: Map<string, TransportBlock[]>;
  private plantEvents: Map<string, TransportEvent[]>;
  private batchEvents: Map<string, TransportEvent[]>;

  // Core operations
  recordEvent(event: TransportEvent): TransportBlock;
  getPlantJourney(plantId: string): PlantJourney | null;
  getEnvironmentalImpact(userId: string): EnvironmentalImpact;
  generateQRData(plantId?: string, batchId?: string): TransportQRData;
  isChainValid(): boolean;
}

Block Creation Flow

Event Input
     │
     ▼
┌─────────────────────┐
│ Calculate Distance  │ (if not provided)
│ Haversine Formula   │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Calculate Carbon    │ (if not provided)
│ factor × distance   │ × weight
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Create Block        │
│ - index             │
│ - timestamp         │
│ - event data        │
│ - previousHash      │
│ - cumulative stats  │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Mine Block          │
│ Find nonce where    │
│ hash starts with    │
│ N zeros             │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Add to Chain        │
│ Update Indexes      │
└──────────┬──────────┘
           │
           ▼
     Return Block

Event Processing

Event Type Handlers

Each event type extracts different IDs for indexing:

function extractPlantIds(event: TransportEvent): string[] {
  switch (event.eventType) {
    case 'planting':
      return event.plantIds;

    case 'growing_transport':
      return event.plantIds;

    case 'harvest':
      return event.plantIds;

    case 'seed_saving':
      return event.parentPlantIds;

    default:
      return [];
  }
}

function extractBatchIds(event: TransportEvent): string[] {
  switch (event.eventType) {
    case 'seed_acquisition':
      return [event.seedBatchId];

    case 'planting':
      return [event.seedBatchId];

    case 'harvest':
      const ids = [event.harvestBatchId];
      if (event.seedBatchIdCreated) ids.push(event.seedBatchIdCreated);
      return ids;

    case 'processing':
      return [...event.harvestBatchIds, event.processingBatchId];

    case 'distribution':
    case 'consumer_delivery':
      return event.batchIds;

    case 'seed_saving':
      return [event.newSeedBatchId];

    case 'seed_sharing':
      return [event.seedBatchId];

    default:
      return [];
  }
}

Distance Calculation

Haversine Formula

static calculateDistance(
  from: TransportLocation,
  to: TransportLocation
): number {
  const R = 6371; // Earth's radius in km

  const dLat = toRadians(to.latitude - from.latitude);
  const dLon = toRadians(to.longitude - from.longitude);

  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRadians(from.latitude)) *
    Math.cos(toRadians(to.latitude)) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);

  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return R * c; // Distance in kilometers
}

Accuracy Notes

Distance Accuracy
< 10 km ± 10 meters
10-100 km ± 100 meters
100-1000 km ± 1 km
> 1000 km ± 10 km

Carbon Calculation

Weight Estimation

function estimateWeight(event: TransportEvent): number {
  switch (event.eventType) {
    case 'seed_acquisition':
    case 'seed_saving':
    case 'seed_sharing':
      return 0.1;  // Seeds are light

    case 'planting':
      return 0.5;  // Seedlings

    case 'growing_transport':
      return 2;    // Potted plants

    case 'harvest':
      return event.netWeight || 5;

    case 'processing':
      return event.outputWeight || 5;

    case 'distribution':
    case 'consumer_delivery':
      return 5;    // Default produce weight

    default:
      return 1;
  }
}

Carbon Formula

function calculateCarbon(
  method: TransportMethod,
  distanceKm: number,
  weightKg: number
): number {
  const factor = CARBON_FACTORS[method] || 0.1;
  return factor * distanceKm * weightKg;
}

Journey Reconstruction

Algorithm

function getPlantJourney(plantId: string): PlantJourney | null {
  // 1. Get all events for this plant
  const events = plantEvents.get(plantId);
  if (!events || events.length === 0) return null;

  // 2. Sort by timestamp
  const sorted = [...events].sort(
    (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
  );

  // 3. Calculate totals
  let totalFoodMiles = 0;
  let totalCarbonKg = 0;
  let daysInTransit = 0;

  for (const event of sorted) {
    totalFoodMiles += event.distanceKm;
    totalCarbonKg += event.carbonFootprintKg;
    daysInTransit += event.durationMinutes / (60 * 24);
  }

  // 4. Determine current stage
  const currentStage = determineStage(sorted);

  // 5. Find lineage info
  const seedAcquisition = sorted.find(e => e.eventType === 'seed_acquisition');
  const planting = sorted.find(e => e.eventType === 'planting');

  // 6. Build journey object
  return {
    plantId,
    seedBatchOrigin: seedAcquisition?.seedBatchId || planting?.seedBatchId,
    currentCustodian: sorted[sorted.length - 1].receiverId,
    currentLocation: sorted[sorted.length - 1].toLocation,
    currentStage,
    events: sorted,
    totalFoodMiles,
    totalCarbonKg,
    daysInTransit: Math.round(daysInTransit),
    daysGrowing: calculateGrowingDays(sorted),
    generation: seedAcquisition?.generation || 0,
    ancestorPlantIds: seedAcquisition?.parentPlantIds || [],
    descendantSeedBatches: findDescendantSeeds(sorted)
  };
}

QR Code Generation

Data Structure

interface TransportQRData {
  plantId?: string;
  batchId?: string;
  blockchainAddress: string;   // First 42 chars of latest hash
  quickLookupUrl: string;      // Web URL for tracking
  lineageHash: string;         // SHA256 of all events (16 chars)
  currentCustodian: string;    // Current holder
  lastEventType: TransportEventType;
  lastEventTimestamp: string;
  verificationCode: string;    // Random 8-char code
}

Generation Process

┌─────────────────────┐
│ Get events for      │
│ plant/batch         │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Calculate lineage   │
│ hash (SHA256)       │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Get blockchain      │
│ address (latest     │
│ block hash)         │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Generate            │
│ verification code   │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────┐
│ Build QR data       │
│ object              │
└──────────┬──────────┘
           │
           ▼
    Return QRData

Chain Validation

Validation Checks

function isChainValid(): boolean {
  for (let i = 1; i < chain.length; i++) {
    const current = chain[i];
    const previous = chain[i - 1];

    // Check 1: Hash integrity
    const expectedHash = calculateHash(
      current.index,
      current.timestamp,
      current.transportEvent,
      current.previousHash,
      current.nonce
    );
    if (current.hash !== expectedHash) {
      return false;  // Hash has been tampered
    }

    // Check 2: Chain linkage
    if (current.previousHash !== previous.hash) {
      return false;  // Chain is broken
    }

    // Check 3: Proof of work
    const target = '0'.repeat(difficulty);
    if (current.hash.substring(0, difficulty) !== target) {
      return false;  // PoW not satisfied
    }
  }

  return true;
}

Storage and Persistence

Export Format

{
  "difficulty": 3,
  "chain": [
    {
      "index": 0,
      "timestamp": "2024-01-01T00:00:00Z",
      "transportEvent": { ... },
      "previousHash": "0",
      "hash": "000abc...",
      "nonce": 12345,
      "cumulativeCarbonKg": 0,
      "cumulativeFoodMiles": 0,
      "chainLength": 1
    }
  ]
}

Import Process

static fromJSON(data: any): TransportChain {
  const chain = new TransportChain(data.difficulty);
  chain.chain = data.chain;

  // Rebuild indexes from chain
  for (const block of chain.chain) {
    chain.indexEvent(block.transportEvent, block);
  }

  return chain;
}

Performance Optimization

Indexing Strategy

Index Use Case Complexity
eventIndex Event lookup by ID O(1)
plantEvents Plant journey O(1)
batchEvents Batch tracking O(1)

Mining Optimization

// Parallel mining hint (future)
// Can be parallelized across CPU cores
function mineBlockParallel(block: TransportBlock): void {
  const workers = os.cpus().length;
  const ranges = divideNonceRange(0, MAX_NONCE, workers);

  // Each worker tries nonces in its range
  // First to find valid hash wins
}

Integration Points

With Plant Blockchain

Transport Chain                  Plant Chain
──────────────                  ───────────
plantIds in events  ←─────────→  plantId in registrations
harvestBatchId      ←─────────→  linked to plant
seedBatchId         ←─────────→  lineage reference

With Vertical Farm Controller

VF Controller                   Transport Chain
─────────────                   ───────────────
startCropBatch()   ─creates─→   planting event
completeHarvest()  ─creates─→   harvest event
                   ─creates─→   distribution event

With Demand Forecaster

Demand Forecaster               Transport Chain
─────────────────               ───────────────
supply matching    ─tracks─→    distribution events
market matches     ─creates─→   consumer_delivery events