← Back to Main Documentation Core Systems Index

Producer Delegation & Range-Based Quantity Control

Last Updated: Mon 16 Jul 2025 - Updated for wallet-first architecture and latest path specifications

Overview

This document specifies how Plings implements range-based quantity control for producer delegation, enabling manufacturers like Coca-Cola to delegate production to factories while maintaining strict offline control over production quantities.

Key Update: Now uses wallet-first architecture with paths like 2.3j.4.5Q.3L8z (class pointer separate) and HD derivations m/44'/501'/1'/3'/1255'/2'/5847'/90000'.

Core Requirements

  1. Offline-first: Factories must be able to produce millions of items without API calls
  2. No pre-registration: Items are only registered when first scanned/used
  3. Exact quantity control: Manufacturers must be able to limit production to exact quantities
  4. Cryptographic security: Impossible to forge identifiers outside authorized ranges
  5. Range enforcement: Built into path structure, not dependent on real-time verification

Architecture Overview

Range-Embedded Path Allocation

Instead of tracking usage counters in real-time, Plings embeds quantity limits directly into the path allocation structure:

Manufacturer Allocation (Wallet-First):
├── Path Prefix: "2.3j.4.5Q" (Coca-Cola → Plant 1255 → Classic Coke → Batch 5847) + Class Pointer
├── Authorized Range: instances 1-90,000
├── HD Derivation: m/44'/501'/1'/3'/1255'/2'/5847'/[1:90000] (Wallet v1)
└── Delegation Key: Private key for this specific batch+range

Key Changes:

Factory Production System

class FactoryProduction {
    constructor(allocation) {
        // Hard-coded from manufacturer allocation
        this.batchPath = allocation.path_prefix;         // "2.3j.4.5Q" (class pointer separate)
        this.authorizedRange = allocation.range;         // { start: 1, end: 90000 }
        this.currentInstance = allocation.range.start;   // 1
        this.privateKey = allocation.delegation_key;     // Factory's private key
        this.walletVersion = allocation.wallet_version;  // 1 (for wallet v1)
    }
    
    produceNextItem() {
        // Built-in range enforcement
        if (this.currentInstance > this.authorizedRange.end) {
            throw new Error(`Production halted: Exceeded authorized range (${this.authorizedRange.end})`);
        }
        
        // Generate path and cryptographic key offline
        const path = `${this.batchPath}.${this.currentInstance}`;
        const hdDerivation = this._pathToHDDerivation(path);
        const instanceKey = deriveHDKey(this.privateKey, hdDerivation);
        
        this.currentInstance++;
        
        return { 
            path: path,                    // "2.3j.4.5Q.2aB" (class pointer separate)
            instanceKey: instanceKey,      // Base58 encoded public key
            hdDerivation: hdDerivation,    // "m/44'/501'/1'/3'/1255'/2'/5847'/42750'"
            qrCodeData: instanceKey        // What goes on the physical tag
        };
    }
    
    _pathToHDDerivation(path) {
        // Convert path to wallet-first HD derivation
        // "2.3j.4.5Q.2aB" → "m/44'/501'/1'/3'/1255'/2'/5847'/42750'"
        const parts = path.split('.');
        let derivation = `m/44'/501'/${this.walletVersion}'`;
        
        for (const part of parts) {
            // All path segments are regular indices (class information via separate pointer)
            derivation += `/${part}'`;
        }
        
        return derivation;
    }
}

Range Allocation Registry

The Plings registry maintains authorized ranges for offline verification:

