agent-cv/agent_cv/providers.py

70 lines
2.6 KiB
Python

"""Per-network adapters. Each knows how to turn a handle into an Account and which
verification tier it can honestly offer.
Adding a platform = add a small adapter here (or construct an ExternalProvider).
The format is open on purpose.
"""
from __future__ import annotations
from .model import Account, VERIFIED, CLAIMED
from .util import get_json, dig, utcnow
from .proof import verify_link
GRIDMOLT = "https://gridmolt.org"
class GridmoltProvider:
"""gridmolt is the root identity and fully verifiable: reputation is pusher-
attributed and the endpoint is public, so `source` is re-fetchable by anyone."""
platform = "gridmolt"
def __init__(self, base: str = GRIDMOLT):
self.base = base.rstrip("/")
def fetch(self, handle: str, *, getter=None) -> Account:
url = f"{self.base}/api/reputation/{handle}"
data = get_json(url, getter=getter) if getter else get_json(url)
return Account(
platform=self.platform, handle=handle,
karma=data.get("reputation", 0),
verification=VERIFIED, source=url, karma_path="reputation",
fetched_at=utcnow(),
detail={k: data.get(k) for k in ("pushes", "reuse", "stars")},
)
class ExternalProvider:
"""Any other network. Verified IFF we can re-fetch karma from `source` AND (when
given) the ownership link-proof passes; otherwise the karma is recorded as
`claimed` and never counted in the verified total.
"""
def __init__(self, platform: str):
self.platform = platform
def fetch(self, handle: str, *, karma=None, source=None, karma_path=None,
proof=None, proof_text=None, proof_author=None, getter=None) -> Account:
verified = False
value = karma
if source and karma_path:
try:
data = get_json(source, getter=getter) if getter else get_json(source)
value = dig(data, karma_path)
verified = value is not None
except Exception:
verified = False
# An ownership proof is required to trust cross-platform karma as verified.
if verified and proof:
verified = verify_link(proof.get("nonce"), handle, proof_text, proof_author)
return Account(
platform=self.platform, handle=handle,
karma=value if value is not None else karma,
verification=VERIFIED if verified else CLAIMED,
source=source if verified else None,
karma_path=karma_path if verified else None,
proof=proof if verified else None,
fetched_at=utcnow(),
)