Art DAG L2 Server - ActivityPub
Ownership registry and ActivityPub federation for Art DAG. Manages asset provenance, cryptographic anchoring, and distributed identity.
Features
- Asset Registry: Content-addressed assets with provenance tracking
- ActivityPub Federation: Standard protocol for distributed social networking
- OpenTimestamps Anchoring: Cryptographic proof of existence on Bitcoin blockchain
- L1 Integration: Record and verify L1 rendering runs
- Storage Providers: S3, IPFS, and local storage backends
- Scoped Authentication: Secure token-based auth for federated L1 servers
Dependencies
- PostgreSQL: Primary data storage
- artdag-common: Shared templates and middleware
- cryptography: RSA key generation and signing
- httpx: Async HTTP client for federation
Quick Start
Docker Deployment
Configuration
Environment Variables
| Variable |
Default |
Description |
ARTDAG_DOMAIN |
artdag.rose-ash.com |
Domain for ActivityPub actors |
ARTDAG_USER |
giles |
Default username |
ARTDAG_DATA |
~/.artdag/l2 |
Data directory |
DATABASE_URL |
(required) |
PostgreSQL connection |
L1_SERVERS |
- |
Comma-separated list of L1 server URLs |
JWT_SECRET |
(generated) |
JWT signing secret |
HOST |
0.0.0.0 |
Server bind address |
PORT |
8200 |
Server port |
JWT Secret
The JWT secret signs authentication tokens. Without a persistent secret, tokens are invalidated on restart.
RSA Keys
ActivityPub requires RSA keys for signing activities:
Keys stored in $ARTDAG_DATA/keys/:
{username}.pem - Private key (chmod 600)
{username}.pub - Public key (in actor profile)
Web UI
| Path |
Description |
/ |
Home page with stats |
/login |
Login form |
/register |
Registration form |
/logout |
Log out |
/assets |
Browse registered assets |
/asset/{name} |
Asset detail page |
/activities |
Published activities |
/activity/{id} |
Activity detail |
/users |
Registered users |
/renderers |
L1 renderer connections |
/anchors/ui |
OpenTimestamps management |
/storage |
Storage provider config |
/download/client |
Download CLI client |
API Reference
Interactive docs: http://localhost:8200/docs
Authentication
| Method |
Path |
Description |
| POST |
/auth/register |
Register new user |
| POST |
/auth/login |
Login, get JWT token |
| GET |
/auth/me |
Get current user info |
| POST |
/auth/verify |
Verify token (for L1 servers) |
Assets
| Method |
Path |
Description |
| GET |
/assets |
List all assets |
| GET |
/assets/{name} |
Get asset by name |
| POST |
/assets |
Register new asset |
| PATCH |
/assets/{name} |
Update asset metadata |
| POST |
/assets/record-run |
Record L1 run as asset |
| POST |
/assets/publish-cache |
Publish L1 cache item |
| GET |
/assets/by-run-id/{run_id} |
Find asset by L1 run ID |
ActivityPub
| Method |
Path |
Description |
| GET |
/.well-known/webfinger |
Actor discovery |
| GET |
/users/{username} |
Actor profile |
| GET |
/users/{username}/outbox |
Published activities |
| POST |
/users/{username}/inbox |
Receive activities |
| GET |
/users/{username}/followers |
Followers list |
| GET |
/objects/{hash} |
Get object by content hash |
| GET |
/activities |
List activities (paginated) |
| GET |
/activities/{ref} |
Get activity by reference |
| GET |
/activity/{index} |
Get activity by index |
OpenTimestamps Anchoring
| Method |
Path |
Description |
| POST |
/anchors/create |
Create timestamp anchor |
| GET |
/anchors |
List all anchors |
| GET |
/anchors/{merkle_root} |
Get anchor details |
| GET |
/anchors/{merkle_root}/tree |
Get merkle tree |
| GET |
/anchors/verify/{activity_id} |
Verify activity timestamp |
| POST |
/anchors/{merkle_root}/upgrade |
Upgrade pending timestamp |
| GET |
/anchors/ui |
Anchor management UI |
| POST |
/anchors/test-ots |
Test OTS functionality |
Renderers (L1 Connections)
| Method |
Path |
Description |
| GET |
/renderers |
List attached L1 servers |
| GET |
/renderers/attach |
Initiate L1 attachment |
| POST |
/renderers/detach |
Detach from L1 server |
Storage Providers
| Method |
Path |
Description |
| GET |
/storage |
List storage providers |
| POST |
/storage |
Add provider (form) |
| POST |
/storage/add |
Add provider (JSON) |
| GET |
/storage/{id} |
Get provider details |
| PATCH |
/storage/{id} |
Update provider |
| DELETE |
/storage/{id} |
Delete provider |
| POST |
/storage/{id}/test |
Test connection |
| GET |
/storage/type/{type} |
Get form for provider type |
L1 Renderer Integration
L2 coordinates with L1 rendering servers for distributed processing.
Configuration
Attachment Flow
- User visits
/renderers and clicks "Attach"
- L2 creates a scoped token bound to the specific L1
- User redirected to L1's
/auth?auth_token=...
- L1 calls L2's
/auth/verify to validate
- L2 checks token scope matches requesting L1
- L1 sets local cookie, attachment recorded in
user_renderers
Security
- Scoped tokens: Tokens bound to specific L1; can't be used elsewhere
- No shared secrets: L1 verifies via L2's
/auth/verify endpoint
- Federated logout: L2 revokes tokens on all attached L1s
OpenTimestamps Anchoring
Cryptographic proof of existence using Bitcoin blockchain.
How It Works
- Activities are collected into merkle trees
- Merkle root submitted to Bitcoin via OpenTimestamps
- Pending proofs upgraded when Bitcoin confirms
- Final proof verifiable without trusted third parties
Verification
Data Model
PostgreSQL Tables
| Table |
Description |
users |
Registered users with hashed passwords |
assets |
Asset registry with content hashes |
activities |
Signed ActivityPub activities |
followers |
Follower relationships |
anchors |
OpenTimestamps anchor records |
anchor_activities |
Activity-to-anchor mappings |
user_renderers |
L1 attachment records |
revoked_tokens |
Token revocation list |
storage_providers |
Storage configurations |
Asset Structure
Activity Structure
CLI Commands
Register Asset
Record L1 Run
Publish L1 Cache Item
Architecture
Federation
L2 implements ActivityPub for federated asset sharing.
Discovery
Actor Profile
Outbox