// Cached locally for offline verification
const rangeRegistry = {
    "2.3j.4.5Q": {
        manufacturer: "Coca-Cola",
        plant_id: 1255,
        plant_name: "Atlanta",
        product_class: "Classic Coke",
        class_pointer: "4K7mX9abDcE",
        authorized_range: { start: 1, end: 90000 },
        delegation_date: "2025-07-15",
        status: "active",
        wallet_version: 1,
        delegation_key_hash: "abc123...", // For verification
    },
    "2.3k.4.5R": {
        manufacturer: "Coca-Cola", 
        plant_id: 1256,
        plant_name: "Mexico City",
        product_class: "Classic Coke",
        class_pointer: "4K7mX9abDcE",
        authorized_range: { start: 1, end: 90000 },
        delegation_date: "2025-07-16",
        status: "active",
        wallet_version: 1
    }
};

Verification Process

Range Compliance Verification

function verifyInstanceInAuthorizedRange(path, instanceKey) {
    // Parse path: "2.3j.4.5Q.2aB" (class pointer separate)
    const pathParts = path.split('.');
    const batchPath = pathParts.slice(0, 4).join('.');  // "2.3j.4.5Q"
    const instanceNumber = parseInt(pathParts[4]);      // 42750
    
    // Get allocation info from cached registry
    const allocation = rangeRegistry[batchPath];
    
    if (!allocation) {
        return { 
            valid: false, 
            reason: "Batch not allocated",
            error_code: "BATCH_NOT_ALLOCATED"
        };
    }
    
    if (allocation.status !== 'active') {
        return { 
            valid: false, 
            reason: `Batch status: ${allocation.status}`,
            error_code: "BATCH_REVOKED"
        };
    }
    
    // Verify instance is within authorized range
    const { start, end } = allocation.authorized_range;
    if (instanceNumber < start || instanceNumber > end) {
        return { 
            valid: false, 
            reason: `Instance ${instanceNumber} outside authorized range ${start}-${end}`,
            error_code: "RANGE_VIOLATION",
            authorized_range: { start, end },
            violation_amount: instanceNumber > end ? instanceNumber - end : start - instanceNumber
        };
    }
    
    // Proceed to cryptographic verification with wallet-aware derivation
    return verifyCryptographicDerivation(path, instanceKey, allocation.wallet_version);
}

Complete Verification Chain

function verifyPlingsIdentifier(path, instanceKey) {
    // 1. Parse and validate path format
    const pathValidation = validatePathFormat(path);
    if (!pathValidation.valid) return pathValidation;
    
    // 2. Verify instance is within authorized production range
    const rangeValidation = verifyInstanceInAuthorizedRange(path, instanceKey);
    if (!rangeValidation.valid) return rangeValidation;
    
    // 3. Verify cryptographic derivation from delegation key
    const cryptoValidation = verifyCryptographicDerivation(path, instanceKey);
    if (!cryptoValidation.valid) return cryptoValidation;
    
    // 4. All checks passed
    return {
        valid: true,
        manufacturer: rangeValidation.manufacturer,
        product_class: rangeValidation.product_class,
        batch_info: extractBatchInfo(path),
        verification_method: "range_controlled_delegation"
    };
}

Delegation Management

Creating New Delegations

async function createProducerDelegation(manufacturerId, plantId, productClass, quantity, walletVersion = 1) {
    // 1. Generate unique batch ID
    const batchId = await getNextBatchId(manufacturerId, plantId, productClass);
    
    // 2. Create path prefix (class pointer generated separately)
    const pathPrefix = `${manufacturerId}.${plantId}.${productClass}.${batchId}`;
    const classPointer = generateClassPointer(manufacturerId, plantId, productClass);
    
    // 3. Define authorized range
    const authorizedRange = { start: 1, end: quantity };
    
    // 4. Derive delegation key using wallet-first architecture
    const hdDerivation = `m/44'/501'/${walletVersion}'/${manufacturerId}'/${plantId}'/${productClass}'/${batchId}'`;
    const delegationKey = deriveHardenedKey(getWalletMasterKey(walletVersion), hdDerivation);
    
    // 5. Register in path registry
    await registerRangeAllocation({
        wallet_version: walletVersion,
        path_prefix: pathPrefix,
        authorized_range: authorizedRange,
        delegation_key: delegationKey.publicKey,
        hd_derivation: hdDerivation,
        manufacturer: getManufacturerName(manufacturerId),
        plant_id: plantId,
        product_class: productClass,
        class_pointer: classPointer,
        allocated_quantity: quantity,
        status: "active"
    });
    
    return {
        wallet_version: walletVersion,
        path_prefix: pathPrefix,
        authorized_range: authorizedRange,
        delegation_key: delegationKey.privateKey, // Sent securely to factory
        public_key: delegationKey.publicKey       // Stored in registry
    };
}

