Commit Graph

527 Commits

Author SHA1 Message Date
Z. Cliffe Schreuders
b2c8362d91 Allow unlocked doors and containers to notify server for access
Fixed issue where unlocked doors/containers couldn't be opened because
the server wasn't being notified to add them to unlockedRooms/unlockedObjects.

Server changes (game.rb):
- Updated validate_unlock to accept method='unlocked' for unlocked targets
- Added logic to grant access for unlocked doors/objects without validation

Client changes (doors.js):
- Updated handleDoorInteraction to notify server for unlocked doors
- Calls notifyServerUnlock with method='unlocked' before opening

Client changes (interactions.js):
- Added notifyServerForUnlockedContainer helper function
- Updated container interaction to notify server before launching minigame

This ensures that all room/container access is properly authorized on the
server side, preventing 403 Forbidden errors when loading room/container data.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
3494c739a5 Trust client validation for item-based unlock methods
Updated validate_unlock to use two-tier validation model:
- Server trusts client validation for item-based locks (key, lockpick, biometric, bluetooth, rfid)
- Server validates knowledge-based locks (pin, password)

This fixes 422 errors when unlocking with keys/lockpicking where attempt is nil,
since these methods don't require server-side answer validation.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
a3d1ba3826 Add server-side unlock notification for all lock types
- Created notifyServerUnlock helper function to DRY up code
- Updated lockpicking, key, biometric, bluetooth, and RFID unlocks to call server API
- All unlock methods now:
  1. Validate unlock client-side (minigame/item check)
  2. Notify server to update player_state
  3. Receive room/container data in response
  4. Pass serverResponse to unlockTarget

This ensures:
- Server tracks all unlocks in player_state (unlockedRooms/unlockedObjects)
- Room endpoint can validate access (403 if not unlocked)
- Single API call returns data needed (roomData for doors, contents for containers)
- Consistent behavior across all lock types
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
d2901eafa7 Optimize unlock flow to use single API call for doors and containers
Server-side changes:
- Unlock endpoint already returns roomData for doors

Client-side changes:
- Pass serverResponse through minigame callback chain
- Store serverResponse in minigame gameResult (password & PIN)
- Update minigame-starters to pass result to callbacks
- Update unlock-system callbacks to accept and pass serverResponse
- Pass roomData to unlockDoor for doors
- Cache roomData in roomDataCache before loadRoom is called
- loadRoom checks cache before making API call

Benefits:
- Doors: Unlock + room load = 1 API call instead of 2
- Containers: Unlock + contents = 1 API call instead of 2
- More efficient, faster user experience
- Consistent pattern for both doors and containers
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
77544520aa Return container contents in unlock API response
- Add find_object_in_scenario helper to locate objects by ID or name
- Include hasContents and contents fields in unlock response for containers
- Update password and PIN minigames to populate scenarioData.contents from server response
- This allows the container minigame to launch after successful server-side unlock

Without this, the contents field was filtered for security, preventing the container UI from launching.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
a02d2e3a82 Import ApiClient in main game and use correct gameId path
- Import ApiClient in game.js to ensure window.ApiClient is set early
- Use window.breakEscapeConfig?.gameId instead of window.gameId in minigames
- Consistent with the rest of the codebase

Without importing ApiClient in the main game flow, window.ApiClient wasn't available when minigames needed it.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
4676e43122 Fix ApiClient name and handle empty string as null in minigames
- Use correct ApiClient casing (window.ApiClient not window.APIClient)
- Check for both null and empty string to trigger server validation
- Add fallback to support both naming conventions
- Add debug logging to show which validation method is used

The ApiClient is exported as window.ApiClient but code was checking for window.APIClient.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
3bc9d9a0b1 Fix password minigame submit button and add debug logging
- Make submit button always visible (not just when hints are enabled)
- Add console logging to track validation flow
- Debug why server validation isn't being triggered

This ensures users can submit passwords and helps diagnose validation issues.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
8328374e5f Add logging and name fallback to unlock validation
- Add detailed logging to validate_unlock method to debug validation issues
- Check both object 'id' and 'name' fields when searching for objects
- Log password comparison details for debugging

