Migrating to ActingWeb 3.7
Overview
ActingWeb 3.7 is a major developer API enhancement release that extends the SubscriptionManager and TrustManager interfaces with cleaner, more powerful methods. The handlers have been refactored to use a four-tier architecture for better separation of concerns.
Key Changes:
Extended developer API with new methods for subscriptions and trust management
New wrapper classes (
SubscriptionWithDiffs) for cleaner APIsAutomatic lifecycle hook triggering in trust operations
Handlers refactored to delegate business logic to developer API
HTTP REST API remains 100% backward compatible
Who Needs to Migrate?
You need to migrate if:
Your application uses
ActorInterface,SubscriptionManager, orTrustManagerdirectly in Python codeYou call core
Actormethods for subscription or trust operationsYou want to use the new cleaner APIs with better type safety
You do NOT need to migrate if:
Your application only uses ActingWeb’s HTTP REST endpoints (
/properties,/trust,/subscriptions)You only use hooks and don’t call developer API methods directly
The HTTP API is 100% backward compatible
Breaking Changes
Developer API Extensions
The developer API has been extended with new methods. Old methods still work, but new code should use the enhanced APIs:
SubscriptionManager Changes
New Methods:
create_local_subscription(peer_id, target, ...)- Create subscriptions with proper diff registrationget_subscription_with_diffs(peer_id, subscription_id)- ReturnsSubscriptionWithDiffswrapperget_callback_subscription(peer_id)- Get callback subscription (outbound)delete_callback_subscription(peer_id)- Delete callback subscription
New Wrapper Class:
SubscriptionWithDiffs- Clean access to subscription data and diffs.get_diffs()- Get pending diffs.mark_diff_delivered(diff_id)- Mark diff as delivered.subscriptionproperty - Access underlying subscription data
TrustManager Changes
New Methods:
create_verified_trust(peer_id, relationship, ...)- Create trust with automatic lifecycle hooksmodify_and_notify(peer_id, ...)- Modify trust and notify peerdelete_peer_trust(peer_id)- Delete trust with proper cleanuptrustee_rootproperty - Get trustee root URL
Migration Guide
Subscription Operations
Before (v3.6 and earlier):
from actingweb.actor import Actor
# Direct core Actor usage
actor = Actor(actor_id, config)
sub = actor.get_subscription_obj(peerid=peer_id, subid=sub_id)
if sub:
diffs = sub.get_diffs()
for diff in diffs:
# Process diff
pass
After (v3.7+):
from actingweb.interface import ActorInterface
# Clean developer API
actor = ActorInterface.get_by_id(actor_id, config)
sub_with_diffs = actor.subscriptions.get_subscription_with_diffs(
peer_id=peer_id,
subscription_id=sub_id
)
if sub_with_diffs:
diffs = sub_with_diffs.get_diffs()
for diff in diffs:
# Process diff
sub_with_diffs.mark_diff_delivered(diff["id"])
Benefits:
✅ Type-safe wrapper with IDE autocompletion
✅ Cleaner method names (
peer_idnotpeerid)✅ Built-in diff marking convenience method
✅ Better error handling and validation
Creating Subscriptions
Before (v3.6 and earlier):
from actingweb.actor import Actor
actor = Actor(actor_id, config)
subscription = actor.create_subscription(
peerid=peer_id,
target="properties",
subtarget="temperature"
)
After (v3.7+):
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
subscription = actor.subscriptions.create_local_subscription(
peer_id=peer_id,
target="properties",
subtarget="temperature"
)
Benefits:
✅ Automatic diff registration
✅ Cleaner parameter names
✅ Better validation and error messages
Callback Subscriptions
Callback subscriptions (outbound, where we receive callbacks from peers) now have dedicated methods:
Before (v3.6 and earlier):
# Mixed with regular subscriptions
from actingweb.actor import Actor
actor = Actor(actor_id, config)
sub = actor.get_subscription(peerid=peer_id)
After (v3.7+):
# Explicit callback subscription methods
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
# Get callback subscription (we receive callbacks)
callback_sub = actor.subscriptions.get_callback_subscription(peer_id)
# Delete callback subscription
actor.subscriptions.delete_callback_subscription(peer_id)
Benefits:
✅ Clear distinction between inbound and outbound subscriptions
✅ API explicitly documents subscription direction
✅ Prevents confusion in multi-directional subscription scenarios
Trust Relationship Operations
Creating Trust Relationships
Before (v3.6 and earlier):
from actingweb.actor import Actor
actor = Actor(actor_id, config)
trust = actor.create_trust(
peerid=peer_id,
relationship="friend",
desc="My friend"
)
# Manual lifecycle hook triggering may be needed
After (v3.7+):
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
trust = actor.trust.create_verified_trust(
peer_id=peer_id,
relationship="friend",
desc="My friend"
)
# trust_approved hook triggered automatically
Benefits:
✅ Automatic lifecycle hook triggering (
trust_approved)✅ Cleaner parameter names (
peer_idnotpeerid)✅ Better error handling and validation
✅ Intention-revealing method name
Modifying Trust Relationships
Before (v3.6 and earlier):
from actingweb.actor import Actor
actor = Actor(actor_id, config)
trust = actor.get_trust(peerid=peer_id)
if trust:
trust["desc"] = "Updated description"
actor.modify_trust(trust)
# Manual peer notification may be needed
After (v3.7+):
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
success = actor.trust.modify_and_notify(
peer_id=peer_id,
desc="Updated description"
)
# Peer automatically notified of changes
Benefits:
✅ Automatic peer notification
✅ Simpler API (no need to get, modify, save pattern)
✅ Better error handling
Deleting Trust Relationships
Before (v3.6 and earlier):
from actingweb.actor import Actor
actor = Actor(actor_id, config)
actor.delete_trust(peerid=peer_id)
# Manual cleanup may be needed
After (v3.7+):
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
success = actor.trust.delete_peer_trust(peer_id)
# trust_deleted hook triggered automatically
# Peer notified, cleanup performed
Benefits:
✅ Automatic lifecycle hook triggering (
trust_deleted)✅ Proper cleanup (permissions, subscriptions, etc.)
✅ Peer notification handled automatically
Accessing Trustee Root
Before (v3.6 and earlier):
from actingweb.actor import Actor
actor = Actor(actor_id, config)
trustee_root = actor.property["trustee_root"]
After (v3.7+):
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
trustee_root = actor.trust.trustee_root
Benefits:
✅ Clean property access
✅ Type-safe
✅ Better IDE support
Property Operations (Unchanged)
PropertyStore was already well-designed in v3.6, so no changes are needed:
from actingweb.interface import ActorInterface
actor = ActorInterface.get_by_id(actor_id, config)
# Get all properties
all_props = actor.properties.to_dict()
# Get specific property
value = actor.properties.get("my_property")
value = actor.properties["my_property"] # Also works
# Set property
actor.properties["my_property"] = "new_value"
# Delete property
actor.properties.delete("my_property")
del actor.properties["my_property"] # Also works
Architecture Changes
Four-Tier Architecture
Handlers have been refactored to a clean four-tier architecture:
v3.6 (Two-Tier):
HTTP Handler
↓ (direct call)
Core Actor
↓
Database
Problems:
Business logic scattered between handlers and core
Handlers tightly coupled to core implementation
Difficult to test handler logic independently
v3.7 (Four-Tier):
HTTP Handler (HTTP concerns only)
↓
Developer API (business logic)
↓
Core Actor (data access)
↓
Database
Benefits:
✅ Clean separation of concerns
✅ Handlers are thin HTTP adapters
✅ Business logic testable via unit tests
✅ Developer API is full-featured
✅ Easy to extend and maintain
This architectural change does not affect application code using the developer API - it only improves the internal structure.
Testing Your Migration
After migrating to v3.7, verify your application works correctly:
Unit Tests
Test your business logic using the new developer API methods:
import pytest
from actingweb.interface import ActorInterface
from actingweb.config import Config
def test_subscription_with_diffs():
"""Test the new subscription wrapper API."""
config = Config(...)
actor = ActorInterface.get_by_id(actor_id, config)
# Get subscription with diffs
sub_with_diffs = actor.subscriptions.get_subscription_with_diffs(
peer_id="peer123",
subscription_id="sub456"
)
assert sub_with_diffs is not None
diffs = sub_with_diffs.get_diffs()
assert len(diffs) >= 0
Integration Tests
Your existing integration tests should continue to work without changes since the HTTP API is backward compatible:
def test_subscription_endpoint():
"""HTTP endpoint remains unchanged."""
response = requests.get(
f"{actor_url}/subscriptions/{peer_id}",
auth=(username, password)
)
assert response.status_code == 200
data = response.json()
# Response format unchanged
Type Checking
Run type checking to catch any API usage issues:
poetry run pyright actingweb your_app/
Benefits of Upgrading
Type Safety
New methods return typed wrapper objects with full IDE support:
# IDE autocompletion works
sub_with_diffs = actor.subscriptions.get_subscription_with_diffs(...)
sub_with_diffs.get_diffs() # IDE suggests this method
sub_with_diffs.mark_diff_delivered() # And this one
sub_with_diffs.subscription # And this property
Automatic Lifecycle Hooks
Trust operations now trigger hooks automatically:
# trust_approved hook triggered automatically
trust = actor.trust.create_verified_trust(...)
# trust_deleted hook triggered automatically
actor.trust.delete_peer_trust(peer_id)
Cleaner APIs
Intention-revealing method names make code self-documenting:
# Clear what this does
actor.subscriptions.get_callback_subscription(peer_id)
# vs old generic method
actor.get_subscription(peerid=peer_id) # What kind of subscription?
Better Testing
Unit test business logic without HTTP concerns:
# Test subscription logic in isolation
def test_subscription_processing():
actor = ActorInterface.get_by_id(actor_id, config)
sub_with_diffs = actor.subscriptions.get_subscription_with_diffs(...)
# No HTTP requests, no database setup needed
# Pure business logic testing
Comprehensive Docstrings
All new methods include detailed docstrings with examples:
help(actor.subscriptions.get_subscription_with_diffs)
# Shows full documentation with parameter descriptions and examples
Backward Compatibility
HTTP API
The HTTP REST API remains 100% backward compatible:
GET/POST/PUT/DELETE /propertiesGET/POST/PUT/DELETE /trustGET/POST/DELETE /subscriptionsGET/POST /callbacksAll other endpoints unchanged
Old Developer API Methods
Core Actor methods still work (not deprecated):
# These still work in v3.7
actor.get_subscription_obj(peerid=peer_id, subid=sub_id)
actor.create_subscription(peerid=peer_id, ...)
actor.create_trust(peerid=peer_id, ...)
actor.modify_trust(trust)
actor.delete_trust(peerid=peer_id)
However, new code should use the enhanced developer API for better type safety and cleaner APIs.
Summary
ActingWeb 3.7 extends the developer API with cleaner, more powerful methods while maintaining full HTTP API compatibility. The changes primarily benefit applications using the Python developer API directly.
Key Actions:
✅ Review your code for direct
Actormethod usage✅ Migrate to new
SubscriptionManagerandTrustManagermethods✅ Update to use
SubscriptionWithDiffswrapper✅ Run tests to verify migration
✅ Enjoy better type safety and cleaner APIs
Remember: If you only use HTTP endpoints, no migration is needed!
For questions or issues, see: