gilesb a2190801e8 feat: add user registration and JWT authentication
- POST /auth/register - create account
- POST /auth/login - get JWT token
- GET /auth/me - get current user
- POST /auth/verify - verify token (for L1)
- Password hashing with bcrypt
- 30-day JWT tokens

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 14:43:14 +00:00
2026-01-07 12:04:58 +00:00

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

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:

# 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 <container> 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

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

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)

curl "http://localhost:8200/.well-known/webfinger?resource=acct:giles@artdag.rose-ash.com"

Get actor profile

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
Description
No description provided
Readme 2.2 MiB
Languages
Python 91.3%
HTML 8.4%
Dockerfile 0.2%
Shell 0.1%