Revoking Delegations

async function revokeDelegation(pathPrefix, reason) {
    // 1. Update registry status
    await updateRangeAllocation(pathPrefix, {
        status: "revoked",
        revoked_at: new Date().toISOString(),
        revocation_reason: reason
    });
    
    // 2. Propagate to verification nodes
    await propagateRegistryUpdate(pathPrefix);
    
    // 3. Log audit trail
    await logDelegationRevocation(pathPrefix, reason);
    
    return {
        revoked: true,
        path_prefix: pathPrefix,
        reason: reason,
        effective_immediately: true
    };
}

Example Scenarios

Scenario 1: Coca-Cola Delegates Classic Coke Production to Atlanta

// Coca-Cola creates delegation for Atlanta
const atlantaDelegation = await createProducerDelegation(
    3,        // Coca-Cola manufacturer ID
    1255,     // Atlanta plant ID  
    2,        // Classic Coke product class
    90000     // 90,000 cans authorized
);

// Result:
// Path: "2.3j.4.5Q"
// Range: 1-90,000
// HD Derivation: m/44'/501'/1'/3'/1255'/2'/5847'/[1:90000]
// Atlanta can produce: 2.3j.4.5Q.2 through 2.3j.4.5Q.3L8z

// Atlanta production system configured with:
const atlantaProduction = new FactoryProduction({
    path_prefix: "2.3j.4.5Q",
    range: { start: 1, end: 90000 },
    delegation_key: atlantaDelegation.delegation_key,
    wallet_version: 1
});

Scenario 2: Atlanta Attempts Overproduction

// Atlanta produces authorized quantity
for (let i = 1; i <= 90000; i++) {
    const can = atlantaProduction.produceNextItem();
    // Success: generates 2.3j.4.5Q.2, 2.3j.4.5Q.3, ..., 2.3j.4.5Q.3L8z
}

// Atlanta attempts to produce beyond authorization
try {
    const extraCan = atlantaProduction.produceNextItem(); // Would be 2.3j.4.5Q.3L9A
} catch (error) {
    console.log(error.message); 
    // "Production halted: Exceeded authorized range (90000)"
}

// If Atlanta manually tries to create unauthorized instance:
const unauthorizedPath = "2.3j.4.5Q.3L92";  // Class pointer separate
const fakeKey = deriveHDKey(atlantaDelegation.delegation_key, "m/44'/501'/1'/3'/1255'/2'/5847'/90001'");

// Verification will fail:
const verification = verifyPlingsIdentifier(unauthorizedPath, fakeKey);
// Result: { valid: false, reason: "Instance 90001 outside authorized range 1-90000" }

Scenario 3: Transferring Production to Mexico

// Coca-Cola revokes Atlanta's future production
await revokeDelegation("2.3j.4.5Q", "Production transferred to Mexico plant");

// Coca-Cola creates new delegation for Mexico
const mexicoDelegation = await createProducerDelegation(
    3,        // Coca-Cola
    1256,     // Mexico plant ID
    2,        // Classic Coke  
    90000     // 90,000 cans authorized
);

// Result: Mexico gets path "2.3k.4.5R" with range 1-90,000 (class pointer separate)
// Atlanta's old delegation for "2.3j.4.5Q" is revoked
// No production overlap or confusion possible

Database Schema

Range Allocation Table