This helps diagnose why correct passwords might not be accepted.
2025-11-22 00:46:56 +00:00
Z. Cliffe Schreuders
02fc7f6876 Add server-side validation support to password and PIN minigames
- Update password minigame to call server API when correctPassword is null
- Update PIN minigame to call server API when correctPin is null
- Pass lockable and type parameters to minigames for server validation
- Maintain backwards compatibility with client-side validation
- Handle network errors gracefully without counting failed attempts

This allows minigames to validate attempts server-side for security, preventing client-side answer spoofing.
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
b27cde13d0 Fix unlock detection to work with server-side data filtering
- Update unlock-system.js to check 'locked' field instead of 'requires' for lock detection
- Pass null for key/pin/password required values (server validates)
- Preserve 'requires' field for biometric/bluetooth locks (contains item identifiers, not answers)
- Update both Game model and controller filtering methods

Fixes issue where locked objects didn't prompt for unlock after server-side filtering was implemented.
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
cb2d342802 Fix Array into String conversion error in track_npc_encounters
Changes:
- Add player_state type checking before accessing encounteredNPCs
- Reset player_state to empty hash if not a Hash type
- Add comprehensive logging for type mismatches
- Change from concat to array addition (+) to avoid in-place mutation issues
- Wrap entire method in try-catch to prevent NPC tracking from breaking room loading
- Add detailed error logging with stack traces

Fixes:
- TypeError: no implicit conversion of Array into String
- Handles legacy data where player_state might be malformed
- Room loading continues even if NPC tracking fails
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
c2ed2fb033 Fix TypeError in track_npc_encounters and add robust error handling to room endpoint
Changes:
- Fix track_npc_encounters to handle case where encounteredNPCs is not an array
- Add type checking to ensure encounteredNPCs is always an array before operations
- Add comprehensive error handling and logging to room endpoint
- Add scenario_data presence check before processing room request
- Wrap room endpoint in try-catch to catch and log all errors

Fixes:
- TypeError: no implicit conversion of String into Array on line 312
- Prevents 500 errors when player_state has malformed data
- Provides clear error messages and stack traces for debugging
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
905c5643b5 Fix scenario endpoint to return filtered data and revert client to use /scenario
Changes:
- Revert client game.js to use /scenario endpoint instead of /scenario_map
- Update /scenario endpoint to return filtered_scenario_for_bootstrap
- Add filter_requires_recursive method to remove sensitive 'requires' fields
- Keep /scenario_map for potential future navigation queries
- Add error handling to scenario endpoint

Rationale:
- The game client expects full scenario structure (startRoom, rooms, startItemsInInventory, etc.)
- scenario_map returns minimal structure incompatible with game initialization
- filtered_scenario_for_bootstrap provides room metadata without objects (lazy-loaded)
- filter_requires_recursive ensures puzzle solutions aren't exposed to client
- Maintains security while providing necessary data for game initialization
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
25dff05d39 Add comprehensive error handling and logging to scenario_map endpoint
- Add try-catch blocks to prevent 500 errors
- Add logging to help diagnose issues
- Add nil checks for scenario_data and rooms
- Skip individual rooms that fail to process
- Return descriptive error messages for debugging
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
a945859730 Implement comprehensive server-side validation and data filtering for client actions
Server-side changes:
- Game model: Initialize starting items in player inventory from scenario
- Game model: Add filter_requires_and_contents_recursive to hide solutions and locked contents
- Game model: Fix filtered_room_data to preserve lockType while removing requires
- GamesController: Add scenario_map endpoint for minimal layout metadata
- GamesController: Update room endpoint with access control and NPC encounter tracking
- GamesController: Add container endpoint for lazy-loading locked container contents
- GamesController: Update inventory endpoint with comprehensive validation
  - Validates item exists in scenario
  - Checks item is takeable
  - Verifies container is unlocked if item is in container
  - Verifies room is unlocked if room is locked
  - Checks NPC is encountered if item held by NPC
