Platform overhaul: Quarkus/Vue modernization, Keycloak auth, shadcn-vue migration, Azure decoupling#1
Open
dominikhorn93 wants to merge 37 commits into
Open
Platform overhaul: Quarkus/Vue modernization, Keycloak auth, shadcn-vue migration, Azure decoupling#1dominikhorn93 wants to merge 37 commits into
dominikhorn93 wants to merge 37 commits into
Conversation
- Quarkus 3.27.4 (JDK 25 compatible, security fixes, 2 years of updates) - Rename quarkus-resteasy-reactive* to quarkus-rest* (3.9+ artifact names) - Lombok 1.18.46 via annotationProcessorPaths (required since JDK 23 disabled implicit classpath annotation processing) - JaCoCo 0.8.15, quarkus-bucket4j 1.0.7 - Extract CamundaOperateServiceFactory from CamundaCloudImportUsecase: usecase no longer builds HTTP clients itself, tests mock the factory instead of spying on the usecase Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Vue 3.3 -> 3.5, Vite 4 -> 7, TypeScript 5.2 -> 5.9, vue-tsc 1 -> 3 - Vuetify 3.3 -> 3.12, bpmn-js 14 -> 18, axios 1.5 -> 1.17 (CVE fixes) - Pinia 2 -> 3, pinia-plugin-persistedstate 3 -> 4 (persist option renamed paths -> pick; drop nonexistent activeProjectByGroup entry) - vue-i18n 9 (EOL) -> 11, vue-router 4.2 -> 4.6 - ESLint 8 legacy config -> ESLint 9 flat config with vue3-recommended + TS recommended + prettier skip-formatting - moduleResolution: bundler; pin all versions exactly (project rule) - Drop unused deps: core-js, @babel/types, @types/cytoscape - New scripts: type-check, lint:check, format, format:check Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docker-compose.yml: PostgreSQL 17 with fuzzystrmatch extension auto-enabled via scripts/init-db.sql (host port 5433 to avoid clashes with other local databases) - Makefile: setup, db-up/down/reset, backend(-pg), frontend, test, lint, format, build targets - dev-postgres profile now matches the compose service and keeps data between restarts (update instead of drop-and-create) - Remove committed rsaPrivateKey.pem from the index and ignore intermediate key files (NOTE: rotate keys if this pair was ever used in production - it remains in git history) - Prod profile: disable SQL logging; migrate deprecated quarkus.package.type to quarkus.package.jar.type - frontend/.env.example documents VITE_APP_MODE Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- New frontend-checks workflow: Prettier, ESLint, type-checked build on every PR touching frontend/ - backend-tests: also trigger on root pom.xml changes; add concurrency group to cancel superseded runs - Rewrite git hooks: failures now actually abort (the old hooks only echoed and continued); pre-commit runs fast lint/format checks on staged files only, pre-push runs the affected test suites - Dependabot for Maven, npm and GitHub Actions - frontend-maven-plugin: Node 20 (EOL) -> 22 LTS, yarn 1.22.22 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mp.jwt.verify.audience=proa-client is configured, but TokenService
never set an aud claim on issued tokens, so signer and verifier
disagreed. Add .audience("proa-client") and assert it in the test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- XSS fix: ProjectOverview delete-confirmation rendered user-controlled project/version names via v-html; now uses <i18n-t> slots so names are escaped text nodes - Declare emits in all components (40 occurrences) - Fix v-for keys, prop mutation (dialog v-model -> computed + close event), required-prop defaults, component name casing - Replace any-casts with precise types; remove dead vars/params - Convert setMode.js to ESM (setMode.mjs) - Mechanical Prettier/ESLint --fix formatting across all sources yarn lint:check, format:check and build are all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- pre-push used 'eslint --ignore-path', which ESLint 9 flat config
rejects - every frontend push would have been falsely blocked.
Use 'yarn lint:check' instead
- New 'desktop' profile with file-backed H2 (~/.proa) so released
desktop jars actually persist data across restarts
- default-schema=${STAGE:local} so the jar can start without STAGE
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Tailwind v4 via @tailwindcss/vite; preflight intentionally NOT imported yet so Vuetify keeps working during the strangler-fig migration (see comment in src/styles/shadcn.css) - shadcn theme tokens (oklch) with primary mapped to the existing brand blue (#1867C0 equivalent); dark-mode variables prepared - components.json + cn() util; 19 ui components generated via CLI: alert avatar badge button card checkbox dialog dropdown-menu input label select separator sheet skeleton switch table tabs textarea tooltip - ESLint override for generated src/components/ui/** - All new deps pinned exactly (project rule) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Any authenticated web-mode user could read, delete or import into other users' projects by guessing ids - process-model, process-map and Camunda-import endpoints never checked project membership. - ProjectAccessService (usecases) + ProjectAccessRepository port + ProjectAccessDao impl: resolve resource id (process model, connection, project version) -> owning project -> membership (OWNER/COLLABORATEUR) of the JWT user - ProjectAccessVerifier (rest) applies the check in web mode before every usecase call; 403 for non-members, 404 for unknown ids; desktop mode unchanged - Verified id semantics: outside ProjectResource, the 'projectId' path segment is a ProjectVersionTable id (documented in ProjectAccessService) - 59 new tests incl. cross-user 403/404 cases; suite: 324 green - Test profile pins default-schema=PUBLIC (H2) after STAGE:local default broke native cleanup queries Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
API layer (src/api): single axios client with baseURL /api, auth header injection from the store, and 401 interceptor (web mode: clear session + redirect to sign-in; login uses skipAuth). Typed feature modules auth/users/projects/processModels/processMap/ settings/camundaCloud replace raw axios calls copy-pasted across 17 components; authHeader.ts and ad-hoc services deleted. Shared types moved out of .vue files into src/types (kills circular imports). Bug fixes: - ProcessMap view state (graph, paper layout, filters, hidden cells/ports/links) now saved AND loaded under the project version id - restore was silently broken by mismatched keys - Active instance counter counted every non-ACTIVE instance as 1 - Router guards: no more window.history.back(); proper vue-router 4 return values, direct-entry redirects to ProjectOverview - Global snackbar moved to the default layout (was Home-only) - v-model-on-setterless-computed fixed in AuthenticationDialog and EditUserDialog; lastName input no longer type=email - SettingsDrawer: VITE_OPERATE_REGION_ID name fixed, save errors surfaced; Gemini failures no longer lock the upload dialog - Sort comparator and i18n gaps (5 components, en/de) fixed yarn lint:check, format:check, build: green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- XXE: secure DocumentBuilderFactory/TransformerFactory settings in BpmnOperations (DOCTYPE disallowed, external entities/DTD/stylesheet access off); DOCTYPE pre-check on BPMN uploads returns a clear 400; test proves external-entity BPMN is rejected without entity resolution (camunda-xml-model parser verified DTD-safe) - app.mode now defaults to web everywhere: a missing property fails CLOSED (auth on) instead of silently disabling authorization - New WebModeAuthorizationTest exercises 401/403/200 with real signed JWTs - role checks were previously never tested (tests ran desktop) - Bean Validation: registration validates email format and password length (validation group keeps seeded admin login working) - FileService no longer swallows IOException (uploads can't be silently stored empty); NPE fixes in ProjectRepositoryImpl (unknown project -> NoResultException) and SettingsRepositoryImpl (create-on-first-write) - AdminInitializer warns loudly when default admin credentials are used in web mode; printStackTrace replaced with quarkus Log Tests: 346 green (+22). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gration docs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First strangler-fig wave (see docs/UI-MIGRATION.md): - SignIn: Card composition, Input/Label with aria-invalid errors, destructive Alert, loading state on submit (prevents double login) - AuthenticationDialog + CreateAccount/ChangePassword/ProfileDialog/ EditProfileDialog: shadcn Dialog driven by the existing SelectedDialog store mechanism; persistent semantics preserved - ManageUsers/EditUserDialog: shadcn Table, Badge roles, ghost icon actions with Tooltip, destructive delete button - Validation logic unchanged (firstRuleError helper runs the same rule arrays); store calls, emits, i18n keys and API calls intact - mdi icons -> lucide; authentication.css removed - Button.vue: export Props interface (TS4023 under composite builds; re-apply if regenerated) lint:check, format:check, build: green. No Vuetify usage left in the migrated files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…artifacts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…upling - Multi-step flows (save/replace/delete process model) now run in one transaction: class-level @transactional on the repository impls and the orchestrating usecase methods; includes rollback test that fails if the annotation is removed. Fixed two latent bugs surfaced by the shared persistence context (managed-entity mutation during connection copy; flush/clear before bulk delete) - ProcessModelRepository port no longer leaks the JPA entity ProcessModelTable: returns ProcessModelReference record; usecases package now imports zero repository.tables types - JAX-RS ExceptionMappers (403/404/400/500) replace per-endpoint try/catch; bodies keep the shape the frontend reads (exceptionType); generic 500 logs without leaking internals - JPA entity hygiene: id-based equals + constant hashCode for ProcessModelTable (lives in HashSets, Lombok hashed mutable/lazy state) and missing hashCode on ProjectVersionTable - SearchQueryHelper dedups the levenshtein-vs-exact db-kind conditional across four DAOs Tests: 358 green (+13, -1 obsolete). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Vuetify ships an unlayered element reset (div { padding: 0 } etc.).
Unlayered CSS beats every @layer rule, so all padding/margin
utilities in shadcn components computed to 0. Import the utilities
WITHOUT layer(...) so they win by class specificity during the
coexistence phase. Verified live: dialog p-6 now applies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backend (adversarially verified by the branch review): - DOCTYPE pre-check falsely rejected BPMN with '<!DOCTYPE' as inert text (CDATA scripts, comments). Removed; ModelParseExceptionMapper now turns parser rejections into a clean 400 without leaking internals. Regression fixture proves CDATA doctype text uploads fine - JWT audience was never actually enforced: smallrye reads mp.jwt.verify.audiences (plural), all profiles used the singular key. Renamed in all four profiles; negative tests (missing/wrong aud -> 401) lock the enforcement in. Tests: 362 green Infra/docs: - make setup bootstraps frontend/.env (fresh clones ran the frontend in desktop mode against a web backend) - Released desktop jars are now a real artifact: db-kind is fixed at build time, so release.yml builds pro-a-*-desktop.jar with the desktop profile; README/properties comments corrected - pre-push fallback emits one path per line (it silently skipped all frontend checks before) - ARCHITECTURE.md frontend tree updated to the post-branch reality Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…id, polish - All Tailwind utilities now use the tw: prefix (components.json prefix + regenerated ui components + rewritten feature files). Vuetify ships unlayered !important utilities with identical names (.border, .rounded-lg, runtime .bg-primary) that overrode shadcn styling - badges rendered Vuetify light-blue, buttons lost hover, borders broke. Verified in the built CSS and in the running app - Portaled layers (dialog/select/dropdown/tooltip/sheet) raised to tw:z-[2400] so they stack above Vuetify's app bar; exceptions documented in docs/UI-MIGRATION.md - C8 import sent the project id where the backend expects a project VERSION id - imports in web mode hit the new authorization check and failed. Now resolves the active version id - 401 auto-logout also closes any open auth dialog - Live field validation restored (reward-early-punish-late watchers) - Dialogs get sr-only DialogDescriptions (Reka a11y warnings gone) - setMode.mjs no longer rewrites the production application.properties - SignIn height accounts for Vuetify's app bar (no phantom scrollbar) - prettier scope aligned across hook/CI/scripts (+ .prettierignore) - docs/IMPROVEMENTS.md committed (was referenced but untracked) lint:check, format:check, build green; flows re-verified in the running app via Playwright. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ADR-0001: replace the homegrown identity stack with Keycloak/OIDC (quarkus-oidc bearer verification, oidc-client-ts PKCE flow, local user provisioning via CurrentUserService); authorization stays in the application. Evidence: the June 2026 review found exploitable defects exactly in the self-built layer. ADR-0002: framework-free diagram core as yarn workspace packages, consolidate rendering on diagram-js (port the JointJS map, elkjs layout), TS relation detection kept honest against the Java implementation via a shared conformance fixture suite; VS Code extension consumes the core via a workspace adapter. Sequenced after ADR-0001. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keycloak 26.6 on port 8181 via docker-compose; realm 'proa' with public PKCE client proa-frontend, realm roles User/Admin (User is default on registration), registration + password reset enabled, short access tokens (5m) with SSO session, brute-force protection, and two dev users (admin@proa.local/admin, user@proa.local/user). Verified: realm imports and OIDC discovery responds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- oidc-client-ts 3.5.0: Authorization Code + PKCE against the proa realm; session in sessionStorage via the library (userToken/userRole no longer persisted by the store - single source of truth) - Router guard (web mode) lazily initializes auth and redirects unauthenticated users to Keycloak; new /signin-callback view; desktop mode never loads the OIDC machinery (separate chunk) - 401 interceptor now clears auth state and re-enters the OIDC flow - Removed: SignIn view, CreateAccount, ChangePassword, api/auth (login/register) - registration, credentials and password reset live in Keycloak now; profile dialogs show email read-only with an SSO hint and link to the Keycloak account console - Roles derived from realm_access.roles in the access token - i18n: new SSO keys (en/de), ~25 dead auth keys removed lint:check, format:check, build: green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…th (ADR-0001) - quarkus-oidc (service type) verifies bearer tokens; realm roles map via realm_access/roles; issuer enforced (audience deliberately not: Keycloak public-client tokens carry aud=account - documented) - New request-scoped CurrentUserService: provisions the local UserTable row on first authenticated request (email/name claims), syncs the role from the token; replaces every jwt userId-claim parse - Deleted: TokenService, AuthenticationResource (login/register), lockout + AuthenticationRepository, AdminInitializer, bucket4j rate limiting, elytron/bcrypt, jjwt, generate-keys.sh and runtime key handling; UserTable lost password/failedLoginAttempts; self-service email changes return 400 (identity provider owns email) - Test profiles: desktop bulk runs with OIDC tenant disabled; web-mode profile verifies against the checked-in test public key (no container): 401/403/200 + provisioning and role-sync tests - Makefile/README/deploy.yml updated: no key generation step; web-mode dev needs 'make auth-up'; prod requires QUARKUS_OIDC_AUTH_SERVER_URL and VITE_OIDC_* repo vars Tests: 336 green (net deletion of the homegrown-auth suite). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Parallel first requests of a freshly logged-in user each created a
local row (no unique constraint on email) -> NonUniqueResultException
on every subsequent lookup. UserTable.email is now unique and
CurrentUserService recovers from a lost insert race by re-reading
the winner's row; no outer transaction so the constraint violation
cannot poison caller work
- dev/desktop H2 profiles pin default-schema=PUBLIC (they inherited
the prod ${STAGE:local} default and spammed schema-not-found DDL
warnings)
Verified live: Keycloak login -> exactly one provisioned user with
role/names from token claims; logout ends the SSO session. Backend
suite green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Identity is Keycloak's domain; the app's domain is project membership. Removes ManageUsers/admin endpoints/local profile editing and the app-level Admin role; adds pending invitations resolved at first login - invitees no longer need to have logged in before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- deploy.yml fails fast when web mode is deployed without the VITE_OIDC_* repo variables (previously baked empty values) - backend/.gitignore re-ignores legacy generated JWT keys so old checkouts cannot accidentally track them - make db-reset scoped to the db service (no longer destroys the Keycloak realm); Makefile help texts tell the truth about Docker - ARCHITECTURE.md/UI-MIGRATION.md updated to the post-ADR-0001 state (authservice/startup gone, api/auth modules, sign-in via Keycloak) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- UserTable identity key is now the immutable oidcSubject (unique);
email demoted to synced profile data (recycled addresses must not
inherit the old owner's account - review finding). Legacy rows are
claimed exactly once via guarded UPDATE on the owner's next
verified login; recycled emails get a fresh row
- New ProjectInvitationTable + invitation lifecycle: inviting an
unknown email stores a pending invitation (idempotent); known email
becomes a membership immediately; CurrentUserService redeems
pending invitations on login - only with email_verified=true (an
unverified self-registration must not collect invitations, nor
claim a legacy row)
- New endpoints: GET/DELETE /api/project/{id}/invitation[/{invId}]
(owner-only); contributor POST returns MEMBER_ADDED vs
INVITATION_PENDING; project deletion cleans up its invitations
- Removed per ADR-0003: admin user endpoints (list/patch/delete),
self-PATCH profile (Keycloak account console owns profile data)
- Race-safety: unique (user,project) on memberships, PESSIMISTIC_WRITE
on redemption, guarded claim UPDATE; 31 new tests cover the races,
recycling and the REST lifecycle
Tests: 372 green (+36).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ADR-0003) - Deleted ManageUsers view/route/AppBar button, EditUserDialog, EditProfileDialog and the requiresAdmin gating; ProfileDialog is read-only with the Keycloak account-console link - ProjectDetailDialog: 'Invite' distinguishes member-added vs invitation-sent, shows pending invitations with revoke (shadcn, owner errors via snackbar); api/projects gained inviteMember/ getInvitations/revokeInvitation, api/users slimmed to getCurrentUser - OIDC fixes from the adversarial review: redirectOnce lock released on settle (browser-Back no longer bricks sign-in), 401 redirect loop breaker (sessionStorage marker, max 2 attempts/30s), silent renew error retried once before the session lapses, original AxiosError preserved when Keycloak is unreachable, transient selectedDialog no longer persisted lint:check, format:check, build: green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- application.properties: prod datasource no longer hardcodes the
Azure Postgres host - fully env-driven via QUARKUS_DATASOURCE_URL/
USERNAME/PASSWORD (also removes the review's 'dev and prod share one
Azure DB/login' coupling). default-schema=${STAGE:local} kept as a
generic optional schema selector
- deploy.yml: replaces Azure ACR login + azure/webapps-deploy with a
vendor-neutral container publish to GitHub Container Registry
(ghcr.io/<repo>:dev|prod + :sha). The deploy target is now
decoupled - the image is published, where it runs is a separate ops
decision that supplies QUARKUS_DATASOURCE_* and
QUARKUS_OIDC_AUTH_SERVER_URL. ADR-0001 frontend .env guard preserved
- README: vendor-neutral managed-Postgres fuzzystrmatch note; also
drops the Gemini line from the settings docs (the feature itself is
removed in the companion commit; it returns later via MCP)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The process-description AI generator called Google's API directly from the browser with a key fetched from /api/settings - the long-standing client-side-secret finding. Removed entirely; an AI description feature will be re-added later through an MCP server instead. Frontend: drop @google/generative-ai; remove the generate-description affordance and its dead error/loading state in ProcessList; remove the Gemini API-key section from SettingsDrawer; drop geminiApiKey from the Settings type, the ProcessMap settings backfill and the i18n keys. Backend: drop geminiApiKey from the Settings entity/table/mapping and its test assertions; Camunda Modeler/Operate settings are untouched. Note: prod hibernate generation=update does not drop columns, so the existing gemini_api_key column lingers harmlessly until a real migration; no data action needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ProjectOverview: tiles -> Card, version v-select -> Select, the three dialogs -> Dialog (delete-confirm keeps the XSS-safe <i18n-t> slots) - ProjectDetailDialog: outer dialog/card -> shadcn; the project-invitation UI and its api calls preserved unchanged - ProcessList: toolbar/list/FABs/dialogs -> shadcn; v-file-input -> styled native file input; v-progress-* -> Progress/Loader2; BPMN upload/parse logic and api/processModels calls untouched - ProcessTreeNode: recursive list-group -> div rows with local expand state - PageNotFound: centered shadcn layout - New ui/progress component (CLI, pins restored) Vuetify shell + global snackbar intentionally untouched (migrated last). Vuetify grep over the 5 files: 0 hits. lint/format/build green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CamundaCloudImport: toolbar/list/checkboxes/dialogs/FABs -> shadcn; email filter v-menu -> Popover; api/camundaCloud calls intact (importProcessModels still passes the project VERSION id) - ProcessModel + ProcessDetailDialog: Vuetify chrome -> shadcn; the bpmn-js viewers themselves untouched - ProcessMap chrome (Toolbar/Sidebar/Legend/LegendItem/NavigationButtons) -> shadcn; sidebar is a non-modal fixed panel (must not dim the canvas) - ProcessMap.vue: only the Vuetify chrome migrated (loading, mouse-following tooltip, wrapper). The ENTIRE JointJS canvas (paper, graph, element classes, zoom/pan/layout, persistence) left untouched for the diagram-js extraction (ADR-0002) - New ui/popover (tw:z-[2400], pins restored) Vuetify shell + snackbar still intentionally present (migrated next). Vuetify grep over the 9 files: 0 hits. lint/format/build green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Default/AppBar/View/SettingsDrawer shell migrated to shadcn/Tailwind: v-app/v-main -> flex layout; v-app-bar -> sticky header; nav drawer and SettingsDrawer -> Sheet; language menu -> DropdownMenu - Global snackbar -> vue-sonner: store.showSnackbar keeps its (message, type) signature, body now calls toast.*; dead snackbar state and SnackbarConfigs removed - Vuetify fully removed: vuetify, vite-plugin-vuetify, @mdi/font, webfontloader, roboto-fontface, @types/webfontloader deps gone; plugins/vuetify.ts + webfontloader.ts, styles/settings.scss + global.css deleted; vuetify() out of vite.config; tsconfig types pruned. vue-sonner pinned 2.0.9 - Header fixed at 64px and <main> at calc(100vh-4rem) to preserve the definite-height ancestor the JointJS/bpmn-js canvases depend on - shadcn.css left as-is: Tailwind preflight enabling is a deliberate separate follow-up Typography now uses Tailwind's default sans (Roboto was Vuetify's). No v-* / Vuetify left except stale comment lines in shadcn.css. lint/format/build green; canvases verified next in the running app. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Without preflight there was no base element reset: native <button> chrome showed through ghost buttons and there was no base font-family (everything rendered in the browser's serif default). Preflight is imported in layer(base); utilities stay unlayered so they keep winning by specificity. Verified in the running app: sans-serif typography and clean header icon buttons. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three issues surfaced when rendering the map with real data (first time this session); none were the @joint version skew first suspected: 1. Crash in @joint/layout-directed-graph: its toGraphLib builds the graphlib graph via setEdge(source.id, target.id), silently creating a phantom node for any endpoint that is not a real element, then crashes in importElement (getCell -> undefined). A single link ending at a bare point also aborts its cell loop (it uses break, not continue). Guard before layout: drop links whose endpoints are missing/not real elements - they cannot be routed on the map anyway. 2. Canvas height collapsed to 0 (regression from the shadcn shell migration): .full-screen-below-toolbar used height: calc(100% - 64px), but percentage heights no longer resolve because the routed <main> is a flex-1 item inside a min-h-screen column (indefinite for percentage children). Switched to a viewport-based calc(100vh - 128px). 3. View.vue: tidy the arbitrary value to calc(100vh_-_4rem). Verified in the running app (Keycloak + backend + Vite): uploaded a BPMN, opened the map, the process node renders with all ports. Known minor nit: auto-fit on first load of a single isolated node doesn't recenter (manual fit works) - left for the diagram-js renderer extraction (ADR-0002) that replaces this layer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review findings: - HIGH: vue-sonner ships its stylesheet separately and does no runtime style injection, so the toaster (store.showSnackbar -> toast) rendered with no positioning/background/animation. Import vue-sonner/style.css in main.ts. Verified: 98 data-sonner rules now in the bundled CSS. (My E2E missed this - toasts flashed but I didn't inspect their style.) - sass was only used by the deleted Vuetify settings.scss; removed from devDependencies and pruned from the lockfile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ling Review found the docs stale against this branch's changes: - UI-MIGRATION.md: migration is COMPLETE - all areas shadcn, snackbar vue-sonner, Vuetify removed, preflight enabled; removal checklist ticked; only the JointJS map canvas remains (ADR-0002). Optional follow-ups listed (canonicalize shadcn.css, revert z-[2400], map auto-fit nit) - ARCHITECTURE.md: plugins no longer Vuetify; UI-migration deviation marked complete; Gemini note removed; deploy bullet now GHCR/decoupled - IMPROVEMENTS.md: mark the Gemini-key-in-browser and Azure-shared-DB action items resolved on this branch; coexistence note updated to 'Vuetify fully removed' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Large, end-to-end overhaul of ProA developed over several autonomous sessions. It is one PR by request; it is best reviewed commit by commit (37 atomic, individually-green commits). Architecture decisions are recorded under
docs/adr/.What's in here
Toolchain modernization
annotationProcessorPaths, JaCoCo 0.8.15.Guardrails
exit 1andcore.hooksPathwas never set): fast pre-commit (lint/format), pre-push (affected test suites).Frontend ChecksCI workflow (Prettier/ESLint/type-check/build);Backend Teststriggers on rootpom.xmltoo; Dependabot for Maven/npm/Actions.Local dev setup
make setup+make backend/backend-pg/frontend/auth-up;docker-composewith PostgreSQL 17 (+fuzzystrmatch) and Keycloak;.env.example; rewritten README.Security & authentication — ADR-0001 (Keycloak/OIDC)
quarkus-oidc(backend) +oidc-client-tsPKCE (frontend). Authorization stays in the app.v-html), XXE (BPMN parsing hardening), fail-openapp.modedefault (now fail-closed), and a missing JWTaudclaim. Identity is keyed on the immutable OIDC subject (email-recycling takeover prevented).Project invitations — ADR-0003
Gemini removed
@google/generative-aifeature (API key reached the browser) is removed entirely; it returns later as an MCP-backed, server-side feature.Deployment decoupled from Azure
QUARKUS_DATASOURCE_*andQUARKUS_OIDC_AUTH_SERVER_URL).Vuetify → shadcn-vue (complete)
vue-sonner, Tailwind preflight enabled. Only the JointJS process-map canvas remains, intentionally deferred to the diagram-js extraction (ADR-0002).Verification
./mvnw verify— 372 tests green.yarn lint:check/format:check/build— green.rsaPrivateKey.pemis in git history and old jars (the runtime no longer uses it after ADR-0001, but treat it as compromised if ever deployed).QUARKUS_OIDC_AUTH_SERVER_URL+ theVITE_OIDC_*repo variables, register deployed origins as redirect URIs.sslmode=requirein the prod JDBC URL).Deferred follow-ups
hibernate generation=update),vue-i18nlegacy→composition API, Pinia god-store split, optionalshadcn.csscanonicalization /z-[2400]revert (seedocs/UI-MIGRATION.md).🤖 Generated with Claude Code