OTRS-Skill: Plugin hier oder eigenes Repo? #7

Open
opened 2026-09-05 09:39:44 +02:00 by jhs · 2 comments
Owner

Ich habe mir eine CLI für OTRS 5 gebaut (Generic Interface): Tickets suchen,
Metadaten lesen, interne Notizen schreiben, zuweisen, anlegen, seit gestern auch
mit Datei-Anhängen. Sie läuft bei mir als lokaler Claude-Skill
(~/.claude/skills/otrs/) und war bisher nirgends versioniert — das will ich
ändern.

Die Struktur würde in diesen Marketplace passen (plugins/otrs/skills/otrs/ wie
bei humhub und mediawiki), ein OTRS-Plugin gibt es hier noch nicht. Ob es
hier richtig liegt, weiß ich aber nicht — deshalb die Frage an dich, bevor ich
etwas anlege.

Was dagegen spricht: Das Ding ist auf unsere AVV-Lage zugeschnitten. Es
maskiert Namen, Adressen und IPs vor jeder Ausgabe (lokale Namenserkennung über
Ollama), unterdrückt Tickettitel komplett, wenn das Modell nicht antwortet,
führt ein Zugriffsprotokoll mit 90-Tage-Frist und kann bewusst keinen
Mailversand an Kunden. Wer das Plugin installiert, erbt dieses Verhalten, ohne
die Gründe zu kennen. Ohne eigene OTRS-Zugangsdaten läuft es ohnehin nicht.

Was mich mehr umtreibt: Mit sko/ticketing gibt es bereits ein CLI an
derselben Schnittstelle (und mit cbr/Wissensschicht ein Konzept, das OTRS
ebenfalls anfassen wird). Bevor ich ein zweites Werkzeug zementiere:

  1. Soll so etwas grundsätzlich hier als Plugin liegen, oder gehören Werkzeuge
    mit Zugangsdaten und Firmen-Spezifika in eigene Repos?
  2. Baust du an ticketing in dieselbe Richtung weiter? Buchen und Schließen
    kann es ja bereits — dann wäre sinnvoller, meine Lese- und Notiz-Funktionen
    dort einzubringen, statt zwei CLIs zu pflegen.

Ich lege bis zu deiner Antwort nichts an; lokal liegt es jetzt in einem
Git-Repo, damit nichts verloren geht.

Ich habe mir eine CLI für OTRS 5 gebaut (Generic Interface): Tickets suchen, Metadaten lesen, interne Notizen schreiben, zuweisen, anlegen, seit gestern auch mit Datei-Anhängen. Sie läuft bei mir als lokaler Claude-Skill (`~/.claude/skills/otrs/`) und war bisher nirgends versioniert — das will ich ändern. Die Struktur würde in diesen Marketplace passen (`plugins/otrs/skills/otrs/` wie bei `humhub` und `mediawiki`), ein OTRS-Plugin gibt es hier noch nicht. Ob es hier richtig liegt, weiß ich aber nicht — deshalb die Frage an dich, bevor ich etwas anlege. **Was dagegen spricht:** Das Ding ist auf unsere AVV-Lage zugeschnitten. Es maskiert Namen, Adressen und IPs vor jeder Ausgabe (lokale Namenserkennung über Ollama), unterdrückt Tickettitel komplett, wenn das Modell nicht antwortet, führt ein Zugriffsprotokoll mit 90-Tage-Frist und kann bewusst keinen Mailversand an Kunden. Wer das Plugin installiert, erbt dieses Verhalten, ohne die Gründe zu kennen. Ohne eigene OTRS-Zugangsdaten läuft es ohnehin nicht. **Was mich mehr umtreibt:** Mit `sko/ticketing` gibt es bereits ein CLI an derselben Schnittstelle (und mit `cbr/Wissensschicht` ein Konzept, das OTRS ebenfalls anfassen wird). Bevor ich ein zweites Werkzeug zementiere: 1. Soll so etwas grundsätzlich hier als Plugin liegen, oder gehören Werkzeuge mit Zugangsdaten und Firmen-Spezifika in eigene Repos? 2. Baust du an `ticketing` in dieselbe Richtung weiter? Buchen und Schließen kann es ja bereits — dann wäre sinnvoller, meine Lese- und Notiz-Funktionen dort einzubringen, statt zwei CLIs zu pflegen. Ich lege bis zu deiner Antwort nichts an; lokal liegt es jetzt in einem Git-Repo, damit nichts verloren geht.
Owner