- GamesController: Update unlock endpoint with transaction safety
- GamesController: Update sync_state to verify room accessibility
- Routes: Add scenario_map and container routes

Client-side changes:
- inventory.js: Make addToInventory async and add server validation before local updates
- container-minigame.js: Add lazy-loading of container contents from server
- game.js: Update to use scenario_map endpoint for reduced initial payload
- api-client.js: Add getScenarioMap method alongside getScenario

Security improvements:
- Prevents client-side cheating by validating all actions server-side
- Hides solution fields (requires) from client responses
- Hides locked container contents until unlocked
- Enforces room and container access controls
- Tracks NPC encounters automatically
- All validation failures return clear error messages

Implements plans from:
- planning_notes/validate_client_actions/GOALS_AND_DECISIONS.md
- planning_notes/validate_client_actions/IMPLEMENTATION_PLAN.md
2025-11-22 00:46:55 +00:00
Z. Cliffe Schreuders
9b1a1d0021 fix: correct typo in parallax animation function and enhance story source loading logic 2025-11-21 15:41:54 +00:00
Z. Cliffe Schreuders
fbb69f9c53 Implement comprehensive server-side validation and client integration for inventory and container management
- Added server-side validation for inventory actions, ensuring items are validated before being added to the player's inventory.
- Updated client-side `addToInventory()` function to include server validation and error handling for inventory actions.
- Implemented container loading logic to fetch contents from the server, handling locked containers appropriately.
- Enhanced player state initialization to ensure starting items are correctly added to the inventory.
- Clarified NPC `itemsHeld` structure and updated validation logic to match the expected item format.
- Improved error handling for room access and container interactions, including transaction safety for state mutations.
- Introduced new endpoints for scenario mapping and bulk inventory synchronization.
- Added performance optimizations, including caching filtered room data and implementing JSON schema validation for item structures.
- Established a detailed implementation plan with phased priorities and testing gaps identified for future work.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
b465592c4f feat: implement GamesController with sync_state, unlock, and inventory actions 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
09e0631b08 refactor: reorganize API routes and remove unused bootstrap endpoint 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
d2893f06cf Update test database: modified test.sqlite3 to reflect new schema changes 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
c2fadcd169 Add integration and model tests for BreakEscape game mechanics
- Implement RoomLazyLoadTest to verify room data retrieval and error handling for non-existent rooms.
- Create FilteredScenarioTest to ensure scenario data is filtered correctly for game initialization, preserving navigation structure while removing unnecessary details like objects and NPCs.
- Add tests for lock requirements and ensure original scenario data remains unmodified after filtering.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
6e65b9030d Add integration tests for asset loading and NPC story file handling
- Added tests to verify serving of door tile image and key-operations minigame module.
- Created new NPCInkLoadingTest to check various scenarios for NPC story file loading:
  - Return 404 for NPCs without story files and for non-existent NPCs.
  - Validate handling of missing NPC parameter.
  - Ensure correct API endpoint construction in npc-lazy-loader.
  - Verify person-chat and phone-chat minigames use the correct story loading endpoint.
  - Confirm npc-manager loads stories via API endpoint without direct fetch of storyPath.
  - Check asset path resolution in person-chat-portraits and phone-chat-ui.
  - Ensure ink endpoint returns correct MIME type and handles special characters in NPC IDs.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
