diff --git a/HACKTIVITY_INTEGRATION.md b/HACKTIVITY_INTEGRATION.md new file mode 100644 index 0000000..91b2c7b --- /dev/null +++ b/HACKTIVITY_INTEGRATION.md @@ -0,0 +1,298 @@ +# Integrating BreakEscape into Hacktivity + +## Prerequisites + +- Hacktivity running Rails 7.0+ +- PostgreSQL database +- User model with Devise +- Pundit for authorization (recommended) + +## Installation Steps + +### 1. Add to Gemfile + +```ruby +# Gemfile (in Hacktivity repository) +gem 'break_escape', path: '../BreakEscape' +``` + +### 2. Install and Migrate + +```bash +bundle install +rails break_escape:install:migrations +rails db:migrate +rails db:seed # Creates missions from scenario directories +``` + +### 3. Mount Engine + +```ruby +# config/routes.rb +mount BreakEscape::Engine => "/break_escape" +``` + +### 4. Configure + +```ruby +# config/initializers/break_escape.rb +BreakEscape.configure do |config| + config.standalone_mode = false # Mounted mode in Hacktivity +end +``` + +### 5. Verify User Model + +Ensure your User model has these methods for Pundit authorization: + +```ruby +class User < ApplicationRecord + def admin? + # Your admin check logic + end + + def account_manager? + # Optional: account manager check logic + end +end +``` + +### 6. Add Navigation Link (Optional) + +```erb + +<%= link_to "BreakEscape", break_escape_path %> +``` + +### 7. Restart Server + +```bash +rails restart +# or +touch tmp/restart.txt +``` + +### 8. Verify Installation + +Navigate to: `https://your-hacktivity.com/break_escape/` + +You should see the mission selection screen. + +## Configuration Options + +### Environment Variables + +```bash +# .env (or similar) +BREAK_ESCAPE_STANDALONE=false # Mounted mode (default) +``` + +### Custom Configuration + +```ruby +# config/initializers/break_escape.rb +BreakEscape.configure do |config| + # Mode + config.standalone_mode = false + + # Demo user (only used in standalone mode) + config.demo_user_handle = ENV['BREAK_ESCAPE_DEMO_USER'] || 'demo_player' +end +``` + +## Authorization Integration + +BreakEscape uses Pundit policies by default. It expects: + +### Game Access +- **Owner**: Users can only access their own games +- **Admin/Account Manager**: Can access all games + +### Mission Visibility +- **All Users**: Can see published missions +- **Admin/Account Manager**: Can see all missions (including unpublished) + +### Custom Policies + +To customize authorization, create policy overrides in Hacktivity: + +```ruby +# app/policies/break_escape/game_policy.rb (in Hacktivity) +module BreakEscape + class GamePolicy < ::BreakEscape::GamePolicy + def show? + # Custom logic here + super || custom_access_check? + end + end +end +``` + +## Database Tables + +BreakEscape adds 3 tables to your database: + +1. **break_escape_missions** - Metadata for scenarios + - `name`, `display_name`, `description`, `published`, `difficulty_level` + +2. **break_escape_games** - Player game instances + - `player` (polymorphic: User), `mission_id`, `scenario_data` (JSONB), `player_state` (JSONB) + +3. **break_escape_demo_users** - Optional (standalone mode only) + - Only created if migrations run, can be safely ignored in mounted mode + +## API Endpoints + +Once mounted, these endpoints are available: + +- **Mission List**: `GET /break_escape/missions` +- **Play Mission**: `GET /break_escape/missions/:id` +- **Game View**: `GET /break_escape/games/:id` +- **Scenario Data**: `GET /break_escape/games/:id/scenario` +- **NPC Scripts**: `GET /break_escape/games/:id/ink?npc=:npc_id` +- **Bootstrap**: `GET /break_escape/games/:id/bootstrap` +- **State Sync**: `PUT /break_escape/games/:id/sync_state` +- **Unlock**: `POST /break_escape/games/:id/unlock` +- **Inventory**: `POST /break_escape/games/:id/inventory` + +## Asset Serving + +Static game assets are served from `public/break_escape/`: +- JavaScript: `public/break_escape/js/` +- CSS: `public/break_escape/css/` +- Images: `public/break_escape/assets/` + +These are served by the engine's static file middleware. + +## Troubleshooting + +### 404 errors on /break_escape/ + +**Solution**: Ensure engine is mounted in `config/routes.rb` + +```ruby +mount BreakEscape::Engine => "/break_escape" +``` + +### Authentication errors + +**Solution**: Verify `current_user` method works in your ApplicationController + +```ruby +# In Hacktivity's ApplicationController +def current_user + # Should return User instance or nil +end +``` + +### Asset 404s (CSS/JS not loading) + +**Solution**: Check that `public/break_escape/` directory exists and contains game files + +```bash +ls public/break_escape/js/ +ls public/break_escape/css/ +ls public/break_escape/assets/ +``` + +### Ink compilation errors + +**Solution**: Verify `bin/inklecate` executable exists and is executable + +```bash +chmod +x scenarios/inklecate +# Or ensure inklecate is in PATH +``` + +### CSRF token errors on API calls + +**Solution**: Ensure your layout includes CSRF meta tags + +```erb + +<%= csrf_meta_tags %> +``` + +### Database migration issues + +**Solution**: Check PostgreSQL is running and migrations ran successfully + +```bash +rails db:migrate:status | grep break_escape +# Should show all migrations as "up" +``` + +## Performance Considerations + +### JIT Ink Compilation +- First NPC interaction compiles `.ink` → `.json` (~300ms) +- Subsequent interactions use cached JSON (~10ms) +- Compiled files persist across restarts +- Production: Pre-compile all .ink files during deployment + +### Scenario Generation +- ERB templates render on game creation (~50ms) +- Scenario data cached in `games.scenario_data` JSONB +- No re-rendering during gameplay + +### State Sync +- Periodic sync every 30 seconds (configurable) +- Uses Rails cache for temporary state +- Database writes only on unlock/inventory changes + +## Security Notes + +1. **CSRF Protection**: All POST/PUT endpoints require valid CSRF tokens +2. **Authorization**: Pundit policies enforce access control +3. **XSS Prevention**: Content Security Policy enabled +4. **SQL Injection**: All queries use parameterized statements +5. **Session Security**: Sessions tied to user authentication + +## Monitoring + +### Key Metrics to Track + +- Game session duration +- Mission completion rates +- Unlock attempt failures (may indicate difficulty issues) +- Ink compilation times (should be ~300ms first time) +- State sync success rate + +### Logs to Monitor + +```ruby +# Game creation +"[BreakEscape] Game created: ID=123, Mission=ceo_exfil" + +# Ink compilation +"[BreakEscape] Compiling helper1_greeting.ink..." +"[BreakEscape] Compiled helper1_greeting.ink (45.2 KB)" + +# Unlock validation +"[BreakEscape] Unlock validated: door=office, method=password" +``` + +## Updating BreakEscape + +```bash +cd ../BreakEscape +git pull origin main + +cd ../Hacktivity +bundle install +rails break_escape:install:migrations # Install new migrations +rails db:migrate +rails restart +``` + +## Support + +For issues specific to BreakEscape engine: +- Check `README.md` in BreakEscape repository +- Review implementation plan in `planning_notes/` +- Check game client logs in browser console + +For Hacktivity integration issues: +- Verify Devise authentication is working +- Check Pundit policies are configured +- Review Rails logs for errors diff --git a/README.md b/README.md index 37fdb5a..1c81636 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,114 @@ -# BreakEscape -Short description and motivation. +# BreakEscape Rails Engine -## Usage -How to use my plugin. +Cybersecurity training escape room game as a mountable Rails Engine. + +## Features + +- 24+ cybersecurity escape room scenarios +- Server-side progress tracking with 2-table schema +- Randomized passwords per game instance via ERB +- JIT Ink script compilation for NPC dialogue +- Polymorphic player support (User/DemoUser) +- Pundit authorization +- RESTful API for game state management +- Session-based state persistence ## Installation -Add this line to your application's Gemfile: + +In your Gemfile: ```ruby -gem "break_escape" +gem 'break_escape', path: 'path/to/break_escape' ``` -And then execute: +Then: + ```bash -$ bundle +bundle install +rails break_escape:install:migrations +rails db:migrate +rails db:seed # Optional: creates missions from scenarios ``` -Or install it yourself as: +## Mounting in Host App + +In your `config/routes.rb`: + +```ruby +mount BreakEscape::Engine => "/break_escape" +``` + +## Usage + +### Standalone Mode (Development) + ```bash -$ gem install break_escape +export BREAK_ESCAPE_STANDALONE=true +rails server +# Visit http://localhost:3000/break_escape/ ``` -## Contributing -Contribution directions go here. +### Mounted Mode (Production) + +Mount in Hacktivity or another Rails app. The engine will use the host app's `current_user` via Devise. + +## Configuration + +```ruby +# config/initializers/break_escape.rb +BreakEscape.configure do |config| + config.standalone_mode = false # true for development + config.demo_user_handle = 'demo_player' +end +``` + +## Database Schema + +- `break_escape_missions` - Scenario metadata (name, display_name, published, difficulty) +- `break_escape_games` - Player state + scenario snapshot (JSONB) +- `break_escape_demo_users` - Standalone mode only (optional) + +## API Endpoints + +- `GET /games/:id/scenario` - Scenario JSON (ERB-generated) +- `GET /games/:id/ink?npc=X` - NPC script (JIT compiled from .ink) +- `GET /games/:id/bootstrap` - Initial game data +- `PUT /games/:id/sync_state` - Sync player state +- `POST /games/:id/unlock` - Validate unlock attempt +- `POST /games/:id/inventory` - Update inventory + +## Architecture + +### ERB Scenario Generation +Scenarios are stored as `.json.erb` templates and rendered on-demand with randomized values: +- `<%= random_password %>` - Generates unique password per game +- `<%= random_pin %>` - Generates unique 4-digit PIN +- `<%= random_code %>` - Generates unique hex code + +### JIT Ink Compilation +NPC dialogue scripts compile on first request (~300ms): +1. Check if `.json` exists and is newer than `.ink` +2. If needed, run `inklecate` to compile +3. Cache compiled JSON for subsequent requests + +### State Management +Player state stored in JSONB column: +- Current room and unlocked rooms +- Inventory and collected items +- NPC encounters +- Global variables (synced with client) +- Health and minigame state + +## Testing + +```bash +rails test +``` ## License -The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). + +MIT + +## Documentation + +See `HACKTIVITY_INTEGRATION.md` for integration guide.