Codebase Architecture

Audience: Contributors who want to understand the ActingWeb codebase structure.

This document provides an overview of the ActingWeb codebase architecture and module responsibilities.

Directory Structure

actingweb/
├── __init__.py              # Package initialization
├── actor.py                 # Core Actor class
├── config.py                # Configuration management
├── property.py              # Property storage
├── trust.py                 # Trust relationships
├── subscription.py          # Event subscriptions
├── oauth.py                 # Legacy OAuth
├── oauth2.py                # OAuth2 implementation
├── aw_proxy.py              # Peer HTTP communication
├── aw_web_obj.py            # Web request/response abstraction
├── on_aw.py                 # Base hook class
│
├── handlers/                # HTTP request handlers
│   ├── base_handler.py      # Common handler functionality
│   ├── properties.py        # Property endpoints
│   ├── trust.py             # Trust endpoints
│   ├── subscription.py      # Subscription endpoints
│   ├── callbacks.py         # Callback endpoints
│   ├── methods.py           # Method endpoints
│   ├── actions.py           # Action endpoints
│   ├── factory.py           # Actor creation
│   ├── oauth.py             # OAuth endpoints
│   ├── oauth2_callback.py   # OAuth2 callback
│   ├── meta.py              # Actor metadata
│   ├── www.py               # Web UI
│   └── devtest.py           # Development/testing
│
├── interface/               # Modern developer API
│   ├── app.py               # ActingWebApp fluent API
│   ├── actor_interface.py   # ActorInterface wrapper
│   ├── property_store.py    # PropertyStore dict-like API
│   ├── trust_manager.py     # TrustManager API
│   ├── subscription_manager.py  # SubscriptionManager API
│   ├── hook_registry.py     # Hook registration
│   ├── authenticated_views.py   # Permission-enforced access
│   └── integrations/        # Framework integrations
│       ├── base_integration.py  # Shared integration logic
│       ├── flask_integration.py # Flask support
│       └── fastapi_integration.py # FastAPI support
│
└── db/                      # Database abstraction layer
    ├── __init__.py          # Config-aware DB accessors
    ├── protocols.py         # Database interface protocols
    ├── dynamodb/            # DynamoDB backend
    │   ├── actor.py         # Actor storage
    │   ├── property.py      # Property storage
    │   ├── trust.py         # Trust storage
    │   └── subscription.py  # Subscription storage
    └── postgresql/          # PostgreSQL backend
        ├── actor.py         # Actor storage
        ├── property.py      # Property storage
        ├── trust.py         # Trust storage
        └── subscription.py  # Subscription storage

Core Classes

Actor

File: actingweb/actor.py

The central class representing a user’s instance. Responsibilities:

  • Actor lifecycle (creation, deletion)

  • Property storage access

  • Trust relationship management

  • Subscription management

  • Peer communication

class Actor:
    id: str              # Unique actor ID
    config: Config       # Configuration
    property: Property   # Property storage

    def get_properties(self) -> Dict
    def set_property(self, name: str, value: Any)
    def get_trust_relationships(self) -> List[Dict]
    def create_trust(self, ...) -> Dict
    # ... async variants for peer communication

Config

File: actingweb/config.py

Application-wide configuration. Responsibilities:

  • Database configuration

  • Authentication settings

  • Feature toggles

  • Actor type definitions

Property

File: actingweb/property.py

Low-level property storage. Responsibilities:

  • CRUD operations on properties

  • JSON serialization

  • Database abstraction

Trust

File: actingweb/trust.py

Trust relationship storage. Responsibilities:

  • Trust CRUD operations

  • Permission storage

  • Relationship type management

Subscription

File: actingweb/subscription.py

Event subscription storage. Responsibilities:

  • Subscription CRUD

  • Diff management

  • Callback tracking

Developer API Layer

The interface/ module provides the modern developer API:

ActingWebApp

File: actingweb/interface/app.py

Fluent configuration API. Responsibilities:

  • Application configuration

  • Framework integration

  • Hook registration

  • Trust type definitions

ActorInterface

File: actingweb/interface/actor_interface.py

High-level actor wrapper. Responsibilities:

  • Clean API for actor operations

  • Access to PropertyStore, TrustManager, SubscriptionManager

  • Authenticated view creation

PropertyStore

File: actingweb/interface/property_store.py

Dictionary-like property access. Responsibilities:

  • Pythonic property access (actor.properties["key"])

  • Automatic JSON serialization

  • Change notification (register_diffs)

  • Hook execution

