## StoryTeller Development Workflow ### Stack and Layout - **Backend**: Quarkus 3.31.2 (Java 21, Maven). - **Frontend**: React 18 + TypeScript + Vite in `src/main/web`. - **Database**: PostgreSQL with Liquibase migrations. - **Auth**: SmallRye JWT with RSA key signing; BCrypt password hashing. - **API Contract**: OpenAPI 3.0.3 at `src/main/resources/openapi/story-teller-api.yaml`. - **Generated Code**: - Java interfaces/models: `target/generated-sources/openapi/java/src/gen/java/` - TypeScript client: `src/main/web/src/api/generated/` ### Local Setup 1. **Prerequisites**: JDK 21, Maven 3.9+, PostgreSQL, Node.js 22 (managed by frontend-maven-plugin). 2. **Database**: Create a PostgreSQL database: ```sql CREATE DATABASE storyteller; CREATE USER storyteller WITH PASSWORD 'storyteller'; GRANT ALL PRIVILEGES ON DATABASE storyteller TO storyteller; ``` 3. **Build everything**: `mvn package` (generates API code, compiles Java, builds frontend, runs tests). 4. **Run in dev mode**: `mvn quarkus:dev` (hot reload, frontend proxy at http://localhost:5173). 5. **Frontend dev**: `cd src/main/web && npm run dev` (standalone Vite dev server, proxies `/api` to Quarkus). ### Default Admin Account After first startup, Liquibase seeds an admin user: - **Username**: `admin` - **Password**: `admin` Change this immediately in non-development environments. ### OpenAPI-First Rules - The OpenAPI YAML is the **single source of truth** for backend and frontend API contracts. - **Never edit generated files** in `target/generated-sources/` or `src/main/web/src/api/generated/`. - To change the API: 1. Edit `src/main/resources/openapi/story-teller-api.yaml`. 2. Run `mvn generate-sources` to regenerate Java and TypeScript. 3. Update service/resource implementations to match new interfaces. ### Common Commands | Command | Description | |---|---| | `mvn generate-sources` | Regenerate Java+TS from OpenAPI | | `mvn compile` | Compile Java backend | | `mvn test` | Run unit tests | | `mvn package` | Full build: Java + frontend + tests | | `mvn quarkus:dev` | Dev mode with hot reload | | `cd src/main/web && npm run dev` | Frontend dev server | ### Architecture Overview ``` de.neitzel.storyteller ├── business/ # Business logic services ├── common/ │ └── security/ # JWT, password hashing, auth context ├── data/ │ ├── entity/ # JPA entities │ └── repository/ # Panache repositories └── fascade/ ├── api/ # Generated OpenAPI interfaces (DO NOT EDIT) ├── model/ # Generated OpenAPI models (DO NOT EDIT) └── rest/ # REST resource implementations ``` ### Authentication Flow 1. Client sends `POST /api/auth/login` with username/password. 2. Server verifies credentials, returns signed JWT with user claims. 3. Client stores JWT in localStorage and sends it as `Authorization: Bearer ` on all subsequent requests. 4. Quarkus SmallRye JWT validates the token on protected endpoints. 5. `AuthContext` (request-scoped CDI bean) extracts user identity from the JWT. ### Authorization - **Public**: `/api/auth/*` - **Admin-only**: `/api/users/*` (user management) - **Authenticated users**: `/api/scenarios/*`, `/api/stories/*` (with per-user ownership checks) ### Story Generation & Compaction The AI step generation flow includes automatic context compaction: 1. Client sends a direction prompt. 2. Server estimates context size (scene + characters + unmerged steps + direction). 3. If it exceeds the limit (~12K chars), the oldest half of unmerged steps are compacted into the scene description. 4. Steps are marked `addedToScene = true` after compaction. 5. The AI generates the next step from the (possibly compacted) context. 6. The response includes a `compacted` flag so the frontend can prompt the user to review the updated scene. **Note**: The current AI adapter is a stub that generates placeholder text. Replace the `generateAiContinuation` and `compactScene` methods in `StoryService` with actual LLM integration. ### Testing - Unit tests use JUnit 5 + Mockito in `src/test/java/`. - Tests cover auth, user service, scenario service, and story service. - Run with `mvn test`. ### Troubleshooting - **JWT errors**: Ensure `privateKey.pem` and `publicKey.pem` exist in `src/main/resources/`. - **Generated code issues**: Run `mvn clean generate-sources` to rebuild from scratch. - **TypeScript errors**: Check that `src/main/web/node_modules` exists; run `npm install` in `src/main/web`. - **DB connection**: Verify PostgreSQL is running and the `storyteller` database/user exist.