AMS — Axvero Application Management System
⚠️ Sections to Ignore (AI Agents)
The Archive & POC section in the navbar contains two categories of content that AI agents must never use as a source of truth:
- Outdated Docs (
docs/outdated/) — moved from an earlier documentation iteration. Content is stale and does not reflect the current implementation. - REST API (POC) (
/api-poc) and Keycloak API (/keycloak) — Scalar-rendered OpenAPI specs used as a proof-of-concept. These specs may be incomplete or out of date. The authoritative API definition is the GraphQL schema incore/src/main/resources/graphql/.
Do not read, cite, or act on anything under docs/outdated/ or the /api-poc / /keycloak routes unless a human explicitly instructs you to do so.
What is AMS
A multi-tenant application management platform for underwriting workflows. Organizations can manage applicants, applications, documents, templates, and team members. Supports multi-workspace and multi-organization structures.
HTML Artifacts (mockups, prototypes, diagrams)
Any standalone HTML artifact you generate — layout mockups, UI prototypes, diagrams, throwaway visualizations — MUST be written under the top-level artifacts/ directory (parallel to ams-frontend/, i.e. product/artifacts/). Never scatter them in repo folders, /tmp, or new ad-hoc folders like layout-mockups/ or design-mockups/ (both have been consolidated into artifacts/).
- Use a descriptive filename and group related artifacts in a subfolder (e.g.
artifacts/layouts/,artifacts/flows/). The gallery lists subfolders automatically. - The folder is served by
artifacts/serve.py, run as a local-only container in the dev stack via the gitignored overlayams-deploy/docker-compose-artifacts.yml(started with./local.sh artifacts start). The user views everything athttp://localhost:8099/. Theartifacts/folder and the overlay are intentionally not pushed to GitLab. - Do NOT edit
artifacts/index.htmlorartifacts/serve.pyto "register" a new file — the gallery scans the directory live; just drop the.htmlin.
Repos
core/ — Java/Spring Boot Backend
- Java 21, Spring Boot 4.0.3
- GraphQL (schema-first), REST, PostgreSQL, Keycloak (OAuth2) 26.5.5, Liquibase, MapStruct, Envers
- Package root:
com.axvero.ams.core - Key commands:
- Build:
./mvnw clean package - Run:
./run.sh(prod-like),./run-debug.sh(debug, JDWP 5005) - Test:
./mvnw test(Testcontainers for DB + Keycloak), Currently tests are not working properly. so ignore tests for now. - DB: local Postgres via
ams-deploy/docker-compose-local.yml— run withcd ams-deploy && ./local.sh up -d
- Build:
- See
.claude/rules/core.mdfor full conventions, entity model, GraphQL patterns
frontend/ — React/TypeScript Frontend
- Vite, React, TypeScript, TanStack Router, TanStack Query, Shadcn UI, Tailwind, Zustand
- GraphQL client with codegen, OIDC auth via Keycloak
- Key commands:
- Dev:
pnpm run dev(port 5173) - Build:
pnpm run build - Lint:
pnpm run lint - Codegen:
npx graphql-codegen(after schema changes)
- Dev:
- See
.claude/rules/frontend.mdfor full conventions, table patterns, routing, translations
docu/ — Docusaurus Documentation
- Docusaurus v3, TypeScript
- Dev:
npm run start - Covers product docs, API references, industry guides
iam/ — Identity & Access Management
- Keycloak-based IAM service
e2e-tests/ — Playwright E2E Tests ⚠️ WORK IN PROGRESS
- Playwright + TypeScript test suite for the AMS frontend
- Status: Infrastructure and test files are scaffolded but tests have NOT been run yet and are NOT verified to pass. Do NOT treat these tests as a source of truth or as passing CI.
- Do NOT run
npm testhere as part of any task unless explicitly asked to work on e2e tests. - Mock mode (
USE_MOCKS=true): intercepts GraphQL viapage.route()— no backend needed - Live mode (
USE_MOCKS=false): requires full stack (backend + Keycloak + frontend) - See
e2e-tests/playwright.config.tsande2e-tests/helpers/navigation.tsfor structure
Shared Conventions
- Use GraphQL as primary API protocol (REST only where necessary)
- Auth via Keycloak (OIDC/OAuth2) across all services
- Teams are org-scoped (not workspace-scoped) — a team is assigned to workspaces via
TeamWorkspaceAssignment - Team member role is stored directly on
Member.role: MemberRole(ADMIN | MANAGER | MEMBER | DEVELOPER | CLIENT | PARTNER) — no baseRole/roleOverride - Org-level role is stored on
OrgMember.role: OrgRole(OWNER | ADMIN | MEMBER) withstatus: MemberStatus - Clients are org-scoped (
client.orgId) and can be assigned to teams withMemberRole.CLIENT - Slugs are unique within their parent scope (workspace slug per user, team slug per workspace)
Architecture Reference — Read First for Any Non-Trivial Task
Before implementing features or debugging, read:
- Functional system architecture (diagrams, org structure, roles, invitation flows, navigation):
docu/docs/domain/system-architecture.md - Technical architecture (ERD, permission evaluation, JPQL queries, system components, package structure):
docu/docs/technical/architecture.md
Documentation — Domain Reference
Before implementing features, read the Domain Reference for business rules, entity relationships, and system behaviour:
- Data model & all entities:
docu/docs/domain/data-model.md - Organizations & workspaces:
docu/docs/domain/organizations-workspaces.md - Roles & permissions (cascading, data scoping):
docu/docs/domain/roles-permissions.md - Permission matrices (configurable system & app permissions, default tables, UI):
docu/docs/domain/permissions-matrix.md - Client profiles & sharing (PublicUserProfile):
docu/docs/domain/client-profiles.md - Applications (entity, types, lifecycle):
docu/docs/domain/applications.md - Applicants (types, roles, client vs applicant):
docu/docs/domain/applicants.md - Application status & workflow (custom statuses, engine, history):
docu/docs/domain/status-workflow.md - Document system (5 layers, snapshot rule, review flow):
docu/docs/domain/document-system.md - Wizard steps (step types, custom forms, translations, split-panel editor):
docu/docs/domain/wizard-steps.md - Comments & messaging (internal vs external, categories, action log):
docu/docs/domain/comments-messaging.md - Notifications (flow, triggers, message format):
docu/docs/domain/notifications.md - Subscription & Billing (org plans, personal plans, Stripe, lifecycle, superadmin platform):
docu/docs/domain/subscription.md - LDAP / Directory Integration (Keycloak federation, org scoping, test connection, Docker networking):
docu/docs/domain/ldap.md - Patent Research (EPO OPS integration, per-org PDF cache via FileStorageService, PDFBox page merge, quota model, Espacenet ToS rationale):
docu/docs/domain/patent-research.md
Feature Guides
-
See
docu/docs/ai/claude/rules/frontend-build.mdfor build errors vs. warnings, what to ignore, knownas anypatterns, missing codegen types, and how to confirm the build is clean -
See
docu/docs/ai/claude/rules/notifications.mdfor the full notification system (bell icon, panel, persistence, message format, where to fire notifications) -
See
docu/docs/ai/claude/rules/messages.mdfor the redesigned Messages system (2026-07) — conversation inbox + unified timeline (global Variant B page, per-app tab), shared CommentFilterBar with activity opt-in, two-action app/category menus, workspaceApplicationComments stream (bytea search pitfall), viewport-lock + feed-anchoring gotchas -
See
docu/docs/ai/claude/rules/core-application-status.mdfor the ApplicationStatus domain model, all renamed/deleted types from the TemplateStatus refactor, GraphQL field names, frontend hook names, and common pitfalls -
See
docu/docs/ai/claude/rules/access-model.mdfor the AUTHORITATIVE access model (2026-06 redesign) — the singleAccessService.canrule (union of all the user's roles' capabilities, NO OWNER bypass, SUPERADMIN-only), evaluator-as-adapter, Team⇄Workspace 1:1 (team.workspace_id), org-scoped capability matrix (org_role_permission+orgRolePermissionMatrixGraphQL), narrow OWNER (billing only),ClientRoleremoval, Access Tiers (need-to-know locks:access_tier/access_tier_grant, criteria client/type/template, grant-only),useAccess()frontend hook, Roles-page capability editor (replaced the two deleted matrix pages), tier badges, and migrations 0147–0150. Supersedespermissions.md/permissions-matrix.md/roles-permissions.mdwhere they disagree. -
See
docu/docs/ai/claude/rules/permissions.mdfor the permission matrix system — entities, services, @PreAuthorize patterns, frontend hooks, how to add a new permission, and common pitfalls (⚠️ partially superseded byaccess-model.md— matrix is now org-scoped, not per-workspace) -
See
docu/docs/ai/claude/rules/system-translations.mdfor the System Translations feature — DB override pipeline, Zustand store, useTranslation hook, admin page, adding keys, common pitfalls -
See
docu/docs/ai/claude/rules/ai-assistant.mdfor the AI Assistant feature — OrgAIConfig entity, AIProvider abstraction, chat panel, Zustand store, context injection (AI Translate), seeding pitfalls, DB constraint fix -
See
docu/docs/ai/claude/rules/async-jobs.mdfor the Async Job system — background task infrastructure,AsyncJobentity,AsyncJobServicelifecycle,@Asyncwiring pattern,useJobProgresshook,JobProgressDisplaycomponent, common pitfalls -
See
docu/docs/ai/claude/rules/help-center.mdfor the Help Center AI chat page —HelpCenterChatService,platform-guide.txtmaintenance,HELP_CENTERChatMode,MarkdownMessagelink resolver, session history filtering, common pitfalls -
See
docu/docs/ai/claude/rules/subscription.mdfor the Subscription & Billing system — org/personal plans,SubscriptionPlanentity,OrgSubscriptionService/UserSubscriptionService, Stripe webhook controller,SubscriptionLifecycleScheduler,<UpgradeDialog>,<PlanBadge>, superadmin admin pages, common pitfalls -
See
ams-docu/docs/ai/claude/rules/e2e.mdfor the Playwright e2e test project atproduct/ams-e2e/— live-mode tests (Keycloak ROPC + backend + Mailpit), two-project config with setup → chromium, OIDC storageState pattern, page-object conventions, BANK demo seed contents, Mailpit action-token flow, and the common pitfalls (custom sign-in form, action-email subject, split-panel card grids, sign-out in header ProfileDropdown, sidebar workspace-switcher selector collision). Read this before writing any new e2e spec. -
Use
/a-skillto create or update a skill — covers naming conventions, four-file pattern, templates, checklist, and rename instructions -
See
.claude/agents/workflow-statuses-feature.mdfor template statuses, status transitions matrix, ReactFlow workflow builder, application workflow display, WorkflowEngine, system handlers, and all known pitfalls -
See
.claude/agents/wizard-steps-feature.mdfor the wizard steps split-panel editor — step types, detail components, custom form schema + JSON editor, translation system, DnD reordering, layout pitfalls -
See
.claude/skills/a-ams-deploy/SKILL.mdfor the full deployment reference —ams-deployrepo layout, Portainer GitOps stacks (develop + production), GitFlow CI/CD pipeline,keycloak-config-clirealm import, all Portainer env vars, rollback procedure, and known pitfalls. Read this before touching any CI pipeline, docker-compose file, Portainer stack, or Keycloak realm config. -
See
.claude/skills/a-billing-go-live/SKILL.mdfor the ONE-TIME Stripe/billing production activation checklist — USER tasks (account activation, live keys, dashboard-only dunning/branding toggles, final EUR prices, legal) vs CLAUDE tasks (live-mode API config, catalog sync, webhook registration via API, real-money smoke test), plus the webhook/security gotchas learned in test mode. Read before the first production release that takes payments; complements/a-prod-release. -
See
ams-docu/docs/ai/claude/rules/local-dev.mdfor the local development setup —docker-compose-local.yml,local.sh, optional service profiles,application-local.yamlSpring config, port map, and common pitfalls. Read this before modifying local Docker infra or native app config. -
See
docu/docs/ai/claude/rules/ldap.mdfor the LDAP/Directory Integration —OrgLdapConfigentity,KeycloakLdapService, realm-level federation + org scoping viafederationLink,addEnabledMapper, Jackson mixin for admin client version mismatch,TrustAllSSLSocketFactory, Docker networking pitfall -
See
docu/docs/ai/claude/rules/realtime-subscriptions.mdfor realtime GraphQL subscriptions —PostgresPubSubLISTEN/NOTIFY,RealtimePublisher→@TransactionalEventListener(AFTER_COMMIT),RealtimeTopics,@SubscriptionMappingcontroller pattern,RealtimeAuthHelper(do NOT readSecurityContextHolder), 8KBpg_notifylimit,useGraphQLSubscriptionNewwithinvalidateKeysOnReconnect, 5-min safety-net polling -
See
docu/docs/ai/claude/rules/layout.mdfor the split-panel layout system — 7 primitives insrc/components/layout/split-panel/, mail-flush 2-column and 3-column templates, theembeddedprop,SidebarNav'sstretchprop,react-resizable-panelsv2 pinning, hover/selected tokens, height/flex rules. Read before building or migrating any list+detail page. -
See
.claude/skills/a-layout-application-details/SKILL.mdfor the application detail page layout — variation on the 3-column embedded chrome with a status/assignee/lock strip slot above the outlet, mobile sticky top bar, breadcrumb placement,SidebarNavpillTabsmobile variant. Read before touchingsrc/features/applications/detail/index.tsxor its tabs. -
See
.claude/skills/a-view-modes/SKILL.mdfor the application detail page view-mode system — two independent Zustand flags (useFocusModeStore,useReadingModeStore) that progressively strip chrome to recover screen real estate. Stackable (4 user-visible states from 2 booleans). Reading mode is gated to the patent PDF tab and auto-exits on tab drift. Heights flow through the flex chain — no hardcoded100svh − Xremcalcs. Read before adding a new "expand"/"compact"/"presentation" mode anywhere in AMS so the chrome-collapse pattern (Zustand + ESC + unmount-cleanup + flex-chain height) is reused, not reinvented. -
See
docu/docs/ai/claude/rules/fees.mdfor the Fees subsystem — the three layers (catalogFeeCategory/FeeDefinition/presets/OrgVatRateConfig→ per-applicationApplicationFeewith the surcharge/discount/VAT fee math →FeePaymentoccurrence anchor →FeeReceipt+FeeReceiptAllocationpartial-payment model), the deliberate scope decisions (installments yes, overpayment/credit/cross-fee allocation NO — do not rebuild accounts-receivable),FeeProjectionService+summarize+ reminders (unifiedReminder+ opt-in attach-letter), invoice AI-indexing (FEE_INVOICE), the Fees-tab Overview anatomy (Fee roll-up / Occurrence card / Ledger / Invoice / Payment cards),markPaid-as-recordReceipt-wrapper, the one-time-occurrence refetch bug, hand-writtenTypedDocumentString(no codegen), and migrations 0154–0163 -
See
ams-docu/docs/ai/claude/rules/email-pdf.mdfor the Email & PDF Templates systems + the reminder bridge — PDF letters (PdfTemplatebody +letterheadHtml/footerHtml,TemplateVariableResolver{{vars}}/addressBlock/client.reference/locale formatting/org-shared client profile,TemplateRenderServiceA4@pagerunning-element header/footer that repeat per page + footer pinned + preview-vs-PDF modes + openhtmltopdf no-SVG,LetterGenerationService, DIN-5008 layout,PdfTemplateSeedHelper/LsgBrandingAssets), email templates (OrgEmailTemplatecontent wrapped inEMAIL_LAYOUT,EmailTemplateService,ReminderEmailService,EmailAttachmentbyte[], emailbuilder.js editor), and the unifiedRemindersystem (ReminderService.fire, opt-inattachLetterTemplateId). Migrations 0161–0163 -
See
.claude/skills/a-ai-document-rag/SKILL.mdfor the Document RAG feature —OrgDocumentRagConfigper-org embedding connector,EmbeddingModelFactoryBYOK + platform fallback (mirrorsChatModelFactory), indexing pipeline (DocumentIndexingTriggerAFTER_COMMIT →DocumentIndexingConsumer@Async→DocumentIndexingService@Transactional→DocumentSummarizationService), hand-rolledapplication_document_chunktable withvector(1536)HNSW + scope-filterable columns (NOT spring-ai'svector_store),DocumentChunkDaonative SQL with?::vectorcast +Locale.ROOT, fourDocumentAnalysisToolsexposed to the LLM,AISummaryCardat the top of the slot detail panel, JPQL projection pattern (findApplicationIdById/findWorkspaceIdById) for@Asynclazy-init avoidance, and the migration constraint sweep (0073 async_job_type, 0074 chat_mode). Read before working incom.axvero.ams.core.documentrag/,com.axvero.ams.core.document.ai/,DocumentAnalysisTools,AISummaryCard, or any Doc RAG settings page. -
See
ams-docu/docs/ai/claude/rules/frontend-mock.mdfor the/dev/shellredesign mock + the redesign port — the mock renders the SAME shared presentational components the live app uses (documents/components/documents-panel.tsxDocumentsPanel,create/components/upload-zone.tsx) fed by fixtures + local state (features/dev/shell-sandbox,application-detail-mock,documents-sandbox,docs-fixtures.ts), so a shared-component change updates BOTH mock and live; mock-only render-prop demos (DemoCommentThread,DemoAddDocumentButton/DemoMasterLibraryDialog) stand in for data-wired live components (CommentTab,AddFromMasterDialog) that can't run in the providerless sandbox; the redesign is the ONLY live Documents view now (classicview1/2/3removed); how to port mock UX deltas to the real app (and drop mock features that need backend, e.g. category filter); canonical upload =useUploadZoneController(drag-drop+browse+camera); typecheck viapnpm exec tsc -p tsconfig.app.json --noEmit(tsc -bflakyTS5083). Read before touching anything undersrc/features/dev/or the shared Documents redesign components. -
See
ams-docu/docs/ai/claude/rules/demo-org-investment.mdfor the Investment demo org + ETF Research feature — issuer-direct ETF connectors (per-orgOrgEtfConfig, SHARED cross-org catalog scraped from the iShares DE product sitemap via asyncSCRAPE_ETF_CATALOGjob), on-demand full-holdings ingestion (eager fetch-on-save, 24h TTL, per-orgOrgEtfHoldingsSnapshot+ ISIN-keyedetf_positionrows, weight-sum validation, raw file viaFileContext.ETF_HOLDINGS), theETF_RESEARCHapplication tab +EtfProviderAdapterSPI (Wave 1 = iShares only), theInvestmentDemoSeedervertical (position = one app per trade cycle, mandate carries recurring fees, WorkflowEngine status staging), and the pitfall table (graphqls enum sync, hardcoded frontend tab/connector lists, 1-based vs 0-based paging, OffsetDateTime DTOs, commons-csv 1.11.0 pin, iShares siteEntryPassthrough gate). Read before touchingams-core/.../etf/,seed/investment/, or the etf-research / etf-connector frontend features.
Skill Conventions
All skills live in .claude/skills/ and must be named with the a- prefix (e.g. a-validate, a-ai-assistant-feature). This prefix distinguishes owner-created skills from built-in Claude Code commands.
There are two kinds of skills:
- Action skills — a single
SKILL.mdwith step-by-step instructions for a repeatable task (e.g.a-validate,a-codegen,a-commit) - Feature skills — four companion files that together document a system component end-to-end:
docu/docs/domain/<feature>.md— user documentationdocu/docs/ai/claude/rules/<feature>.md— technical/architecture reference for AI agents.claude/agents/a-<feature>.md— agent definition (loaded by theAgenttool).claude/skills/a-<feature>/SKILL.md— skill entry point
To create or update a skill, use /a-skill. It contains the full template, checklist, and update/rename instructions.
Skill files are symlinked — .claude/skills/<skill>/SKILL.md and ams-docu/docs/ai/claude/skills/<skill>/SKILL.md point to the same file. One edit updates both. Never cp between them.
Agents Available
See .claude/agents/ for available agents:
-
complete-feature— full CRUD feature with listing + detail pages (frontend) -
simple-table— listing-only table feature (frontend) -
create-application-process— multi-step wizard form (frontend) -
a-messages— Messages system (conversation inbox + unified timeline, global + per-app, shared filter bar, unread tracking, deep links). Replaces the removedmessages-featureagent -
workflow-statuses-feature— template statuses (custom status CRUD, transitions matrix), ReactFlow workflow builder, and application detail workflow display (read-only flow + history tab) -
a-wizard-steps-feature— wizard steps split-panel editor: step types, custom form schema (JSON editor + live preview), translation system (per-locale, auto-derived keys), DnD reordering, detail components for all step types -
a-ai-assistant-feature— AI Config settings, global chat panel, AI Translate for wizard steps, Zustand store, context injection, provider abstraction (Claude + OpenAI) -
a-async-jobs-feature— async job infrastructure:AsyncJobentity,AsyncJobServicelifecycle,@Asyncwiring,useJobProgresshook,JobProgressDisplaycomponent; add new job types here -
a-help-center-feature— Help Center AI chat page:HelpCenterChatService,platform-guide.txtmaintenance,HELP_CENTERChatMode,MarkdownMessagelink resolver, session history filtering by chatMode -
a-subscription-billing-feature— Subscription & Billing system: org plans, personal plans, Stripe integration,SubscriptionLifecycleScheduler,<UpgradeDialog>feature gating,<PlanBadge>, org/personal billing pages, Axvero Platform superadmin pages (dashboard, plans editor, org management, email templates, schedules, Stripe config) -
a-local-dev— local development Docker Compose setup: infrastructure services, optional profiles,local.sh,application-local.yaml, port map, common pitfalls -
a-e2e— Playwright end-to-end tests atproduct/ams-e2e/: live-mode suite, ROPC auth + storageState, page-object conventions, Mailpit action-token flow, BANK demo seed contents, known selector pitfalls (custom sign-in form, split-panel card grids, header ProfileDropdown sign-out) -
a-layout— split-panel layout system: 7 primitives (SplitPanelShell,SplitPanelCard,SplitPanelPageHeader,SplitPanelColumn,SplitPanelHeader,SplitPanelBody,SplitPanelList/ListItem,SplitPanelEmpty), 2-column standalone + 3-column embedded (Invitations-style) templates,embeddedprop,SidebarNav'sstretchprop, resizable columns viareact-resizable-panelsv2, height/flex rules, hover/selected tokens. Read before migrating any list+detail page to the unified shell. -
a-fee— Fees subsystem: catalog (FeeCategory/FeeDefinition/presets/OrgVatRateConfig), per-applicationApplicationFee+ the surcharge/discount/VAT fee math,FeePaymentoccurrence anchor, theFeeReceipt+FeeReceiptAllocationpartial-payment model (installments, no overpayment, no credit/cross-fee allocation),FeeProjectionService/summarize/reminders, invoice AI-indexing, and the Fees-tab Overview anatomy -
a-email-pdf— Email & PDF Templates + the reminder bridge: PDF letters (PdfTemplatebody +letterheadHtml/footerHtml,TemplateVariableResolver,TemplateRenderServiceA4@pagerunning-element header/footer + preview-vs-PDF modes + openhtmltopdf no-SVG,LetterGenerationService, DIN-5008 layout,PdfTemplateSeedHelper/LsgBrandingAssets), email templates (OrgEmailTemplatecontent wrapped inEMAIL_LAYOUT,EmailTemplateService,ReminderEmailService,EmailAttachmentbyte[], emailbuilder.js editor), and the unifiedRemindersystem (ReminderService.fire, opt-inattachLetterTemplateId, fee-letter-scoped picker) -
a-frontend-mock— the/dev/shellredesign mock + the redesign port: mocked chrome (features/dev/shell-sandbox,application-detail-mock,documents-sandbox) rendering the SAME shared presentational components the live app uses (DocumentsPanel,upload-zone) fed by fixtures + local state, so shared-component edits update mock AND live; mock-only render-prop demos (DemoCommentThread,DemoAddDocumentButton/DemoMasterLibraryDialog) for data-wired components that can't run in the providerless sandbox; redesign is the only live Documents view (classicview1/2/3removed); port workflow (deltas to the real app, drop backend-needing mock features); canonical upload (useUploadZoneController);tsc -p tsconfig.app.json --noEmit(nottsc -b) -
a-demo-org-investment— Investment demo org (InvestmentDemoSeeder: wealth-management workspaces, mandate/position/research templates, staged workflows, seed-enabled ETF tab + connector) + ETF Research feature (issuer-direct provider adapters, shared catalog scrape, on-demand per-org holdings snapshots, application ETF Research tab, connector settings/hub pages)
Git Commit Convention
- Do NOT add
Co-Authored-Bylines to commit messages - Keep commit messages concise and descriptive
- Format: short summary line, then bullet points if needed