TrustManager

File: actingweb/interface/trust_manager.py

Trust relationship operations. Responsibilities:

  • Trust CRUD with lifecycle hooks

  • Permission checking

  • Async peer communication

SubscriptionManager

File: actingweb/interface/subscription_manager.py

Subscription operations. Responsibilities:

  • Subscription CRUD

  • Diff management with wrapper classes

  • Async peer subscription

Handler Layer

Handlers process HTTP requests and delegate to the developer API:

BaseHandler

File: actingweb/handlers/base_handler.py

Common handler functionality:

  • Authentication (basic, bearer, passphrase)

  • Response formatting (JSON, HTML)

  • Actor loading

  • Error responses

Specialized Handlers

Each handler type has specific responsibilities:

  • PropertiesHandler: Property CRUD, lists, metadata

  • TrustHandler: Trust CRUD, verification protocol

  • SubscriptionHandler: Subscription CRUD, diffs

  • CallbacksHandler: Incoming peer callbacks

  • MethodsHandler: Custom method hooks

  • ActionsHandler: Custom action hooks

  • FactoryHandler: Actor creation

  • OAuthHandler: OAuth flow

  • OAuth2CallbackHandler: OAuth2 callback processing

Framework Integrations

BaseActingWebIntegration

File: actingweb/interface/integrations/base_integration.py

Shared integration logic:

  • Handler class selection

  • Route mapping

  • OAuth discovery metadata

FlaskActingWebIntegration

File: actingweb/interface/integrations/flask_integration.py

Flask-specific integration:

  • Route registration

  • Request/response adaptation

  • Template rendering

FastAPIActingWebIntegration

File: actingweb/interface/integrations/fastapi_integration.py

FastAPI-specific integration:

  • Async route handlers

  • Pydantic models

  • OpenAPI documentation

Data Flow

Request Processing

HTTP Request
    │
    ▼
Framework (Flask/FastAPI)
    │
    ▼
Integration (builds AWWebObj)
    │
    ▼
Handler (processes request)
    │
    ▼
Developer API (ActorInterface, etc.)
    │
    ▼
Core Classes (Actor, Property, etc.)
    │
    ▼
Database (DynamoDB)

Hook Execution

Handler receives request
    │
    ▼
Handler calls developer API method
    │
    ▼
Developer API executes registered hooks
    │
    ▼
Hook function receives ActorInterface
    │
    ▼
Hook performs business logic
    │
    ▼
Result returned through chain

Inter-Actor Communication

ActingWeb enables distributed communication between actors. This section shows the complete flow when Actor A establishes trust with Actor B, creates subscriptions, and receives callbacks when Actor B’s data changes.

1. Trust Establishment

Actor A                                          Actor B
─────────                                        ─────────
TrustHandler.post()
  └─> TrustManager.create_relationship()
        └─> Actor.create_reciprocal_trust()
              ├─> GET {B}/                       ← Verify peer exists
              ├─> Create local trust (approved=True)
              └─> POST {B}/trust/{rel}  ────────> TrustRelationshipHandler.post()
                                                    └─> create_verified_trust()
                                                          ├─> GET {A}/trust/{rel}/{B}
                                                          └─> Create local trust record

[trust_initiated hook]                          [trust_request_received hook]

If auto-approved:
  modify_trust_and_notify() ─────────────────────> [trust_fully_approved_remote hook]
                                                    └─> Can trigger sync_peer_async()

2. Subscription Creation (A subscribes to B)

Actor A                                          Actor B
─────────                                        ─────────
SubscriptionRootHandler.post()
  └─> subscribe_to_peer()
        └─> create_remote_subscription()
              └─> POST {B}/subscriptions/{A} ──> SubscriptionRelationshipHandler.post()
                    [callback=True locally]         └─> create_local_subscription()
                                                          [callback=False - sends TO A]

3. Peer Sync (A pulls data from B after trust approval)

Actor A                                          Actor B
─────────                                        ─────────
sync_peer_async(peer_id=B)
  ├─> Optionally: refresh_peer_profile_async()
  ├─> Optionally: refresh_peer_capabilities_async()
  ├─> Optionally: fetch_peer_permissions_async() ──> GET {B}/permissions/{A}
  └─> For each subscription:
        sync_subscription_async()
          ├─> GET {B}/subscriptions/{A}/{subid}  ──> Returns diffs
          ├─> CallbackProcessor.process_callback()
          ├─> RemotePeerStore.apply_callback_data()
          └─> PUT {B}/subscriptions/{A}/{subid}  ──> Clear processed diffs