9ac86a2c8d Add integration and unit tests for asset loading and content type determination
- Created `AssetLoadingIntegrationTest` to verify the loading of game assets in the correct order, including JavaScript, CSS, and sound files.
- Implemented tests to ensure proper handling of asset paths, security constraints, and response headers.
- Added `StaticFilesControllerUnitTest` to test the content type determination logic for various file extensions, ensuring case insensitivity and handling of multiple dots in filenames.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
3acaa62c26 feat: Enhance game UI with improved loading display and mobile touch handling 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
5b11fa9dbb Add static file serving and enhance game UI
- Implement StaticFilesController to serve CSS, JS, and asset files for the BreakEscape engine.
- Update routes to include static file paths for CSS, JS, and assets.
- Refactor game show view to load multiple CSS files and include Google Fonts.
- Remove application stylesheet link from the layout.
- Modify various CSS files to improve layout and styling, including HUD and inventory.
- Update JavaScript files to ensure asset paths are correctly prefixed with /break_escape/.
- Enhance minigame UI components, including notifications, modals, and overlays.
- Adjust game-over screen and health UI to use correct asset paths.
- Update constants and crypto workstation utility to reflect new asset paths.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
0ef0b028b5 fix: Use plain HTML tags for static assets instead of Rails helpers
- Change stylesheet_link_tag to plain <link> tag
- Change javascript_include_tag to plain <script> tag
- Fix CSS file path from styles.css to main.css
- This prevents Rails from trying to process static files through asset pipeline
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
72d09f5afc feat: Add rake task to load engine seed data
- Create break_escape:seed rake task
- Task can be run with: bin/rails app:break_escape:seed
- Loads mission data from scenarios/ directory
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
e758a0bef1 chore: Update test artifacts after running new server response tests 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
4764f5881e test: Add comprehensive server response tests
- Add HTML response tests for missions index (checks mission cards rendered)
- Add game page tests (checks game container and config injection)
- Add API endpoint tests:
  * scenario endpoint returns JSON scenario data
  * bootstrap endpoint returns complete game state
  * sync_state endpoint updates player position
  * unlock endpoint validates and rejects invalid attempts
  * inventory endpoint adds items to player inventory
- Fix inventory API to use action_type instead of reserved 'action' param

All 23 tests passing with 64 assertions verifying server returns correct data!
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
e18950c6d7 feat: Configure dummy app for development with engine migrations
- Add root route that redirects to missions list
- Fix ApplicationController to fallback to demo user when current_user unavailable
- Configure dummy app to load engine migrations in application.rb
- Create test/dummy/db/migrate directory
- Successfully migrated and seeded database with 26 missions

Now visiting http://localhost:3000 will show the missions selection page!
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
19b52cd826 chore: Add .gitignore, update Gemfile and Gemfile.lock for Rails 7.2.3, and clean up development environment settings 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
2d3ce4a6ad chore: Update test artifacts after successful test run 2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
08a89eace5 refactor: Move scenarios to root and update paths
- Move scenarios from app/assets/scenarios/ to scenarios/
- Update Mission model to use BreakEscape::Engine.root instead of Rails.root
- Update seeds.rb to use engine root for scenario discovery
- Update tests to use engine root for path assertions

This ensures scenarios are found correctly in both mounted (Hacktivity)
and standalone (test) environments.

All 12 tests now passing with 19 assertions!
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
f44c211d53 fix: Make tests database-agnostic and fix fixture loading
- Update migration to support both PostgreSQL (jsonb) and SQLite (json)
- Fix Rails 8 compatibility (remove config.assets)
- Configure Pundit to use current_player instead of current_user
- Add explicit fixture class mappings for engine fixtures
- Configure standalone mode for tests
- Update test fixtures with proper timestamps and structure
- Improve game test to create data programmatically

Tests now run with 10/12 assertions passing. Remaining errors are due to
missing test scenario files, which can be addressed separately.
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
1656c8864d docs: Add comprehensive documentation
- Update README with complete feature list and usage
- Add architecture documentation (ERB, JIT, state management)
- Create HACKTIVITY_INTEGRATION.md guide
- Include installation, configuration, and troubleshooting
- Document API endpoints and security considerations
- Add monitoring and performance notes

