# 🛡️ RANGERBLOCK SECURITY INTEGRATION PLAN v2.0
## Project Codename: "SHEPHERD PROTOCOL"
### Unified Identity, Registration & App Sync System

---

## REVISION NOTES (v2.0)
- Added: ranger-chat-lite ↔ RangerPlex bidirectional sync
- Added: On-chain identity registration
- Added: Settings migration (lite → full app)
- Added: First-app security considerations (comprehensive)
- Added: Missing security layers David didn't know to ask for

---

## 1. EXECUTIVE SUMMARY

### The Vision
```
User Journey Option A (Chat First):
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Downloads   │────>│ Identity    │────>│ Later adds  │
│ Chat Lite   │     │ Created +   │     │ RangerPlex  │
│ (free/easy) │     │ On-Chain    │     │ (full app)  │
└─────────────┘     └─────────────┘     └─────────────┘
                           │                    │
                           └────────────────────┘
                              SEAMLESS SYNC!
                         (settings, history, keys)

User Journey Option B (RangerPlex First):
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Downloads   │────>│ Full        │────>│ Chat Lite   │
│ RangerPlex  │     │ Identity    │     │ auto-links  │
│ (power user)│     │ On-Chain    │     │ to existing │
└─────────────┘     └─────────────┘     └─────────────┘
```

### Key Principles
1. **Identity is PORTABLE** - One identity, all apps
2. **Blockchain is TRUTH** - On-chain registration = verified
3. **Local is FALLBACK** - Works offline, syncs when connected
4. **Upgrade is SEAMLESS** - Lite → Full with zero friction
5. **Security is INVISIBLE** - Users don't see complexity

---

## 2. ON-CHAIN IDENTITY REGISTRATION

### Why On-Chain?
- **Proof of existence** - Timestamp when identity created
- **Immutable record** - Can't be faked retroactively
- **Cross-app verification** - Any app can verify identity
- **Recovery mechanism** - Blockchain = backup

### Identity Block Structure
```javascript
{
    type: 'IDENTITY_REGISTRATION',
    version: '1.0.0',
    payload: {
        // Public data (visible on chain)
        publicKey: 'RSA-2048 public key (PEM)',
        hardwareIdHash: 'SHA-256 of hardware ID (not raw ID!)',
        nickname: 'IrishRanger',
        appOrigin: 'ranger-chat-lite',  // Which app created this
        capabilities: ['chat', 'voice', 'files'],

        // Timestamps
        createdAt: '2024-12-03T12:00:00.000Z',
        registeredOnChain: '2024-12-03T12:00:05.000Z',

        // Signature
        signature: 'self-signed with private key'
    },
    metadata: {
        blockHeight: 12345,
        previousHash: 'abc123...',
        nonce: 42
    }
}
```

### Registration Flow
```
┌─────────────┐          ┌─────────────┐          ┌─────────────┐
│   CLIENT    │          │ RELAY/HUB   │          │ BLOCKCHAIN  │
└──────┬──────┘          └──────┬──────┘          └──────┬──────┘
       │                        │                        │
       │ 1. Generate identity   │                        │
       │    locally first       │                        │
       │                        │                        │
       │ 2. Connect to relay    │                        │
       ├───────────────────────>│                        │
       │                        │                        │
       │ 3. Submit identity     │                        │
       │    registration block  │                        │
       ├───────────────────────>│                        │
       │                        │                        │
       │                        │ 4. Validate & mine     │
       │                        ├───────────────────────>│
       │                        │                        │
       │                        │ 5. Block confirmed     │
       │                        │<───────────────────────┤
       │                        │                        │
       │ 6. Registration        │                        │
       │    confirmed + block # │                        │
       │<───────────────────────┤                        │
       │                        │                        │
       │ 7. Store block # as    │                        │
       │    proof of identity   │                        │
       │                        │                        │
```

---

## 3. APP SYNC ARCHITECTURE

### Shared Identity Storage
**Location**: `~/.rangerblock/` (cross-app shared folder)

