Files
CoreRasurae 9dc3f7910b
CI / lint (push) Successful in 1m7s
CI / typecheck (push) Successful in 1m8s
CI / security (push) Successful in 1m7s
CI / quality (push) Successful in 41s
CI / integration_tests (push) Successful in 1m13s
CI / build (push) Successful in 1m22s
CI / unit_tests (push) Successful in 3m13s
CI / coverage (push) Successful in 3m9s
CI / status-check (push) Successful in 3s
docs(registry): add MkDocs API documentation and usage examples for Package Registry Client
Created comprehensive MkDocs-formatted API documentation under docs/registry/
covering all public API surfaces from the registry subsystem with real-life
constructive examples:

- index.md: Architecture overview, module relationships, quickstart
- types.md: PackageType, PackageId, PackageReference, PackageContent
- client.md: RegistryClient with all 4 endpoints, auth modes, async patterns
- canonical.md: Canonicalizer pipeline — NFC, RFC-8785, SHA-1, lifecycle stripping
- resolver.md: ReferenceResolver — 3 reference schemes, version alias resolution
- exceptions.md: RegistryError hierarchy — all 9 typed exceptions with HTTP mapping
- cache.md: RegistryCache — LRU eviction, TTL, SHA-1 tamper detection, singleflight
- integration.md: 4 end-to-end workflows (ordering pipeline, email categorization,
  CI/CD verification, multi-tenant provisioning)

Updated mkdocs.yml nav tree with docs/registry/ entries.

Refs: #51
2026-06-17 14:09:28 +00:00

4.1 KiB

Package Registry Client

CleverActors Package Registry Subsystem — Client-Side Implementation of the Package Registry Standard v1.0.0


Overview

The Package Registry Client implements the Package Registry Standard v1.0.0 on the client side. It provides a complete, async-first library for discovering, resolving, fetching, caching, and validating versioned packages of AI components — actors, graphs, agents, templates, skills, MCP servers, and LSP services — from any compliant registry server.

Architecture

src/cleveractors/registry/
├── __init__.py              Public re-exports
├── types.py                 Core data types (PackageType, PackageId, PackageReference, PackageContent)
├── exceptions.py            Typed exception hierarchy (RegistryError + 9 subclasses)
├── client.py                Async HTTP client (RegistryClient) — all 4 API endpoints
├── canonical.py             Canonicalizer — RFC-8785 canonical JSON + SHA-1 hashing
├── resolver.py              ReferenceResolver — parse and resolve all 3 reference schemes
├── reference_resolver.py    PackageContentResolver — multi-server client pool with caching
├── cache.py                 RegistryCache — LRU + TTL + tamper detection with singleflight
└── local_store.py           LocalPackageStore — resolve `local:<path>` references from disk

Module Relationships

PackageReference ──► ReferenceResolver ──► PackageId
       │                    │
       │                    ▼
       │              RegistryClient (HTTP)
       │                    │
       │                    ▼
       └──────────► PackageContentResolver
                            │
                 ┌──────────┼──────────┐
                 ▼          ▼          ▼
          RegistryCache  Canonicalizer  LocalPackageStore

Module Map

Module Role
Types PackageType, PackageId, PackageReference, PackageContent — frozen dataclasses and enums
Client RegistryClient — async HTTP client implementing all 4 endpoints (§8)
Canonicalizer Canonicalizer — deterministic RFC-8785 JSON, NFC normalization, SHA-1 hashing
Resolver ReferenceResolver — parse all 3 reference schemes, resolve version aliases
Exceptions RegistryError hierarchy — 9 typed exceptions with HTTP status mapping
Cache RegistryCache — LRU eviction, TTL expiration, SHA-1 tamper detection, singleflight
Integration End-to-end workflows combining multiple modules

Quickstart

import asyncio
from cleveractors.registry import (
    RegistryClient,
    RegistryCache,
    CacheFactory,
    ReferenceResolver,
    PackageReference,
)


async def main() -> None:
    # 1. Create an authenticated client for your registry server
    client = RegistryClient(
        base_url="https://registry.example.com",
        api_key="your-api-key",
    )

    # 2. Wrap it with transparent caching (optional but recommended)
    cache = RegistryCache(client, max_size=512, ttl=600.0)

    # 3. Fetch a package by its content-addressed ID
    content = await cache.get_package(
        "pkg_act_a1b2c3d4e5f67890abcdef1234567890abcdef"
    )
    print(f"Package name: {content['name']}")

    # 4. Resolve a named package with version
    resolved = await cache.resolve_package(
        package_type="actor",
        namespace="acme",
        name="order-validator",
        version="v1.0.0",
    )
    print(f"Resolved to: {resolved['package_id']}")

    # 5. Parse and resolve references with the resolver
    resolver = ReferenceResolver(client=client)
    ref = resolver.parse("registry.example.com:acme/order-validator@latest")
    package_id = await resolver.resolve(ref.original_reference)
    print(f"Resolved ID: {package_id}")

    await cache.close()


if __name__ == "__main__":
    asyncio.run(main())