# Legal Consent Hub - AI Context ## Overview Platform for digital applications, approvals, and discussions with GDPR compliance features. Enables organizations to create, manage, and track application forms with version control and PDF export. --- ## Architecture | Layer | Stack | |-------|-------| | **Frontend** | Nuxt 4.2.0, Vue 3, Nuxt UI 4.3.0, Pinia, TypeScript, i18n (de/en) | | **Backend** | Spring Boot 3.4.2, Kotlin 1.9.25, Java 21, PostgreSQL, Liquibase | | **Auth** | Keycloak (OAuth2/JWT), nuxt-auth-utils | | **PDF** | LaTeX (lualatex) via Thymeleaf templates | | **API** | OpenAPI 3.0.3 spec → auto-generated clients | --- ## Form Structure (3-Level Hierarchy) ``` ApplicationForm └── Section (FormElementSection) ├── title, shortTitle, description ├── isTemplate, templateReference, titleTemplate ← for spawning └── SubSection (FormElementSubSection) └── FormElement ├── id (UUID), reference (string key) ├── type: SELECT | CHECKBOX | RADIOBUTTON | TEXTFIELD | TEXTAREA | SWITCH | RICH_TEXT | DATE | TABLE ├── options: FormOption[] (value, label, processingPurpose, employeeDataCategory, columnConfig) ├── visibilityConditions[] (AND logic) ├── sectionSpawnTriggers[] ├── isClonable, tableRowPreset ``` --- ## Key Features ### Visibility Conditions - Elements shown/hidden based on other element values - Multiple conditions use **AND logic** - Operators: `EQUALS`, `NOT_EQUALS`, `IS_EMPTY`, `IS_NOT_EMPTY` - Reference elements by `reference` key (not ID) - Hidden elements: excluded from validation, PDF export, and values cleared ### Section Spawning - Template sections (`isTemplate: true`) spawn when trigger conditions met - Title interpolation: `{{triggerValue}}` placeholder - Spawned sections linked via `spawnedFromElementReference` - One element can have multiple `sectionSpawnTriggers` ### Clonable Elements - `isClonable: true` shows "Add another" button - Deep cloning with auto-generated references (`modul_1` → `modul_2`) - Values reset on clone (TEXTAREA/TEXTFIELD) ### Table Cross-References - Column references other table's column: `columnConfig.sourceTableReference` - Row presets from source table: `tableRowPreset` - Filter conditions limit available values --- ## Composables | Composable | Purpose | |------------|---------| | `useFormElementVisibility` | Evaluate visibility conditions | | `useSectionSpawning` | Process spawn triggers, clone templates | | `useClonableElements` | Clone elements with reference generation | | `useFormElementValueClearing` | Clear values when elements become hidden | | `useTableCrossReferences` | Resolve table column/row references | | `useApplicationFormValidator` | Form validation rules | | `useLogger` | Consola logger instance | --- ## API Endpoints ``` # Forms GET/POST /application-forms GET/PUT/DELETE /application-forms/{id} POST /application-forms/{id}/submit # Templates GET/POST /application-form-templates GET/PUT/DELETE /application-form-templates/{id} # Versions GET /application-forms/{id}/versions GET /application-forms/{id}/versions/{n} POST /application-forms/{id}/versions/{n}/restore GET /application-forms/{id}/versions/{n}/pdf # Comments GET /application-forms/{id}/comments POST /application-forms/{id}/form-elements/{elementId}/comments PUT/DELETE /comments/{id} # Notifications GET /notifications?organizationId= GET /notifications/unread/count?userId=&organizationId= (public) PUT /notifications/{id}/mark-read PUT /notifications/mark-all-read DELETE /notifications/clear-all ``` --- ## Roles (Keycloak-managed) `CHIEF_EXECUTIVE_OFFICER`, `BUSINESS_DEPARTMENT`, `IT_DEPARTMENT`, `HUMAN_RESOURCES`, `HEAD_OF_WORKS_COUNCIL`, `WORKS_COUNCIL`, `EMPLOYEE` --- ## Development ```bash # Frontend (port 3001) cd legalconsenthub && pnpm install && pnpm run dev # Backend (port 8080) cd legalconsenthub-backend && ./gradlew bootRun # Generate API clients pnpm run api:generate # Frontend ./gradlew generate_legalconsenthub_server # Backend ``` --- ## Seed Data Maintenance The application automatically seeds initial data on first startup: ### 1. Template Seeding **Seeder:** `InitialApplicationFormTemplateSeeder` **File:** `legalconsenthub-backend/src/main/resources/seed/initial_application_form_template.yaml` **Condition:** Seeds if no templates exist (`isTemplate = true`) **Purpose:** Comprehensive IT system approval workflow template **IMPORTANT:** Keep this file updated when form structure or validation rules change. ### 2. Application Form Seeding **Seeder:** `InitialApplicationFormSeeder` **File:** `legalconsenthub-backend/src/main/resources/seed/initial_application_form.yaml` **Condition:** Seeds if no forms exist for empty organizationId (`isTemplate = false`) **Purpose:** Realistic SAP S/4HANA application form for development and UI testing **organizationId:** Empty string (global form visible to all organizations) **Content:** Pre-filled IT system introduction form based on the template structure with realistic SAP S/4HANA values **IMPORTANT:** Keep this file synchronized with template changes. When template structure changes, update the demo form accordingly. **Note:** - Forms with empty/null organizationId act as "global" forms and are visible to all organizations - This allows the demo form to appear regardless of the current organization context - The demo form is derived from the template structure with values filled for realistic testing - Demonstrates visibility conditions, section spawning, clonable elements, and GDPR compliance features --- ## Key Files | File | Purpose | |------|---------| | `api/legalconsenthub.yml` | OpenAPI spec (source of truth) | | `legalconsenthub-backend/src/main/resources/templates/application_form_latex_template.tex` | PDF template | | `legalconsenthub-backend/src/main/resources/seed/initial_application_form_template.yaml` | Initial form template (isTemplate=true) | | `legalconsenthub-backend/src/main/resources/seed/initial_application_form.yaml` | SAP S/4HANA demo application form (global, filled with realistic values) | | `legalconsenthub-backend/src/main/resources/db/changelog/` | Liquibase migrations | | `.github/workflows/pipeline.yaml` | CI/CD workflow | --- ## Rules for AI 1. **Never auto-generate SQL migrations** - Liquibase migrations are manual 2. **Use mapper classes** for all DTO↔Entity conversions (never in services/controllers) 3. **No hardcoded UI strings** - Use i18n (`de.json`, `en.json`) 4. **API-first** - Modify OpenAPI spec, then regenerate clients 5. **Organization context** - Always consider `organizationId` for multi-tenancy. Forms with empty/null organizationId are "global" forms visible to all organizations 6. **Form structure is 3-level** - Section → SubSection → Element 7. **Roles managed in Keycloak** - Not in application database 8. **Nuxt UI 4** - For any UI-related questions, use the Nuxt UI MCP server to get current component docs and examples ### PDF Export Validation After changes to form elements, visibility, or spawning: - Test both HTML and PDF export for real form instances - Verify all element types render correctly - Ensure template sections excluded, spawned sections included - Hotspots: `ApplicationFormFormatService.kt`, `application_form_latex_template.tex` ### Code Style - Order functions top-down by abstraction (public API first, helpers below) - Keep `CLAUDE.md` updated when introducing architectural changes