Ich bin hin- und hergerissen, also schreibe ich erst mal auf, was ich sicher weiss.

Zu deiner Frage 2: ja, ich brauche dasselbe

Und zwar dringender, als mir lieb ist. Wenn ich mit Claude arbeite und für das Vorgehen auf ticketing verweise, baut es sich die fehlenden Teile jedes Mal neu zusammen - importiert OTRSClient, ruft Methoden direkt auf. Heute wieder, bei einem Sicherheitsvorfall: drei Tickets, Notizen und Anlegen, alles on-the-fly.

Das ist kein Zustand. Es funktioniert, aber es ist jedes Mal frisch geschrieben und jedes Mal ungeprüft.

Die Lücke in ticketing, genau benannt

Die CLI kann heute: close, transfer, eigen, remove-ack, ansible, dashboard, needrestart, note, anwesenheit, wait.

Was fehlt, sind ausgerechnet die beiden Dinge, die man im Gespräch mit einem Modell braucht:

1. Kommentieren, ohne zu schliessen. notiz_und_zeit_buchen() gibt es, aber sie ist auf Abschluss verdrahtet - src/ticket/otrs.py:216:

'State': 'closed successful',

Wer nur eine Notiz anhängen will, muss an der Methode vorbei auf _patchen() gehen, also auf eine private Funktion. Genau das ist heute dreimal passiert.

2. Ticket anlegen. ticket_erstellen() existiert im Modul und kann sogar owner direkt setzen - aber es gibt keinen CLI-Befehl dafür. Erreichbar ist es nur im Inneren von ticket ansible.

note hilft hier nicht, das bucht eine Lazy-Leistung, keine OTRS-Notiz.

Was ich brauche, vollständig

  • Ticket lesen und kommentieren, mit Zeiterfassung - ohne Statuswechsel
  • Ticket anlegen - mit Owner, Queue, Priorität

Mehr nicht. Für gelegentliche Arbeit reicht das.

Zu deiner Frage 1: mein Zwiespalt, und ein Vorschlag

Dass Werkzeuge mit Zugangsdaten und Firmen-Spezifika in eigene Repos gehören, finde ich richtig. Dass dein Vorgehen als Skill woanders verlorengeht, aber auch nicht.

Vielleicht liegt der Schnitt nicht zwischen „hier oder eigenes Repo", sondern zwischen Werkzeug und Verhalten:

gehört wohin
Die CLI - Endpunkte, Auth, Anhänge, Fehlerbehandlung ein Repo, meinetwegen ticketing
Die Regeln - was das Modell darf, was maskiert wird, was es nie tut Skill, hier im Marketplace

Dann pflegen wir eine CLI statt zweier, und deine AVV-Regeln sind kein Verhalten, das man mit der Installation ungefragt erbt, sondern eine Richtlinie, die man bewusst lädt.

Deine Lese- und Notiz-Funktionen würden mir in ticketing sofort helfen - samt Anhängen, das fehlt dort ganz.

Zum Maskieren: für meinen Fall störend

Ehrlich gesagt würde mich das Maskieren bei der Arbeit behindern. Ich arbeite damit an unserer eigenen Infrastruktur, und da brauche ich Hostnamen, IPs und Kontonamen wörtlich - heute zum Beispiel, um einen offenen Datenbank-Port und die Herkunft eines Brute-Force zu dokumentieren. Ein unterdrückter Tickettitel wäre da ein Rückschritt.

Deine Gründe sind trotzdem gültig, sie gelten nur für eine andere Nutzung. Also eher ein Schalter als eine eingebaute Eigenschaft - und die Vorgabe entscheidet, wer es einsetzt.

Eine Regel, die ich unabhängig davon drin haben will

Wenn das als Skill formuliert wird, dann bitte mit dieser Zusage:

In einem Ticket von Kunde A tauchen keine Namen, Hosts oder Kennungen von Kunde B auf.

