commits
- Consistently renamed the project from "ATProto Connect" to "Social Sync" in `fabric.mod.json`, README, and UI components.
- Renamed core mod entry points and objects from `Atprotoconnect` to `socialsync` for both client and server.
- Incremented version to 0.5.0 in `gradle.properties`, `fabric.mod.json`, and README.
- Expanded client configuration with several new user preferences:
- Implemented a "Compact Layout" option for the Mod Menu screen.
- Added security toggles for local storage encryption and automated cache clearing on logout.
- Added a preference to toggle sync notifications in the chat.
- Enhanced session management to support conditional AES-256-GCM encryption.
- Refactored `RecordManager` to use a more streamlined TID generation method.
- Registered `DebugScreenMixin` for improved client-side debugging.
- Updated the README with a revised directory structure, new documentation links, and completed roadmap items.
AtProtoConfigScreen is now a proper settings panel with all
ClientPreferences fields exposed:
- Authentication section (login/logout with status)
- Sync consent toggles (stats, sessions, achievements, server status)
- Sync frequency cycle buttons (1/5/10/15/30/60/120/240 min)
- UI preferences (notifications, F3 status, compact layout)
- Privacy settings (encrypted storage, clear on logout)
- Reset to Defaults button
Removes /atproto config and /atproto gui commands — ModMenu is
now the canonical entry point for settings. Help text updated
to point to Mod Menu instead.
- Add achievements and server-status to sync command list
- Mention config screen as alternative to commands for consent toggles
- Update roadmap checkbox to reflect all 4 consent categories
- Remove completed items from Future Possibilities
- Add PlayerSyncPreferencesStore to project structure
- Update architecture diagram with consent store and new storage
- Add sync-preferences/ to configuration files section
- Remove RateLimiter from architecture (server-side login removed)
Login is handled client-side via the mod config screen. Removes:
- AtProtoCommands.loginDeprecated() (dead code, not registered)
- AtProtoSessionManager.createSession() (deprecated, unused)
- AtProtoClient.createSession() (server-side, unused)
- AtProtoClient.CreateSessionRequest data class
- RateLimiter field and cleanup() from AtProtoCommands
- Stale /atproto login references in help text
Unused imports (Duration, Instant, ServerPlayer, SecurityUtils)
cleaned up. RateLimiter.kt kept for potential future use.
Profile records are identity declarations rather than data sync, so
only skip syncing when the player has disabled ALL four categories.
Also updates the class docstring to reference PlayerSyncPreferencesStore
instead of the old PlayerIdentityStore consent fields.
PlayerSyncPreferencesStore is now the single source of truth for all
sync consent (stats, sessions, achievements, server status). The old
syncStats/syncSessions fields on PlayerIdentityStore are legacy-only
and migrated on startup.
- Wire all 4 sync services to check syncPreferencesStore instead of
identityStore.getSyncConsent()
- Expand /atproto sync commands to 4 categories
- Client-side /atproto sync now updates PreferencesManager and sends
SyncPreferencesPacket to server
- Add consent toggles to AtProtoConfigScreen
- Remove old logSyncConsentChange from SecurityAuditor
- Add migration: extractLegacySyncConsent + migrateFromIdentityStore
- Call ServerNetworkHandlers.register() during server initialization
- Enables server to receive and process sync preference updates from clients
- Registers SyncPreferencesPacket type for Fabric networking
- Add logSyncPreferenceChange() for sync preference updates
- Add logSecurityEvent() for generic security event logging
- Track all data types toggled (stats, sessions, achievements, server status)
- Audit log includes player name and UUID for traceability
- Register SyncPreferencesPacket type on server
- Handle client preference updates asynchronously
- Validate player is authenticated before accepting updates
- Persist preferences to PlayerSyncPreferencesStore
- Audit log all sync preference changes
- Error handling and logging for failed preference updates
- Add SyncPreferencesPacket for C2S communication
- Packet includes all sync settings: stats, sessions, achievements, server status
- Includes sync frequencies for each data type
- Serializable with StreamCodec for Fabric networking
- Allows client to send preference updates to server
- Implement PlayerSyncPreferences data class (UUID stored as String for serialization)
- Store player preferences per-player in JSON files
- Methods to load, save, update, and delete player preferences
- Support for granular sync control: stats, sessions, achievements, server status
- Track sync frequencies for each data type
- Admin methods to list all players with preferences
- Automatic directory creation and error handling
- Implement ClientPreferences data class with serialization
- Store preferences locally in JSON format (client-only, no privacy concerns)
- Sync options: stats, sessions, achievements, server status
- Configurable sync frequencies (in minutes)
- UI preference toggles: notifications, F3 display, compact layout
- Privacy options: encrypted storage, cache cleanup on logout
- PreferencesManager singleton for centralized access
Reflect completed features: OAuth, stat syncing, achievement syncing,
session tracking, server status, sync consent controls. Update roadmap.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Periodically sync server status to AT Protocol with literal:self rkey.
Includes version, online players, MOTD, game mode, difficulty, PvP status.
Syncs every 5 minutes when at least one authenticated player is online
(their session is used for the write).
Note: Requires an authenticated player to write. A future "server account"
concept would allow server operators to authenticate independently.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Track when players join and leave servers, creating player.session records
with join/leave times, duration, and quit reason. Uses ServerPlayConnectionEvents
for join/leave detection. Respects syncSessions consent. Flushes all open
sessions on server stop with "server_stop" quit reason.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
AT Protocol data is always public by design, so "publicStats"/"publicSessions"
flags in the profile record were misleading. Renamed to "syncStats"/"syncSessions"
to clarify that these control whether data is written at all, not who can see it.
Changes:
- Remove publicStats/publicSessions from player.profile lexicon
- Rename fields to syncStats/syncSessions in PlayerIdentityStore
- Rename /atproto privacy to /atproto sync with clearer language
- Update all services to use getSyncConsent() instead of getPrivacySettings()
- Update client commands to match
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add ClientSecurityUtils with the same AES-256-GCM encryption used
server-side. ClientSessionManager now encrypts session files on save
and decrypts on load, with automatic migration from plaintext (v2)
to encrypted (v3) format. The encryption key is stored separately
with owner-only file permissions.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add AchievementSyncService that creates achievement records when a
player earns a full advancement. Uses a mixin on PlayerAdvancements.award()
to detect completion. Respects the publicStats privacy setting and
deduplicates within a session. Advancement records include category,
challenge status, and human-readable names.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add publicStats and publicSessions fields to PlayerIdentity with
server-side /atproto privacy commands to toggle visibility. The
PlayerStatSyncService now checks publicStats before syncing. A new
PlayerProfileService writes the player.profile record to AT Protocol
on identity link and privacy changes. Client-side /atproto privacy
command shows current settings and directs to server commands.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Replace the single password-only login form with a dual-mode interface:
- "OAuth Login (Recommended)" opens browser for ATProto OAuth
- "App Password Login" remains as fallback
- Updated help text, status display, and security notice
- Shows auth type (OAuth vs app-password) in session info
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Pass ClientAtProtoClient into OAuthManager and implement resolveIdentity()
using the existing handle→DID→PDS resolution chain. This fixes the
NotImplementedError that was blocking the OAuth flow from completing.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
ATProto uses browser-based OAuth with localhost callback, not the
device authorization flow. Updated the roadmap item accordingly.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- AtProtoSessionManager.PlayerSession: add authType field (oauth/app_password)
- storeVerifiedSession: accept authType parameter
- AuthenticatePacket: include authType in client→server packet
- ServerNetworkHandler: pass authType through to session storage
- AtProtoCommands: display auth type in /atproto whoami output;
update help text to mention OAuth browser login
The server now knows whether a session came from OAuth or app-password
auth, enabling future DPoP-aware request handling on the server side.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add OAuthManager to client initializer
- ClientAtProtoCommands: /atproto login <handle> now triggers OAuth
browser flow; /atproto login <handle> <password> remains as fallback
- ClientSessionManager: store and manage OAuth sessions alongside
app-password sessions; makeAuthenticatedRequest includes DPoP proof
for OAuth sessions
- ClientAtProtoClient: add xrpcRequestWithDpop() using DPoP auth scheme
OAuth is now the recommended login method. App-password login is
preserved as a fallback for users who prefer it.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements the core OAuth 2.1 client-side flow per ATProto spec:
- PkceUtils: RFC 7636 code verifier/challenge generation (S256)
- DpopProof: RFC 9449 DPoP proof JWT construction (ES256/P-256)
- OAuthCallbackServer: localhost HTTP server for browser redirect
- OAuthModels: serializable types for server metadata, PAR, tokens
- OAuthManager: full flow orchestration (discovery, PAR, token exchange)
All OAuth requests include DPoP proof headers. PAR is mandatory per
ATProto spec. Token exchange includes PKCE code verifier.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add a brief README note for using `nix develop` and lock the new flake inputs for reproducible Java 21 tooling.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add a periodic server-side stat sync service that snapshots linked, authenticated players and records their Minecraft statistics to AT Protocol.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Major improvements to build system, authentication flow, and user experience:
Build System:
- Configure common source set for shared security/network code
- Fix compilation errors by properly organizing source sets
- Add Mod Menu integration for configuration GUI
Client-Side Authentication:
- Replace Slingshot with official Bluesky identity resolution APIs
- Use com.atproto.identity.resolveHandle for standard handle resolution
- Improve error handling and user feedback
- Add /atproto config and /atproto gui commands
New Features:
- Add AtProtoConfigScreen for GUI-based authentication
- Integrate with Mod Menu for easy access to settings
- No-typing-required login flow with visual feedback
- Client-side password handling with security notices
Code Organization:
- Move security classes to src/common/kotlin/com/jollywhoppers/security/
- Move network classes to src/common/kotlin/com/jollywhoppers/network/
- Organize server code under atproto/server/ package
- Organize client code under atproto/client/ package
- Move example code to docs/examples/
This update resolves all compilation errors and provides a much better
user experience with GUI-based authentication.
Updates README and build configuration from 0.0.1 to 0.3.0 to match the
addition of client-side authentication, hardened security, and the
RecordManager API. Project remains alpha and pre-1.0.
Shift AT Protocol authentication fully to the client for improved security.
Client now handles login and session creation locally, with verified sessions
sent to the server via network packets. Server-side login commands are removed
and deprecated APIs are marked accordingly.
Adds client-side initialisation, commands, and packet handlers, and updates
server session management to store verified client-authenticated sessions.
Also updates RecordManager and examples to use explicit kotlinx.serialization
serializers, improving type safety and avoiding reified Serializable bounds.
Introduce a full-featured RecordManager for AT Protocol repositories.
Adds type-safe CRUD operations for records, including create, read, list,
update (upsert), and delete, with support for pagination, compare-and-swap,
and atomic batch writes via applyWrites.
Includes utility helpers for TID generation and AT URI parsing, plus
serialisable request/response models.
Also adds a comprehensive examples module demonstrating real-world usage
patterns (stats syncing, achievements, profiles, safe updates, pagination,
and atomic transactions) to serve as reference documentation.
- Encrypt session data at rest using AES-256-GCM
- Add rate limiting and temporary lockouts for auth attempts
- Introduce security audit logging for sensitive operations
- Harden HTTP client against SSRF and DNS rebinding
- Enforce restricted file permissions and atomic writes
- Improve error sanitisation to avoid leaking sensitive details
- Update README with security features, config details, and roadmap
Add core AT Protocol integration with Slingshot-based PDS resolution,
player identity linking, authenticated sessions, and in-game commands.
Includes session persistence, token refresh, and expanded documentation.
- Consistently renamed the project from "ATProto Connect" to "Social Sync" in `fabric.mod.json`, README, and UI components.
- Renamed core mod entry points and objects from `Atprotoconnect` to `socialsync` for both client and server.
- Incremented version to 0.5.0 in `gradle.properties`, `fabric.mod.json`, and README.
- Expanded client configuration with several new user preferences:
- Implemented a "Compact Layout" option for the Mod Menu screen.
- Added security toggles for local storage encryption and automated cache clearing on logout.
- Added a preference to toggle sync notifications in the chat.
- Enhanced session management to support conditional AES-256-GCM encryption.
- Refactored `RecordManager` to use a more streamlined TID generation method.
- Registered `DebugScreenMixin` for improved client-side debugging.
- Updated the README with a revised directory structure, new documentation links, and completed roadmap items.
AtProtoConfigScreen is now a proper settings panel with all
ClientPreferences fields exposed:
- Authentication section (login/logout with status)
- Sync consent toggles (stats, sessions, achievements, server status)
- Sync frequency cycle buttons (1/5/10/15/30/60/120/240 min)
- UI preferences (notifications, F3 status, compact layout)
- Privacy settings (encrypted storage, clear on logout)
- Reset to Defaults button
Removes /atproto config and /atproto gui commands — ModMenu is
now the canonical entry point for settings. Help text updated
to point to Mod Menu instead.
- Add achievements and server-status to sync command list
- Mention config screen as alternative to commands for consent toggles
- Update roadmap checkbox to reflect all 4 consent categories
- Remove completed items from Future Possibilities
- Add PlayerSyncPreferencesStore to project structure
- Update architecture diagram with consent store and new storage
- Add sync-preferences/ to configuration files section
- Remove RateLimiter from architecture (server-side login removed)
Login is handled client-side via the mod config screen. Removes:
- AtProtoCommands.loginDeprecated() (dead code, not registered)
- AtProtoSessionManager.createSession() (deprecated, unused)
- AtProtoClient.createSession() (server-side, unused)
- AtProtoClient.CreateSessionRequest data class
- RateLimiter field and cleanup() from AtProtoCommands
- Stale /atproto login references in help text
Unused imports (Duration, Instant, ServerPlayer, SecurityUtils)
cleaned up. RateLimiter.kt kept for potential future use.
PlayerSyncPreferencesStore is now the single source of truth for all
sync consent (stats, sessions, achievements, server status). The old
syncStats/syncSessions fields on PlayerIdentityStore are legacy-only
and migrated on startup.
- Wire all 4 sync services to check syncPreferencesStore instead of
identityStore.getSyncConsent()
- Expand /atproto sync commands to 4 categories
- Client-side /atproto sync now updates PreferencesManager and sends
SyncPreferencesPacket to server
- Add consent toggles to AtProtoConfigScreen
- Remove old logSyncConsentChange from SecurityAuditor
- Add migration: extractLegacySyncConsent + migrateFromIdentityStore
- Register SyncPreferencesPacket type on server
- Handle client preference updates asynchronously
- Validate player is authenticated before accepting updates
- Persist preferences to PlayerSyncPreferencesStore
- Audit log all sync preference changes
- Error handling and logging for failed preference updates
- Implement PlayerSyncPreferences data class (UUID stored as String for serialization)
- Store player preferences per-player in JSON files
- Methods to load, save, update, and delete player preferences
- Support for granular sync control: stats, sessions, achievements, server status
- Track sync frequencies for each data type
- Admin methods to list all players with preferences
- Automatic directory creation and error handling
- Implement ClientPreferences data class with serialization
- Store preferences locally in JSON format (client-only, no privacy concerns)
- Sync options: stats, sessions, achievements, server status
- Configurable sync frequencies (in minutes)
- UI preference toggles: notifications, F3 display, compact layout
- Privacy options: encrypted storage, cache cleanup on logout
- PreferencesManager singleton for centralized access
Periodically sync server status to AT Protocol with literal:self rkey.
Includes version, online players, MOTD, game mode, difficulty, PvP status.
Syncs every 5 minutes when at least one authenticated player is online
(their session is used for the write).
Note: Requires an authenticated player to write. A future "server account"
concept would allow server operators to authenticate independently.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Track when players join and leave servers, creating player.session records
with join/leave times, duration, and quit reason. Uses ServerPlayConnectionEvents
for join/leave detection. Respects syncSessions consent. Flushes all open
sessions on server stop with "server_stop" quit reason.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
AT Protocol data is always public by design, so "publicStats"/"publicSessions"
flags in the profile record were misleading. Renamed to "syncStats"/"syncSessions"
to clarify that these control whether data is written at all, not who can see it.
Changes:
- Remove publicStats/publicSessions from player.profile lexicon
- Rename fields to syncStats/syncSessions in PlayerIdentityStore
- Rename /atproto privacy to /atproto sync with clearer language
- Update all services to use getSyncConsent() instead of getPrivacySettings()
- Update client commands to match
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add ClientSecurityUtils with the same AES-256-GCM encryption used
server-side. ClientSessionManager now encrypts session files on save
and decrypts on load, with automatic migration from plaintext (v2)
to encrypted (v3) format. The encryption key is stored separately
with owner-only file permissions.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add AchievementSyncService that creates achievement records when a
player earns a full advancement. Uses a mixin on PlayerAdvancements.award()
to detect completion. Respects the publicStats privacy setting and
deduplicates within a session. Advancement records include category,
challenge status, and human-readable names.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add publicStats and publicSessions fields to PlayerIdentity with
server-side /atproto privacy commands to toggle visibility. The
PlayerStatSyncService now checks publicStats before syncing. A new
PlayerProfileService writes the player.profile record to AT Protocol
on identity link and privacy changes. Client-side /atproto privacy
command shows current settings and directs to server commands.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Replace the single password-only login form with a dual-mode interface:
- "OAuth Login (Recommended)" opens browser for ATProto OAuth
- "App Password Login" remains as fallback
- Updated help text, status display, and security notice
- Shows auth type (OAuth vs app-password) in session info
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Pass ClientAtProtoClient into OAuthManager and implement resolveIdentity()
using the existing handle→DID→PDS resolution chain. This fixes the
NotImplementedError that was blocking the OAuth flow from completing.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- AtProtoSessionManager.PlayerSession: add authType field (oauth/app_password)
- storeVerifiedSession: accept authType parameter
- AuthenticatePacket: include authType in client→server packet
- ServerNetworkHandler: pass authType through to session storage
- AtProtoCommands: display auth type in /atproto whoami output;
update help text to mention OAuth browser login
The server now knows whether a session came from OAuth or app-password
auth, enabling future DPoP-aware request handling on the server side.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add OAuthManager to client initializer
- ClientAtProtoCommands: /atproto login <handle> now triggers OAuth
browser flow; /atproto login <handle> <password> remains as fallback
- ClientSessionManager: store and manage OAuth sessions alongside
app-password sessions; makeAuthenticatedRequest includes DPoP proof
for OAuth sessions
- ClientAtProtoClient: add xrpcRequestWithDpop() using DPoP auth scheme
OAuth is now the recommended login method. App-password login is
preserved as a fallback for users who prefer it.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements the core OAuth 2.1 client-side flow per ATProto spec:
- PkceUtils: RFC 7636 code verifier/challenge generation (S256)
- DpopProof: RFC 9449 DPoP proof JWT construction (ES256/P-256)
- OAuthCallbackServer: localhost HTTP server for browser redirect
- OAuthModels: serializable types for server metadata, PAR, tokens
- OAuthManager: full flow orchestration (discovery, PAR, token exchange)
All OAuth requests include DPoP proof headers. PAR is mandatory per
ATProto spec. Token exchange includes PKCE code verifier.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Major improvements to build system, authentication flow, and user experience:
Build System:
- Configure common source set for shared security/network code
- Fix compilation errors by properly organizing source sets
- Add Mod Menu integration for configuration GUI
Client-Side Authentication:
- Replace Slingshot with official Bluesky identity resolution APIs
- Use com.atproto.identity.resolveHandle for standard handle resolution
- Improve error handling and user feedback
- Add /atproto config and /atproto gui commands
New Features:
- Add AtProtoConfigScreen for GUI-based authentication
- Integrate with Mod Menu for easy access to settings
- No-typing-required login flow with visual feedback
- Client-side password handling with security notices
Code Organization:
- Move security classes to src/common/kotlin/com/jollywhoppers/security/
- Move network classes to src/common/kotlin/com/jollywhoppers/network/
- Organize server code under atproto/server/ package
- Organize client code under atproto/client/ package
- Move example code to docs/examples/
This update resolves all compilation errors and provides a much better
user experience with GUI-based authentication.
Shift AT Protocol authentication fully to the client for improved security.
Client now handles login and session creation locally, with verified sessions
sent to the server via network packets. Server-side login commands are removed
and deprecated APIs are marked accordingly.
Adds client-side initialisation, commands, and packet handlers, and updates
server session management to store verified client-authenticated sessions.
Also updates RecordManager and examples to use explicit kotlinx.serialization
serializers, improving type safety and avoiding reified Serializable bounds.
Introduce a full-featured RecordManager for AT Protocol repositories.
Adds type-safe CRUD operations for records, including create, read, list,
update (upsert), and delete, with support for pagination, compare-and-swap,
and atomic batch writes via applyWrites.
Includes utility helpers for TID generation and AT URI parsing, plus
serialisable request/response models.
Also adds a comprehensive examples module demonstrating real-world usage
patterns (stats syncing, achievements, profiles, safe updates, pagination,
and atomic transactions) to serve as reference documentation.
- Encrypt session data at rest using AES-256-GCM
- Add rate limiting and temporary lockouts for auth attempts
- Introduce security audit logging for sensitive operations
- Harden HTTP client against SSRF and DNS rebinding
- Enforce restricted file permissions and atomic writes
- Improve error sanitisation to avoid leaking sensitive details
- Update README with security features, config details, and roadmap