commits
aside.note had no dark mode color override, leaving it #666 on #0b0b0b
(nearly invisible). Match note-inline's dark mode color #9ca3af.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The checkbox was labeled 'Hide notes' with checked=hideNotes, meaning
unchecked by default (notes hidden from user's perspective). Relabeled
to 'Show notes' with inverted binding: checked=!hideNotes so it starts
checked (notes visible). Inverted the event handler accordingly so
checking 'Show notes' sets hideNotes=false (don't strip).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Store authorization server URL in OAuth session
- Refresh tokens using PDS-specific token endpoint
- Support OAuth refresh_token grant type
- Maintain backward compatibility with legacy sessions
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace inline resolveHandle() and resolvePDSFromPLC() functions
with services.ResolveHandleToDID() and services.ResolvePDSEndpoint()
as specified in Task 2.
Changes:
- Import services package in routes_login.go
- Use services.ResolveHandleToDID() for handle resolution
- Use services.ResolvePDSEndpoint() for PDS and auth server discovery
- Remove duplicate inline functions resolveHandle() and resolvePDSFromPLC()
- Maintain graceful fallback to bsky.social on resolution failures
- Add logging for handle resolution and PDS discovery steps
All tests passing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Resolve handle to DID and discover PDS endpoint
- Use PDS-specific authorization and token endpoints
- Store authorization server in OAuth session
- Support non-Bluesky PDS instances
- Resolve AT Protocol handles to DIDs
- Discover PDS endpoints from DID documents (did:plc and did:web)
- Support authorization server discovery
- Fallback to Bluesky directory for handle resolution
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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)
The checkbox was labeled 'Hide notes' with checked=hideNotes, meaning
unchecked by default (notes hidden from user's perspective). Relabeled
to 'Show notes' with inverted binding: checked=!hideNotes so it starts
checked (notes visible). Inverted the event handler accordingly so
checking 'Show notes' sets hideNotes=false (don't strip).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace inline resolveHandle() and resolvePDSFromPLC() functions
with services.ResolveHandleToDID() and services.ResolvePDSEndpoint()
as specified in Task 2.
Changes:
- Import services package in routes_login.go
- Use services.ResolveHandleToDID() for handle resolution
- Use services.ResolvePDSEndpoint() for PDS and auth server discovery
- Remove duplicate inline functions resolveHandle() and resolvePDSFromPLC()
- Maintain graceful fallback to bsky.social on resolution failures
- Add logging for handle resolution and PDS discovery steps
All tests passing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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)