Das ist mir mehrfach untergekommen. Ein Modell, das gerade mehrere Vorgänge im Kopf hat, zieht beim Schreiben Beispiele aus dem falschen. Fällt beim Lesen oft nicht auf, ist aber genau das, was keiner von beiden Kunden sehen darf.

Das ist keine Maskierung im Nachhinein, sondern eine Regel beim Schreiben - und die gehört in den Skill, nicht in die CLI.

Ich bin hin- und hergerissen, also schreibe ich erst mal auf, was ich sicher weiss. ## Zu deiner Frage 2: ja, ich brauche dasselbe Und zwar dringender, als mir lieb ist. Wenn ich mit Claude arbeite und für das Vorgehen auf `ticketing` verweise, **baut es sich die fehlenden Teile jedes Mal neu zusammen** - importiert `OTRSClient`, ruft Methoden direkt auf. Heute wieder, bei einem Sicherheitsvorfall: drei Tickets, Notizen und Anlegen, alles on-the-fly. Das ist kein Zustand. Es funktioniert, aber es ist jedes Mal frisch geschrieben und jedes Mal ungeprüft. ## Die Lücke in `ticketing`, genau benannt Die CLI kann heute: `close`, `transfer`, `eigen`, `remove-ack`, `ansible`, `dashboard`, `needrestart`, `note`, `anwesenheit`, `wait`. Was fehlt, sind ausgerechnet die beiden Dinge, die man im Gespräch mit einem Modell braucht: **1. Kommentieren, ohne zu schliessen.** `notiz_und_zeit_buchen()` gibt es, aber sie ist auf Abschluss verdrahtet - `src/ticket/otrs.py:216`: ```python 'State': 'closed successful', ``` Wer nur eine Notiz anhängen will, muss an der Methode vorbei auf `_patchen()` gehen, also auf eine private Funktion. Genau das ist heute dreimal passiert. **2. Ticket anlegen.** `ticket_erstellen()` existiert im Modul und kann sogar `owner` direkt setzen - aber es gibt keinen CLI-Befehl dafür. Erreichbar ist es nur im Inneren von `ticket ansible`. `note` hilft hier nicht, das bucht eine Lazy-Leistung, keine OTRS-Notiz. ## Was ich brauche, vollständig - **Ticket lesen und kommentieren, mit Zeiterfassung** - ohne Statuswechsel - **Ticket anlegen** - mit Owner, Queue, Priorität Mehr nicht. Für gelegentliche Arbeit reicht das. ## Zu deiner Frage 1: mein Zwiespalt, und ein Vorschlag Dass Werkzeuge mit Zugangsdaten und Firmen-Spezifika in eigene Repos gehören, finde ich richtig. Dass dein Vorgehen als Skill woanders verlorengeht, aber auch nicht. Vielleicht liegt der Schnitt nicht zwischen „hier oder eigenes Repo", sondern **zwischen Werkzeug und Verhalten**: | | gehört wohin | |---|---| | Die CLI - Endpunkte, Auth, Anhänge, Fehlerbehandlung | **ein** Repo, meinetwegen `ticketing` | | Die Regeln - was das Modell darf, was maskiert wird, was es nie tut | Skill, hier im Marketplace | Dann pflegen wir eine CLI statt zweier, und deine AVV-Regeln sind kein Verhalten, das man mit der Installation ungefragt erbt, sondern eine Richtlinie, die man bewusst lädt. Deine Lese- und Notiz-Funktionen würden mir in `ticketing` sofort helfen - samt Anhängen, das fehlt dort ganz. ## Zum Maskieren: für meinen Fall störend Ehrlich gesagt würde mich das Maskieren bei der Arbeit behindern. Ich arbeite damit an unserer eigenen Infrastruktur, und da brauche ich Hostnamen, IPs und Kontonamen wörtlich - heute zum Beispiel, um einen offenen Datenbank-Port und die Herkunft eines Brute-Force zu dokumentieren. Ein unterdrückter Tickettitel wäre da ein Rückschritt. Deine Gründe sind trotzdem gültig, sie gelten nur für eine andere Nutzung. Also eher ein Schalter als eine eingebaute Eigenschaft - und die Vorgabe entscheidet, wer es einsetzt. ## Eine Regel, die ich unabhängig davon drin haben will Wenn das als Skill formuliert wird, dann bitte mit dieser Zusage: > **In einem Ticket von Kunde A tauchen keine Namen, Hosts oder Kennungen von Kunde B auf.** Das ist mir mehrfach untergekommen. Ein Modell, das gerade mehrere Vorgänge im Kopf hat, zieht beim Schreiben Beispiele aus dem falschen. Fällt beim Lesen oft nicht auf, ist aber genau das, was keiner von beiden Kunden sehen darf. Das ist keine Maskierung im Nachhinein, sondern eine Regel beim Schreiben - und die gehört in den Skill, nicht in die CLI.
Owner