CREATE TABLE range_allocations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    wallet_version INTEGER NOT NULL,
    path_prefix VARCHAR(50) NOT NULL,
    manufacturer_id INTEGER NOT NULL,
    plant_id INTEGER NOT NULL,
    product_class INTEGER NOT NULL,
    class_pointer VARCHAR(11) NOT NULL,
    batch_id INTEGER NOT NULL,
    authorized_start INTEGER NOT NULL,
    authorized_end INTEGER NOT NULL,
    delegation_public_key TEXT NOT NULL,
    hd_derivation VARCHAR(100) NOT NULL,
    status VARCHAR(20) DEFAULT 'active',
    allocated_at TIMESTAMP DEFAULT NOW(),
    revoked_at TIMESTAMP NULL,
    revocation_reason TEXT NULL,
    
    CONSTRAINT fk_wallet_version FOREIGN KEY (wallet_version) 
        REFERENCES wallet_versions(version_id),
    CONSTRAINT fk_manufacturer FOREIGN KEY (wallet_version, manufacturer_id) 
        REFERENCES manufacturer_registry(wallet_version, manufacturer_index),
    CONSTRAINT unique_path_per_wallet UNIQUE (wallet_version, path_prefix),
    CONSTRAINT valid_range CHECK (authorized_start <= authorized_end),
    CONSTRAINT valid_status CHECK (status IN ('active', 'revoked', 'completed')),
    CONSTRAINT valid_class_pointer CHECK (length(class_pointer) = 11)
);

CREATE INDEX idx_range_allocations_wallet_path ON range_allocations(wallet_version, path_prefix);
CREATE INDEX idx_range_allocations_manufacturer ON range_allocations(wallet_version, manufacturer_id);
CREATE INDEX idx_range_allocations_status ON range_allocations(status);
CREATE INDEX idx_range_allocations_plant ON range_allocations(plant_id);

Security Considerations

Range Enforcement Security

  1. Built-in Limits: Range limits are embedded in factory systems, not dependent on network
  2. Cryptographic Proof: Each instance requires valid cryptographic derivation
  3. Registry Verification: Offline verification checks both range and cryptography
  4. Audit Trail: Complete history of all delegations and revocations
  5. Immutable Allocation: Once allocated, ranges cannot be retroactively changed

Attack Prevention

Implementation Guidelines

For Client Applications

// Cache range registry for offline verification
const cacheRangeRegistry = async () => {
    const registry = await fetchRangeRegistry();
    localStorage.setItem('plings_range_registry', JSON.stringify(registry));
    localStorage.setItem('plings_registry_updated', Date.now().toString());
};

// Verify using cached registry (works offline)
const verifyOffline = (path, instanceKey) => {
    const cachedRegistry = JSON.parse(localStorage.getItem('plings_range_registry') || '{}');
    return verifyInstanceInAuthorizedRange(path, instanceKey, cachedRegistry);
};

For Factory Systems

// Initialize production system with delegation
const initializeProduction = (delegation) => {
    // Validate delegation format
    if (!delegation.path_prefix || !delegation.authorized_range || !delegation.delegation_key) {
        throw new Error('Invalid delegation format');
    }
    
    // Create production instance with hard limits
    return new FactoryProduction(delegation);
};

// Secure key storage
const storeDelegationKey = (key) => {
    // Use HSM or secure enclave for production
    // Never log or expose private keys
    return secureKeyStorage.store(key);
};

Future Enhancements

Planned Features

  1. Multi-line Allocation: Split single batch across multiple production lines
  2. Dynamic Range Adjustment: Modify ranges without creating new batches
  3. Predictive Allocation: AI-driven quantity forecasting
  4. Real-time Monitoring: Optional production telemetry without blocking offline operation
  5. Cross-plant Coordination: Shared batch allocation between multiple factories

Scalability Considerations


This specification ensures that producer delegation provides manufacturers with precise quantity control while maintaining Plings’ core offline-first architecture and cryptographic security guarantees.