# Art DAG L2 Server - ActivityPub Ownership registry and ActivityPub federation for Art DAG. ## What it does - **Registry**: Maintains owned assets with content hashes - **Activities**: Creates signed ownership claims (Create activities) - **Federation**: ActivityPub endpoints for follow/share - **L1 Integration**: Records completed L1 runs as owned assets ## Setup ```bash pip install -r requirements.txt # Configure (optional - defaults shown) export ARTDAG_DOMAIN=artdag.rose-ash.com export ARTDAG_USER=giles export ARTDAG_DATA=~/.artdag/l2 export ARTDAG_L1=http://localhost:8100 # Generate signing keys (required for federation) python setup_keys.py # Start server python server.py ``` ## Key Setup ActivityPub requires RSA keys for signing activities. Generate them: ```bash # Local python setup_keys.py # Or with custom paths python setup_keys.py --data-dir /data/l2 --user giles # In Docker, exec into container or mount volume docker exec -it python setup_keys.py ``` Keys are stored in `$ARTDAG_DATA/keys/`: - `{username}.pem` - Private key (chmod 600, NEVER share) - `{username}.pub` - Public key (included in actor profile) **Important**: Private keys are gitignored. Back them up securely. Losing them invalidates all your signatures. ## API Endpoints ### Server Info | Method | Path | Description | |--------|------|-------------| | GET | `/` | Server info | ### ActivityPub | Method | Path | Description | |--------|------|-------------| | GET | `/.well-known/webfinger?resource=acct:user@domain` | 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/{content_hash}` | Get object by hash | ### Registry | Method | Path | Description | |--------|------|-------------| | GET | `/registry` | Full registry | | GET | `/registry/{name}` | Get asset by name | | POST | `/registry` | Register new asset | | POST | `/registry/record-run` | Record L1 run as owned asset | ## Example Usage ### Register an asset ```bash curl -X POST http://localhost:8200/registry \ -H "Content-Type: application/json" \ -d '{ "name": "my-video", "content_hash": "abc123...", "asset_type": "video", "tags": ["art", "generated"] }' ``` ### Record an L1 run ```bash curl -X POST http://localhost:8200/registry/record-run \ -H "Content-Type: application/json" \ -d '{ "run_id": "uuid-from-l1", "output_name": "my-rendered-video" }' ``` ### Discover actor (WebFinger) ```bash curl "http://localhost:8200/.well-known/webfinger?resource=acct:giles@artdag.rose-ash.com" ``` ### Get actor profile ```bash curl -H "Accept: application/activity+json" http://localhost:8200/users/giles ``` ## Data Storage Data stored in `~/.artdag/l2/`: - `registry.json` - Asset registry - `activities.json` - Signed activities - `actor.json` - Actor profile - `followers.json` - Followers list ## Architecture ``` L2 Server (port 8200) │ ├── POST /registry → Register asset → Create activity → Sign │ ├── POST /registry/record-run → Fetch L1 run → Register output │ │ │ └── GET L1_SERVER/runs/{id} │ ├── GET /users/{user}/outbox → Return signed activities │ └── POST /users/{user}/inbox → Receive Follow requests ```