commits
Reduced main.go from 1,320 lines to 143 lines (89% reduction) by extracting
reusable components into dedicated packages:
## New Packages
- **middleware/auth.go**: Authentication and session management
- PDSRequest: DPoP-based ATProto authentication with retry logic
- AuthedDo: Authenticated HTTP requests with auto token refresh
- GetDIDAndHandle: User identity resolution (OAuth + legacy)
- RefreshSession: Token refresh handling
- **services/blob.go**: Document and blob operations
- UploadBlob: Blob upload with retry
- GetDocNameAndText: Document fetching from ATProto
- RenderPDF: Screenplay PDF generation (moved from pdf.go)
- SanitizeFilename: Safe filename handling
- **services/atproto.go**: ATProto protocol utilities
- ResolveHandle: Handle to DID resolution
- ResolvePDSFromPLC: PDS endpoint discovery
- **handlers/static/handler.go**: Static file serving
- Precompressed file support (Brotli/Gzip)
- ETag caching
- Content-type handling
## Benefits
- Separation of concerns: each package has single responsibility
- Testability: all logic can be unit tested independently
- Maintainability: changes localized to specific packages
- Reusability: services used by multiple handlers
- Clean dependency injection through constructors
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
- Extracted handlers into packages:
- handlers/atp: /atp/session, /atp/post, /atp/doc via DI
- handlers/oauth: OAuthManager (ES256 DPoP + client assertion), routes for metadata, JWKS, logout, resume, login, callback
- Removed legacy OAuth code from server/main.go; replaced global wiring with package manager (oauthManager = om)
- Kept pdsBaseFromUser and pdsRequest using oauthManager; exported GenerateDPoPProofWithToken
Auth decisions implemented (per team memory)
- Start auth by handle (login flow resolves PDS from handle/DID)
- Build DPoP JWTs using Go stdlib (ES256)
- Token exchange includes resource & scope
- Dual-scheme PDS requests: DPoP first with nonce retry; Bearer+DPoP fallback for non-DPoP tokens
Tests
- handlers/oauth: metadata, JWKS, cookie session, login redirect, resource fallback, callback nonce retry + legacy session hook
- server: pdsRequest integration tests for nonce retry and DPoP->Bearer fallback
Build & Dev
- Dockerfile: copy entire server/ tree so internal packages resolve; keep module cache
- Added go.work at repo root (go 1.24.0) to support root-based builds (buildpacks/CI)
- go.mod tidy: removed unused modules and stabilized indirects
Result
- Local build/tests pass
- Staging deploy via Fly succeeds (uses Dockerfile)
Reduced main.go from 1,320 lines to 143 lines (89% reduction) by extracting
reusable components into dedicated packages:
## New Packages
- **middleware/auth.go**: Authentication and session management
- PDSRequest: DPoP-based ATProto authentication with retry logic
- AuthedDo: Authenticated HTTP requests with auto token refresh
- GetDIDAndHandle: User identity resolution (OAuth + legacy)
- RefreshSession: Token refresh handling
- **services/blob.go**: Document and blob operations
- UploadBlob: Blob upload with retry
- GetDocNameAndText: Document fetching from ATProto
- RenderPDF: Screenplay PDF generation (moved from pdf.go)
- SanitizeFilename: Safe filename handling
- **services/atproto.go**: ATProto protocol utilities
- ResolveHandle: Handle to DID resolution
- ResolvePDSFromPLC: PDS endpoint discovery
- **handlers/static/handler.go**: Static file serving
- Precompressed file support (Brotli/Gzip)
- ETag caching
- Content-type handling
## Benefits
- Separation of concerns: each package has single responsibility
- Testability: all logic can be unit tested independently
- Maintainability: changes localized to specific packages
- Reusability: services used by multiple handlers
- Clean dependency injection through constructors
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
- Extracted handlers into packages:
- handlers/atp: /atp/session, /atp/post, /atp/doc via DI
- handlers/oauth: OAuthManager (ES256 DPoP + client assertion), routes for metadata, JWKS, logout, resume, login, callback
- Removed legacy OAuth code from server/main.go; replaced global wiring with package manager (oauthManager = om)
- Kept pdsBaseFromUser and pdsRequest using oauthManager; exported GenerateDPoPProofWithToken
Auth decisions implemented (per team memory)
- Start auth by handle (login flow resolves PDS from handle/DID)
- Build DPoP JWTs using Go stdlib (ES256)
- Token exchange includes resource & scope
- Dual-scheme PDS requests: DPoP first with nonce retry; Bearer+DPoP fallback for non-DPoP tokens
Tests
- handlers/oauth: metadata, JWKS, cookie session, login redirect, resource fallback, callback nonce retry + legacy session hook
- server: pdsRequest integration tests for nonce retry and DPoP->Bearer fallback
Build & Dev
- Dockerfile: copy entire server/ tree so internal packages resolve; keep module cache
- Added go.work at repo root (go 1.24.0) to support root-based builds (buildpacks/CI)
- go.mod tidy: removed unused modules and stabilized indirects
Result
- Local build/tests pass
- Staging deploy via Fly succeeds (uses Dockerfile)