# SPDX-License-Identifier: Apache-2.0 # © 2026 Lutar, Stephen P. — SZL Holdings · ORCID 0009-0001-0110-4173 · Doctrine v11 # Authored by SZL Enterprise-Integration Team. Co-Authored-By: Perplexity Computer Agent. """szl_connectors.base — the ONE connector abstraction (not N hacks). Every enterprise CRM/ERP/platform/data-source binds to a single `Connector` base class. Each provider is a thin subclass whose ONLY per-provider variation is the body of `health()` / `read()` / `write()` (the real HTTP) + the auth wiring. The UI, the MCP layer, and the governance layer treat every connector identically. HARD DOCTRINE (non-negotiable — woven throughout): • NO fabricated records. A connector returns REAL live provider data (CONNECTED), an honest empty READY ("provide credentials to activate" + the exact secret name), or a clearly-LABELED SAMPLE (`sample_reason` set, used ONLY where no free tier exists). ERROR is honest. • NO committed keys. Every credential is read from env/Space-secret ONLY. Receipts store credential FINGERPRINT HASHES, never the key value. • Every write() is Λ-gated (Λ never 1.0) + DSSE/Khipu-receipted. • Trust never 100% (conformal anti-overconfidence floor 1/(n+1)). • 0 runtime CDN in served apps; these are live DATA fetches (data, not code). This generalizes the proven honest-state discipline already shipping in `szl_a11oy_live_feeds.py` (CISA KEV / NVD / arXiv wired live, labelled `live: true/false` + `source_status`) into a first-class connector framework. API references targeted (publicly documented shapes; SZL writes its own original client code, never copies proprietary SDK code) — see each subclass module's docstring + the package NOTICE. """ from __future__ import annotations import hashlib import json import os import time import urllib.error as _ue import urllib.parse as _up import urllib.request as _ur from dataclasses import asdict, dataclass, field from datetime import datetime, timezone from enum import Enum from typing import Any, Literal # ── auth kinds the framework understands ────────────────────────────────── AuthKind = Literal["none", "api_key", "oauth2", "basic", "aws_sigv4", "token"] _UA = "SZL-Connectors/1.0 (sovereign enterprise mesh; contact@szlholdings.ai)" _TIMEOUT = 8.0 class State(str, Enum): """The honest state of a connector RIGHT NOW.""" CONNECTED = "connected" # creds present + health() passed → LIVE provider data READY = "ready" # implemented + tested vs API shape; awaiting customer creds SAMPLE = "sample" # labeled fixture ONLY where no free tier exists ERROR = "error" # creds present but provider unreachable/denied (honest) def _now() -> str: return datetime.now(timezone.utc).isoformat() # ── typed return objects (propagated unchanged to UI + MCP) ──────────────── @dataclass class HealthReport: connector_id: str state: State auth_kind: AuthKind env_vars: list[str] # exact secret names this connector reads missing_env: list[str] # which are absent (drives "provide credentials") provider_base: str # the real API base it will hit checked_at: str = field(default_factory=_now) detail: str = "" # human-readable honest reason latency_ms: float | None = None sample_reason: str | None = None # if SAMPLE: WHY (e.g. "no free tier") free_tier: bool = False def to_dict(self) -> dict[str, Any]: d = asdict(self) d["state"] = self.state.value if isinstance(self.state, State) else self.state return d @dataclass class Records: connector_id: str category: str state: State # CONNECTED | READY | SAMPLE — propagated to UI records: list[dict[str, Any]] # [] when READY (no creds) — NEVER faked source: str # provider name + endpoint actually hit fetched_at: str = field(default_factory=_now) live: bool = False # True only when CONNECTED + real fetch receipt_hash: str | None = None # set for write(); reads are low-gate note: str = "" # honest label rendered in the UI source-chip schema_preview: list[str] = field(default_factory=list) # column headers for READY tiles count: int = 0 def to_dict(self) -> dict[str, Any]: d = asdict(self) d["state"] = self.state.value if isinstance(self.state, State) else self.state d["count"] = len(self.records) return d @dataclass class WriteResult: connector_id: str ok: bool state: State receipt_hash: str | None # DSSE/Khipu receipt — REQUIRED for any write lambda_value: float | None # Λ score of the action (NEVER 1.0) quorum: dict | None = None # 2-person / 3-of-4 status for state-changing detail: str = "" dsse: dict | None = None def to_dict(self) -> dict[str, Any]: d = asdict(self) d["state"] = self.state.value if isinstance(self.state, State) else self.state return d # ── HTTP helpers (single egress, brief no-op here; subclasses add caching) ─ def http_json(url: str, headers: dict | None = None, method: str = "GET", data: bytes | None = None, timeout: float = _TIMEOUT) -> tuple[int, Any]: """Return (status_code, parsed_json_or_text). Never raises into the request path.""" req = _ur.Request(url, headers={"User-Agent": _UA, **(headers or {})}, method=method, data=data) try: with _ur.urlopen(req, timeout=timeout) as resp: raw = resp.read().decode("utf-8", "replace") try: return resp.status, json.loads(raw) except Exception: return resp.status, raw except _ue.HTTPError as e: try: body = e.read().decode("utf-8", "replace") except Exception: body = "" return e.code, body except Exception as e: return 0, str(e) def http_text(url: str, headers: dict | None = None, timeout: float = _TIMEOUT) -> tuple[int, str]: req = _ur.Request(url, headers={"User-Agent": _UA, **(headers or {})}) try: with _ur.urlopen(req, timeout=timeout) as resp: return resp.status, resp.read().decode("utf-8", "replace") except _ue.HTTPError as e: return e.code, "" except Exception as e: return 0, str(e) # Credential fingerprints are derived with PBKDF2-HMAC-SHA256, not a single # SHA-256 pass. A bare hash of a (possibly low-entropy) credential is cheap to # brute-force / rainbow-table from the fingerprint alone (CodeQL # py/weak-sensitive-data-hashing). The fixed domain-separation salt keeps the # fingerprint DETERMINISTIC — the same credential always maps to the same # fingerprint, which is the whole point of a correlation fingerprint — while the # work factor makes recovery expensive. An optional deployment pepper # (SZL_FINGERPRINT_PEPPER) adds a keyed secret an attacker cannot precompute. _CRED_FP_SALT = b"szl.killinchu.cred-fingerprint.v1" _CRED_FP_ITERATIONS = 200_000 def cred_fingerprint(value: str) -> str: """Brute-force-resistant fingerprint of a credential — what a receipt may carry. NEVER the value. PBKDF2-HMAC-SHA256 over a deterministic salt (+ the optional SZL_FINGERPRINT_PEPPER) so a low-entropy credential cannot be recovered from its fingerprint, yet the same credential always maps to the same fingerprint.""" salt = _CRED_FP_SALT + os.environ.get("SZL_FINGERPRINT_PEPPER", "").encode("utf-8") dk = hashlib.pbkdf2_hmac("sha256", value.encode("utf-8"), salt, _CRED_FP_ITERATIONS) return "pbkdf2-sha256:" + dk.hex()[:32] # ── the honesty core — resolve_state() ───────────────────────────────────── def resolve_state(*, auth_kind: AuthKind, missing_env: list[str], has_fixture: bool, free_tier: bool, probe_ok: bool | None, probe_detail: str = "", ) -> tuple[State, str, str | None]: """The single decision function every connector uses to report an honest state. Returns (state, detail, sample_reason). Rules (verbatim from ENTERPRISE_INTEGRATION_SPEC §1.1): missing_env != [] → READY (render "provide credentials") auth_kind == "none" and provider reachable → CONNECTED (keyless live NOW) creds present and health() 200 → CONNECTED creds present and health() fails → ERROR (honest reason) no free tier AND no creds AND fixture set → SAMPLE (sample_reason mandatory) """ # keyless: reachability decides if auth_kind == "none": if probe_ok is True: return State.CONNECTED, probe_detail or "keyless public API reachable — live data", None if probe_ok is False: if has_fixture: return (State.SAMPLE, probe_detail or "keyless provider unreachable; labelled sample", "provider unreachable at request time") return State.ERROR, probe_detail or "keyless provider unreachable", None # probe not run (manifest cheap path) → optimistic CONNECTED label, verified on read return State.CONNECTED, "keyless public API — verified live on read", None # credentialed connectors if missing_env: # no creds yet if has_fixture and not free_tier: return (State.SAMPLE, "no free tier; labelled sample until credentials provided", "no free tier — connect to activate") secret_list = ", ".join(missing_env) return (State.READY, f"provide credentials to activate — set {secret_list}", None) # creds present → reachability decides if probe_ok is True: return State.CONNECTED, probe_detail or "credentials present + provider reachable — live data", None if probe_ok is False: return State.ERROR, probe_detail or "credentials present but provider unreachable/denied", None # creds present, probe deferred return State.CONNECTED, "credentials present — verified live on read", None # ── the base Connector ───────────────────────────────────────────────────── class Connector: """Base. Subclass per provider. Real HTTP only; honest states only. Subclass MUST set the class attributes below and override `read()` (and `write()` if the connector is writable). `health()` has a sane default that calls `_probe()` (override `_probe()` for a cheap reachability check). """ id: str = "base" category: str = "data_source" # crm|erp|identity|comms|itsm|warehouse|storage|observability|data_source|mesh|maritime|air|geo|vuln auth_kind: AuthKind = "none" env_vars: list[str] = [] # secret names; NEVER hardcode the values provider_base: str = "" # real API base URL free_tier: bool = False # True if a free dev sandbox / open demo / keyless exists writable: bool = False mcp_tool: str = "szl_connector_read" sample_records: list[dict[str, Any]] | None = None sample_reason_text: str | None = None schema_preview: list[str] = [] # column headers the tile shows in READY state docs_url: str = "" # "verify it yourself" link label: str = "" # human display name # ── credential resolution (env-only) ────────────────────────────────── def _creds(self) -> dict[str, str]: return {k: os.environ[k] for k in self.env_vars if os.environ.get(k)} def _missing_env(self) -> list[str]: # OAuth2 connectors: only the CLIENT_ID/SECRET (+ refresh) gate activation; # we report ALL declared env_vars that are absent. return [k for k in self.env_vars if not os.environ.get(k)] # ── cheap reachability probe (override per provider) ────────────────── def _probe(self) -> tuple[bool | None, str]: """Return (probe_ok, detail). None = deferred (manifest cheap path).""" return None, "" # ── default health() using resolve_state() ──────────────────────────── def health(self, *, probe: bool = False) -> HealthReport: missing = self._missing_env() probe_ok: bool | None = None detail_probe = "" latency = None if probe: # only probe if keyless OR creds present if self.auth_kind == "none" or not missing: t0 = time.time() probe_ok, detail_probe = self._probe() latency = round((time.time() - t0) * 1000, 1) state, detail, sample_reason = resolve_state( auth_kind=self.auth_kind, missing_env=missing, has_fixture=bool(self.sample_records), free_tier=self.free_tier, probe_ok=probe_ok, probe_detail=detail_probe, ) return HealthReport( connector_id=self.id, state=state, auth_kind=self.auth_kind, env_vars=list(self.env_vars), missing_env=missing, provider_base=self.provider_base, detail=detail, latency_ms=latency, sample_reason=sample_reason or self.sample_reason_text, free_tier=self.free_tier, ) # ── read() — subclasses override; default returns honest READY/SAMPLE ─ def read(self, query: dict | None = None) -> Records: h = self.health(probe=True) if h.state == State.SAMPLE and self.sample_records: return Records( connector_id=self.id, category=self.category, state=State.SAMPLE, records=list(self.sample_records), source=f"{self.label or self.id} (labelled SAMPLE)", live=False, note=h.sample_reason or "labelled sample (no free tier)", schema_preview=list(self.schema_preview), ) # READY / ERROR → zero rows, honest note (NEVER fabricated) return Records( connector_id=self.id, category=self.category, state=h.state, records=[], source=self.provider_base, live=False, note=h.detail, schema_preview=list(self.schema_preview), ) def write(self, action: dict | None = None) -> WriteResult: raise NotImplementedError(f"connector {self.id} is read-only") # ── convenience: a READY/SAMPLE Records helper for subclasses ───────── def _ready_records(self, detail: str) -> Records: return Records( connector_id=self.id, category=self.category, state=State.READY, records=[], source=self.provider_base, live=False, note=detail, schema_preview=list(self.schema_preview), ) __all__ = [ "AuthKind", "State", "HealthReport", "Records", "WriteResult", "Connector", "resolve_state", "http_json", "http_text", "cred_fingerprint", "_now", ]