Rails Engine Migration Complete! 🎉
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
2868695265 feat: Add standalone mode support
- Create DemoUser migration for standalone development
- Add DemoUser model with polymorphic games association
- Add configuration system (standalone vs mounted)
- Use ENV variables for configuration
- current_player method supports both modes (ApplicationController)
- Can run without Hacktivity for development
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
8b71cf5f2f test: Add comprehensive test suite
- Add fixtures for missions, demo_users, games
- Add model tests for Mission and Game
- Add controller tests for MissionsController
- Test validations, scopes, and methods
- Test state management and health clamping
- Ready for integration testing in host app
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
006ed4af3e feat: Add client-side API integration layer
- Add config.js for API configuration and CSRF token handling
- Add api-client.js wrapper for server communication
- Add state-sync.js for periodic state synchronization
- Support multiple CSRF token sources (config object and meta tag)
- Provide detailed error messages for configuration issues
- Enable GET/POST/PUT requests with proper auth headers
- Expose ApiClient globally for game code integration
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
4140a23ab4 feat: Add views for missions and game
- Add missions index view with grid layout
- Add game show view with Phaser container
- Include CSP nonces for inline scripts
- Bootstrap game configuration in window object
- Load game CSS and JavaScript
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
c127ba6f03 feat: Add Pundit authorization policies
- Add ApplicationPolicy base class
- Add GamePolicy (owner or admin can access)
- Add MissionPolicy (published visible to all)
- Implement Scope for filtering records
- Support admin and account_manager roles
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
f6c9ceb5e8 feat: Add controllers and routes
- Add MissionsController for scenario selection
- Add GamesController with scenario/ink endpoints
- Add JIT Ink compilation logic
- Add API::GamesController for game state management
- Configure routes with REST + API endpoints
- Add authorization hooks (Pundit)
- Add polymorphic player support (current_player helper)
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
4681c75c83 feat: Add seed file for mission metadata
- Create missions from scenario directories
- Auto-discover scenarios in app/assets/scenarios/
- Simple metadata only (no scenario data in DB)
- Scenario data generated on-demand via ERB
2025-11-21 15:27:54 +00:00
Z. Cliffe Schreuders
447cde6356 feat: Add database schema and models
- Create break_escape_missions table (metadata only)
- Create break_escape_games table (state + scenario snapshot)
- Add Mission model with ERB scenario generation
- Add Game model with state management methods
- Use JSONB for flexible state storage
- Polymorphic player association (User/DemoUser)
2025-11-21 15:27:53 +00:00
Z. Cliffe Schreuders
d2ef5ff6aa refactor: Convert scenarios to ERB templates
- Move scenario JSON files to app/assets/scenarios/
- Rename to .erb extension (24 scenarios converted)
- Keep .ink files in scenarios/ink/ for JIT compilation
- Each scenario now in own directory
- Add conversion script for future use
2025-11-21 15:27:53 +00:00
Z. Cliffe Schreuders
ea70cf4297 refactor: Move game files to public/break_escape/
- Move js/ to public/break_escape/js/
- Move css/ to public/break_escape/css/
- Move assets/ to public/break_escape/assets/
- Preserve git history with mv command
- Keep index.html.reference for reference
2025-11-21 15:27:53 +00:00
Z. Cliffe Schreuders
680c7bfcae feat: Generate Rails Engine structure
- Create mountable engine with isolated namespace
- Configure Pundit authorization
- Set up gemspec with dependencies
- Configure generators for test_unit with fixtures
2025-11-21 15:27:53 +00:00
Z. Cliffe Schreuders
87fae7cb07 refactor: Simplify unlock loading UI dramatically
User correctly pointed out the loading UI was over-engineered.

## Simplifications:

### Before (over-complicated):
- Complex timeline management
- Success/failure flash effects (green/red)
- Spinner alternatives
- Stored references on sprites
- Timeline cleanup logic
- ~150 lines of code

### After (simple):
- startThrob(sprite) - Blue tint + pulsing alpha
- stopThrob(sprite) - Kill tweens, reset
- ~20 lines of code

## Why This Works:

1. **Door sprites get removed anyway** when they open
2. **Container items transition** to next state automatically
3. **Game already shows alerts** for success/error
4. **Only need feedback** during the ~100-300ms API call

## API Changes:

- showUnlockLoading() → startThrob()
- clearUnlockLoading() → stopThrob()
- No success/failure parameter needed
- No stored references to clean up

