link-stack/CLAUDE.md

115 lines
6.4 KiB
Markdown
Raw Normal View History

2026-02-13 18:34:13 +01:00
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is a monorepo for CDR Link - a Zammad addon and supporting services built by the Center for Digital Resilience. It adds Signal, WhatsApp, and voice channel support to Zammad via a custom `.zpm` addon package, along with a standalone WhatsApp bridge service. It uses pnpm workspaces and Turborepo for orchestration.
**Tech Stack:**
- Zammad 6.5.x as the core helpdesk platform
- Ruby (Rails initializers, controllers, models, jobs) for the Zammad addon
- TypeScript/Node.js for build tooling and the WhatsApp bridge
- CoffeeScript for Zammad legacy UI extensions
- Vue 3 for Zammad desktop UI extensions
- Docker for containerization
- PostgreSQL, Redis, Memcached as backing services
## Project Structure
```
apps/
bridge-whatsapp/ # Standalone WhatsApp bridge (Hapi.js + Baileys)
packages/
zammad-addon-link/ # Zammad addon source (Ruby, CoffeeScript, Vue, TS)
src/ # Addon source files (installed into /opt/zammad/)
scripts/build.ts # Builds .zpm package from src/
scripts/migrate.ts # Generates new migration stubs
docker/
zammad/ # Custom Zammad Docker image
Dockerfile # Extends zammad/zammad-docker-compose base image
install.rb # Extracts addon files from .zpm at build time
setup.rb # Registers addon packages at container startup
addons/ # Built .zpm files (gitignored, generated by turbo build)
compose/ # Docker Compose service definitions
```
## Common Development Commands
```bash
pnpm install # Install all dependencies
turbo build # Build all packages (generates .zpm files)
npm run docker:zammad:build # Build custom Zammad Docker image
npm run docker:all:up # Start all Docker services
npm run docker:all:down # Stop all Docker services
npm run docker:zammad:restart # Restart railsserver + scheduler (after Ruby changes)
npm run update-version <version> # Update version across all packages
npm run clean # Remove all build artifacts and dependencies
```
## Zammad Addon Architecture
### Addon Build & Deploy Pipeline
1. `turbo build` runs `tsx scripts/build.ts` in `packages/zammad-addon-link/`
2. Build script base64-encodes all files under `src/`, produces `docker/zammad/addons/zammad-addon-link-v{version}.zpm`
3. `docker/zammad/Dockerfile` builds a custom image:
- Copies `.zpm` files and runs `install.rb` to extract addon files into the Zammad directory tree
- Rebuilds Vite frontend (`bundle exec vite build`) to include addon Vue components
- Precompiles assets (`rake assets:precompile`) to include addon CoffeeScript
- Applies `sed` patches (OpenSearch compatibility, entrypoint injection)
4. At container startup, `setup.rb` registers the addon via `Package.install()` and runs migrations
### How the Addon Extends Zammad
**New files (no upstream conflict risk):** Controllers, channel drivers, jobs, routes, policies, library classes, views, CSS, SVG icons, frontend plugins. These add Signal/WhatsApp/voice channel support.
**Replaced stock files (HIGH conflict risk - must be manually merged on Zammad upgrades):**
- `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/ArticleReply.vue` - Adds channel whitelist filtering via `cdr_link_allowed_channels` setting
- `app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue` - Adds Signal notification recipient field
- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue` - Adds Signal column to notification matrix
- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/types.ts` - Extended notification types
- `app/assets/javascripts/app/controllers/_profile/notification.coffee` - Signal notification prefs (legacy UI)
- `app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee` - Signal column (legacy UI)
- `app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee` - Notification matrix mixin
- `app/assets/javascripts/app/views/generic/notification_matrix.jst.eco` - Notification matrix template
- `app/assets/javascripts/app/views/profile/notification.jst.eco` - Notification profile template
**Runtime monkey-patches (HIGH conflict risk):**
- `config/initializers/opensearch_compatibility.rb` - Prepends to `SearchIndexBackend._mapping_item_type_es()` to replace `'flattened'` with `'flat_object'` for OpenSearch
- `config/initializers/cdr_signal.rb` - Injects `after_create` callbacks into `Ticket::Article` and `Link` models
- `config/initializers/cdr_whatsapp.rb` - Injects `after_create` callback into `Ticket::Article`
**Dockerfile-level patches:**
- `lib/search_index_backend.rb` - `sed` replaces `'flattened'` with `'flat_object'`
- `/docker-entrypoint.sh` - `sed` injects addon install commands after `# es config` anchor
- `contrib/nginx/zammad.conf` - Adds `/link` proxy location in embedded mode
### Key Zammad API Dependencies
The addon depends on these Zammad interfaces remaining stable:
- `Channel::Driver` interface (`fetchable?`, `disconnect`, `deliver`, `streamable?`)
- `Ticket::Article` model callbacks and `Sender`/`Type` lookup by name
- `Link` model and `Link::Type`/`Link::Object`
- `SearchIndexBackend._mapping_item_type_es` method
- `Transaction` backend registration system
- `Package.install(file:)` / `Package.uninstall(name:, version:)` API
- `CreatesTicketArticles` controller concern
- Policy naming convention (`controllers/<name>_controller_policy.rb`)
## Zammad Development Notes
- After changing any Ruby files, restart railsserver and scheduler: `npm run docker:zammad:restart`
- The addon must be rebuilt (`turbo build`) and the Docker image rebuilt (`npm run docker:zammad:build`) for changes to take effect in Docker
- Use `/zammad-compat <version>` to check upstream Zammad for breaking changes before upgrading
- The current Zammad base version is set in `docker/zammad/Dockerfile` as `ARG ZAMMAD_VERSION`
## Docker Services
Defined in `docker/compose/`:
- **zammad.yml**: zammad-init, zammad-railsserver, zammad-nginx, zammad-scheduler, zammad-websocket, zammad-memcached, zammad-redis
- **bridge-whatsapp.yml**: bridge-whatsapp
- **postgresql.yml**: postgresql
- **signal-cli-rest-api.yml**: signal-cli-rest-api
- **opensearch.yml**: opensearch + dashboards