zevora / agent /evolution /contribution.py
Dani12po's picture
ZEVORA 0.2.0 - source distribution (sanitized release)
4d2ab8d verified
Raw History Blame Contribute Delete
3.9 kB
"""Consent-aware, pre-sanitized collective contribution queue."""
from datetime import datetime, timezone
import hashlib
import json
from typing import Any
from ..config import settings
from ..memory.store import Store
from .registry import CollectiveRegistry
from .sanitizer import sanitize
CONSENT_SETTINGS = {
'skill': 'collective_consent_skills',
'knowledge': 'collective_consent_knowledge',
'routing': 'collective_consent_routing',
'evaluation': 'collective_consent_evaluation',
}
class ContributionQueue:
def __init__(self, store: Store):
self.store = store
def enqueue(self, contribution_type: str, payload: dict[str, Any]) -> dict:
consent_setting = CONSENT_SETTINGS.get(contribution_type)
if not settings.collective_learning_enabled:
return {'accepted': False, 'reason': 'collective_learning_disabled'}
if not consent_setting or not bool(getattr(settings, consent_setting, False)):
return {'accepted': False, 'reason': 'consent_required'}
result = sanitize(contribution_type, payload)
if not result.accepted or result.payload is None:
return {'accepted': False, 'reason': ','.join(result.reasons) or 'sanitization_rejected'}
serialized = json.dumps(result.payload, sort_keys=True, separators=(',', ':'))
digest = hashlib.sha256(serialized.encode()).hexdigest()
now = datetime.now(timezone.utc).isoformat()
with self.store.connection() as conn:
conn.execute('''INSERT OR IGNORE INTO contribution_queue(
contribution_type,payload_json,content_hash,consent_scope,status,
rejection_reason,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?)''',
(contribution_type, serialized, digest, consent_setting, 'sanitized', None, now, now),
)
return {'accepted': True, 'content_hash': digest, 'status': 'sanitized'}
def pending(self) -> list[dict]:
with self.store.connection() as conn:
rows = conn.execute(
"SELECT id,contribution_type,payload_json,content_hash FROM contribution_queue WHERE status='sanitized' ORDER BY id"
).fetchall()
return [{
'id': row['id'], 'type': row['contribution_type'],
'payload': json.loads(row['payload_json']), 'content_hash': row['content_hash'],
} for row in rows]
async def publish(self, registry: CollectiveRegistry, *, approved: bool = False) -> dict:
"""Upload requires an explicit caller approval even after stored consent."""
if not approved:
raise PermissionError('publishing contributions requires explicit approval')
pending = self.pending()
if not pending:
return {'published': 0, 'registry': 'none'}
result = await registry.publish([
{'type': item['type'], 'payload': item['payload'], 'content_hash': item['content_hash']}
for item in pending
])
now = datetime.now(timezone.utc).isoformat()
with self.store.connection() as conn:
conn.executemany(
"UPDATE contribution_queue SET status='published',updated_at=? WHERE id=?",
[(now, item['id']) for item in pending],
)
return result
def status(self) -> dict:
with self.store.connection() as conn:
rows = conn.execute('SELECT status,COUNT(*) count FROM contribution_queue GROUP BY status').fetchall()
return {
'enabled': settings.collective_learning_enabled,
'consent': {key: bool(getattr(settings, value, False)) for key, value in CONSENT_SETTINGS.items()},
'queue': {row['status']: row['count'] for row in rows},
'silent_uploads': False,
}