4. Property Change Callback (B notifies A in real-time)

Actor B (publisher)                              Actor A (subscriber)
───────────────────                              ────────────────────
Property changed (PUT /properties/foo)
  └─> register_diffs(target="properties", subtarget="foo")
        ├─> Check if subscription suspended
        ├─> Get subscriptions (callback=False - inbound)
        └─> For each subscription:
              ├─> Filter by peer permissions
              ├─> add_diff() to subscription
              └─> callback_subscription()
                    └─> POST {A}/callbacks/subscriptions/{B}/{subid}
                                                └─> CallbacksHandler.post()
                                                      └─> CallbackProcessor.process_callback()
                                                            └─> RemotePeerStore.apply_callback_data()
                                                            └─> [subscription hook]

5. Permission Change Callback (B grants/revokes permissions to A)

Actor B                                          Actor A
─────────                                        ─────────
Permission modified for A
  └─> POST {A}/callbacks/permissions/{B}  ────> CallbacksHandler.post()
                                                  ├─> PeerPermissionStore.store_permissions()
                                                  ├─> detect_permission_changes()
                                                  ├─> Auto-delete if revoked (if configured)
                                                  └─> [permissions callback hook]

6. Subscription Suspension & Resync

Actor B                                          Actor A
─────────                                        ─────────
subscriptions.suspend(target, subtarget)
  └─> Diffs NOT registered during suspension

... bulk operations ...

subscriptions.resume(target, subtarget)
  └─> For each affected subscription:
        └─> callback_subscription_resync()
              └─> POST resync callback ────────> CallbackProcessor._handle_resync()
                                                  └─> Clear pending, reset state
                                                  └─> RemotePeerStore.apply_resync_data()

Key Implementation Files

The following table maps components to their implementation files:

Component

File

Purpose

Trust handling

actingweb/actor.py:922-1250

Trust creation/verification

Trust handler

actingweb/handlers/trust.py

HTTP endpoints

Subscription

actingweb/subscription.py

Subscription storage

Subscription handler

actingweb/handlers/subscription.py

HTTP endpoints

Subscription manager

actingweb/interface/subscription_manager.py

High-level API

Callback processor

actingweb/callback_processor.py

Sequencing, gaps, resync

Remote storage

actingweb/remote_storage.py

Store peer data locally

Peer permissions

actingweb/peer_permissions.py

Cache what peers grant us

Fan-out

actingweb/fanout.py

Parallel delivery, circuit break

Suspension

actingweb/db/*/subscription_suspension.py

Pause diff registration

Database Layer

ActingWeb uses a pluggable database architecture supporting both DynamoDB and PostgreSQL backends.

Config-Aware DB Accessors

For Contributors: When working with database classes, use the config-aware accessor functions from actingweb.db instead of directly instantiating classes. This ensures proper configuration injection.

Recommended Pattern:

from actingweb.db import get_property, get_actor, get_trust

# Good - configuration is automatically injected
db_property = get_property(config)
db_actor = get_actor(config)
db_trust = get_trust(config)

Avoid Direct Instantiation:

# Avoid - bypasses configuration injection
db_property = config.DbProperty.DbProperty()

Why This Matters:

  • Property lookup table settings (use_lookup_table, indexed_properties) must be properly configured

  • Accessor functions provide type-safe, testable interfaces

  • Clearer dependency on configuration

Available Accessors:

  • get_property(config) - Property database operations

  • get_property_list(config) - Batch property operations

  • get_actor(config) - Actor database operations

  • get_actor_list(config) - Batch actor operations

  • get_trust(config) - Trust database operations

  • get_trust_list(config) - Batch trust operations

  • get_peer_trustee(config) - PeerTrustee operations

  • get_subscription(config) - Subscription operations

  • get_attribute(config) - Attribute/bucket operations

See actingweb/db/__init__.py for complete list with documentation.

Key Design Patterns

  1. Layered Architecture

    Core → Developer API → Handlers → Integrations

  2. Dependency Injection

    Handlers receive webobj, config, hooks DB classes receive configuration via accessor functions

  3. Adapter Pattern

    AWWebObj adapts framework-specific requests

  4. Wrapper Pattern

    ActorInterface wraps Actor with clean API

  5. Hook Pattern

    Extensible business logic via decorators

  6. Factory Pattern

    DB accessor functions create properly configured instances

See Also