Zu Frage 2: gebaut, liegt in ticketing

Ich habe heute die beiden Lücken geschlossen, die ich oben benannt hatte, plus
zwei Dinge, die beim Bauen dazukamen.

Kommando was es tut
ticket show TICKET [-a] [--json] Kopfdaten und Artikel lesen
ticket comment TICKET --text … [--zeit ZE] interne Notiz, ohne Statuswechsel
ticket create -t … -b … [-o OWNER] Ticket anlegen, mit Owner/Queue/Priorität
ticket close TICKET --text … --zeit ZE gezielt schließen, ohne fzf

TICKET ist Ticketnummer oder TicketID, das wird an der Länge unterschieden.

notiz_und_zeit_buchen() war wie beschrieben auf closed successful
verdrahtet; darunter liegt jetzt notiz_hinzufuegen(), die den Status nur
anfasst, wenn einer angegeben ist. Das Schließen ist nur noch dieser Aufruf mit
state='closed successful'. Der interaktive Weg über fzf bleibt unverändert,
die Ticketangabe ist die zweite Form von close.

Die vier sind für den Aufruf durch ein Modell gebaut und weichen darin bewusst
vom Rest der CLI ab: alles über Flags statt Rückfragen, Text auch über stdin,
TicketID maschinenlesbar auf stdout. Schreibzugriffe fragen trotzdem nach,
--ja schaltet das ab.

Was der Abgleich mit otrs-dashboard-lizzy gebracht hat

Das war die halbe Arbeit, und es hat sich gelohnt — drei Dinge, die ich sonst
falsch gemacht oder nicht gewusst hätte:

TicketCreate ohne Owner lässt das Ticket nicht unbesetzt. OTRS macht den
Anlegenden zum Besitzer. Mein altes Hilfsskript behauptete das Gegenteil, und
ich hatte es ungeprüft übernommen. An 184194/184195 nachgerechnet: beide ohne
Owner angelegt, beide bei mir gelandet.

Eine Notiz allein schützt das Ticket nicht. Der Abschnitt dazu in eurer
FALLSTRICKE.md ist von gestern und beschreibt genau die Falle, in die
ticket comment gelaufen wäre: 1_14_Tage_nicht_aktualisiert misst die
Wartezeit, nicht die Einträge. comment frischt eine abgelaufene
Wiedervorlage jetzt um 20 Minuten auf, mit denselben Einschränkungen wie bei
euch — nur wenn schon abgelaufen, nur bei pending…, Notiz und Termin in einem
PATCH.

Eine Einschränkung bleibt: customer_wait steht in eurer Datenbank und ist
über die OTRS-API nicht sichtbar. Für solche Tickets gibt es
--ohne-wiedervorlage; automatisch erkennen kann ticketing sie nicht.

TicketGet meldet gebuchte Zeit nicht zurück — in OTRS 5 liegt sie in
time_accounting, der Artikel hat kein time_unit. Ich hätte fast
geschlossen, die Buchung sei fehlgeschlagen. Nachgewiesen habe ich sie dann
über euren Artikel-Endpunkt (time_min).

Alles belegt an zwei Wegwerf-Tickets in Monitoring (184431, 184438), beide
inzwischen geschlossen.

Zu Frage 1: der Vorschlag steht

Was mir jetzt in ticketing fehlt und bei dir da ist: Anhänge. Das wäre der
nächste sinnvolle Beitrag, wenn du magst — die Stelle dafür ist
OTRSClient.notiz_hinzufuegen().

