Add Claude .md and skill
This commit is contained in:
parent
1b5f85627c
commit
99b92fe4ce
3 changed files with 319 additions and 0 deletions
197
.claude/skills/zammad-compat/SKILL.md
Normal file
197
.claude/skills/zammad-compat/SKILL.md
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
---
|
||||||
|
name: zammad-compat
|
||||||
|
description: Check upstream Zammad for breaking changes before upgrading the addon
|
||||||
|
disable-model-invocation: true
|
||||||
|
argument-hint: "[target-version]"
|
||||||
|
allowed-tools: Bash(git clone *), Bash(git -C /tmp/zammad-upstream *)
|
||||||
|
---
|
||||||
|
|
||||||
|
# Zammad Upstream Compatibility Check
|
||||||
|
|
||||||
|
Check the upstream zammad/zammad repository for changes that could break or require updates to our Zammad addon (`packages/zammad-addon-link`).
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
- `$ARGUMENTS` - Optional: target Zammad version/tag/branch to compare against (e.g. `6.6.0`, `stable`). If not provided, ask the user what version to compare against. The current version is in `docker/zammad/Dockerfile` as the `ZAMMAD_VERSION` ARG.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. Read the current Zammad version from `docker/zammad/Dockerfile` (the `ARG ZAMMAD_VERSION=` line).
|
||||||
|
2. Clone or update the upstream Zammad repository:
|
||||||
|
- If `/tmp/zammad-upstream` does not exist, clone it: `git clone --bare https://github.com/zammad/zammad.git /tmp/zammad-upstream`
|
||||||
|
- If it exists, update it: `git -C /tmp/zammad-upstream fetch --all --tags`
|
||||||
|
3. Determine the version range. The current version is the `ZAMMAD_VERSION` from step 1. The target version is the argument or user-provided version. Both versions should be used as git refs (tags are typically in the format `X.Y.Z`).
|
||||||
|
|
||||||
|
## Checks to Perform
|
||||||
|
|
||||||
|
Run ALL of these checks and compile results into a single report.
|
||||||
|
|
||||||
|
### 1. Replaced Stock Files
|
||||||
|
|
||||||
|
These are stock Zammad files that our addon REPLACES with modified copies. Changes upstream mean we need to port those changes into our modified versions.
|
||||||
|
|
||||||
|
For each file below, diff the upstream version between the current and target version. Report any changes found.
|
||||||
|
|
||||||
|
**Vue/TypeScript (Desktop UI):**
|
||||||
|
- `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/ArticleReply.vue`
|
||||||
|
- `app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue`
|
||||||
|
- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue`
|
||||||
|
- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/types.ts`
|
||||||
|
|
||||||
|
**CoffeeScript (Legacy UI):**
|
||||||
|
- `app/assets/javascripts/app/controllers/_profile/notification.coffee`
|
||||||
|
- `app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee`
|
||||||
|
- `app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee`
|
||||||
|
- `app/assets/javascripts/app/views/generic/notification_matrix.jst.eco`
|
||||||
|
- `app/assets/javascripts/app/views/profile/notification.jst.eco`
|
||||||
|
|
||||||
|
Command pattern for each file:
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream diff <current-version> <target-version> -- <file-path>
|
||||||
|
```
|
||||||
|
|
||||||
|
If a file does not exist at either version, note that (it may have been added, removed, or renamed).
|
||||||
|
|
||||||
|
### 2. Monkey-Patched Files
|
||||||
|
|
||||||
|
These are files our addon patches at runtime via Ruby `prepend`, `include`, or `after_initialize` hooks. Changes to these files could break our patches.
|
||||||
|
|
||||||
|
**Search Backend (OpenSearch compatibility patch):**
|
||||||
|
- `lib/search_index_backend.rb` - We prepend `SearchIndexBackendOpenSearchPatch` to override `_mapping_item_type_es`. Check if this method signature or the `'flattened'` string usage has changed.
|
||||||
|
|
||||||
|
**Core Models (callback injection targets):**
|
||||||
|
- `app/models/ticket/article.rb` - We inject `after_create` callbacks via `include` for Signal and WhatsApp message delivery. Check for changes to the callback chain, model structure, or the `Sender`/`Type` lookup patterns.
|
||||||
|
- `app/models/link.rb` - We inject an `after_create` callback for Signal group setup on ticket split. Check for structural changes.
|
||||||
|
|
||||||
|
**Transaction System:**
|
||||||
|
- `app/models/transaction/` directory - We register `Transaction::SignalNotification` as backend `0105_signal_notification`. Check if the transaction backend system has been refactored.
|
||||||
|
|
||||||
|
**Icons:**
|
||||||
|
- `public/assets/images/icons.svg` - Our initializers append SVG icons at boot time. Check if the SVG structure or the icon injection mechanism has changed.
|
||||||
|
|
||||||
|
Command pattern:
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream diff <current-version> <target-version> -- <file-path>
|
||||||
|
```
|
||||||
|
|
||||||
|
For the search backend specifically, also check if `_mapping_item_type_es` still exists and still returns `'flattened'`:
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream show <target-version>:lib/search_index_backend.rb | grep -n -A5 '_mapping_item_type_es\|flattened'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. API Surface Dependencies
|
||||||
|
|
||||||
|
These are Zammad APIs/interfaces/mixins our addon relies on. Changes could cause runtime failures.
|
||||||
|
|
||||||
|
**Channel Driver Interface:**
|
||||||
|
- `app/models/channel/driver/` - Check if the driver base class or interface expectations have changed (methods: `fetchable?`, `disconnect`, `deliver`, `streamable?`).
|
||||||
|
|
||||||
|
**Controller Concerns:**
|
||||||
|
- `app/controllers/concerns/creates_ticket_articles.rb` - Used by our webhook controllers. Check for interface changes.
|
||||||
|
|
||||||
|
**Ticket Article Types & Senders:**
|
||||||
|
- `app/models/ticket/article/type.rb` and `app/models/ticket/article/sender.rb` - We look up types by name (`'signal message'`, `'whatsapp message'`). Check for changes in how types are registered or looked up.
|
||||||
|
|
||||||
|
**Authentication/Authorization:**
|
||||||
|
- `app/policies/` directory structure - We create policies matching `controllers/` names. Check if the policy naming convention or base class has changed.
|
||||||
|
|
||||||
|
**Package System:**
|
||||||
|
- `lib/package.rb` or the package install/uninstall API - We use `Package.install(file:)` and `Package.uninstall(name:, version:)` in setup.rb.
|
||||||
|
|
||||||
|
**Scheduler/Job System:**
|
||||||
|
- `app/jobs/` base class patterns - Our jobs inherit from ApplicationJob. Check for changes.
|
||||||
|
|
||||||
|
Command pattern:
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream diff --stat <current-version> <target-version> -- <path>
|
||||||
|
git -C /tmp/zammad-upstream diff <current-version> <target-version> -- <specific-file>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Path Collision Detection
|
||||||
|
|
||||||
|
Check if the target Zammad version has added any NEW files at paths that collide with our addon files. Our addon installs files at these paths:
|
||||||
|
|
||||||
|
**Controllers:** `app/controllers/channels_cdr_signal_controller.rb`, `channels_cdr_voice_controller.rb`, `channels_cdr_whatsapp_controller.rb`, `cdr_signal_channels_controller.rb`, `cdr_ticket_article_types_controller.rb`, `formstack_controller.rb`, `opensearch_controller.rb`
|
||||||
|
|
||||||
|
**Models:** `app/models/channel/driver/cdr_signal.rb`, `cdr_whatsapp.rb`, `app/models/ticket/article/enqueue_communicate_cdr_signal_job.rb`, `enqueue_communicate_cdr_whatsapp_job.rb`, `app/models/link/setup_split_signal_group.rb`, `app/models/transaction/signal_notification.rb`
|
||||||
|
|
||||||
|
**Jobs:** `app/jobs/communicate_cdr_signal_job.rb`, `communicate_cdr_whatsapp_job.rb`, `signal_notification_job.rb`, `create_ticket_from_form_job.rb`
|
||||||
|
|
||||||
|
**Libraries:** `lib/cdr_signal.rb`, `cdr_signal_api.rb`, `cdr_signal_poller.rb`, `cdr_whatsapp.rb`, `cdr_whatsapp_api.rb`, `signal_notification_sender.rb`
|
||||||
|
|
||||||
|
**Routes:** `config/routes/cdr_signal_channels.rb`, `channel_cdr_signal.rb`, `channel_cdr_voice.rb`, `channel_cdr_whatsapp.rb`, `cdr_ticket_article_types.rb`, `formstack.rb`, `opensearch.rb`
|
||||||
|
|
||||||
|
**Frontend Plugins:** `app/frontend/shared/entities/ticket-article/action/plugins/cdr_signal.ts`, `cdr_whatsapp.ts`, `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/signalMessage.ts`, `whatsappMessage.ts`
|
||||||
|
|
||||||
|
Check if any of these paths exist in the target version:
|
||||||
|
```bash
|
||||||
|
for path in <list-of-paths>; do
|
||||||
|
git -C /tmp/zammad-upstream show <target-version>:$path 2>/dev/null && echo "COLLISION: $path exists upstream"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Dockerfile Patch Targets
|
||||||
|
|
||||||
|
Check files that are patched at Docker build time via `sed`:
|
||||||
|
|
||||||
|
- `lib/search_index_backend.rb` - `sed` replaces `'flattened'` with `'flat_object'`. Verify the string still exists in the target version.
|
||||||
|
- `contrib/nginx/zammad.conf` - Structure modified for embedded mode. Check for format changes.
|
||||||
|
- `docker-entrypoint.sh` - We inject addon install commands after the `# es config` comment. Verify this comment/anchor still exists.
|
||||||
|
|
||||||
|
Check the upstream Docker entrypoint:
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream show <target-version>:contrib/docker/docker-entrypoint.sh 2>/dev/null | grep -n 'es config' || echo "Anchor comment not found - check entrypoint structure"
|
||||||
|
```
|
||||||
|
|
||||||
|
Also check the Zammad Docker Compose repo if relevant (the base image may come from `zammad/zammad-docker-compose`).
|
||||||
|
|
||||||
|
### 6. Database Schema Conflicts
|
||||||
|
|
||||||
|
Check if the target Zammad version adds any columns or tables that could conflict with our migrations:
|
||||||
|
- Column names: `whatsapp_uid`, `signal_uid`, `signal_username` on the users table
|
||||||
|
- Setting names containing: `signal_notification`, `cdr_link`, `formstack`, `opensearch_dashboard`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream diff <current-version> <target-version> -- db/migrate/ | grep -i 'signal\|whatsapp\|formstack\|opensearch'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Frontend Build System
|
||||||
|
|
||||||
|
Check if the Vite/asset pipeline configuration has changed significantly, since our addon relies on being compiled into the Zammad frontend:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream diff --stat <current-version> <target-version> -- vite.config.ts app/frontend/vite.config.ts config/initializers/assets.rb Gemfile
|
||||||
|
```
|
||||||
|
|
||||||
|
Also check if CoffeeScript/Sprockets support has been removed (would break our legacy UI files):
|
||||||
|
```bash
|
||||||
|
git -C /tmp/zammad-upstream show <target-version>:Gemfile 2>/dev/null | grep -i 'coffee\|sprockets'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Report Format
|
||||||
|
|
||||||
|
Compile all findings into a structured report:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Zammad Compatibility Report: <current-version> -> <target-version>
|
||||||
|
|
||||||
|
### CRITICAL (Action Required Before Upgrade)
|
||||||
|
- [List files that changed upstream AND are replaced by our addon - these need manual merging]
|
||||||
|
- [List any broken monkey-patch targets]
|
||||||
|
- [List any path collisions]
|
||||||
|
|
||||||
|
### WARNING (Review Needed)
|
||||||
|
- [List API surface changes that could affect our code]
|
||||||
|
- [List Dockerfile patch targets that changed]
|
||||||
|
- [List build system changes]
|
||||||
|
|
||||||
|
### INFO (No Action Needed)
|
||||||
|
- [List files checked with no changes]
|
||||||
|
- [List confirmed-safe paths]
|
||||||
|
|
||||||
|
### Recommended Actions
|
||||||
|
- For each CRITICAL item, describe what needs to be done
|
||||||
|
- Note any files that should be re-copied from upstream and re-patched
|
||||||
|
```
|
||||||
|
|
||||||
|
For each changed file in CRITICAL, show the upstream diff so the user can see what changed and decide how to integrate it.
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -32,3 +32,11 @@ ENVIRONMENT_VARIABLES_MIGRATION.md
|
||||||
local-scripts/*
|
local-scripts/*
|
||||||
docs/
|
docs/
|
||||||
packages/zammad-addon-link/test/
|
packages/zammad-addon-link/test/
|
||||||
|
|
||||||
|
# Allow Claude Code project config (overrides global gitignore)
|
||||||
|
!CLAUDE.md
|
||||||
|
!.claude/
|
||||||
|
.claude/**
|
||||||
|
!.claude/skills/
|
||||||
|
!.claude/skills/**
|
||||||
|
.claude/settings.local.json
|
||||||
|
|
|
||||||
114
CLAUDE.md
Normal file
114
CLAUDE.md
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
# 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue