Implement Book of Owners and license system

- Add ownership ledger with public aliases and private identity mapping
- Create license transaction tracking and upgrade automation
- Implement validation system for SC/SK awards based on licenses
- Set up privacy protection with .gitignore for sensitive data
- Initialize founding entrepreneur as owner #001
- Ready for founding work audit process
master
Robbert Schep 2025-08-04 14:45:23 +02:00
parent 0b777d311f
commit 5738af29df
14 changed files with 817 additions and 0 deletions

7
currency-ledger/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
# Privacy Protection - Never commit personal data
ownership/identity-mapping.csv
**/identity-mapping.csv
# Backup files
*.backup
*.bak

View File

@ -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
1 timestamp,type,amount,from,to,reference,description,approver,phase,evidence_link
1 timestamp,type,amount,from,to,reference,description,approver,phase,evidence_link
2 # Smartup Credits (SC) Transaction Ledger
3 # Format: ISO timestamp, SC/REDEEM, amount, from_user, to_user, task_id, description, approver, phase, link_to_work
4 # Example: 2025-01-15T10:30:00Z,SC,50,,alice,task-123,Backend API completion,bob,validation,https://forgejo.../issues/123

View File

@ -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
1 timestamp,type,amount,from,to,reference,description,awarded_by,category,evidence_link
1 timestamp,type,amount,from,to,reference,description,awarded_by,category,evidence_link
2 # Social Karma (SK) Transaction Ledger
3 # Format: ISO timestamp, KARMA/DECAY, amount, from_user, to_user, event_id, description, awarder, category, evidence
4 # Example: 2025-01-15T11:00:00Z,KARMA,10,,alice,pr-456,Excellent code review for mesh protocol,bob,code_review,https://forgejo.../pull/456

View File

@ -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
1 timestamp,event_type,amount_eur_delta,total_eur_balance,sc_outstanding,sc_liability_eur,ratio,notes,reference
1 timestamp,event_type,amount_eur_delta,total_eur_balance,sc_outstanding,sc_liability_eur,ratio,notes,reference
2 # Treasury Balance and SC Liability Tracking
3 # Format: ISO timestamp, event_type, EUR_change, total_EUR, total_SC, SC_value_EUR, ratio, notes, reference
4 # The 3x Rule: sc_liability_eur must be ≤ 3x total_eur_balance
5 2025-01-15T00:00:00Z,INIT,0,0,0,0,0.0,Treasury initialized - Smartup Zero launch,system-init

View File

@ -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
1 owner_id display_name license_type license_date current_sk voting_weight status last_updated
2 001 robbert_founder work 2025-08-04T14:37:16.470130Z 0 1.00 active 2025-08-04T14:37:16.470130Z

View File

@ -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
1 timestamp owner_id transaction_type from_license to_license payment_eur upgrade_reason reference approver
2 2025-08-04T14:37:16.470130Z 001 FOUNDER work 0 founding_entrepreneur system-init smartup-zero-launch

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

122
currency-ledger/scripts/generate-reports.py Normal file → Executable file
View File

@ -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()

View File

@ -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()

View File

@ -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()

123
currency-ledger/scripts/validate-ledger.py Normal file → Executable file
View File

@ -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()