# RANGERBLOCK REGISTRATION & CONSENT BLOCKCHAIN SYSTEM ## Project Codename: "SENTINEL PROTOCOL" ### Version 1.0.0 - December 4, 2025 --- ## CLASSIFICATION: PRIVATE **DO NOT COMMIT TO PUBLIC GIT** --- ## 1. EXECUTIVE SUMMARY ### The Vision When a user: 1. Creates identity (hardware-bound) 2. Accepts Terms of Use (18+, content policy, etc.) A **REGISTRATION BLOCK** is created on the RangerBlock blockchain, providing: - Immutable proof of acceptance - Cryptographic signature - Admin notification for approval - Privilege assignment upon approval ### Components Needed | Component | Purpose | Location | |-----------|---------|----------| | RegistrationBlock.sol | Solidity contract for EVM chains | Blockchain/contracts/ | | registration-service.cjs | Node.js registration handler | rangerblock/lib/ | | consent-service.cjs | Consent/terms handler | rangerblock/lib/ | | Admin integration | View/approve registrations | ~/.claude/ranger/admin/ | ### Apps Covered - ranger-chat-lite (Electron) - just-chat (Terminal) - server-only (Server deployment) - RangerPlex (Full browser) --- ## 2. REGISTRATION BLOCK STRUCTURE ### 2.1 Solidity Contract (Remix Standard) ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title RangerRegistration * @dev User registration and consent tracking for RangerBlock * @author David Keane (IrishRanger) + Claude Code (Ranger) */ contract RangerRegistration { // ======================================================================== // STRUCTURES // ======================================================================== struct Registration { bytes32 userIdHash; // SHA256 of userId bytes32 publicKeyHash; // SHA256 of RSA public key bytes32 hardwareIdHash; // SHA256 of hardware fingerprint string username; // Display name string appType; // ranger-chat-lite, just-chat, etc. // Consent string termsVersion; // "1.0.0" bytes32 termsHash; // SHA256 of terms text bytes signature; // RSA signature of consent // Timestamps uint256 registeredAt; // Block timestamp uint256 consentedAt; // When terms accepted // Status RegistrationStatus status; // pending, approved, denied, revoked string statusReason; // Reason for status change // Admin address approvedBy; // Admin who approved uint256 approvedAt; // Approval timestamp } enum RegistrationStatus { PENDING, APPROVED, DENIED, REVOKED } // ======================================================================== // STATE // ======================================================================== address public owner; address public supremeAdmin; mapping(bytes32 => Registration) public registrations; // userIdHash => Registration mapping(bytes32 => bool) public hardwareUsed; // hardwareIdHash => used bytes32[] public registrationList; // All registration IDs uint256 public totalRegistrations; uint256 public pendingCount; uint256 public approvedCount; uint256 public deniedCount; // ======================================================================== // EVENTS // ======================================================================== event RegistrationSubmitted( bytes32 indexed userIdHash, string username, string appType, uint256 timestamp ); event RegistrationApproved( bytes32 indexed userIdHash, address approvedBy, uint256 timestamp ); event RegistrationDenied( bytes32 indexed userIdHash, address deniedBy, string reason, uint256 timestamp ); event RegistrationRevoked( bytes32 indexed userIdHash, address revokedBy, string reason, uint256 timestamp ); event ConsentRecorded( bytes32 indexed userIdHash, string termsVersion, bytes32 termsHash, uint256 timestamp ); // ======================================================================== // MODIFIERS // ======================================================================== modifier onlyOwner() { require(msg.sender == owner || msg.sender == supremeAdmin, "Not authorized"); _; } modifier onlyAdmin() { require(msg.sender == owner || msg.sender == supremeAdmin, "Not admin"); _; } // ======================================================================== // CONSTRUCTOR // ======================================================================== constructor(address _supremeAdmin) { owner = msg.sender; supremeAdmin = _supremeAdmin; } // ======================================================================== // REGISTRATION FUNCTIONS // ======================================================================== /** * @dev Submit a new registration with consent */ function register( bytes32 userIdHash, bytes32 publicKeyHash, bytes32 hardwareIdHash, string memory username, string memory appType, string memory termsVersion, bytes32 termsHash, bytes memory signature ) public returns (bool) { // Check hardware not already used (prevents ban evasion) require(!hardwareUsed[hardwareIdHash], "Hardware already registered"); // Check not already registered require(registrations[userIdHash].registeredAt == 0, "Already registered"); // Create registration Registration storage reg = registrations[userIdHash]; reg.userIdHash = userIdHash; reg.publicKeyHash = publicKeyHash; reg.hardwareIdHash = hardwareIdHash; reg.username = username; reg.appType = appType; reg.termsVersion = termsVersion; reg.termsHash = termsHash; reg.signature = signature; reg.registeredAt = block.timestamp; reg.consentedAt = block.timestamp; reg.status = RegistrationStatus.PENDING; // Mark hardware as used hardwareUsed[hardwareIdHash] = true; // Add to list registrationList.push(userIdHash); totalRegistrations++; pendingCount++; emit RegistrationSubmitted(userIdHash, username, appType, block.timestamp); emit ConsentRecorded(userIdHash, termsVersion, termsHash, block.timestamp); return true; } /** * @dev Approve a pending registration (admin only) */ function approve(bytes32 userIdHash) public onlyAdmin { Registration storage reg = registrations[userIdHash]; require(reg.registeredAt > 0, "Registration not found"); require(reg.status == RegistrationStatus.PENDING, "Not pending"); reg.status = RegistrationStatus.APPROVED; reg.approvedBy = msg.sender; reg.approvedAt = block.timestamp; pendingCount--; approvedCount++; emit RegistrationApproved(userIdHash, msg.sender, block.timestamp); } /** * @dev Deny a pending registration (admin only) */ function deny(bytes32 userIdHash, string memory reason) public onlyAdmin { Registration storage reg = registrations[userIdHash]; require(reg.registeredAt > 0, "Registration not found"); require(reg.status == RegistrationStatus.PENDING, "Not pending"); reg.status = RegistrationStatus.DENIED; reg.statusReason = reason; pendingCount--; deniedCount++; emit RegistrationDenied(userIdHash, msg.sender, reason, block.timestamp); } /** * @dev Revoke an approved registration (admin only) */ function revoke(bytes32 userIdHash, string memory reason) public onlyAdmin { Registration storage reg = registrations[userIdHash]; require(reg.registeredAt > 0, "Registration not found"); require(reg.status == RegistrationStatus.APPROVED, "Not approved"); reg.status = RegistrationStatus.REVOKED; reg.statusReason = reason; approvedCount--; emit RegistrationRevoked(userIdHash, msg.sender, reason, block.timestamp); } // ======================================================================== // VIEW FUNCTIONS // ======================================================================== function getRegistration(bytes32 userIdHash) public view returns ( string memory username, string memory appType, string memory termsVersion, RegistrationStatus status, uint256 registeredAt, uint256 approvedAt ) { Registration storage reg = registrations[userIdHash]; return ( reg.username, reg.appType, reg.termsVersion, reg.status, reg.registeredAt, reg.approvedAt ); } function isApproved(bytes32 userIdHash) public view returns (bool) { return registrations[userIdHash].status == RegistrationStatus.APPROVED; } function isPending(bytes32 userIdHash) public view returns (bool) { return registrations[userIdHash].status == RegistrationStatus.PENDING; } function getPendingCount() public view returns (uint256) { return pendingCount; } function getStats() public view returns ( uint256 total, uint256 pending, uint256 approved, uint256 denied ) { return (totalRegistrations, pendingCount, approvedCount, deniedCount); } } ``` --- ## 3. NODE.JS INTEGRATION ### 3.1 Registration Block (JSON Format for RangerBlock P2P) For our custom blockchain (non-EVM), registrations are blocks: ```javascript // Registration block structure const registrationBlock = { type: 'USER_REGISTRATION', version: '1.0.0', // Identity (hashed for privacy) identity: { userIdHash: 'sha256_of_rb_xxx', publicKeyHash: 'sha256_of_public_key', hardwareIdHash: 'sha256_of_hardware_fingerprint', username: 'SwiftRanger', appType: 'ranger-chat-lite' }, // Consent record consent: { termsVersion: '1.0.0', termsHash: 'sha256_of_terms_text', acceptedAt: '2025-12-04T10:30:00.000Z', ageConfirmed: true, // User confirmed 18+ signature: 'RSA_signature_of_consent' }, // Block metadata metadata: { timestamp: '2025-12-04T10:30:05.000Z', previousHash: 'abc123...', nonce: 12345, minedBy: 'relay_node_id' }, // Status (updated by admin) status: { current: 'pending', // pending, approved, denied, revoked updatedAt: null, updatedBy: null, reason: null } }; ``` ### 3.2 Registration Service (registration-service.cjs) ```javascript // Location: rangerblock/lib/registration-service.cjs class RegistrationService { constructor(identityService, consentService) { this.identity = identityService; this.consent = consentService; } // Create registration block async createRegistrationBlock() { } // Submit to relay (goes to admin queue) async submitRegistration(block) { } // Check registration status async checkStatus(userId) { } // Handle approval notification onApproved(callback) { } // Handle denial notification onDenied(callback) { } } ``` --- ## 4. ADMIN INTEGRATION ### 4.1 Admin Dashboard Updates **New "Registrations" Tab:** ``` ┌─────────────────────────────────────────────────────────────────┐ │ PENDING REGISTRATIONS (3) │ ├───────┬──────────────┬─────────────────┬───────────┬───────────┤ │ # │ Username │ App │ Date │ Actions │ ├───────┼──────────────┼─────────────────┼───────────┼───────────┤ │ 1 │ SwiftRanger │ ranger-chat-lite│ Dec 4 │ [A] [D] │ │ 2 │ StormWolf │ just-chat │ Dec 4 │ [A] [D] │ │ 3 │ NightHawk │ just-chat │ Dec 4 │ [A] [D] │ └───────┴──────────────┴─────────────────┴───────────┴───────────┘ [A] = Approve [D] = Deny [V] = View Details Registration Details (SwiftRanger): ───────────────────────────────────── User ID: rb_abc123... Hardware: M4Max-xxx (masked) App: ranger-chat-lite Registered: 2025-12-04 10:30:05 Terms: v1.0.0 (18+ accepted) Signature: ✓ Valid Status: PENDING [A]pprove [D]eny [B]ack ``` ### 4.2 Admin Registry Updates Add to `admin-registry.cjs`: ```javascript // Registration queue management getPendingRegistrations() { } approveRegistration(userIdHash, adminId) { } denyRegistration(userIdHash, adminId, reason) { } revokeRegistration(userIdHash, adminId, reason) { } // Consent verification verifyConsent(userIdHash) { } getConsentRecord(userIdHash) { } ``` --- ## 5. APP INTEGRATION FLOW ### 5.1 ranger-chat-lite Flow ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ App Start │────>│ Check │────>│ Show │ │ │ │ Identity │ │ Terms Modal │ └─────────────┘ └─────────────┘ └──────┬──────┘ │ ┌──────────────────────────┘ │ User Accepts v ┌─────────────┐ ┌─────────────┐ │ Sign │────>│ Submit to │ │ Consent │ │ Relay │ └─────────────┘ └──────┬──────┘ │ ┌────────────────────┘ v ┌─────────────┐ │ PENDING │ <── Limited features │ status │ (view only) └──────┬──────┘ │ ┌────────────┴────────────┐ v v ┌───────────┐ ┌───────────────┐ │ APPROVED │ │ DENIED │ │ Full │ │ Show reason, │ │ access │ │ exit app │ └───────────┘ └───────────────┘ ``` ### 5.2 just-chat Flow Same flow but terminal-based: 1. First run → Show terms in terminal 2. User types 'y' to accept 3. Consent signed and submitted 4. Status: PENDING (can view chat, can't send) 5. When approved → Full access 6. When denied → Exit with message ### 5.3 server-only Flow Server operators get different terms: 1. Setup script shows server terms 2. Operator accepts 3. Server registration submitted 4. Admin approves server node 5. Server can join network --- ## 6. PRIVILEGE SYSTEM ### 6.1 Status-Based Privileges | Status | Chat | Voice | Files | DM | Channels | |--------|------|-------|-------|----|----------| | PENDING | View | No | No | No | View | | APPROVED | Full | Full | Full | Full | Full | | DENIED | No | No | No | No | No | | REVOKED | No | No | No | No | No | ### 6.2 Implementation ```javascript // In each app's message handler if (registrationStatus !== 'APPROVED') { if (registrationStatus === 'PENDING') { showNotification('Registration pending admin approval. View-only mode.'); return false; // Can't send } else { showError('Access denied. Contact admin.'); exitApp(); } } ``` --- ## 7. FILES TO CREATE | File | Location | Purpose | |------|----------|---------| | RangerRegistration.sol | Blockchain/contracts/ | Solidity contract | | registration-service.cjs | rangerblock/lib/ | Node.js registration | | consent-service.cjs | rangerblock/lib/ | Consent management | | Admin dashboard updates | ~/.claude/ranger/admin/ | Registration queue UI | --- ## 8. IMPLEMENTATION PHASES ### Phase 1: Core Infrastructure (This Week) - [ ] Create RangerRegistration.sol - [ ] Create registration-service.cjs - [ ] Create consent-service.cjs - [ ] Test locally ### Phase 2: Admin Integration (Next Week) - [ ] Add registration queue to admin-registry.cjs - [ ] Add Registrations tab to admin-dashboard.cjs - [ ] Test approve/deny flow ### Phase 3: App Integration (Week 3) - [ ] Integrate into ranger-chat-lite - [ ] Integrate into just-chat - [ ] Integrate into server-only setup - [ ] Test end-to-end ### Phase 4: Testing (Week 4) - [ ] Test on MSI Vector - [ ] Test on AWS - [ ] Security review - [ ] Deploy to production --- ## 9. SECURITY NOTES ### What Admin Can See: - Username - App type - Registration date - Terms version accepted - Signature validity - Hardware ID (hashed, for ban enforcement) ### What Admin CANNOT See: - Full userId (only hash) - Full hardware fingerprint - Private key - Message content ### Hardware Ban Enforcement: - Hardware ID hashed but tracked - If banned user creates new identity, same hardware = blocked - Admin can see "hardware previously used by banned user" --- **Document Status**: READY FOR IMPLEMENTATION **Created**: December 4, 2025 **Author**: Claude Code (Ranger) for David Keane (IrishRanger) *Rangers lead the way!*