{"owner":"OWASP","repo":"SecurityShepherd","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nInstructions for AI coding agents working on this repository.\n\n## Project overview\n\nOWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are independent Android apps under `mobile/MobileShepherd/`.\n\n## Intentionally vulnerable code — DO NOT FIX\n\nThe following paths contain **deliberately insecure code** used for security training. Do not fix, refactor, or flag security vulnerabilities in these files:\n\n- `src/main/java/servlets/module/lesson/` — lesson servlets with intentional vulnerabilities\n- `src/main/java/servlets/module/challenge/` — challenge servlets with intentional vulnerabilities\n- `mobile/MobileShepherd/` — mobile challenge apps with intentional vulnerabilities\n\nSecurity improvements should only be made to the **platform infrastructure** (authentication, session management, admin functions, DB layer, etc.), never to the training content.\n\n## Code style\n\nAll Java code MUST be formatted with [Google Java Format](https://github.com/google/google-java-format), bound to the Maven build via [Spotless](https://github.com/diffplug/spotless) and pinned in `pom.xml`. CI enforces this with `mvn spotless:check` (the `lint-java` job) and will reject unformatted code.\n\nBefore committing Java changes, run:\n\n```bash\nmvn spotless:apply\n```\n\n## Java version\n\nThe project targets **Java 8**. All code must compile against Java 8, even though CI uses Java 17 for linting and building. Do not use Java 9+ APIs or language features.\n\n## Build and test\n\n```bash\nmvn -Pdocker clean install -DskipTests -B   # build WAR with Docker profile (required before docker compose)\ndocker compose build                          # build Docker images\nmvn test -B                                   # unit tests\nmvn verify -DskipUTs=true -DmongoDocker -B   # integration tests (requires MySQL + MongoDB)\n```\n\nThe `-Pdocker` profile must run before `docker compose build` — it generates SQL scripts, MongoDB init scripts, and TLS keystores.\n\n### Running tests locally\n\n**Always run tests locally before pushing to remote.**\n\nIntegration tests require a running database. For quick local test runs, start a plain MariaDB container:\n\n```bash\ndocker run -d --name secshep_test_db \\\n  -e MYSQL_ROOT_PASSWORD=CowSaysMoo \\\n  -e MYSQL_DATABASE=core \\\n  -p 3306:3306 \\\n  mariadb:10.6.11\n```\n\nThe docker-compose `db` service is **not suitable for quick test runs** — it requires `mvn -Pdocker validate` first to generate SQL init scripts, and those scripts run on first container startup to create all challenge schemas.\n\n### Docker DB init fails with SQL syntax error\n\nIf the MariaDB container exits immediately with `ERROR 1064 (42000) at line 181` referencing a `CREATE PROCEDURE` statement, this is a **stale Docker image cache** issue, not a bug in the SQL.\n\nThe SQL source files have `DELIMITER` statements commented out (for compatibility with tools that don't support `DELIMITER`). A build script (`docker/scripts/convert-sql-scripts.sh`) uncomments them when Maven copies the files to `docker/mariadb/target/`. If Docker reuses a cached image from before the conversion ran, the procedures fail to parse.\n\nFix: `docker compose build --no-cache db && docker compose up -d db`\n\n### Test credentials\n\nTests read DB connection details from `.env` via dotenv. The key values:\n\n- `TEST_MYSQL_HOST` — default `127.0.0.1`\n- `TEST_MYSQL_PORT` — default `3306`\n- `TEST_MYSQL_PASSWORD` — must match the password on the running database\n\nThe `.env` file ships with `TEST_MYSQL_PASSWORD=password` (used in CI where a separate MySQL service is configured with that password). When running locally against the container above (password `CowSaysMoo`), either:\n\n```bash\n# Option 1: override at test time\nTEST_MYSQL_PASSWORD=CowSaysMoo mvn test -B\n\n# Option 2: update .env temporarily\n```\n\nDo not commit `.env` changes that break CI.\n\n### First-time app setup\n\nAfter `docker compose up`, the app redirects to `https://localhost/setup.jsp` for initial database configuration. **Ask the user before performing setup** — they may prefer to configure it themselves via the browser. If they ask you to do it:\n\n1. Get the auth token:\n   ```bash\n   docker exec secshep_tomcat cat /usr/local/tomcat/conf/SecurityShepherd.auth\n   ```\n2. Submit the setup via curl (the TLS cert is self-signed, use `-k`):\n   ```bash\n   curl -k -s -X POST https://localhost/setup \\\n     -d \"dbhost=secshep_mariadb\" \\\n     -d \"dbport=3306\" \\\n     -d \"dbuser=root\" \\\n     -d \"dbpass=CowSaysMoo\" \\\n     -d \"dboverride=override\" \\\n     -d \"dbauth=<AUTH_TOKEN>\" \\\n     -d \"mhost=secshep_mongo\" \\\n     -d \"mport=27017\"\n   ```\n\nThe setup servlet parameter names (from `Setup.java`) are:\n- `dbhost`, `dbport`, `dbuser`, `dbpass` — MySQL/MariaDB connection\n- `dboverride` — set to `override` to reinitialize schemas\n- `dbauth` — the auth token (NOT `authToken`)\n- `mhost`, `mport` — MongoDB connection (required, even if not using mongo challenges)\n\nThe hostname must be the **Docker container name** (e.g. `secshep_mariadb`), not `localhost`, since the Tomcat container connects over the Docker network.\n\n## Git workflow\n\n- Never commit directly to `master` or `dev`\n- Branch naming: `dev#{issueNumber}` (e.g. `dev#536`)\n- PRs always target `dev`, not `master`\n\n## Project structure\n\n- `src/main/java/` — web app source\n  - `dbProcs/` — database layer: `Database.java` (connection pooling), `Getter.java` (read queries), `Setter.java` (write queries), `MongoDatabase.java`, `Constants.java`, `FileInputProperties.java`\n  - `servlets/` — platform servlets (Login, Register, Setup, etc.)\n  - `servlets/admin/` — admin servlets (`config/`, `moduleManagement/`, `userManagement/`)\n  - `servlets/module/` — module framework (`SolutionSubmit.java`, `GetModule.java`, etc.) plus `challenge/` and `lesson/` (intentionally vulnerable — do not fix)\n  - `utils/` — shared utilities (validation, hashing, scoring, XSS/SQL filters)\n- `src/main/resources/` — config and challenge properties files\n- `src/test/java/` — unit tests\n- `src/it/java/` — integration tests (require running DB containers)\n- `mobile/MobileShepherd/` — independent Android apps (Gradle-based, not part of Maven build)\n\n## Database\n\n- MySQL/MariaDB for the core app and SQL-based challenges\n- MongoDB for NoSQL challenges\n- Each challenge uses isolated DB credentials scoped to its own schema — do not consolidate challenge DB users\n- Encoding must be `utf8mb4` (not `utf8`) for full Unicode support\n- Password hashing uses Argon2 (requires `libargon2` native library)\n\n### SQL schema files\n\n- `src/main/resources/database/coreSchema.sql` — **source of truth** for the core database: users table, settings table, stored procedures (user management, authentication, class management, scoring), and seed data (default admin user, default settings)\n- `src/main/resources/database/moduleSchemas.sql` — challenge and lesson schemas with intentionally vulnerable data (treat as training content, not infrastructure)\n- `docker/mariadb/target/` — **build-generated copies** produced by `mvn -Pdocker`; not source of truth, do not edit directly\n\nThe `settings` table stores admin-configurable options as key-value pairs (`setting` VARCHAR, `value` VARCHAR). Known keys: `adminCheatsEnabled`, `playerCheatsEnabled`, `moduleLayout`, `enableFeedback`, `openRegistration`, `scoreboardStatus`, `scoreboardClass`, `hasStartTime`, `startTime`, `hasLockTime`, `lockTime`, `hasEndTime`, `endTime`, `enableTranslations`, `defaultClass`.\n\nStored procedures use `DELIMITER` statements that are commented out in the source SQL (for tool compatibility). The build script `docker/scripts/convert-sql-scripts.sh` uncomments them when copying to `docker/mariadb/target/`. See the \"Docker DB init fails\" section above if procedures fail to parse.\n\n## Agent behaviors\n\n### Always run tests before pushing\n\nRun `mvn test -B` locally before pushing any code changes. If integration tests are relevant to your changes, run those too. Do not rely solely on CI to catch failures.\n\n### Bug fixes must include tests\n\nWhen fixing a bug, always write a test that reproduces the bug first, then apply the fix. The test should fail without the fix and pass with it.\n\n### Keep documentation up to date\n\nWhen making significant changes (new features, architectural changes, build/config changes, new dependencies), check whether these files need updating:\n\n- `AGENTS.md` (this file)\n- `CONTRIBUTING.md`\n- `README.md`\n- Files in `docs/`\n\nDo not scan these files on every change — only review and update them when your changes would make their content inaccurate.\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nInstructions for AI coding agents working on this repository.\n\n## Project overview\n\nOWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are independent Android apps under `mobile/MobileShepherd/`.\n\n## Intentionally vulnerable code — DO NOT FIX\n\nThe following paths contain **deliberately insecure code** used for security training. Do not fix, refactor, or flag security vulnerabilities in these files:\n\n- `src/main/java/servlets/module/lesson/` — lesson servlets with intentional vulnerabilities\n- `src/main/java/servlets/module/challenge/` — challenge servlets with intentional vulnerabilities\n- `mobile/MobileShepherd/` — mobile challenge apps with intentional vulnerabilities\n\nSecurity improvements should only be made to the **platform infrastructure** (authentication, session management, admin functions, DB layer, etc.), never to the training content.\n\n## Code style\n\nAll Java code MUST be formatted with [Google Java Format](https://github.com/google/google-java-format), bound to the Maven build via [Spotless](https://github.com/diffplug/spotless) and pinned in `pom.xml`. CI enforces this with `mvn spotless:check` (the `lint-java` job) and will reject unformatted code.\n\nBefore committing Java changes, run:\n\n```bash\nmvn spotless:apply\n```\n\n## Java version\n\nThe project targets **Java 8**. All code must compile against Java 8, even though CI uses Java 17 for linting and building. Do not use Java 9+ APIs or language features.\n\n## Build and test\n\n```bash\nmvn -Pdocker clean install -DskipTests -B   # build WAR with Docker profile (required before docker compose)\ndocker compose build                          # build Docker images\nmvn test -B                                   # unit tests\nmvn verify -DskipUTs=true -DmongoDocker -B   # integration tests (requires MySQL + MongoDB)\n```\n\nThe `-Pdocker` profile must run before `docker compose build` — it generates SQL scripts, MongoDB init scripts, and TLS keystores.\n\n### Running tests locally\n\n**Always run tests locally before pushing to remote.**\n\nIntegration tests require a running database. For quick local test runs, start a plain MariaDB container:\n\n```bash\ndocker run -d --name secshep_test_db \\\n  -e MYSQL_ROOT_PASSWORD=CowSaysMoo \\\n  -e MYSQL_DATABASE=core \\\n  -p 3306:3306 \\\n  mariadb:10.6.11\n```\n\nThe docker-compose `db` service is **not suitable for quick test runs** — it requires `mvn -Pdocker validate` first to generate SQL init scripts, and those scripts run on first container startup to create all challenge schemas.\n\n### Docker DB init fails with SQL syntax error\n\nIf the MariaDB container exits immediately with `ERROR 1064 (42000) at line 181` referencing a `CREATE PROCEDURE` statement, this is a **stale Docker image cache** issue, not a bug in the SQL.\n\nThe SQL source files have `DELIMITER` statements commented out (for compatibility with tools that don't support `DELIMITER`). A build script (`docker/scripts/convert-sql-scripts.sh`) uncomments them when Maven copies the files to `docker/mariadb/target/`. If Docker reuses a cached image from before the conversion ran, the procedures fail to parse.\n\nFix: `docker compose build --no-cache db && docker compose up -d db`\n\n### Test credentials\n\nTests read DB connection details from `.env` via dotenv. The key values:\n\n- `TEST_MYSQL_HOST` — default `127.0.0.1`\n- `TEST_MYSQL_PORT` — default `3306`\n- `TEST_MYSQL_PASSWORD` — must match the password on the running database\n\nThe `.env` file ships with `TEST_MYSQL_PASSWORD=password` (used in CI where a separate MySQL service is configured with that password). When running locally against the container above (password `CowSaysMoo`), either:\n\n```bash\n# Option 1: override at test time\nTEST_MYSQL_PASSWORD=CowSaysMoo mvn test -B\n\n# Option 2: update .env temporarily\n```\n\nDo not commit `.env` changes that break CI.\n\n### First-time app setup\n\nAfter `docker compose up`, the app redirects to `https://localhost/setup.jsp` for initial database configuration. **Ask the user before performing setup** — they may prefer to configure it themselves via the browser. If they ask you to do it:\n\n1. Get the auth token:\n   ```bash\n   docker exec secshep_tomcat cat /usr/local/tomcat/conf/SecurityShepherd.auth\n   ```\n2. Submit the setup via curl (the TLS cert is self-signed, use `-k`):\n   ```bash\n   curl -k -s -X POST https://localhost/setup \\\n     -d \"dbhost=secshep_mariadb\" \\\n     -d \"dbport=3306\" \\\n     -d \"dbuser=root\" \\\n     -d \"dbpass=CowSaysMoo\" \\\n     -d \"dboverride=override\" \\\n     -d \"dbauth=<AUTH_TOKEN>\" \\\n     -d \"mhost=secshep_mongo\" \\\n     -d \"mport=27017\"\n   ```\n\nThe setup servlet parameter names (from `Setup.java`) are:\n- `dbhost`, `dbport`, `dbuser`, `dbpass` — MySQL/MariaDB connection\n- `dboverride` — set to `override` to reinitialize schemas\n- `dbauth` — the auth token (NOT `authToken`)\n- `mhost`, `mport` — MongoDB connection (required, even if not using mongo challenges)\n\nThe hostname must be the **Docker container name** (e.g. `secshep_mariadb`), not `localhost`, since the Tomcat container connects over the Docker network.\n\n## Git workflow\n\n- Never commit directly to `master` or `dev`\n- Branch naming: `dev#{issueNumber}` (e.g. `dev#536`)\n- PRs always target `dev`, not `master`\n\n## Project structure\n\n- `src/main/java/` — web app source\n  - `dbProcs/` — database layer: `Database.java` (connection pooling), `Getter.java` (read queries), `Setter.java` (write queries), `MongoDatabase.java`, `Constants.java`, `FileInputProperties.java`\n  - `servlets/` — platform servlets (Login, Register, Setup, etc.)\n  - `servlets/admin/` — admin servlets (`config/`, `moduleManagement/`, `userManagement/`)\n  - `servlets/module/` — module framework (`SolutionSubmit.java`, `GetModule.java`, etc.) plus `challenge/` and `lesson/` (intentionally vulnerable — do not fix)\n  - `utils/` — shared utilities (validation, hashing, scoring, XSS/SQL filters)\n- `src/main/resources/` — config and challenge properties files\n- `src/test/java/` — unit tests\n- `src/it/java/` — integration tests (require running DB containers)\n- `mobile/MobileShepherd/` — independent Android apps (Gradle-based, not part of Maven build)\n\n## Database\n\n- MySQL/MariaDB for the core app and SQL-based challenges\n- MongoDB for NoSQL challenges\n- Each challenge uses isolated DB credentials scoped to its own schema — do not consolidate challenge DB users\n- Encoding must be `utf8mb4` (not `utf8`) for full Unicode support\n- Password hashing uses Argon2 (requires `libargon2` native library)\n\n### SQL schema files\n\n- `src/main/resources/database/coreSchema.sql` — **source of truth** for the core database: users table, settings table, stored procedures (user management, authentication, class management, scoring), and seed data (default admin user, default settings)\n- `src/main/resources/database/moduleSchemas.sql` — challenge and lesson schemas with intentionally vulnerable data (treat as training content, not infrastructure)\n- `docker/mariadb/target/` — **build-generated copies** produced by `mvn -Pdocker`; not source of truth, do not edit directly\n\nThe `settings` table stores admin-configurable options as key-value pairs (`setting` VARCHAR, `value` VARCHAR). Known keys: `adminCheatsEnabled`, `playerCheatsEnabled`, `moduleLayout`, `enableFeedback`, `openRegistration`, `scoreboardStatus`, `scoreboardClass`, `hasStartTime`, `startTime`, `hasLockTime`, `lockTime`, `hasEndTime`, `endTime`, `enableTranslations`, `defaultClass`.\n\nStored procedures use `DELIMITER` statements that are commented out in the source SQL (for tool compatibility). The build script `docker/scripts/convert-sql-scripts.sh` uncomments them when copying to `docker/mariadb/target/`. See the \"Docker DB init fails\" section above if procedures fail to parse.\n\n## Agent behaviors\n\n### Always run tests before pushing\n\nRun `mvn test -B` locally before pushing any code changes. If integration tests are relevant to your changes, run those too. Do not rely solely on CI to catch failures.\n\n### Bug fixes must include tests\n\nWhen fixing a bug, always write a test that reproduces the bug first, then apply the fix. The test should fail without the fix and pass with it.\n\n### Keep documentation up to date\n\nWhen making significant changes (new features, architectural changes, build/config changes, new dependencies), check whether these files need updating:\n\n- `AGENTS.md` (this file)\n- `CONTRIBUTING.md`\n- `README.md`\n- Files in `docs/`\n\nDo not scan these files on every change — only review and update them when your changes would make their content inaccurate.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nInstructions for AI coding agents working on this repository.\n\n## Project overview\n\nOWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are independent Android apps under `mobile/MobileShepherd/`.\n\n## Intentionally vulnerable code — DO NOT FIX\n\nThe following paths contain **deliberately insecure code** used for security training. Do not fix, refactor, or flag security vulnerabilities in these files:\n\n- `src/main/java/servlets/module/lesson/` — lesson servlets with intentional vulnerabilities\n- `src/main/java/servlets/module/challenge/` — challenge servlets with intentional vulnerabilities\n- `mobile/MobileShepherd/` — mobile challenge apps with intentional vulnerabilities\n\nSecurity improvements should only be made to the **platform infrastructure** (authentication, session management, admin functions, DB layer, etc.), never to the training content.\n\n## Code style\n\nAll Java code MUST be formatted with [Google Java Format](https://github.com/google/google-java-format), bound to the Maven build via [Spotless](https://github.com/diffplug/spotless) and pinned in `pom.xml`. CI enforces this with `mvn spotless:check` (the `lint-java` job) and will reject unformatted code.\n\nBefore committing Java changes, run:\n\n```bash\nmvn spotless:apply\n```\n\n## Java version\n\nThe project targets **Java 8**. All code must compile against Java 8, even though CI uses Java 17 for linting and building. Do not use Java 9+ APIs or language features.\n\n## Build and test\n\n```bash\nmvn -Pdocker clean install -DskipTests -B   # build WAR with Docker profile (required before docker compose)\ndocker compose build                          # build Docker images\nmvn test -B                                   # unit tests\nmvn verify -DskipUTs=true -DmongoDocker -B   # integration tests (requires MySQL + MongoDB)\n```\n\nThe `-Pdocker` profile must run before `docker compose build` — it generates SQL scripts, MongoDB init scripts, and TLS keystores.\n\n### Running tests locally\n\n**Always run tests locally before pushing to remote.**\n\nIntegration tests require a running database. For quick local test runs, start a plain MariaDB container:\n\n```bash\ndocker run -d --name secshep_test_db \\\n  -e MYSQL_ROOT_PASSWORD=CowSaysMoo \\\n  -e MYSQL_DATABASE=core \\\n  -p 3306:3306 \\\n  mariadb:10.6.11\n```\n\nThe docker-compose `db` service is **not suitable for quick test runs** — it requires `mvn -Pdocker validate` first to generate SQL init scripts, and those scripts run on first container startup to create all challenge schemas.\n\n### Docker DB init fails with SQL syntax error\n\nIf the MariaDB container exits immediately with `ERROR 1064 (42000) at line 181` referencing a `CREATE PROCEDURE` statement, this is a **stale Docker image cache** issue, not a bug in the SQL.\n\nThe SQL source files have `DELIMITER` statements commented out (for compatibility with tools that don't support `DELIMITER`). A build script (`docker/scripts/convert-sql-scripts.sh`) uncomments them when Maven copies the files to `docker/mariadb/target/`. If Docker reuses a cached image from before the conversion ran, the procedures fail to parse.\n\nFix: `docker compose build --no-cache db && docker compose up -d db`\n\n### Test credentials\n\nTests read DB connection details from `.env` via dotenv. The key values:\n\n- `TEST_MYSQL_HOST` — default `127.0.0.1`\n- `TEST_MYSQL_PORT` — default `3306`\n- `TEST_MYSQL_PASSWORD` — must match the password on the running database\n\nThe `.env` file ships with `TEST_MYSQL_PASSWORD=password` (used in CI where a separate MySQL service is configured with that password). When running locally against the container above (password `CowSaysMoo`), either:\n\n```bash\n# Option 1: override at test time\nTEST_MYSQL_PASSWORD=CowSaysMoo mvn test -B\n\n# Option 2: update .env temporarily\n```\n\nDo not commit `.env` changes that break CI.\n\n### First-time app setup\n\nAfter `docker compose up`, the app redirects to `https://localhost/setup.jsp` for initial database configuration. **Ask the user before performing setup** — they may prefer to configure it themselves via the browser. If they ask you to do it:\n\n1. Get the auth token:\n   ```bash\n   docker exec secshep_tomcat cat /usr/local/tomcat/conf/SecurityShepherd.auth\n   ```\n2. Submit the setup via curl (the TLS cert is self-signed, use `-k`):\n   ```bash\n   curl -k -s -X POST https://localhost/setup \\\n     -d \"dbhost=secshep_mariadb\" \\\n     -d \"dbport=3306\" \\\n     -d \"dbuser=root\" \\\n     -d \"dbpass=CowSaysMoo\" \\\n     -d \"dboverride=override\" \\\n     -d \"dbauth=<AUTH_TOKEN>\" \\\n     -d \"mhost=secshep_mongo\" \\\n     -d \"mport=27017\"\n   ```\n\nThe setup servlet parameter names (from `Setup.java`) are:\n- `dbhost`, `dbport`, `dbuser`, `dbpass` — MySQL/MariaDB connection\n- `dboverride` — set to `override` to reinitialize schemas\n- `dbauth` — the auth token (NOT `authToken`)\n- `mhost`, `mport` — MongoDB connection (required, even if not using mongo challenges)\n\nThe hostname must be the **Docker container name** (e.g. `secshep_mariadb`), not `localhost`, since the Tomcat container connects over the Docker network.\n\n## Git workflow\n\n- Never commit directly to `master` or `dev`\n- Branch naming: `dev#{issueNumber}` (e.g. `dev#536`)\n- PRs always target `dev`, not `master`\n\n## Project structure\n\n- `src/main/java/` — web app source\n  - `dbProcs/` — database layer: `Database.java` (connection pooling), `Getter.java` (read queries), `Setter.java` (write queries), `MongoDatabase.java`, `Constants.java`, `FileInputProperties.java`\n  - `servlets/` — platform servlets (Login, Register, Setup, etc.)\n  - `servlets/admin/` — admin servlets (`config/`, `moduleManagement/`, `userManagement/`)\n  - `servlets/module/` — module framework (`SolutionSubmit.java`, `GetModule.java`, etc.) plus `challenge/` and `lesson/` (intentionally vulnerable — do not fix)\n  - `utils/` — shared utilities (validation, hashing, scoring, XSS/SQL filters)\n- `src/main/resources/` — config and challenge properties files\n- `src/test/java/` — unit tests\n- `src/it/java/` — integration tests (require running DB containers)\n- `mobile/MobileShepherd/` — independent Android apps (Gradle-based, not part of Maven build)\n\n## Database\n\n- MySQL/MariaDB for the core app and SQL-based challenges\n- MongoDB for NoSQL challenges\n- Each challenge uses isolated DB credentials scoped to its own schema — do not consolidate challenge DB users\n- Encoding must be `utf8mb4` (not `utf8`) for full Unicode support\n- Password hashing uses Argon2 (requires `libargon2` native library)\n\n### SQL schema files\n\n- `src/main/resources/database/coreSchema.sql` — **source of truth** for the core database: users table, settings table, stored procedures (user management, authentication, class management, scoring), and seed data (default admin user, default settings)\n- `src/main/resources/database/moduleSchemas.sql` — challenge and lesson schemas with intentionally vulnerable data (treat as training content, not infrastructure)\n- `docker/mariadb/target/` — **build-generated copies** produced by `mvn -Pdocker`; not source of truth, do not edit directly\n\nThe `settings` table stores admin-configurable options as key-value pairs (`setting` VARCHAR, `value` VARCHAR). Known keys: `adminCheatsEnabled`, `playerCheatsEnabled`, `moduleLayout`, `enableFeedback`, `openRegistration`, `scoreboardStatus`, `scoreboardClass`, `hasStartTime`, `startTime`, `hasLockTime`, `lockTime`, `hasEndTime`, `endTime`, `enableTranslations`, `defaultClass`.\n\nStored procedures use `DELIMITER` statements that are commented out in the source SQL (for tool compatibility). The build script `docker/scripts/convert-sql-scripts.sh` uncomments them when copying to `docker/mariadb/target/`. See the \"Docker DB init fails\" section above if procedures fail to parse.\n\n## Agent behaviors\n\n### Always run tests before pushing\n\nRun `mvn test -B` locally before pushing any code changes. If integration tests are relevant to your changes, run those too. Do not rely solely on CI to catch failures.\n\n### Bug fixes must include tests\n\nWhen fixing a bug, always write a test that reproduces the bug first, then apply the fix. The test should fail without the fix and pass with it.\n\n### Keep documentation up to date\n\nWhen making significant changes (new features, architectural changes, build/config changes, new dependencies), check whether these files need updating:\n\n- `AGENTS.md` (this file)\n- `CONTRIBUTING.md`\n- `README.md`\n- Files in `docs/`\n\nDo not scan these files on every change — only review and update them when your changes would make their content inaccurate.\n","category":"root","tokens":2169}]}