feat: multi-actor ActivityPub support

Each registered user now has their own ActivityPub actor:
- Generate RSA keys per user on registration
- Webfinger resolves any registered user (@user@domain)
- Actor endpoints work for any registered user
- Each user has their own outbox (filtered activities)
- Activities signed with the publishing user's keys
- Objects attributed to the asset owner

Removed:
- ARTDAG_USER config (no longer single-actor)
- L1_SERVER config (comes with each request)

Added:
- /ui/users page listing all registered users
- user_exists() helper function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-07 19:54:11 +00:00
parent 58a125de1a
commit 4155427f03
4 changed files with 121 additions and 57 deletions

View File

@@ -103,7 +103,9 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
def create_user(data_dir: Path, username: str, password: str, email: Optional[str] = None) -> User:
"""Create a new user."""
"""Create a new user with ActivityPub keys."""
from keys import generate_keypair
users = load_users(data_dir)
if username in users:
@@ -119,6 +121,9 @@ def create_user(data_dir: Path, username: str, password: str, email: Optional[st
users[username] = user.model_dump()
save_users(data_dir, users)
# Generate ActivityPub keys for this user
generate_keypair(data_dir, username)
return user