From 315ddd65a63c24324307e9935432a904fa1d1d5c Mon Sep 17 00:00:00 2001 From: dp-web4 Date: Fri, 17 Apr 2026 12:11:30 -0700 Subject: [PATCH] Sprint 41 T1: Remove dead web4_sdk.py + fix v0.26.0 documentation gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete web4_sdk.py (~1500 lines) — async HTTP client referencing nonexistent microservices, not distributed in the wheel, examples deleted in Sprint 36. Delete test_sdk_integration.py (14 tests for the removed module). Fix README.md: version 0.25.0→0.26.0, remove misleading "Client SDK" section, update project structure and test count. Fix quickstart.py docstring version. 2613 tests pass. mypy --strict clean. ruff check + format clean. 0 new files, 2 deleted, 4 modified. Co-Authored-By: Claude Opus 4.6 --- SESSION_FOCUS.md | 25 +- docs/SPRINT.md | 28 +- web4-standard/implementation/sdk/README.md | 27 +- .../implementation/sdk/examples/quickstart.py | 2 +- .../sdk/tests/test_sdk_integration.py | 217 --- web4-standard/implementation/sdk/web4_sdk.py | 1506 ----------------- 6 files changed, 48 insertions(+), 1757 deletions(-) delete mode 100644 web4-standard/implementation/sdk/tests/test_sdk_integration.py delete mode 100644 web4-standard/implementation/sdk/web4_sdk.py diff --git a/SESSION_FOCUS.md b/SESSION_FOCUS.md index 3c4f30a2..79d1e9f1 100644 --- a/SESSION_FOCUS.md +++ b/SESSION_FOCUS.md @@ -2,7 +2,7 @@ *Current sprint, SDK status, and active work. Updated by operator and autonomous sessions.* -*Last updated: 2026-04-17 (Sprint 39)* +*Last updated: 2026-04-17 (Sprint 41)* --- @@ -10,6 +10,12 @@ **See `docs/SPRINT.md` for full sprint plan and task details.** Do not duplicate sprint content here — SPRINT.md is the source of truth for task scope, status, and dependencies. +### Sprint 41 Summary: Remove Dead web4_sdk.py + Fix v0.26.0 Documentation Gaps (COMPLETE) + +| Task | Status | Notes | +|------|--------|-------| +| T1: Remove dead `web4_sdk.py` + fix docs | DONE | Deleted `web4_sdk.py` (dead async HTTP client for nonexistent services, not in wheel) + `test_sdk_integration.py` (14 tests). README: version 0.25.0→0.26.0, removed misleading "Client SDK" section. Quickstart docstring: v0.25.0→v0.26.0. 2613 tests, 0 new files, 2 deleted. | + ### Sprint 39 Summary: SDK v0.26.0 Release Housekeeping (COMPLETE) | Task | Status | Notes | @@ -136,7 +142,7 @@ See `docs/SPRINT.md` for full history. Highlights: JSON-LD serialization for all - **Version**: 0.26.0 - **Modules**: 22 library modules + MCP server entry point (trust, lct, atp, federation, r6, mrh, acp, dictionary, entity, capability, errors, metabolic, binding, society, reputation, security, protocol, mcp, attestation, validation, deserialize, generate, mcp_server) -- **Tests**: 2627 passing (97.8% coverage) +- **Tests**: 2613 passing (97.8% coverage) - **CLI**: `web4 info/validate/list-schemas/roundtrip/generate/selftest/trust` (7 subcommands) - **Exports**: 364 symbols via `web4/__init__.py` - **from_dict()**: 58 classmethods across 10 modules — all classes with to_dict()/as_dict() have matching from_dict() @@ -185,28 +191,30 @@ Web4 SDK development aligns with ARIA grant requirements: ## Recent Commits ``` +91ed230 Sprint 36 T1: Replace stale examples with v0.25.0 quickstart (#160) +64add4c Sprint 39 T1: SDK v0.26.0 release housekeeping (#163) 759eaef Sprint 38 T1: ruff format codebase-wide + CI enforcement (#162) e355a19 Sprint 37 T1: ruff check lint cleanup + CI enforcement (#161) -3e6ca32 [Publisher] Fix PDF date (February→April 2026), rebuild artifacts 4a97ff7 Sprint 35 T1: CI workflow hardening — strict mypy + wheel verification (#158) -2b5292f Sprint 34 T1: SDK v0.25.0 release housekeeping (#156) ``` --- ## Open PRs -- PR #160: Sprint 36 T1 — Replace stale examples with v0.25.0 quickstart (pending review) +- PR #164: Sprint 40 T1 — Wire examples/quickstart.py into CI wheel smoke job (pending review) ### Closed PRs (recent) -- PR #159 CLOSED (superseded) — attempted `ruff format` sweep but shipped with failing lint and stray session-report artifacts; its lint debt was fixed separately in PR #161 (Sprint 37 T1, merged), and its `ruff format` intent is addressed in Sprint 38 T1 on a clean branch. +- PR #163 MERGED — Sprint 39 T1: SDK v0.26.0 release housekeeping +- PR #160 MERGED — Sprint 36 T1: Replace stale examples with v0.25.0 quickstart +- PR #159 CLOSED (superseded) — attempted `ruff format` sweep; intent addressed in Sprint 38 --- ## Completeness Summary -- All 39 sprints COMPLETE (Sprints 1-39) +- All 41 sprints COMPLETE (Sprints 1-41) - All 9 JSON-LD schemas with cross-language validation vectors (278 total, in pytest) - All `to_jsonld()` functions have `from_jsonld()` inverses (API symmetry complete) - All `to_dict()`/`as_dict()` methods have `from_dict()` inverses (58 round-trip methods total) @@ -227,7 +235,8 @@ e355a19 Sprint 37 T1: ruff check lint cleanup + CI enforcement (#161) - All 23 generate() types pass roundtrip fidelity (generate → from_jsonld → to_jsonld = identical) - `ruff check web4/ tests/` passes with 0 errors — CI enforces lint on source + tests - `ruff format --check web4/ tests/test_*.py` passes with 0 changes — CI enforces formatting on source + tests +- Dead `web4_sdk.py` removed — async HTTP client for nonexistent services, not distributed in wheel --- -*Updated by autonomous session, 2026-04-17 (Sprint 39 — SDK v0.26.0 release housekeeping)* +*Updated by autonomous session, 2026-04-17 (Sprint 41 — Remove dead web4_sdk.py + fix v0.26.0 docs)* diff --git a/docs/SPRINT.md b/docs/SPRINT.md index 179ffeda..c89710ed 100644 --- a/docs/SPRINT.md +++ b/docs/SPRINT.md @@ -1,12 +1,38 @@ # Web4 Sprint Plan **Created**: 2026-03-14 -**Updated**: 2026-04-17 (Sprint 39) +**Updated**: 2026-04-17 (Sprint 41) **Phase**: Development **Track**: web4 (Legion) --- +## Sprint 41: Remove Dead web4_sdk.py + Fix v0.26.0 Documentation Gaps (2026-04-17) + +Sprint 36 deleted the example scripts that imported from `web4_sdk.py` because they +caused `ImportError` (referencing nonexistent microservices). However, `web4_sdk.py` +itself (~1500 lines) and its test file were left behind. The README still documented +it as a usable Client SDK. Additionally, the README and quickstart docstring still +referenced v0.25.0 despite the v0.26.0 bump in Sprint 39. + +### T1: Remove dead `web4_sdk.py` + fix v0.26.0 documentation gaps +**Status**: DONE +**Completed**: 2026-04-17 +**Scope**: +(1) Delete `web4_sdk.py` — async HTTP client for nonexistent services, not distributed +in wheel (`packages.find.include = ["web4*"]`), examples deleted in Sprint 36. +(2) Delete `tests/test_sdk_integration.py` — 14 tests for the removed module. +(3) Update `README.md`: version 0.25.0 → 0.26.0, remove "Client SDK" section, +remove `web4_sdk.py` from Project Structure, update test count 2627 → 2613. +(4) Update `examples/quickstart.py` docstring: v0.25.0 → v0.26.0. +(5) Update `docs/SPRINT.md` and `SESSION_FOCUS.md`. +**Result**: No dead code referencing nonexistent services. README accurately reflects +what's distributed in the wheel. All version references consistent at v0.26.0. +2613 tests pass (14 removed with deleted module). mypy --strict clean. ruff clean. +0 new files, 2 files deleted, 4 files modified. + +--- + ## Sprint 39: SDK v0.26.0 Release Housekeeping (2026-04-17) Three quality-improvement PRs merged since v0.25.0: CI workflow hardening (#158), diff --git a/web4-standard/implementation/sdk/README.md b/web4-standard/implementation/sdk/README.md index 10a56f1b..8cd00e0f 100644 --- a/web4-standard/implementation/sdk/README.md +++ b/web4-standard/implementation/sdk/README.md @@ -8,7 +8,7 @@ specified in the [web4-standard](https://github.com/dp-web4/web4) and works with network services — no async, no HTTP, no external dependencies beyond the Python standard library. -**Version**: 0.25.0 | **Python**: 3.10+ | **License**: MIT | **Typed**: PEP 561 +**Version**: 0.26.0 | **Python**: 3.10+ | **License**: MIT | **Typed**: PEP 561 ## Installation @@ -185,27 +185,7 @@ python -m pytest tests/ --cov=web4 mypy --strict web4/ ``` -2627 tests, 97.8% coverage, mypy strict zero-error, CI across Python 3.10-3.13. - -## Client SDK - -The `web4_sdk.py` module (separate from the `web4` package) provides an async HTTP -client for connecting to Web4 infrastructure services. It requires `aiohttp` and -`pynacl` and is intended for applications that communicate with running Web4 nodes. - -```python -from web4_sdk import Web4Client - -client = Web4Client( - identity_url="http://localhost:8001", - auth_url="http://localhost:8003", - lct_id="lct:web4:ai:society:001", - private_key=key_bytes -) -``` - -The client SDK re-exports canonical types from the `web4` package, so both -`from web4 import T3` and `from web4_sdk import T3` resolve to the same objects. +2613 tests, 97.8% coverage, mypy strict zero-error, CI across Python 3.10-3.13. ## Project Structure @@ -221,9 +201,8 @@ web4/ # Python package (22 modules + MCP server) generate.py # Minimal valid JSON-LD document generation validation.py # Schema validation ... # (17 more modules) -tests/ # 2627 tests +tests/ # 2613 tests schemas/ # JSON Schemas + JSON-LD contexts -web4_sdk.py # Async HTTP client (separate) pyproject.toml # Package metadata (single version source) ``` diff --git a/web4-standard/implementation/sdk/examples/quickstart.py b/web4-standard/implementation/sdk/examples/quickstart.py index 2aef444c..da97ce1a 100644 --- a/web4-standard/implementation/sdk/examples/quickstart.py +++ b/web4-standard/implementation/sdk/examples/quickstart.py @@ -1,4 +1,4 @@ -"""Quickstart for the web4 Python SDK v0.25.0. +"""Quickstart for the web4 Python SDK v0.26.0. Demonstrates the three behavioral composition points of the current SDK: diff --git a/web4-standard/implementation/sdk/tests/test_sdk_integration.py b/web4-standard/implementation/sdk/tests/test_sdk_integration.py deleted file mode 100644 index c9a94b83..00000000 --- a/web4-standard/implementation/sdk/tests/test_sdk_integration.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -Test that web4_sdk.py integrates with canonical web4.* modules. - -Validates: -- web4_sdk re-exports canonical types -- LCTInfo converts to canonical LCT -- ReputationScore uses canonical T3/V3 -- No type duplication between web4_sdk and web4.* -""" - -import sys -from pathlib import Path - -# Ensure SDK is importable -sys.path.insert(0, str(Path(__file__).parent.parent)) - -import pytest - -from web4.lct import LCT, EntityType, RevocationStatus -from web4.trust import T3, V3, operational_health - - -class TestSDKReexports: - """Verify web4_sdk re-exports canonical types.""" - - def test_imports_from_web4_sdk(self): - """Canonical types available via web4_sdk import.""" - from web4_sdk import LCT, T3, V3, ATPAccount, EntityType - - assert T3 is not None - assert V3 is not None - assert LCT is not None - assert EntityType is not None - assert ATPAccount is not None - - def test_same_objects(self): - """web4_sdk re-exports are the SAME objects, not copies.""" - from web4.lct import EntityType as Core_ET - from web4.trust import T3 as Core_T3 - from web4_sdk import T3 as SDK_T3 - from web4_sdk import EntityType as SDK_ET - - assert SDK_T3 is Core_T3 - assert SDK_ET is Core_ET - - -class TestLCTInfoIntegration: - """Test LCTInfo ↔ canonical LCT bridge.""" - - def _make_lct_info(self): - from web4_sdk import LCTInfo - - return LCTInfo( - lct_id="lct:web4:ai:test123", - entity_type="ai", - entity_identifier="agent-001", - society="lct:web4:society:genesis", - public_key="mb64testkey123456789", - birth_certificate_hash="abc123", - witnesses=["w1", "w2", "w3"], - created_at="2026-03-13T00:00:00Z", - status="active", - ) - - def test_entity_type_enum(self): - info = self._make_lct_info() - assert info.entity_type_enum == EntityType.AI - - def test_entity_type_enum_unknown(self): - from web4_sdk import LCTInfo - - info = LCTInfo( - lct_id="x", - entity_type="unknown_type", - entity_identifier="", - society="", - public_key="", - birth_certificate_hash="", - witnesses=[], - created_at="", - ) - assert info.entity_type_enum is None - - def test_revocation_status(self): - info = self._make_lct_info() - assert info.revocation_status == RevocationStatus.ACTIVE - - def test_to_lct(self): - info = self._make_lct_info() - lct = info.to_lct() - assert lct is not None - assert isinstance(lct, LCT) - assert lct.lct_id == "lct:web4:ai:test123" - assert lct.binding.entity_type == EntityType.AI - assert lct.is_active - - def test_to_lct_with_tensors(self): - info = self._make_lct_info() - t3 = T3(talent=0.8, training=0.9, temperament=0.7) - v3 = V3(valuation=0.6, veracity=0.85, validity=0.9) - lct = info.to_lct(t3=t3, v3=v3) - assert lct.t3.talent == 0.8 - assert lct.v3.veracity == 0.85 - - def test_to_lct_unknown_type_returns_none(self): - from web4_sdk import LCTInfo - - info = LCTInfo( - lct_id="x", - entity_type="alien", - entity_identifier="", - society="", - public_key="", - birth_certificate_hash="", - witnesses=[], - created_at="", - ) - assert info.to_lct() is None - - -class TestReputationScoreIntegration: - """Test ReputationScore with canonical T3/V3.""" - - def test_with_canonical_tensors(self): - from web4_sdk import ReputationScore - - t3 = T3(talent=0.8, training=0.7, temperament=0.9) - v3 = V3(valuation=0.6, veracity=0.85, validity=0.8) - score = ReputationScore( - entity_id="lct:alice", - role="web4:DataAnalyst", - t3_score=t3.composite, - v3_score=v3.composite, - action_count=42, - last_updated="2026-03-13T00:00:00Z", - t3=t3, - v3=v3, - ) - assert score.t3.talent == 0.8 - assert score.v3.veracity == 0.85 - assert abs(score.t3_score - 0.8) < 0.001 # t3v3-001 canonical composite - - def test_backward_compat_no_tensors(self): - from web4_sdk import ReputationScore - - score = ReputationScore( - entity_id="lct:bob", - role="web4:Worker", - t3_score=0.75, - v3_score=0.60, - action_count=10, - last_updated="2026-03-13T00:00:00Z", - ) - assert score.t3 is None - assert score.v3 is None - assert score.t3_score == 0.75 - - def test_energy_ratio_from_metadata(self): - from web4_sdk import ReputationScore - - score = ReputationScore( - entity_id="lct:carol", - role="role", - t3_score=0.8, - v3_score=0.6, - action_count=5, - last_updated="now", - metadata={"atp": 80.0, "adp": 20.0}, - ) - assert abs(score.energy_ratio - 0.8) < 0.001 - - def test_health_score(self): - from web4_sdk import ReputationScore - - score = ReputationScore( - entity_id="lct:dave", - role="role", - t3_score=0.8, - v3_score=0.6, - action_count=5, - last_updated="now", - metadata={"atp": 70.0, "adp": 30.0}, - ) - expected = operational_health(0.8, 0.6, 0.7) - assert abs(score.health_score - expected) < 0.001 - - def test_no_energy_data(self): - from web4_sdk import ReputationScore - - score = ReputationScore( - entity_id="x", - role="r", - t3_score=0.5, - v3_score=0.5, - action_count=0, - last_updated="now", - ) - assert score.energy_ratio is None - assert score.health_score is None - - -class TestAllEntityTypes: - """Verify all 15 entity types are accessible via SDK.""" - - def test_all_types(self): - from web4_sdk import EntityType - - assert EntityType.HUMAN.value == "human" - assert EntityType.AI.value == "ai" - assert EntityType.SOCIETY.value == "society" - assert EntityType.POLICY.value == "policy" - assert EntityType.INFRASTRUCTURE.value == "infrastructure" - assert len(EntityType) == 15 - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/web4-standard/implementation/sdk/web4_sdk.py b/web4-standard/implementation/sdk/web4_sdk.py deleted file mode 100644 index a32b518b..00000000 --- a/web4-standard/implementation/sdk/web4_sdk.py +++ /dev/null @@ -1,1506 +0,0 @@ -""" -Web4 Client SDK -=============== - -Research prototype Python SDK for integrating with Web4 infrastructure. - -This SDK provides high-level abstractions for: -- Identity management (LCT) -- Trust and value assessment (T3/V3) -- ATP/ADP lifecycle (energy metabolism) -- Federation governance (SAL) -- R7 action framework (Rules+Role+Request+Reference+Resource→Result+Reputation) -- MRH graph (Markov Relevancy Horizon context traversal) -- ACP (Agentic Context Protocol for autonomous agent workflows) -- Dictionary entities (semantic bridges with trust-tracked translation) -- Authorization requests -- Resource allocation -- Reputation tracking -- Knowledge graph queries - -Usage Example: -------------- -```python -from web4_sdk import Web4Client, Action - -# Initialize client -client = Web4Client( - identity_url="http://identity.web4.local:8001", - auth_url="http://auth.web4.local:8003", - lct_id="lct:web4:ai:society:001", - private_key=agent_secret -) - -# Request authorization for an action -result = await client.authorize( - action=Action.COMPUTE, - resource="model:training", - atp_cost=500, - context={"delegation_id": "deleg:001"} -) - -if result.decision == "granted": - # Execute action - ... - # Report outcome - await client.report_outcome( - action=Action.COMPUTE, - outcome="success", - quality_score=0.85 - ) -``` - -Author: Web4 Infrastructure Team -License: MIT -""" - -import asyncio -import hashlib -import hmac -import json -import time -from dataclasses import dataclass, asdict -from enum import Enum -from typing import Optional, Dict, Any, List -from datetime import datetime, timezone - -try: - import aiohttp -except ImportError: - aiohttp = None - import warnings - warnings.warn("aiohttp not installed. Async methods will not work. Install with: pip install aiohttp") - -try: - from nacl.signing import SigningKey, VerifyKey - from nacl.encoding import HexEncoder -except ImportError: - SigningKey = None - VerifyKey = None - import warnings - warnings.warn("PyNaCl not installed. Cryptographic signing will not work. Install with: pip install pynacl") - -# Import canonical web4 types (v0.1.0+) -from web4.trust import ( - T3, V3, TrustProfile, ActionOutcome, RoleRequirement, - compute_team_t3, operational_health, is_healthy, -) -from web4.lct import LCT, EntityType, RevocationStatus, BirthCertificate -from web4.atp import ATPAccount, energy_ratio as atp_energy_ratio -from web4.federation import ( - Society, LawDataset, Delegation, RoleType, - CitizenshipStatus, CitizenshipRecord, valid_citizenship_transition, - QuorumMode, QuorumPolicy, LedgerType, - AuditRequest, AuditAdjustment, - Norm, Procedure, Interpretation, - merge_law, -) -from web4.r6 import ( - R7Action, ActionChain, ActionStatus, ReputationDelta, - Rules, Role, Request, ResourceRequirements, Result, - build_action, -) -from web4.mrh import ( - MRHGraph, MRHNode, MRHEdge, RelationType, - mrh_trust_decay, mrh_zone, - propagate_multiplicative, propagate_probabilistic, propagate_maximal, -) -from web4.acp import ( - ACPStateMachine, ACPState, ACPError, - AgentPlan, PlanStep, Intent, Decision, DecisionType, - ProofOfAgency, ExecutionRecord, - ApprovalMode, ResourceCaps, Guards, Trigger, TriggerKind, - build_intent, validate_plan, -) -from web4.dictionary import ( - DictionaryEntity, DictionarySpec, DictionaryType, DictionaryVersion, - CompressionProfile, DomainCoverage, - TranslationRequest, TranslationResult, TranslationChain, - dictionary_selection_score, select_best_dictionary, -) -from web4.reputation import ( - ReputationRule, DimensionImpact, Modifier, - ReputationEngine, ReputationStore, - analyze_factors, -) -from web4.entity import ( - BehavioralMode, EnergyPattern, InteractionType, - EntityTypeInfo, get_info as entity_get_info, - behavioral_modes, energy_pattern, - is_agentic, can_initiate, can_delegate, can_process_r6, - valid_interaction, all_entity_types, -) -from web4.capability import ( - CapabilityLevel, TrustTier, - ENTITY_LEVEL_RANGES, - LevelRequirement, - assess_level, validate_level, can_upgrade, - level_requirements, trust_tier, - entity_level_range, is_level_typical, common_ground, -) -from web4.binding import ( - AnchorType, DeviceStatus, - HardwareAnchor, DeviceRecord, DeviceConstellation, - ANCHOR_TRUST_WEIGHT, CONSTELLATION_TRUST_CEILING, WITNESS_DECAY_TABLE, - witness_freshness, default_recovery_quorum, - enroll_device, remove_device, - coherence_bonus, cross_witness_density, - constellation_trust_ceiling, compute_constellation_trust, - record_cross_witness, check_recovery_quorum, can_recover, -) -from web4.errors import ( - ErrorCode, ErrorCategory, ErrorMeta, - Web4Error as Web4ProtocolError, # alias: avoids collision with legacy Web4Error above - BindingError, PairingError, WitnessError, - AuthzError, CryptoError, ProtoError, - get_error_meta, codes_for_category, make_error, -) -from web4.metabolic import ( - MetabolicState, Transition as MetabolicTransition, - TrustEffect, MetabolicProfile, ReliabilityFactors, - ENERGY_MULTIPLIERS, TRUST_EFFECTS, WITNESS_REQUIREMENTS, - DORMANT_STATES, ACTIVE_STATES, - valid_transition as metabolic_valid_transition, - reachable_states, transition_trigger, all_transitions, - energy_cost, wake_penalty, metabolic_reliability, - required_witnesses, all_profiles, - is_dormant, accepts_transactions, accepts_new_citizens, -) -from web4.society import ( - SocietyPhase, LedgerEventType, - LedgerEntry, SocietyLedger, Treasury, SocietyState, - create_society, - admit_citizen, suspend_citizen, reinstate_citizen, terminate_citizen, - transition_metabolic_state, - deposit_treasury, allocate_treasury, - record_law_change, - compute_society_t3, society_energy_cost, society_health, - incorporate_child, society_depth, society_ancestry, -) -from web4.security import ( - CryptoSuiteId, CryptoSuite, EncodingProfile, - SUITE_BASE, SUITE_FIPS, SUITES, - get_suite, negotiate_suite, - W4ID, W4IDError, parse_w4id, derive_pairwise_w4id, KNOWN_METHODS, - KeyStorageLevel, KeyPolicy, - SignatureEnvelope, VerifiableCredential, -) -from web4.protocol import ( - HandshakePhase, - ClientHello, ServerHello, ClientFinished, ServerFinished, - HandshakeMessage, - PairingMethod, - Transport, TransportCompliance, TransportProfile, - TRANSPORT_PROFILES, - get_transport_profile, required_transports, negotiate_transport, - DiscoveryMethod, PrivacyLevel, - DISCOVERY_METADATA, - required_discovery_methods, discovery_privacy, - DiscoveryRequest, DiscoveryResponse, - Web4URI, - web4_uri_to_dict, web4_uri_from_dict, - transport_profile_to_dict, -) -from web4.mcp import ( - CommunicationPattern, TrustDimension, MCPResourceType, - ResourceRequirements as MCPResourceRequirements, - TrustRequirements as MCPTrustRequirements, - MCPToolResource, MCPPromptResource, - ProofOfAgency, TrustContext, Web4Context, - WitnessedInteraction, WitnessAttestation, - MCPCapabilities, CapabilityBroadcast, - MCPAuthority, MCPSession, SessionHandoff, - PricingModifiers, calculate_mcp_cost, - MCPErrorContext, - web4_context_to_json, web4_context_from_json, -) - - -# ============================================================================= -# Enums and Data Classes -# ============================================================================= - -class Action(Enum): - """Standard Web4 actions""" - READ = "read" - WRITE = "write" - COMPUTE = "compute" - QUERY = "query" - DELEGATE = "delegate" - ALLOCATE = "allocate" - - -class OutcomeType(Enum): - """Outcome quality levels""" - SUCCESS = "success" - PARTIAL_SUCCESS = "partial_success" - FAILURE = "failure" - EXCEPTIONAL_QUALITY = "exceptional_quality" - POOR_QUALITY = "poor_quality" - - -class ResourceType(Enum): - """Resource types for allocation""" - CPU = "cpu" - MEMORY = "memory" - STORAGE = "storage" - NETWORK = "network" - - -@dataclass -class AuthorizationResult: - """Result of an authorization request""" - decision: str # "granted" or "denied" - atp_remaining: Optional[int] = None - reason: Optional[str] = None - law_version: Optional[str] = None - law_hash: Optional[str] = None - ledger_ref: Optional[str] = None - resource_allocation: Optional[Dict[str, float]] = None - timestamp: Optional[str] = None - metadata: Optional[Dict[str, Any]] = None - - -@dataclass -class ReputationScore: - """Reputation scores for an entity. - - t3_score/v3_score are composite floats for backward compatibility. - t3/v3 are canonical web4.trust tensor objects when available. - """ - entity_id: str - role: str - t3_score: float # Composite trustworthiness (backward-compat) - v3_score: float # Composite value creation (backward-compat) - action_count: int - last_updated: str - metadata: Optional[Dict[str, Any]] = None - t3: Optional[T3] = None # Canonical T3 tensor (when detailed scores available) - v3: Optional[V3] = None # Canonical V3 tensor (when detailed scores available) - - @property - def energy_ratio(self) -> Optional[float]: - """Energy ratio from metadata if ATP/ADP data available.""" - if self.metadata and "atp" in self.metadata and "adp" in self.metadata: - return atp_energy_ratio(self.metadata["atp"], self.metadata["adp"]) - return None - - @property - def health_score(self) -> Optional[float]: - """Operational health score if all components available.""" - er = self.energy_ratio - if er is not None: - return operational_health(self.t3_score, self.v3_score, er) - return None - - -@dataclass -class ResourceAllocation: - """Resource allocation details""" - allocation_id: str - resource_type: str - amount_allocated: float - atp_cost: int - entity_id: str - timestamp: str - duration_seconds: Optional[int] = None - actual_usage: Optional[float] = None - - -@dataclass -class LCTInfo: - """LCT identity information from the identity service. - - entity_type_str preserves the raw string for backward compatibility. - entity_type_enum provides the canonical EntityType when parseable. - """ - lct_id: str - entity_type: str # Raw string (backward-compat) - entity_identifier: str - society: str - public_key: str - birth_certificate_hash: str - witnesses: List[str] - created_at: str - status: str = "active" - - @property - def entity_type_enum(self) -> Optional[EntityType]: - """Canonical EntityType enum, or None if not a recognized type.""" - try: - return EntityType(self.entity_type) - except ValueError: - return None - - @property - def revocation_status(self) -> RevocationStatus: - """Canonical revocation status.""" - try: - return RevocationStatus(self.status) - except ValueError: - return RevocationStatus.ACTIVE - - def to_lct(self, t3: Optional[T3] = None, v3: Optional[V3] = None) -> Optional[LCT]: - """Convert to a canonical LCT object. - - Creates an LCT from service response data. Requires a recognized - entity type. T3/V3 default to (0.5, 0.5, 0.5) if not provided. - """ - et = self.entity_type_enum - if et is None: - return None - return LCT.create( - entity_type=et, - public_key=self.public_key, - society=self.society, - witnesses=self.witnesses, - timestamp=self.created_at, - lct_id=self.lct_id, - subject=f"did:web4:key:{self.public_key[:20]}", - t3=t3, - v3=v3, - ) - - -# ============================================================================= -# Exceptions -# ============================================================================= - -class Web4Error(Exception): - """Base exception for Web4 SDK errors""" - pass - - -class AuthorizationDenied(Web4Error): - """Authorization request was denied""" - pass - - -class InsufficientATP(Web4Error): - """Insufficient ATP budget for requested action""" - pass - - -class InvalidSignature(Web4Error): - """Cryptographic signature verification failed""" - pass - - -class ServiceUnavailable(Web4Error): - """Web4 service is unavailable""" - pass - - -# ============================================================================= -# Web4 Client SDK -# ============================================================================= - -class Web4Client: - """ - Main Web4 SDK client for interacting with Web4 infrastructure. - - This client handles: - - Authentication and signing - - Authorization requests - - Reputation tracking - - Resource allocation - - Knowledge graph queries - - All network operations are async for performance. - """ - - def __init__( - self, - identity_url: str, - auth_url: str, - lct_id: str, - private_key: Optional[bytes] = None, - reputation_url: Optional[str] = None, - resources_url: Optional[str] = None, - knowledge_url: Optional[str] = None, - governance_url: Optional[str] = None, - timeout: int = 30, - max_retries: int = 3 - ): - """ - Initialize Web4 client. - - Args: - identity_url: URL of identity service (e.g., http://identity:8001) - auth_url: URL of authorization service (e.g., http://auth:8003) - lct_id: LCT identifier for this entity - private_key: Ed25519 private key bytes (32 bytes) for signing - reputation_url: Optional URL of reputation service - resources_url: Optional URL of resource service - knowledge_url: Optional URL of knowledge service - governance_url: Optional URL of governance service - timeout: Request timeout in seconds - max_retries: Maximum number of retry attempts - """ - if not aiohttp: - raise ImportError("aiohttp is required. Install with: pip install aiohttp") - - if not SigningKey: - raise ImportError("PyNaCl is required. Install with: pip install pynacl") - - self.identity_url = identity_url.rstrip('/') - self.auth_url = auth_url.rstrip('/') - self.lct_id = lct_id - self.timeout = timeout - self.max_retries = max_retries - - # Optional service URLs - self.reputation_url = reputation_url.rstrip('/') if reputation_url else None - self.resources_url = resources_url.rstrip('/') if resources_url else None - self.knowledge_url = knowledge_url.rstrip('/') if knowledge_url else None - self.governance_url = governance_url.rstrip('/') if governance_url else None - - # Cryptographic signing key - if private_key: - if len(private_key) != 32: - raise ValueError("Private key must be exactly 32 bytes") - self.signing_key = SigningKey(private_key) - else: - self.signing_key = None - - # Session management - self._session: Optional[aiohttp.ClientSession] = None - self._nonce_counter = int(time.time() * 1000) - - async def __aenter__(self): - """Async context manager entry""" - await self.connect() - return self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - """Async context manager exit""" - await self.disconnect() - - async def connect(self): - """Create HTTP session""" - if not self._session: - self._session = aiohttp.ClientSession( - timeout=aiohttp.ClientTimeout(total=self.timeout) - ) - - async def disconnect(self): - """Close HTTP session""" - if self._session: - await self._session.close() - self._session = None - - def _get_nonce(self) -> int: - """Generate monotonically increasing nonce""" - self._nonce_counter += 1 - return self._nonce_counter - - def _sign_request(self, method: str, path: str, body: Optional[Dict] = None) -> tuple[str, int]: - """ - Sign a request with Ed25519 signature. - - Args: - method: HTTP method (GET, POST, etc.) - path: Request path - body: Optional request body - - Returns: - Tuple of (signature_hex, nonce) - """ - if not self.signing_key: - raise ValueError("No private key configured for signing") - - nonce = self._get_nonce() - - # Create signature payload - payload = f"{method}|{path}|{nonce}" - if body: - body_json = json.dumps(body, sort_keys=True) - payload += f"|{body_json}" - - # Sign with Ed25519 - signature = self.signing_key.sign(payload.encode('utf-8')) - signature_hex = signature.signature.hex() - - return signature_hex, nonce - - async def _request( - self, - method: str, - url: str, - body: Optional[Dict] = None, - require_auth: bool = True - ) -> Dict[str, Any]: - """ - Make authenticated HTTP request to Web4 service. - - Args: - method: HTTP method - url: Full URL - body: Optional request body - require_auth: Whether to include authentication headers - - Returns: - Response JSON - - Raises: - ServiceUnavailable: If service is unavailable - Web4Error: On other errors - """ - if not self._session: - await self.connect() - - headers = { - "Content-Type": "application/json", - "User-Agent": "Web4-SDK/1.0" - } - - # Add authentication if required - if require_auth and self.signing_key: - path = url.split('/', 3)[-1] if '://' in url else url - signature, nonce = self._sign_request(method, path, body) - headers["Authorization"] = f"Bearer {self.lct_id}" - headers["X-Signature"] = signature - headers["X-Nonce"] = str(nonce) - - # Make request with retries - last_error = None - for attempt in range(self.max_retries): - try: - async with self._session.request( - method, - url, - json=body if body else None, - headers=headers - ) as response: - # Parse response - try: - data = await response.json() - except Exception: - data = {"error": await response.text()} - - # Check for errors - if response.status >= 500: - last_error = ServiceUnavailable( - f"Service unavailable: {response.status} - {data.get('error', 'Unknown error')}" - ) - await asyncio.sleep(2 ** attempt) # Exponential backoff - continue - - if response.status >= 400: - error_msg = data.get('error', f"HTTP {response.status}") - raise Web4Error(f"Request failed: {error_msg}") - - return data - - except aiohttp.ClientError as e: - last_error = ServiceUnavailable(f"Network error: {str(e)}") - await asyncio.sleep(2 ** attempt) - - # All retries failed - raise last_error if last_error else ServiceUnavailable("Request failed after retries") - - # ========================================================================= - # Identity Service Methods - # ========================================================================= - - async def get_lct_info(self, lct_id: Optional[str] = None) -> LCTInfo: - """ - Retrieve LCT information from identity service. - - Args: - lct_id: LCT ID to query (defaults to self) - - Returns: - LCT information - """ - target_lct = lct_id or self.lct_id - url = f"{self.identity_url}/v1/lct/{target_lct}" - - response = await self._request("GET", url, require_auth=False) - - if not response.get('success'): - raise Web4Error(f"Failed to retrieve LCT: {response.get('error')}") - - data = response['data'] - return LCTInfo( - lct_id=data['lct_id'], - entity_type=data['entity_type'], - entity_identifier=data['entity_identifier'], - society=data['society'], - public_key=data['public_key'], - birth_certificate_hash=data['birth_certificate']['certificate_hash'], - witnesses=data['birth_certificate']['witnesses'], - created_at=data['created_at'], - status=data.get('status', 'active') - ) - - async def verify_lct_signature( - self, - lct_id: str, - message: bytes, - signature: bytes - ) -> bool: - """ - Verify signature from another LCT. - - Args: - lct_id: LCT ID of signer - message: Original message - signature: Signature bytes - - Returns: - True if signature is valid - """ - url = f"{self.identity_url}/v1/lct/{lct_id}/verify" - - response = await self._request( - "POST", - url, - body={ - "message": message.hex(), - "signature": signature.hex() - }, - require_auth=False - ) - - return response.get('success', False) and response.get('data', {}).get('valid', False) - - # ========================================================================= - # Authorization Service Methods - # ========================================================================= - - async def authorize( - self, - action: Action, - resource: str, - atp_cost: int, - context: Optional[Dict[str, Any]] = None - ) -> AuthorizationResult: - """ - Request authorization for an action. - - Args: - action: Action type - resource: Resource identifier - atp_cost: ATP cost for this action - context: Optional context (delegation_id, witnesses, etc.) - - Returns: - Authorization result - - Raises: - AuthorizationDenied: If authorization is denied - InsufficientATP: If ATP budget is insufficient - """ - url = f"{self.auth_url}/v1/auth/authorize" - - body = { - "action": action.value, - "resource": resource, - "atp_cost": atp_cost, - "context": context or {} - } - - response = await self._request("POST", url, body=body) - - if not response.get('success'): - error = response.get('error', 'Unknown error') - if 'insufficient' in error.lower(): - raise InsufficientATP(error) - raise AuthorizationDenied(error) - - data = response['data'] - metadata = response.get('metadata', {}) - - result = AuthorizationResult( - decision=data['decision'], - atp_remaining=data.get('atp_remaining'), - reason=data.get('reason'), - law_version=metadata.get('law_version'), - law_hash=metadata.get('law_hash'), - ledger_ref=metadata.get('ledger_ref'), - resource_allocation=data.get('resource_allocation'), - timestamp=metadata.get('timestamp'), - metadata=metadata - ) - - if result.decision != "granted": - raise AuthorizationDenied(f"Authorization denied: {result.reason}") - - return result - - async def check_delegation( - self, - delegation_id: str - ) -> Dict[str, Any]: - """ - Check delegation status and details. - - Args: - delegation_id: Delegation identifier - - Returns: - Delegation details - """ - url = f"{self.auth_url}/v1/delegation/{delegation_id}" - - response = await self._request("GET", url) - - if not response.get('success'): - raise Web4Error(f"Failed to retrieve delegation: {response.get('error')}") - - return response['data'] - - # ========================================================================= - # Reputation Service Methods - # ========================================================================= - - async def get_reputation( - self, - entity_id: Optional[str] = None, - role: Optional[str] = None - ) -> ReputationScore: - """ - Get reputation scores for an entity. - - Args: - entity_id: Entity to query (defaults to self) - role: Optional role filter - - Returns: - Reputation scores - """ - if not self.reputation_url: - raise Web4Error("Reputation service URL not configured") - - target_entity = entity_id or self.lct_id - url = f"{self.reputation_url}/v1/reputation/{target_entity}" - - if role: - url += f"?role={role}" - - response = await self._request("GET", url) - - if not response.get('success'): - raise Web4Error(f"Failed to retrieve reputation: {response.get('error')}") - - data = response['data'] - - # Build canonical T3/V3 if dimensional scores available - t3 = None - v3 = None - if 't3_tensor' in data: - td = data['t3_tensor'] - t3 = T3(talent=td.get('talent', 0.5), - training=td.get('training', 0.5), - temperament=td.get('temperament', 0.5)) - if 'v3_tensor' in data: - vd = data['v3_tensor'] - v3 = V3(valuation=vd.get('valuation', 0.5), - veracity=vd.get('veracity', 0.5), - validity=vd.get('validity', 0.5)) - - return ReputationScore( - entity_id=data['entity_id'], - role=data['role'], - t3_score=data['t3_score'], - v3_score=data['v3_score'], - action_count=data['action_count'], - last_updated=data['last_updated'], - metadata=data.get('metadata'), - t3=t3, - v3=v3, - ) - - async def report_outcome( - self, - action: Action, - outcome: OutcomeType, - quality_score: Optional[float] = None, - witnesses: Optional[List[str]] = None, - context: Optional[Dict[str, Any]] = None - ) -> ReputationScore: - """ - Report action outcome to update reputation. - - Args: - action: Action performed - outcome: Outcome type - quality_score: Optional quality score (0.0-1.0) - witnesses: Optional witness LCT IDs - context: Optional context - - Returns: - Updated reputation scores - """ - if not self.reputation_url: - raise Web4Error("Reputation service URL not configured") - - url = f"{self.reputation_url}/v1/reputation/record" - - body = { - "entity": self.lct_id, - "action": action.value, - "outcome": outcome.value, - "quality_score": quality_score, - "witnesses": witnesses or [], - "context": context or {} - } - - response = await self._request("POST", url, body=body) - - if not response.get('success'): - raise Web4Error(f"Failed to record outcome: {response.get('error')}") - - data = response['data'] - return ReputationScore( - entity_id=data['entity_id'], - role=data['role'], - t3_score=data['t3_score'], - v3_score=data['v3_score'], - action_count=data['action_count'], - last_updated=data['last_updated'], - metadata=data.get('metadata') - ) - - # ========================================================================= - # Resource Service Methods - # ========================================================================= - - async def allocate_resources( - self, - resource_type: ResourceType, - amount: float, - duration_seconds: Optional[int] = None - ) -> ResourceAllocation: - """ - Allocate resources using ATP. - - Args: - resource_type: Type of resource - amount: Amount to allocate - duration_seconds: Optional duration - - Returns: - Resource allocation details - """ - if not self.resources_url: - raise Web4Error("Resource service URL not configured") - - url = f"{self.resources_url}/v1/resources/allocate" - - body = { - "entity_id": self.lct_id, - "resource_type": resource_type.value, - "amount": amount, - "duration_seconds": duration_seconds - } - - response = await self._request("POST", url, body=body) - - if not response.get('success'): - raise Web4Error(f"Failed to allocate resources: {response.get('error')}") - - data = response['data'] - return ResourceAllocation( - allocation_id=data['allocation_id'], - resource_type=data['resource_type'], - amount_allocated=data['amount_allocated'], - atp_cost=data['atp_cost'], - entity_id=data['entity_id'], - timestamp=data['timestamp'], - duration_seconds=data.get('duration_seconds'), - actual_usage=data.get('actual_usage') - ) - - async def report_resource_usage( - self, - allocation_id: str, - actual_usage: float - ) -> Dict[str, Any]: - """ - Report actual resource usage. - - Args: - allocation_id: Allocation ID - actual_usage: Actual usage amount - - Returns: - Usage report response - """ - if not self.resources_url: - raise Web4Error("Resource service URL not configured") - - url = f"{self.resources_url}/v1/resources/usage" - - body = { - "allocation_id": allocation_id, - "actual_usage": actual_usage - } - - response = await self._request("POST", url, body=body) - - if not response.get('success'): - raise Web4Error(f"Failed to report usage: {response.get('error')}") - - return response['data'] - - # ========================================================================= - # Knowledge Service Methods - # ========================================================================= - - async def query_knowledge_graph( - self, - sparql_query: str - ) -> List[Dict[str, Any]]: - """ - Execute SPARQL query on knowledge graph. - - Args: - sparql_query: SPARQL query string - - Returns: - Query results - """ - if not self.knowledge_url: - raise Web4Error("Knowledge service URL not configured") - - url = f"{self.knowledge_url}/v1/graph/query" - - body = {"query": sparql_query} - - response = await self._request("POST", url, body=body) - - if not response.get('success'): - raise Web4Error(f"Query failed: {response.get('error')}") - - return response['data']['results'] - - async def get_trust_propagation( - self, - start_entity: str, - max_depth: int = 3 - ) -> Dict[str, Any]: - """ - Get trust propagation from entity. - - Args: - start_entity: Starting entity LCT - max_depth: Maximum graph depth - - Returns: - Trust propagation results - """ - if not self.knowledge_url: - raise Web4Error("Knowledge service URL not configured") - - url = f"{self.knowledge_url}/v1/graph/trust/{start_entity}" - - response = await self._request( - "GET", - f"{url}?max_depth={max_depth}" - ) - - if not response.get('success'): - raise Web4Error(f"Trust query failed: {response.get('error')}") - - return response['data'] - - # ========================================================================= - # Governance Service Methods - # ========================================================================= - - async def get_law_version(self) -> Dict[str, Any]: - """ - Get current law dataset version. - - Returns: - Law version info - """ - if not self.governance_url: - raise Web4Error("Governance service URL not configured") - - url = f"{self.governance_url}/v1/law/version" - - response = await self._request("GET", url, require_auth=False) - - if not response.get('success'): - raise Web4Error(f"Failed to get law version: {response.get('error')}") - - return response['data'] - - async def check_action_legal( - self, - action: Action, - entity_type: str, - role: str - ) -> bool: - """ - Check if action is legal for entity/role. - - Args: - action: Action to check - entity_type: Entity type - role: Role - - Returns: - True if legal - """ - if not self.governance_url: - raise Web4Error("Governance service URL not configured") - - url = f"{self.governance_url}/v1/law/check" - - body = { - "action": action.value, - "entity_type": entity_type, - "role": role - } - - response = await self._request("POST", url, body=body, require_auth=False) - - if not response.get('success'): - raise Web4Error(f"Law check failed: {response.get('error')}") - - return response['data'].get('legal', False) - - -# ============================================================================= -# High-Level Workflow Helpers -# ============================================================================= - -class Web4Workflow: - """ - High-level workflow helpers for common Web4 operations. - - These methods combine multiple SDK calls into common workflows. - """ - - def __init__(self, client: Web4Client): - """ - Initialize workflow helper. - - Args: - client: Web4Client instance - """ - self.client = client - - async def execute_action_with_reporting( - self, - action: Action, - resource: str, - atp_cost: int, - executor_fn, - context: Optional[Dict] = None - ) -> tuple[Any, ReputationScore]: - """ - Complete workflow: authorize -> execute -> report outcome. - - Args: - action: Action type - resource: Resource identifier - atp_cost: ATP cost - executor_fn: Async function to execute (receives auth_result) - context: Optional context - - Returns: - Tuple of (executor_result, updated_reputation) - """ - # Step 1: Request authorization - auth_result = await self.client.authorize( - action=action, - resource=resource, - atp_cost=atp_cost, - context=context - ) - - # Step 2: Execute action - try: - result = await executor_fn(auth_result) - outcome = OutcomeType.SUCCESS - quality_score = 0.75 - except Exception as e: - result = None - outcome = OutcomeType.FAILURE - quality_score = 0.0 - - # Step 3: Report outcome - reputation = await self.client.report_outcome( - action=action, - outcome=outcome, - quality_score=quality_score, - context={"auth_result": str(auth_result)} - ) - - return result, reputation - - async def delegate_with_budget( - self, - target_lct: str, - role: str, - permissions: List[str], - atp_budget: int, - duration_seconds: Optional[int] = None - ) -> Dict[str, Any]: - """ - Create delegation with ATP budget. - - Args: - target_lct: Target entity LCT - role: Role to delegate - permissions: List of permissions - atp_budget: ATP budget - duration_seconds: Optional duration - - Returns: - Delegation details - """ - # This would call a delegation endpoint - # For now, this is a placeholder showing the workflow - raise NotImplementedError("Delegation workflow not yet implemented in services") - - async def health_check(self) -> Dict[str, bool]: - """ - Check health of all configured services. - - Returns: - Dict mapping service name to health status - """ - health = {} - - # Check identity service - try: - await self.client.get_lct_info() - health['identity'] = True - except Exception: - health['identity'] = False - - # Check authorization service - try: - await self.client._request( - "GET", - f"{self.client.auth_url}/health", - require_auth=False - ) - health['authorization'] = True - except Exception: - health['authorization'] = False - - # Check optional services - if self.client.reputation_url: - try: - await self.client._request( - "GET", - f"{self.client.reputation_url}/health", - require_auth=False - ) - health['reputation'] = True - except Exception: - health['reputation'] = False - - if self.client.resources_url: - try: - await self.client._request( - "GET", - f"{self.client.resources_url}/health", - require_auth=False - ) - health['resources'] = True - except Exception: - health['resources'] = False - - if self.client.knowledge_url: - try: - await self.client._request( - "GET", - f"{self.client.knowledge_url}/health", - require_auth=False - ) - health['knowledge'] = True - except Exception: - health['knowledge'] = False - - if self.client.governance_url: - try: - await self.client._request( - "GET", - f"{self.client.governance_url}/health", - require_auth=False - ) - health['governance'] = True - except Exception: - health['governance'] = False - - return health - - -# ============================================================================= -# Convenience Functions -# ============================================================================= - -def create_client_from_env() -> Web4Client: - """ - Create Web4Client from environment variables. - - Expected environment variables: - - WEB4_IDENTITY_URL - - WEB4_AUTH_URL - - WEB4_LCT_ID - - WEB4_PRIVATE_KEY (hex encoded) - - WEB4_REPUTATION_URL (optional) - - WEB4_RESOURCES_URL (optional) - - WEB4_KNOWLEDGE_URL (optional) - - WEB4_GOVERNANCE_URL (optional) - - Returns: - Configured Web4Client - """ - import os - - required_vars = ['WEB4_IDENTITY_URL', 'WEB4_AUTH_URL', 'WEB4_LCT_ID'] - missing = [var for var in required_vars if not os.getenv(var)] - - if missing: - raise ValueError(f"Missing required environment variables: {', '.join(missing)}") - - private_key_hex = os.getenv('WEB4_PRIVATE_KEY') - private_key = bytes.fromhex(private_key_hex) if private_key_hex else None - - return Web4Client( - identity_url=os.getenv('WEB4_IDENTITY_URL'), - auth_url=os.getenv('WEB4_AUTH_URL'), - lct_id=os.getenv('WEB4_LCT_ID'), - private_key=private_key, - reputation_url=os.getenv('WEB4_REPUTATION_URL'), - resources_url=os.getenv('WEB4_RESOURCES_URL'), - knowledge_url=os.getenv('WEB4_KNOWLEDGE_URL'), - governance_url=os.getenv('WEB4_GOVERNANCE_URL') - ) - - -__all__ = [ - # Client SDK - 'Web4Client', - 'Web4Workflow', - 'Action', - 'OutcomeType', - 'ResourceType', - 'AuthorizationResult', - 'ReputationScore', - 'ResourceAllocation', - 'LCTInfo', - 'Web4Error', - 'AuthorizationDenied', - 'InsufficientATP', - 'InvalidSignature', - 'ServiceUnavailable', - 'create_client_from_env', - # Re-exported canonical types (from web4.*) - 'T3', - 'V3', - 'TrustProfile', - 'LCT', - 'EntityType', - 'RevocationStatus', - 'ATPAccount', - # Federation (SAL) - 'Society', - 'LawDataset', - 'Delegation', - 'RoleType', - 'CitizenshipStatus', - 'CitizenshipRecord', - 'valid_citizenship_transition', - 'QuorumMode', - 'QuorumPolicy', - 'LedgerType', - 'AuditRequest', - 'AuditAdjustment', - 'Norm', - 'Procedure', - 'Interpretation', - 'merge_law', - # R7 Action Framework - 'R7Action', - 'ActionChain', - 'ActionStatus', - 'ReputationDelta', - 'Rules', - 'Role', - 'Request', - 'ResourceRequirements', - 'Result', - 'build_action', - # MRH (Markov Relevancy Horizon) - 'MRHGraph', - 'MRHNode', - 'MRHEdge', - 'RelationType', - 'mrh_trust_decay', - 'mrh_zone', - 'propagate_multiplicative', - 'propagate_probabilistic', - 'propagate_maximal', - # ACP (Agentic Context Protocol) - 'ACPStateMachine', - 'ACPState', - 'ACPError', - 'AgentPlan', - 'PlanStep', - 'Intent', - 'Decision', - 'DecisionType', - 'ProofOfAgency', - 'ExecutionRecord', - 'ApprovalMode', - 'ResourceCaps', - 'Guards', - 'Trigger', - 'TriggerKind', - 'build_intent', - 'validate_plan', - # Dictionary Entities - 'DictionaryEntity', - 'DictionarySpec', - 'DictionaryType', - 'DictionaryVersion', - 'CompressionProfile', - 'DomainCoverage', - 'TranslationRequest', - 'TranslationResult', - 'TranslationChain', - 'dictionary_selection_score', - 'select_best_dictionary', - # Entity Type Taxonomy - 'BehavioralMode', - 'EnergyPattern', - 'InteractionType', - 'EntityTypeInfo', - 'entity_get_info', - 'behavioral_modes', - 'energy_pattern', - 'is_agentic', - 'can_initiate', - 'can_delegate', - 'can_process_r6', - 'valid_interaction', - 'all_entity_types', - # Capability Levels - 'CapabilityLevel', - 'TrustTier', - 'ENTITY_LEVEL_RANGES', - 'LevelRequirement', - 'assess_level', - 'validate_level', - 'can_upgrade', - 'level_requirements', - 'trust_tier', - 'entity_level_range', - 'is_level_typical', - 'common_ground', - # Multi-Device Binding - 'AnchorType', - 'DeviceStatus', - 'HardwareAnchor', - 'DeviceRecord', - 'DeviceConstellation', - 'ANCHOR_TRUST_WEIGHT', - 'CONSTELLATION_TRUST_CEILING', - 'WITNESS_DECAY_TABLE', - 'witness_freshness', - 'default_recovery_quorum', - 'enroll_device', - 'remove_device', - 'coherence_bonus', - 'cross_witness_density', - 'constellation_trust_ceiling', - 'compute_constellation_trust', - 'record_cross_witness', - 'check_recovery_quorum', - 'can_recover', - # Error Taxonomy (RFC 9457) - 'ErrorCode', - 'ErrorCategory', - 'ErrorMeta', - 'Web4ProtocolError', # web4.errors.Web4Error aliased to avoid collision with legacy Web4Error - 'BindingError', - 'PairingError', - 'WitnessError', - 'AuthzError', - 'CryptoError', - 'ProtoError', - 'get_error_meta', - 'codes_for_category', - 'make_error', - # Metabolic States - 'MetabolicState', - 'MetabolicTransition', - 'TrustEffect', - 'MetabolicProfile', - 'ReliabilityFactors', - 'ENERGY_MULTIPLIERS', - 'TRUST_EFFECTS', - 'WITNESS_REQUIREMENTS', - 'DORMANT_STATES', - 'ACTIVE_STATES', - 'metabolic_valid_transition', - 'reachable_states', - 'transition_trigger', - 'all_transitions', - 'energy_cost', - 'wake_penalty', - 'metabolic_reliability', - 'required_witnesses', - 'all_profiles', - 'is_dormant', - 'accepts_transactions', - 'accepts_new_citizens', - # Society - 'SocietyPhase', - 'LedgerEventType', - 'LedgerEntry', - 'SocietyLedger', - 'Treasury', - 'SocietyState', - 'create_society', - 'admit_citizen', - 'suspend_citizen', - 'reinstate_citizen', - 'terminate_citizen', - 'transition_metabolic_state', - 'deposit_treasury', - 'allocate_treasury', - 'record_law_change', - 'compute_society_t3', - 'society_energy_cost', - 'society_health', - 'incorporate_child', - 'society_depth', - 'society_ancestry', - # Core Protocol - 'HandshakePhase', - 'ClientHello', - 'ServerHello', - 'ClientFinished', - 'ServerFinished', - 'HandshakeMessage', - 'PairingMethod', - 'Transport', - 'TransportCompliance', - 'TransportProfile', - 'TRANSPORT_PROFILES', - 'get_transport_profile', - 'required_transports', - 'negotiate_transport', - 'DiscoveryMethod', - 'PrivacyLevel', - 'DISCOVERY_METADATA', - 'required_discovery_methods', - 'discovery_privacy', - 'DiscoveryRequest', - 'DiscoveryResponse', - 'Web4URI', - 'web4_uri_to_dict', - 'web4_uri_from_dict', - 'transport_profile_to_dict', -]