## Result:

From 150+ lines down to ~30 lines total.
Same UX, much simpler implementation.

User feedback: "Just set the door or item to throb, and remove when
the loading finishes (the door sprite is removed anyway), and if it's
a container, just follow the unlock with a removal of the animation."
2025-11-20 15:37:38 +00:00
Z. Cliffe Schreuders
266bc7a7ca docs: Clarify CSRF token handling for Hacktivity integration
User correctly noted that Hacktivity's application layout already includes
csrf_meta_tags, so we don't need to add them again.

## Changes:

### Section 9.3.1: Layout Strategy
- Split into Option A (Hacktivity layout - recommended) and Option B (standalone)
- **Option A (Recommended):** Read from existing meta tag
  - Uses Hacktivity's csrf_meta_tags (already present in layout)
  - No duplicate meta tags needed
  - Reads via: document.querySelector('meta[name="csrf-token"]')?.content
- **Option B:** Standalone layout
  - For when engine needs separate layout
  - Must add <%= csrf_meta_tags %> to engine layout
  - Can use <%= form_authenticity_token %> directly

### Section 9.3.3: Token Reading Logic
- Updated config.js to try multiple sources:
  1. window.breakEscapeConfig.csrfToken (if explicitly set)
  2. meta[name="csrf-token"] tag (from Hacktivity layout)
- Better error messages showing all sources checked
- Logs which source provided the token

### Section 9.3.5: Issue #2 Solution
- Updated to reference the fallback logic in 9.3.3
- Added debugging console commands
- Shows how to check all meta tags

## Key Points:

-  Hacktivity layout csrf_meta_tags are reused (don't duplicate)
-  Fallback chain ensures token found from either source
-  Clear guidance for both integration scenarios
-  Better debugging when token is missing

This aligns with Rails best practices and Hacktivity's existing setup.
2025-11-20 15:37:38 +00:00
Z. Cliffe Schreuders
cece95cd7f feat: Add critical implementation details based on review
Based on comprehensive codebase review, enhanced implementation plans with:

## Phase 3 Updates (Scenario Conversion):
- Complete bash script to convert all 26 scenarios to ERB structure
- Explicit list of 3 main scenarios (ceo_exfil, cybok_heist, biometric_breach)
- List of 23 test/demo scenarios for development
- Instructions to rename .json to .erb (actual ERB code added later in Phase 4)
- Preserves git history with mv commands
- Both automated script and manual alternatives provided

## Phase 9 Updates (CSRF Token Handling):
NEW Section 9.3: "Setup CSRF Token Injection"
- Critical security implementation for Rails CSRF protection
- Complete view template with <%= form_authenticity_token %>
- JavaScript config injection via window.breakEscapeConfig
- CSRF token validation and error handling
- Browser console testing procedures
- 5 common CSRF issues with solutions
- Fallback to meta tag if config missing
- Development vs production considerations

## Phase 9 Updates (Async Unlock with Loading UI):
ENHANCED Section 9.5: "Update Unlock Validation with Loading UI"
- New file: unlock-loading-ui.js with Phaser.js throbbing tint effect
- showUnlockLoading(): Blue pulsing animation during server validation
- clearUnlockLoading(): Green flash on success, red flash on failure
- Alternative spinner implementation provided
- Complete unlockTarget() rewrite with async/await server validation
- Loading UI shows during API call (~100-300ms)
- Graceful error handling with user feedback
- Updates for ALL lock types: pin, password, key, lockpick, biometric, bluetooth, RFID
- Minigame callback updates to pass attempt and method to server
- Testing mode fallback (DISABLE_SERVER_VALIDATION)
- Preserves all existing unlock logic after server validation

## Key Features:
- Addresses 2 critical risks from review (CSRF tokens, async validation)
- Solves scenario conversion gap (26 files → ERB structure)
- Maintains backward compatibility during migration
- Comprehensive troubleshooting guidance
- Production-ready security implementation

Total additions: ~600 lines of detailed implementation guidance
2025-11-20 15:37:38 +00:00