A third party ATProto appview

Add CORS configuration to allow all origins for the AppView API

+24 -1
README.md
··· 36 36 - **API Documentation**: Live endpoint listing with performance metrics 37 37 - **Logs & Analytics**: Real-time log viewer with filtering 38 38 39 + ## Design Philosophy: Scale Down, Not Just Up 40 + 41 + **True decentralization means scaling to fit your needs - whether that's a personal instance or a full network mirror.** 42 + 43 + Most current AppViews default to mirroring everything, but this creates centralized liability risks. This AppView takes a different approach with **configurable retention and backfill**: 44 + 45 + ### Why Configurable Retention Matters 46 + 47 + - **Personal Instances**: Run an instance with just your circles' data (days or weeks, not years) 48 + - **Topical Communities**: A gaming community keeps 90 days of game-related posts, a news instance keeps 30 49 + - **Privacy by Design**: Data minimization isn't just good practice - you can't be compelled to hand over data you never stored 50 + - **Technical Defense**: Against authoritarian data seizure or legal overreach, the best defense is not having the data 51 + 52 + ### Flexible Deployment Models 53 + 54 + Configure `BACKFILL_DAYS` and `DATA_RETENTION_DAYS` to match your use case: 55 + 56 + - **Zero-retention ephemeral** (0 days): Real-time only, no history 57 + - **Personal/community** (7-30 days): Recent activity for small groups 58 + - **Topical archive** (90-180 days): Focused collections 59 + - **Full mirror** (0 = unlimited): Complete network history 60 + 61 + This isn't about choosing between centralized or decentralized - it's about **enabling distributed operation at any scale**. Run what you need, store what you want, minimize what you don't. 62 + 39 63 ## Quick Start 40 64 41 65 ### Prerequisites ··· 229 253 - `NODE_ENV`: Environment mode (`development` or `production`) 230 254 - `BACKFILL_DAYS`: Historical backfill in days (0=disabled, >0=backfill X days, default: `0`) 231 255 - `DATA_RETENTION_DAYS`: Auto-prune old data (0=keep forever, >0=prune after X days, default: `0`) 232 - - `DASHBOARD_PASSWORD`: Optional password for dashboard authentication 233 256 - `DB_POOL_SIZE`: Database connection pool size (default: `32`) 234 257 - `MAX_CONCURRENT_OPS`: Max concurrent event processing (default: `80`) 235 258
-1
WEBDID_SETUP.md
··· 213 213 # 2. Configure secrets 214 214 export APPVIEW_DID=did:web:appview.example.com 215 215 export SESSION_SECRET=$(openssl rand -base64 32) 216 - export DASHBOARD_PASSWORD=your-secure-password 217 216 218 217 # 3. Setup DNS 219 218 # Point appview.example.com → your-server-ip
-1
docker-compose.yml
··· 41 41 - REDIS_URL=redis://redis:6379 42 42 - RELAY_URL=wss://bsky.network 43 43 - SESSION_SECRET=${SESSION_SECRET:-change-this-to-a-random-secret-in-production} 44 - - DASHBOARD_PASSWORD=${DASHBOARD_PASSWORD:-} 45 44 - APPVIEW_DID=${APPVIEW_DID:-did:web:appview.local} 46 45 - BACKFILL_DAYS=${BACKFILL_DAYS:-0} 47 46 - DATA_RETENTION_DAYS=${DATA_RETENTION_DAYS:-0}
+16
server/index.ts
··· 43 43 })); 44 44 app.use(express.urlencoded({ extended: false })); 45 45 46 + // CORS configuration - Allow all origins for AppView API 47 + app.use((req, res, next) => { 48 + res.setHeader('Access-Control-Allow-Origin', '*'); 49 + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 50 + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Accept, atproto-accept-labelers'); 51 + res.setHeader('Access-Control-Expose-Headers', 'atproto-content-labelers, atproto-repo-rev'); 52 + 53 + // Handle preflight requests 54 + if (req.method === 'OPTIONS') { 55 + res.sendStatus(200); 56 + return; 57 + } 58 + 59 + next(); 60 + }); 61 + 46 62 // Logging configuration 47 63 const MAX_LOG_LINE_LENGTH = 80; 48 64 const MAX_LOG_LINE_LENGTH_TRUNCATED = 79;