```
~/.rangerblock/
├── identity/
│   ├── master_identity.json       # THE identity (shared)
│   ├── hardware_fingerprint.json  # Device binding
│   ├── chain_registration.json    # On-chain proof
│   └── sync_state.json            # Last sync timestamp
│
├── keys/
│   ├── master_private_key.pem     # RSA-2048 (NEVER leaves device)
│   ├── master_public_key.pem      # Shared with network
│   └── session_keys/              # Per-session encryption keys
│
├── apps/
│   ├── ranger-chat-lite/
│   │   ├── settings.json          # App-specific settings
│   │   ├── chat_history.json      # Message history
│   │   └── contacts.json          # Saved contacts
│   │
│   └── rangerplex/
│       ├── settings.json
│       ├── modules.json           # Enabled modules
│       └── workspace.json         # UI state
│
├── sync/
│   ├── pending_sync.json          # Changes to sync
│   ├── conflict_log.json          # Sync conflicts
│   └── last_sync.json             # Sync metadata
│
└── security/
    ├── trusted_devices.json       # Other devices with same identity
    ├── revocation_list.json       # Compromised keys
    └── audit_log.json             # Security events
```

### App Detection & Sync
```javascript
// When ranger-chat-lite starts:
class AppSyncManager {
    async detectRangerPlex() {
        const paths = [
            '~/.rangerplex',                           // Linux/macOS
            '~/Library/Application Support/RangerPlex', // macOS
            '%APPDATA%/RangerPlex'                     // Windows
        ];

        for (const path of paths) {
            if (await fs.exists(path)) {
                return { installed: true, path };
            }
        }
        return { installed: false };
    }

    async syncWithRangerPlex() {
        const rangerplex = await this.detectRangerPlex();

        if (rangerplex.installed) {
            // RangerPlex exists - sync to shared identity
            await this.mergeIdentities();
            await this.syncSettings();
            await this.notifyUser('Synced with RangerPlex!');
        } else {
            // First app - create shared identity
            await this.createSharedIdentity();
        }
    }
}
```

### Settings Migration (Lite → Full)
```javascript
// When RangerPlex detects existing Chat Lite identity:
async function migrateFromChatLite() {
    const chatLiteData = await loadChatLiteData();

    if (chatLiteData) {
        // Import user's existing identity
        await importIdentity(chatLiteData.identity);

        // Import chat history
        await importChatHistory(chatLiteData.messages);

        // Import contacts
        await importContacts(chatLiteData.contacts);

        // Import preferences
        await importPreferences(chatLiteData.settings);

        // Notify user
        showWelcome(`
            Welcome to RangerPlex!

            We found your Chat Lite identity:
            • Username: ${chatLiteData.identity.nickname}
            • Messages: ${chatLiteData.messages.length}
            • Contacts: ${chatLiteData.contacts.length}

            Everything has been imported automatically!
        `);
    }
}
```

---

## 4. SECURITY CONSIDERATIONS (FIRST APP CHECKLIST)

### Things You Didn't Know to Ask For:

#### A. Input Validation (CRITICAL)
```javascript
// NEVER trust user input!
function sanitizeNickname(input) {
    // Remove dangerous characters
    const clean = input
        .replace(/[<>\"\'\\\/]/g, '')  // No HTML/script injection
        .replace(/[\x00-\x1F]/g, '')   // No control characters
        .trim()
        .substring(0, 32);             // Max length

    // Check against banned patterns
    const banned = ['admin', 'system', 'ranger', 'commander'];
    if (banned.some(b => clean.toLowerCase().includes(b))) {
        throw new Error('Reserved nickname');
    }

    return clean;
}

// Validate ALL WebSocket messages
function validateMessage(data) {
    try {
        const msg = JSON.parse(data);

        // Check required fields
        if (!msg.type || typeof msg.type !== 'string') {
            throw new Error('Invalid message type');
        }

        // Check payload size (prevent DoS)
        if (JSON.stringify(msg).length > 65536) {
            throw new Error('Message too large');
        }

        // Check for injection attempts
        if (containsInjection(msg)) {
            throw new Error('Injection detected');
        }

        return msg;
    } catch (e) {
        logSecurityEvent('INVALID_MESSAGE', { error: e.message, data });
        return null;
    }
}
```

#### B. Rate Limiting (PREVENTS ABUSE)
```javascript
class RateLimiter {
    constructor() {
        this.limits = {
            messages: { max: 10, window: 10000 },      // 10 msgs per 10s
            connections: { max: 3, window: 60000 },    // 3 connects per min
            registrations: { max: 1, window: 86400000 } // 1 reg per day per IP
        };
        this.counters = new Map();
    }

    check(type, identifier) {
        const key = `${type}:${identifier}`;
        const now = Date.now();
        const limit = this.limits[type];

        if (!this.counters.has(key)) {
            this.counters.set(key, []);
        }

        const timestamps = this.counters.get(key)
            .filter(t => now - t < limit.window);

        if (timestamps.length >= limit.max) {
            return { allowed: false, retryAfter: limit.window - (now - timestamps[0]) };
        }

        timestamps.push(now);
        this.counters.set(key, timestamps);
        return { allowed: true };
    }
}
```

#### C. Secure Key Storage (DON'T STORE PLAIN!)
```javascript
const crypto = require('crypto');
const os = require('os');

class SecureKeyStorage {
    // Derive encryption key from hardware + user password
    deriveStorageKey(password) {
        const hardwareId = this.getHardwareId();
        const salt = crypto.createHash('sha256')
            .update(hardwareId + os.userInfo().username)
            .digest();

        return crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
    }

    // Encrypt private key before storage
    encryptPrivateKey(privateKeyPem, password) {
        const key = this.deriveStorageKey(password);
        const iv = crypto.randomBytes(16);
        const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);

        let encrypted = cipher.update(privateKeyPem, 'utf8', 'base64');
        encrypted += cipher.final('base64');

        return {
            encrypted,
            iv: iv.toString('base64'),
            authTag: cipher.getAuthTag().toString('base64')
        };
    }

    // Decrypt on use
    decryptPrivateKey(encryptedData, password) {
        const key = this.deriveStorageKey(password);
        const decipher = crypto.createDecipheriv(
            'aes-256-gcm',
            key,
            Buffer.from(encryptedData.iv, 'base64')
        );
        decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'base64'));

        let decrypted = decipher.update(encryptedData.encrypted, 'base64', 'utf8');
        decrypted += decipher.final('utf8');

        return decrypted;
    }
}
```

#### D. Session Security
```javascript
class SessionManager {
    generateSessionToken(userId, hardwareId) {
        const payload = {
            userId,
            hardwareId,
            issuedAt: Date.now(),
            expiresAt: Date.now() + (24 * 60 * 60 * 1000), // 24 hours
            nonce: crypto.randomBytes(16).toString('hex')
        };

        // Sign the token
        const signature = this.sign(JSON.stringify(payload));

        return Buffer.from(JSON.stringify({ payload, signature }))
            .toString('base64');
    }

    validateSessionToken(token, expectedHardwareId) {
        try {
            const { payload, signature } = JSON.parse(
                Buffer.from(token, 'base64').toString()
            );

            // Check expiry
            if (Date.now() > payload.expiresAt) {
                return { valid: false, reason: 'expired' };
            }

            // Check hardware binding
            if (payload.hardwareId !== expectedHardwareId) {
                return { valid: false, reason: 'hardware_mismatch' };
            }

            // Verify signature
            if (!this.verify(JSON.stringify(payload), signature)) {
                return { valid: false, reason: 'invalid_signature' };
            }

            return { valid: true, payload };
        } catch (e) {
            return { valid: false, reason: 'malformed' };
        }
    }
}
```

#### E. Audit Logging (LEGAL PROTECTION)
```javascript
class AuditLogger {
    constructor(dbPath) {
        this.db = new Database(dbPath);
        this.initSchema();
    }

    log(event) {
        const entry = {
            timestamp: new Date().toISOString(),
            eventType: event.type,
            userId: event.userId || null,
            hardwareId: event.hardwareId || null,
            ipAddress: event.ip || null,
            action: event.action,
            details: JSON.stringify(event.details || {}),
            severity: event.severity || 'INFO'
        };

        this.db.insert('audit_log', entry);

        // Alert Commander for high severity
        if (event.severity === 'CRITICAL') {
            this.alertCommander(entry);
        }
    }

    // Required events to log:
    // - User registration
    // - Login attempts (success/fail)
    // - Message sends (metadata only, not content!)
    // - File transfers (metadata)
    // - Admin actions
    // - Kill switch triggers
    // - Suspicious activity
}
```

#### F. Error Handling (DON'T LEAK INFO)
```javascript
// BAD - leaks internal details
app.use((err, req, res, next) => {
    res.status(500).json({
        error: err.message,
        stack: err.stack,    // NEVER expose stack trace!
        query: req.query     // NEVER echo back user input!
    });
});

// GOOD - generic errors
app.use((err, req, res, next) => {
    const errorId = crypto.randomBytes(8).toString('hex');

    // Log full error internally
    logger.error({
        errorId,
        error: err.message,
        stack: err.stack,
        request: sanitize(req)
    });

    // Return generic message to user
    res.status(500).json({
        error: 'An error occurred',
        errorId: errorId,  // User can report this ID
        support: 'Contact support with this error ID'
    });
});
```