Das Maskieren würde ich weiterhin nicht in der CLI haben wollen, aus dem
genannten Grund. Als Skill, den man bewusst lädt, gern — der Schnitt zwischen
Werkzeug und Regeln scheint mir nach heute eher noch richtiger: ich habe beim
Bauen dreimal in eure Doku geschaut und kein einziges Mal in den
Maskierungs-Code.

## Zu Frage 2: gebaut, liegt in ticketing Ich habe heute die beiden Lücken geschlossen, die ich oben benannt hatte, plus zwei Dinge, die beim Bauen dazukamen. | Kommando | was es tut | |---|---| | `ticket show TICKET [-a] [--json]` | Kopfdaten und Artikel lesen | | `ticket comment TICKET --text … [--zeit ZE]` | interne Notiz, **ohne** Statuswechsel | | `ticket create -t … -b … [-o OWNER]` | Ticket anlegen, mit Owner/Queue/Priorität | | `ticket close TICKET --text … --zeit ZE` | gezielt schließen, ohne fzf | `TICKET` ist Ticketnummer oder TicketID, das wird an der Länge unterschieden. `notiz_und_zeit_buchen()` war wie beschrieben auf `closed successful` verdrahtet; darunter liegt jetzt `notiz_hinzufuegen()`, die den Status nur anfasst, wenn einer angegeben ist. Das Schließen ist nur noch dieser Aufruf mit `state='closed successful'`. Der interaktive Weg über fzf bleibt unverändert, die Ticketangabe ist die zweite Form von `close`. Die vier sind für den Aufruf durch ein Modell gebaut und weichen darin bewusst vom Rest der CLI ab: alles über Flags statt Rückfragen, Text auch über stdin, TicketID maschinenlesbar auf stdout. Schreibzugriffe fragen trotzdem nach, `--ja` schaltet das ab. ## Was der Abgleich mit otrs-dashboard-lizzy gebracht hat Das war die halbe Arbeit, und es hat sich gelohnt — drei Dinge, die ich sonst falsch gemacht oder nicht gewusst hätte: **`TicketCreate` ohne Owner lässt das Ticket nicht unbesetzt.** OTRS macht den Anlegenden zum Besitzer. Mein altes Hilfsskript behauptete das Gegenteil, und ich hatte es ungeprüft übernommen. An 184194/184195 nachgerechnet: beide ohne Owner angelegt, beide bei mir gelandet. **Eine Notiz allein schützt das Ticket nicht.** Der Abschnitt dazu in eurer `FALLSTRICKE.md` ist von gestern und beschreibt genau die Falle, in die `ticket comment` gelaufen wäre: `1_14_Tage_nicht_aktualisiert` misst die Wartezeit, nicht die Einträge. `comment` frischt eine **abgelaufene** Wiedervorlage jetzt um 20 Minuten auf, mit denselben Einschränkungen wie bei euch — nur wenn schon abgelaufen, nur bei `pending…`, Notiz und Termin in einem PATCH. Eine Einschränkung bleibt: `customer_wait` steht in eurer Datenbank und ist über die OTRS-API nicht sichtbar. Für solche Tickets gibt es `--ohne-wiedervorlage`; automatisch erkennen kann ticketing sie nicht. **`TicketGet` meldet gebuchte Zeit nicht zurück** — in OTRS 5 liegt sie in `time_accounting`, der Artikel hat kein `time_unit`. Ich hätte fast geschlossen, die Buchung sei fehlgeschlagen. Nachgewiesen habe ich sie dann über euren Artikel-Endpunkt (`time_min`). Alles belegt an zwei Wegwerf-Tickets in `Monitoring` (184431, 184438), beide inzwischen geschlossen. ## Zu Frage 1: der Vorschlag steht Was mir jetzt in ticketing fehlt und bei dir da ist: **Anhänge**. Das wäre der nächste sinnvolle Beitrag, wenn du magst — die Stelle dafür ist `OTRSClient.notiz_hinzufuegen()`. Das Maskieren würde ich weiterhin nicht in der CLI haben wollen, aus dem genannten Grund. Als Skill, den man bewusst lädt, gern — der Schnitt zwischen Werkzeug und Regeln scheint mir nach heute eher noch richtiger: ich habe beim Bauen dreimal in eure Doku geschaut und kein einziges Mal in den Maskierungs-Code.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: inmedias.it/claude-plugins#7