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

489 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```typescript
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:
```typescript
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
```typescript
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
```typescript
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
```typescript
function calculateCarbon(
method: TransportMethod,
distanceKm: number,
weightKg: number
): number {
const factor = CARBON_FACTORS[method] || 0.1;
return factor * distanceKm * weightKg;
}
```
## Journey Reconstruction
### Algorithm
```typescript
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
```typescript
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
```typescript
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
```json
{
"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
```typescript
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
```typescript
// 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
```