#### G. Content Security (PREVENT ABUSE)
```javascript
class ContentFilter {
    constructor() {
        // Load filters
        this.illegalPatterns = [
            /(?:^|\s)csam(?:\s|$)/i,           // Child abuse material
            /(?:^|\s)bomb(?:\s+making)?(?:\s|$)/i,
            // etc - comprehensive list
        ];

        this.spamPatterns = [
            /(.)\1{10,}/,                       // Repeated characters
            /(https?:\/\/[^\s]+\s*){5,}/,       // Too many URLs
        ];
    }

    check(content) {
        // Check for illegal content
        for (const pattern of this.illegalPatterns) {
            if (pattern.test(content)) {
                return {
                    allowed: false,
                    reason: 'ILLEGAL_CONTENT',
                    action: 'BLOCK_AND_REPORT'
                };
            }
        }

        // Check for spam
        for (const pattern of this.spamPatterns) {
            if (pattern.test(content)) {
                return {
                    allowed: false,
                    reason: 'SPAM_DETECTED',
                    action: 'BLOCK'
                };
            }
        }

        return { allowed: true };
    }
}
```

#### H. TLS/WSS Configuration (ENCRYPT IN TRANSIT)
```javascript
const https = require('https');
const fs = require('fs');

// For production - use proper certificates!
const server = https.createServer({
    key: fs.readFileSync('server-key.pem'),
    cert: fs.readFileSync('server-cert.pem'),

    // Security settings
    minVersion: 'TLSv1.2',            // Minimum TLS version
    ciphers: [
        'ECDHE-ECDSA-AES128-GCM-SHA256',
        'ECDHE-RSA-AES128-GCM-SHA256',
        'ECDHE-ECDSA-AES256-GCM-SHA384',
        'ECDHE-RSA-AES256-GCM-SHA384'
    ].join(':'),
    honorCipherOrder: true
});

// WebSocket over TLS
const wss = new WebSocket.Server({ server });
```

---

## 5. IMPLEMENTATION PHASES (REVISED)

### Phase 1: Shared Identity Library (THIS WEEK)
**Files to Create**:
```
/rangerblock/lib/
├── identity-service.cjs      # Core identity (ported from TS)
├── crypto-utils.cjs          # RSA, signing, encryption
├── storage-utils.cjs         # Cross-platform storage
├── hardware-id.cjs           # Hardware fingerprinting
├── sync-manager.cjs          # App sync logic
└── chain-registration.cjs    # On-chain identity
```

### Phase 2: Update ranger-chat-lite
- Move identity to `~/.rangerblock/`
- Add RangerPlex detection
- Add on-chain registration
- Enable RSA signing

### Phase 3: Auth Server + Just-Chat Updates
- Build server-only/auth-server.cjs
- Update blockchain-chat.cjs
- Update voice-chat.cjs

### Phase 4: Kill Switch Integration
- Add Rain Protocol listeners
- Add Commander verification
- Test shutdown procedures

### Phase 5: RangerPlex Integration
- Detect Chat Lite identity
- Migrate settings
- Unified dashboard

---

## 6. QUICK REFERENCE

### App Paths
| App | Identity Location |
|-----|-------------------|
| ranger-chat-lite | `~/.rangerblock/` (shared) |
| RangerPlex | `~/.rangerblock/` (shared) |
| blockchain-chat.cjs | `~/.rangerblock/` (shared) |
| voice-chat.cjs | `~/.rangerblock/` (shared) |

### API Methods
| Method | Purpose |
|--------|---------|
| `getOrCreateIdentity()` | Get or create shared identity |
| `registerOnChain()` | Register identity on blockchain |
| `syncWithApps()` | Sync settings across apps |
| `validateIdentity()` | Verify identity is valid |
| `migrateFromApp()` | Import from other app |

---

## 7. SUMMARY OF CHANGES (v2.0)

1. **On-Chain Registration**: Every identity gets registered on the blockchain
2. **App Sync**: ranger-chat-lite ↔ RangerPlex automatic sync
3. **Settings Migration**: Seamless upgrade from Lite to Full
4. **Shared Storage**: `~/.rangerblock/` used by ALL apps
5. **Security Additions**:
   - Input validation
   - Rate limiting
   - Encrypted key storage
   - Session security
   - Audit logging
   - Error handling (no info leaks)
   - Content filtering
   - TLS/WSS configuration

---

**Document Classification**: COMMANDER EYES ONLY
**Version**: 2.0
**Created**: December 3, 2024
**Author**: Ranger (AIR9cd99c4515aeb3f6)
**For**: David Keane (IR240474)

🎖️ Rangers lead the way!
