diff --git a/currency-ledger/.gitignore b/currency-ledger/.gitignore new file mode 100644 index 0000000..b4891d2 --- /dev/null +++ b/currency-ledger/.gitignore @@ -0,0 +1,7 @@ +# Privacy Protection - Never commit personal data +ownership/identity-mapping.csv +**/identity-mapping.csv + +# Backup files +*.backup +*.bak diff --git a/currency-ledger/ledger/smartup-credits/transactions.csv b/currency-ledger/ledger/smartup-credits/transactions.csv index e69de29..f52ff52 100644 --- a/currency-ledger/ledger/smartup-credits/transactions.csv +++ b/currency-ledger/ledger/smartup-credits/transactions.csv @@ -0,0 +1,4 @@ +timestamp,type,amount,from,to,reference,description,approver,phase,evidence_link +# Smartup Credits (SC) Transaction Ledger +# Format: ISO timestamp, SC/REDEEM, amount, from_user, to_user, task_id, description, approver, phase, link_to_work +# Example: 2025-01-15T10:30:00Z,SC,50,,alice,task-123,Backend API completion,bob,validation,https://forgejo.../issues/123 diff --git a/currency-ledger/ledger/social-karma/transactions.csv b/currency-ledger/ledger/social-karma/transactions.csv index e69de29..cffe34e 100644 --- a/currency-ledger/ledger/social-karma/transactions.csv +++ b/currency-ledger/ledger/social-karma/transactions.csv @@ -0,0 +1,4 @@ +timestamp,type,amount,from,to,reference,description,awarded_by,category,evidence_link +# Social Karma (SK) Transaction Ledger +# Format: ISO timestamp, KARMA/DECAY, amount, from_user, to_user, event_id, description, awarder, category, evidence +# Example: 2025-01-15T11:00:00Z,KARMA,10,,alice,pr-456,Excellent code review for mesh protocol,bob,code_review,https://forgejo.../pull/456 diff --git a/currency-ledger/ledger/treasury/balance.csv b/currency-ledger/ledger/treasury/balance.csv index e69de29..b1cde59 100644 --- a/currency-ledger/ledger/treasury/balance.csv +++ b/currency-ledger/ledger/treasury/balance.csv @@ -0,0 +1,5 @@ +timestamp,event_type,amount_eur_delta,total_eur_balance,sc_outstanding,sc_liability_eur,ratio,notes,reference +# Treasury Balance and SC Liability Tracking +# Format: ISO timestamp, event_type, EUR_change, total_EUR, total_SC, SC_value_EUR, ratio, notes, reference +# The 3x Rule: sc_liability_eur must be ≤ 3x total_eur_balance +2025-01-15T00:00:00Z,INIT,0,0,0,0,0.0,Treasury initialized - Smartup Zero launch,system-init diff --git a/currency-ledger/ownership/book-of-owners.csv b/currency-ledger/ownership/book-of-owners.csv new file mode 100644 index 0000000..74d1d43 --- /dev/null +++ b/currency-ledger/ownership/book-of-owners.csv @@ -0,0 +1,2 @@ +owner_id,display_name,license_type,license_date,current_sk,voting_weight,status,last_updated +001,robbert_founder,work,2025-08-04T14:37:16.470130Z,0,1.00,active,2025-08-04T14:37:16.470130Z diff --git a/currency-ledger/ownership/license-transactions.csv b/currency-ledger/ownership/license-transactions.csv new file mode 100644 index 0000000..64ae3fa --- /dev/null +++ b/currency-ledger/ownership/license-transactions.csv @@ -0,0 +1,2 @@ +timestamp,owner_id,transaction_type,from_license,to_license,payment_eur,upgrade_reason,reference,approver +2025-08-04T14:37:16.470130Z,001,FOUNDER,,work,0,founding_entrepreneur,system-init,smartup-zero-launch diff --git a/currency-ledger/policies/credit-rates.yml b/currency-ledger/policies/credit-rates.yml index e69de29..9335783 100644 --- a/currency-ledger/policies/credit-rates.yml +++ b/currency-ledger/policies/credit-rates.yml @@ -0,0 +1,45 @@ +# Smartup Credits (SC) Rate Structure +# 1 SC = 1 EUR claim on treasury +# Updated: 2025-01-15 + +# Standard Task Rates +task_rates: + small_task: 25 # 1-2 hours work + medium_task: 50 # 3-4 hours work + large_task: 100 # 5-8 hours work + complex_task: 200 # 1-2 days work + +# ADM Triangle Split (Attacker/Defender Model) +adm_split: + attacker_percentage: 90 # Senior contributor doing main work + defender_percentage: 10 # Junior contributor learning + reviewing + midfielder_percentage: 0 # Engelbot handles automatically + +# Founding Work Audit Rates (Retroactive) +founding_work_rates: + research_hour: 25 # Historical R&D and investigation + planning_hour: 25 # Business plan and strategy creation + coding_hour: 30 # Technical development and prototyping + writing_hour: 20 # Documentation and content creation + governance_hour: 25 # Smartup model design and legal setup + +# Special Contribution Rates +special_rates: + team_captain_monthly: 100 # Monthly leadership bonus + mission_leader_bonus: 50 # Per completed objective + emergency_fix: 150 # Critical bug fixes + community_building: 75 # Outreach and recruitment + +# Phase-Based Multipliers +phase_multipliers: + validation: 1.0 # Standard rates during proof phase + design: 1.1 # 10% bonus during intensive design + production: 1.2 # 20% bonus during crunch time + organization: 1.0 # Back to standard for stable operations + +# Treasury Protection Rules +treasury_rules: + max_outstanding_multiplier: 3 # Outstanding SC ≤ 3x cash treasury + founding_work_cap: 10000 # Maximum retroactive SC for entrepreneur + daily_mint_limit: 500 # Max SC mintable per person per day + requires_defender_approval: true diff --git a/currency-ledger/policies/karma-rules.yml b/currency-ledger/policies/karma-rules.yml index e69de29..5da3af8 100644 --- a/currency-ledger/policies/karma-rules.yml +++ b/currency-ledger/policies/karma-rules.yml @@ -0,0 +1,70 @@ +# Social Karma (SK) Award Structure +# Non-transferable reputation currency +# Updated: 2025-01-15 + +# SK Award Categories +karma_awards: + # Code & Technical Quality + code_review: 5 # Reviewing PRs and providing feedback + bug_find: 10 # Finding and reporting bugs + documentation: 15 # Writing guides and technical docs + + # Community Building + mentoring_session: 10 # One-on-one help with newcomers + mentoring_weekly: 5 # Ongoing mentorship (awarded weekly) + conflict_resolution: 25 # Successfully mediating disputes + onboarding_help: 8 # Helping new members navigate + + # Governance & Leadership + governance_participation: 20 # Leading discussions in General Forum + proposal_accepted: 20 # Successful proposals that pass votes + meeting_facilitation: 15 # Running team meetings effectively + cross_team_coordination: 12 # Bridging different teams + + # Mission Completion + objective_completion: 15 # Completing mission objectives + deadline_hit: 10 # Meeting critical deadlines + quality_delivery: 12 # Exceptional work quality recognition + +# SK Privilege Thresholds +privilege_thresholds: + propose_in_forum: 50 # Can create binding vote proposals + apply_team_captain: 100 # Eligible for team leadership roles + lead_missions: 200 # Can be assigned as Mission Leader + join_leadership_team: 500 # Eligible for Leadership Team + +# Voting Weight (SK enhances but doesn't replace democracy) +voting_weight: + base_vote: 1.0 # Everyone gets 1 vote regardless + sk_bonus_max: 1.5 # Maximum vote weight with high SK + sk_bonus_threshold: 500 # SK needed for max voting bonus + calculation: "min(1.5, 1 + (sk_points / 1000))" + +# SK Decay Mechanism (prevents founder entrenchment) +decay_rules: + monthly_decay_rate: 0.10 # 10% monthly decay + minimum_floor: 0 # Can decay to zero (stay active!) + grace_period_days: 30 # No decay for first month after earning + activity_bonus: 5 # Monthly bonus for active participation + +# Anti-Gaming Measures +validation_rules: + cannot_buy: true # No amount of money gets you SK + cannot_transfer: true # Your reputation is yours alone + cannot_hoard: true # Use influence or lose it to decay + peer_review_required: true # SK awards need defender confirmation + +# SK Sources (who can award SK) +award_sources: + peer_recognition: true # Team members award each other + captain_awards: true # Team Captains can award their team + leadership_awards: true # Leadership Team for exceptional cases + community_votes: true # General Forum for major contributions + automated_systems: false # No bot-awarded SK (human judgment only) + +# Monthly SK Budget (prevents inflation) +team_budgets: + per_team_monthly: 200 # Each team can award 200 SK/month + leadership_monthly: 500 # Leadership Team additional budget + community_monthly: 300 # General Forum discretionary awards + rollover_limit: 0.5 # Unused budget 50% carries to next month diff --git a/currency-ledger/policies/license-policies.yml b/currency-ledger/policies/license-policies.yml new file mode 100644 index 0000000..cc76f38 --- /dev/null +++ b/currency-ledger/policies/license-policies.yml @@ -0,0 +1,105 @@ +# License System Policies +# Updated: 2025-01-15 + +# License Types and Capabilities +license_capabilities: + campaign: + can_earn_sk: true + can_earn_sc: false + sk_categories: ["community_building", "governance_participation", "mentoring_help"] + max_daily_sk: 25 + voting_rights: true + forum_access: "1_general_forum" + + watch: + can_earn_sk: true + can_earn_sc: false + sk_categories: ["all_except_leadership"] + max_daily_sk: 50 + voting_rights: true + forum_access: "1_general_forum,limited_2_workplace" + + work: + can_earn_sk: true + can_earn_sc: true + sk_categories: ["all"] + max_daily_sk: 100 + max_daily_sc: 500 + voting_rights: true + forum_access: "all_tiers" + + organizational: + can_earn_sk: true + can_earn_sc: true + sk_categories: ["all"] + max_daily_sk: 100 + max_daily_sc: 500 + voting_rights: true + voting_weight_bonus: 0 # Same as individual, no special treatment + forum_access: "all_tiers" + +# Automatic Upgrade Rules +upgrade_thresholds: + campaign_to_watch: + sk_required: 100 + additional_requirements: [] + approval_needed: false + notification_required: true + + watch_to_work: + payment_required: 200 # EUR + sk_minimum: 50 # Must demonstrate some engagement + approval_needed: false + + work_to_organizational: + payment_required: 5000 # EUR + sk_minimum: 200 # Must be proven contributor + approval_needed: true # Community/Leadership review + +# License Pricing (increases by phase) +pricing: + validation_phase: + campaign: 0 + watch: 100 + work: 200 + organizational: 5000 + + design_phase: + campaign: 0 + watch: 200 + work: 400 + organizational: 10000 + + production_phase: + campaign: 0 + watch: 400 + work: 800 + organizational: 20000 + + organization_phase: + campaign: 0 + watch: 800 + work: 1600 + organizational: 40000 + +# Identity and Privacy +identity_rules: + alias_required: false + real_name_public: false + can_change_alias: true + alias_change_limit: 2 # per year + privacy_levels: ["full_public", "alias_only", "anonymous"] + +# Voting Weight Calculation +voting_weight: + base_weight: 1.0 + sk_bonus_formula: "min(1.5, 1 + (current_sk / 1000))" + max_weight: 1.5 + organizational_bonus: 0 # No special voting power for big payments + +# Status Management +status_rules: + inactive_threshold_days: 90 # No activity = inactive status + suspension_requires: "leadership_vote" + reactivation_requires: "login_activity" + permanent_ban_requires: "community_vote" diff --git a/currency-ledger/policies/validation-rules.yml b/currency-ledger/policies/validation-rules.yml index e69de29..172ac82 100644 --- a/currency-ledger/policies/validation-rules.yml +++ b/currency-ledger/policies/validation-rules.yml @@ -0,0 +1,82 @@ +# Currency Ledger Validation Rules +# Ensures system integrity and democratic oversight +# Updated: 2025-01-15 + +# Transaction Validation +transaction_rules: + requires_defender_approval: true + requires_captain_approval: true # Team Captain must approve team transactions + requires_evidence: true # Link to completed work required + max_transaction_age_days: 7 # Must be processed within week + retroactive_limit_days: 30 # Can't claim SC for work >30 days old + +# Democratic Oversight +approval_process: + small_transactions_threshold: 100 # SC amounts ≤ 100 need team approval + large_transactions_threshold: 200 # SC amounts > 200 need community review + founding_work_review_days: 7 # Community review period for founding audit + binding_vote_threshold: 3 # Major issues need General Forum vote + lazy_consensus_hours: 48 # 48h for community feedback + +# License Integration (Progressive Transparency) +license_requirements: + campaign_license: + can_view_ledger: true + can_propose_transactions: false + can_approve_transactions: false + watch_license: + can_view_ledger: true + can_propose_transactions: false + can_approve_transactions: false + work_license: + can_view_ledger: true + can_propose_transactions: true # Can claim SC for completed tasks + can_approve_transactions: false + organizational_license: + can_view_ledger: true + can_propose_transactions: true + can_approve_transactions: false # No special approval powers + +# Treasury Protection +treasury_validation: + max_outstanding_ratio: 3.0 # Outstanding SC ≤ 3x treasury EUR + min_treasury_reserve: 1000 # Always keep €1000 emergency reserve + redemption_window_trigger: 0.8 # Open redemption at 80% treasury capacity + fifo_redemption: true # First earned, first redeemed + +# Quality Assurance +quality_rules: + requires_task_reference: true # Must link to Forgejo issue/task + requires_time_estimate: true # Estimate vs actual hours tracking + requires_defender_review: true # Code/work quality confirmation + allows_partial_payments: true # Can pay in installments for large tasks + +# Anti-Fraud Measures +security_rules: + max_daily_sc_per_person: 500 # Prevents gaming + requires_captain_countersign: true # Team Captain must approve team payments + founder_cap_total: 10000 # Max retroactive SC for any founder + community_veto_window: 48 # Hours for community to object + permanent_public_record: true # All transactions permanent in git history + +# Integration Rules +technical_integration: + forgejo_issue_required: true # Must reference actual task + element_notification: true # Announce all awards in General Forum + engelbot_automation: true # Bot handles routine validations + open_collective_sync: true # Treasury sync with OC EU + +# Phase-Specific Rules +phase_rules: + validation_phase: + founding_work_audit: true # Special process for entrepreneur work + community_vote_required: true # Major SC awards need approval + conservative_rates: true # Start with proven rates + design_phase: + increased_complexity_bonus: true # Higher rates for complex design work + science_team_veto: true # Science team can halt inappropriate awards + cross_team_collaboration_bonus: true + production_phase: + crunch_time_multiplier: 1.2 # 20% bonus during intensive development + quality_gates: true # Extra validation for production code + user_feedback_integration: true # Bonus for incorporating diff --git a/currency-ledger/scripts/generate-reports.py b/currency-ledger/scripts/generate-reports.py old mode 100644 new mode 100755 index e69de29..92aab05 --- a/currency-ledger/scripts/generate-reports.py +++ b/currency-ledger/scripts/generate-reports.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +""" +Currency Ledger Report Generator +Creates summary reports for community transparency +""" + +import csv +import yaml +from datetime import datetime +import os +from collections import defaultdict + +def generate_sc_summary(): + """Generate SC summary report""" + print("📊 SMARTUP CREDITS SUMMARY REPORT") + print("=" * 40) + + ledger_file = os.path.join(os.path.dirname(__file__), '..', 'ledger', 'smartup-credits', 'transactions.csv') + + try: + with open(ledger_file, 'r') as f: + reader = csv.DictReader(f) + + user_balances = defaultdict(int) + total_minted = 0 + total_redeemed = 0 + transaction_count = 0 + + for row in reader: + if row['type'] == 'SC': + amount = int(row['amount']) + user_balances[row['to']] += amount + total_minted += amount + transaction_count += 1 + elif row['type'] == 'REDEEM': + amount = int(row['amount']) + user_balances[row['from']] -= amount + total_redeemed += amount + transaction_count += 1 + + print(f"Total SC Minted: {total_minted}") + print(f"Total SC Redeemed: {total_redeemed}") + print(f"SC Outstanding: {total_minted - total_redeemed}") + print(f"Total Transactions: {transaction_count}") + print(f"Active Contributors: {len([u for u in user_balances if user_balances[u] > 0])}") + + # Top contributors + if user_balances: + print("\n🏆 TOP SC EARNERS:") + sorted_users = sorted(user_balances.items(), key=lambda x: x[1], reverse=True) + for i, (user, balance) in enumerate(sorted_users[:5]): + if balance > 0: + print(f"{i+1}. {user}: {balance} SC") + + except FileNotFoundError: + print("❌ No SC transactions found") + except Exception as e: + print(f"❌ Error generating SC report: {e}") + +def generate_treasury_report(): + """Generate treasury health report""" + print("\n💰 TREASURY HEALTH REPORT") + print("=" * 30) + + treasury_file = os.path.join(os.path.dirname(__file__), '..', 'ledger', 'treasury', 'balance.csv') + + try: + with open(treasury_file, 'r') as f: + reader = csv.DictReader(f) + rows = list(reader) + + if rows: + latest = rows[-1] + eur_balance = float(latest['total_eur_balance']) + sc_outstanding = int(latest['sc_outstanding']) + sc_liability = float(latest['sc_liability_eur']) + + print(f"💶 EUR Treasury: €{eur_balance:,.2f}") + print(f"🪙 SC Outstanding: {sc_outstanding:,} SC") + print(f"💸 SC Liability: €{sc_liability:,.2f}") + + if eur_balance > 0: + coverage_ratio = eur_balance / sc_liability if sc_liability > 0 else float('inf') + print(f"📊 Coverage Ratio: {coverage_ratio:.2f}x") + + if coverage_ratio >= 1.0: + print("✅ Full SC redemption possible") + else: + redemption_capacity = int(eur_balance) + print(f"⚠️ Partial redemption: €{redemption_capacity:,} available") + + # 3x rule check + max_allowed_sc = eur_balance * 3 + print(f"🛡️ 3x Rule: {sc_outstanding:,} / {max_allowed_sc:,.0f} SC allowed") + + if sc_outstanding <= max_allowed_sc: + print("✅ 3x Rule: COMPLIANT") + else: + print("🚨 3x Rule: VIOLATION") + + else: + print("⚠️ Treasury initialized but no balance records") + + except FileNotFoundError: + print("❌ No treasury records found") + except Exception as e: + print(f"❌ Error generating treasury report: {e}") + +def main(): + """Generate all reports""" + print("📈 SMARTUP ZERO FINANCIAL REPORTS") + print(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + print("=" * 50) + + generate_sc_summary() + generate_treasury_report() + + print("\n" + "=" * 50) + print("💡 All ledger data is public and auditable in git history") + +if __name__ == "__main__": + main() diff --git a/currency-ledger/scripts/initialize-founder.py b/currency-ledger/scripts/initialize-founder.py new file mode 100755 index 0000000..fbabc8d --- /dev/null +++ b/currency-ledger/scripts/initialize-founder.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +""" +Initialize the founding entrepreneur in Book of Owners +This creates the first owner record for Robbert +""" + +import csv +from datetime import datetime +import os + +def initialize_founder(): + """Add the founding entrepreneur to Book of Owners""" + + base_path = os.path.join(os.path.dirname(__file__), '..') + timestamp = datetime.now().isoformat() + 'Z' + + # Create identity mapping (PRIVATE - not committed) + identity_file = os.path.join(base_path, 'ownership', 'identity-mapping.csv') + with open(identity_file, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['owner_id', 'real_name', 'email', 'display_name', 'privacy_level', 'created_date']) + writer.writerow(['001', 'Robbert Schep', 'robbert@timeline0.org', 'robbert_founder', 'alias_only', timestamp]) + + # Create license transaction record + transactions_file = os.path.join(base_path, 'ownership', 'license-transactions.csv') + with open(transactions_file, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['timestamp', 'owner_id', 'transaction_type', 'from_license', 'to_license', 'payment_eur', 'upgrade_reason', 'reference', 'approver']) + writer.writerow([timestamp, '001', 'FOUNDER', '', 'work', 0, 'founding_entrepreneur', 'system-init', 'smartup-zero-launch']) + + # Update Book of Owners (PUBLIC) + book_file = os.path.join(base_path, 'ownership', 'book-of-owners.csv') + with open(book_file, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['owner_id', 'display_name', 'license_type', 'license_date', 'current_sk', 'voting_weight', 'status', 'last_updated']) + writer.writerow(['001', 'robbert_founder', 'work', timestamp, '0', '1.00', 'active', timestamp]) + + print("✅ Founding entrepreneur initialized in Book of Owners") + print("📝 Identity mapping created (private file)") + print("📊 Ready for founding work audit process") + +if __name__ == "__main__": + initialize_founder() diff --git a/currency-ledger/scripts/manage-owners.py b/currency-ledger/scripts/manage-owners.py new file mode 100755 index 0000000..7082c93 --- /dev/null +++ b/currency-ledger/scripts/manage-owners.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +""" +Book of Owners Management Script +Handles license purchases, upgrades, and validation +""" + +import csv +import yaml +from datetime import datetime +import os +import uuid + +class OwnershipManager: + def __init__(self): + self.base_path = os.path.join(os.path.dirname(__file__), '..') + self.load_policies() + + def load_policies(self): + """Load license policies""" + with open(os.path.join(self.base_path, 'policies', 'license-policies.yml'), 'r') as f: + self.policies = yaml.safe_load(f) + + def generate_owner_id(self): + """Generate unique owner ID""" + # Simple 3-digit incremental ID (could be more sophisticated) + book_file = os.path.join(self.base_path, 'ownership', 'book-of-owners.csv') + try: + with open(book_file, 'r') as f: + reader = csv.DictReader(f) + existing_ids = [int(row['owner_id']) for row in reader if row['owner_id'].isdigit()] + next_id = max(existing_ids) + 1 if existing_ids else 1 + return f"{next_id:03d}" + except (FileNotFoundError, ValueError): + return "001" + + def add_new_owner(self, real_name, email, display_name, license_type, payment_eur=0, privacy_level="alias_only"): + """Add new owner to the system""" + owner_id = self.generate_owner_id() + timestamp = datetime.now().isoformat() + 'Z' + + # Add to identity mapping (private) + identity_file = os.path.join(self.base_path, 'ownership', 'identity-mapping.csv') + with open(identity_file, 'a', newline='') as f: + writer = csv.writer(f) + writer.writerow([owner_id, real_name, email, display_name, privacy_level, timestamp]) + + # Add to license transactions + self.record_license_transaction(owner_id, "PURCHASE", "", license_type, payment_eur, "initial_purchase") + + # Update book of owners + self.update_book_of_owners(owner_id, display_name, license_type) + + print(f"✅ New owner added: {display_name} ({owner_id}) - {license_type} license") + return owner_id + + def record_license_transaction(self, owner_id, transaction_type, from_license, to_license, payment_eur, reason, reference="manual", approver="system"): + """Record license change in transaction log""" + timestamp = datetime.now().isoformat() + 'Z' + + transactions_file = os.path.join(self.base_path, 'ownership', 'license-transactions.csv') + with open(transactions_file, 'a', newline='') as f: + writer = csv.writer(f) + writer.writerow([timestamp, owner_id, transaction_type, from_license, to_license, payment_eur, reason, reference, approver]) + + def update_book_of_owners(self, owner_id, display_name, license_type, current_sk=0, status="active"): + """Update current book of owners record""" + timestamp = datetime.now().isoformat() + 'Z' + voting_weight = min(1.5, 1 + (current_sk / 1000)) + + book_file = os.path.join(self.base_path, 'ownership', 'book-of-owners.csv') + + # Read existing records + records = [] + try: + with open(book_file, 'r') as f: + reader = csv.DictReader(f) + records = [row for row in reader if row['owner_id'] != owner_id] + except FileNotFoundError: + pass + + # Add/update record + records.append({ + 'owner_id': owner_id, + 'display_name': display_name, + 'license_type': license_type, + 'license_date': timestamp, + 'current_sk': current_sk, + 'voting_weight': f"{voting_weight:.2f}", + 'status': status, + 'last_updated': timestamp + }) + + # Write back + with open(book_file, 'w', newline='') as f: + fieldnames = ['owner_id', 'display_name', 'license_type', 'license_date', 'current_sk', 'voting_weight', 'status', 'last_updated'] + writer = csv.DictWriter(f, fieldnames=fieldnames) + writer.writeheader() + writer.writerows(records) + + def check_sk_upgrades(self): + """Check for automatic SK-based license upgrades""" + print("🔍 Checking for automatic license upgrades...") + + # Load current SK balances from karma ledger + sk_balances = self.get_current_sk_balances() + + # Check each owner for upgrade eligibility + book_file = os.path.join(self.base_path, 'ownership', 'book-of-owners.csv') + with open(book_file, 'r') as f: + reader = csv.DictReader(f) + for owner in reader: + owner_id = owner['owner_id'] + current_license = owner['license_type'] + display_name = owner['display_name'] + current_sk = sk_balances.get(display_name, 0) + + # Check campaign -> watch upgrade + if current_license == 'campaign' and current_sk >= 100: + print(f"🎉 Auto-upgrade: {display_name} (Campaign → Watch) - {current_sk} SK earned!") + self.record_license_transaction(owner_id, "UPGRADE_SK", "campaign", "watch", 0, "sk_threshold_100") + self.update_book_of_owners(owner_id, display_name, "watch", current_sk) + + def get_current_sk_balances(self): + """Get current SK balances from karma ledger""" + balances = {} + karma_file = os.path.join(self.base_path, 'ledger', 'social-karma', 'transactions.csv') + + try: + with open(karma_file, 'r') as f: + reader = csv.DictReader(f) + for row in reader: + if row['type'] == 'KARMA': + balances[row['to']] = balances.get(row['to'], 0) + int(row['amount']) + elif row['type'] == 'DECAY': + balances[row['from']] = balances.get(row['from'], 0) - int(row['amount']) + except FileNotFoundError: + pass + + return balances + + def validate_currency_award(self, username, currency_type, amount): + """Validate if user can receive SC or SK award""" + # Get user's license type + book_file = os.path.join(self.base_path, 'ownership', 'book-of-owners.csv') + + try: + with open(book_file, 'r') as f: + reader = csv.DictReader(f) + for owner in reader: + if owner['display_name'] == username: + license_type = owner['license_type'] + + # Check SC eligibility + if currency_type == 'SC': + can_earn = self.policies['license_capabilities'][license_type]['can_earn_sc'] + if not can_earn: + return False, f"{username} has {license_type} license - cannot earn SC (needs work/organizational)" + + # Check SK eligibility + elif currency_type == 'SK': + can_earn = self.policies['license_capabilities'][license_type]['can_earn_sk'] + if not can_earn: + return False, f"{username} has {license_type} license - cannot earn SK" + + return True, f"✅ {username} eligible for {amount} {currency_type}" + + return False, f"❌ {username} not found in Book of Owners" + + except FileNotFoundError: + return False, "❌ Book of Owners not found" + +def main(): + """Main owner management interface""" + manager = OwnershipManager() + + print("📖 BOOK OF OWNERS MANAGEMENT") + print("=" * 40) + print("1. Add new owner") + print("2. Check SK upgrade eligibility") + print("3. Validate currency award") + print("4. Show current owners") + + # For now, just show current owners + book_file = os.path.join(manager.base_path, 'ownership', 'book-of-owners.csv') + try: + with open(book_file, 'r') as f: + reader = csv.DictReader(f) + owners = list(reader) + + if owners: + print(f"\n📊 Current Owners: {len([o for o in owners if o['owner_id']])}") + print("-" * 60) + for owner in owners: + if owner['owner_id']: # Skip header comments + print(f"{owner['owner_id']}: {owner['display_name']} ({owner['license_type']}) - {owner['current_sk']} SK") + else: + print("📝 No owners registered yet") + + except FileNotFoundError: + print("📝 Book of Owners not created yet") + +if __name__ == "__main__": + main() diff --git a/currency-ledger/scripts/validate-ledger.py b/currency-ledger/scripts/validate-ledger.py old mode 100644 new mode 100755 index e69de29..eddceda --- a/currency-ledger/scripts/validate-ledger.py +++ b/currency-ledger/scripts/validate-ledger.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +""" +Currency Ledger Validation Script +Ensures ledger integrity and policy compliance +""" + +import csv +import yaml +from datetime import datetime +import os + +def load_policies(): + """Load policy configuration files""" + policies = {} + policy_dir = os.path.join(os.path.dirname(__file__), '..', 'policies') + + with open(os.path.join(policy_dir, 'credit-rates.yml'), 'r') as f: + policies['credit_rates'] = yaml.safe_load(f) + + with open(os.path.join(policy_dir, 'karma-rules.yml'), 'r') as f: + policies['karma_rules'] = yaml.safe_load(f) + + with open(os.path.join(policy_dir, 'validation-rules.yml'), 'r') as f: + policies['validation'] = yaml.safe_load(f) + + return policies + +def validate_sc_ledger(): + """Validate Smartup Credits ledger""" + print("🔍 Validating Smartup Credits ledger...") + + total_sc = 0 + ledger_file = os.path.join(os.path.dirname(__file__), '..', 'ledger', 'smartup-credits', 'transactions.csv') + + try: + with open(ledger_file, 'r') as f: + reader = csv.DictReader(f) + transaction_count = 0 + + for row in reader: + if row['type'] == 'SC': + total_sc += int(row['amount']) + transaction_count += 1 + elif row['type'] == 'REDEEM': + total_sc -= int(row['amount']) + transaction_count += 1 + + print(f"✅ Total SC Outstanding: {total_sc}") + print(f"✅ Transactions Processed: {transaction_count}") + + except FileNotFoundError: + print("❌ SC ledger file not found") + return False + except Exception as e: + print(f"❌ Error validating SC ledger: {e}") + return False + + return True + +def validate_treasury(): + """Validate treasury balance and 3x rule""" + print("🔍 Validating treasury balance...") + + treasury_file = os.path.join(os.path.dirname(__file__), '..', 'ledger', 'treasury', 'balance.csv') + + try: + with open(treasury_file, 'r') as f: + reader = csv.DictReader(f) + rows = list(reader) + + if rows: + latest = rows[-1] + eur_balance = float(latest['total_eur_balance']) + sc_outstanding = int(latest['sc_outstanding']) + ratio = float(latest['ratio']) + + print(f"✅ EUR Treasury: €{eur_balance}") + print(f"✅ SC Outstanding: {sc_outstanding} SC") + print(f"✅ Current Ratio: {ratio:.2f}") + + # Check 3x rule + if sc_outstanding <= (eur_balance * 3): + print("✅ 3x Rule: COMPLIANT") + else: + print("❌ 3x Rule: VIOLATION - Too much SC outstanding!") + return False + else: + print("⚠️ Treasury initialized but no transactions yet") + + except FileNotFoundError: + print("❌ Treasury file not found") + return False + except Exception as e: + print(f"❌ Error validating treasury: {e}") + return False + + return True + +def main(): + """Main validation function""" + print("🚀 Smartup Zero Currency Ledger Validation") + print("=" * 50) + + # Load policies + try: + policies = load_policies() + print("✅ Policy files loaded successfully") + except Exception as e: + print(f"❌ Error loading policies: {e}") + return + + # Validate ledgers + sc_valid = validate_sc_ledger() + treasury_valid = validate_treasury() + + print("=" * 50) + if sc_valid and treasury_valid: + print("🎉 All validations PASSED - Ledger is healthy!") + else: + print("🚨 Validation FAILED - Check errors above") + +if __name__ == "__main__": + main()