# Security model ## Trust boundaries 1. **Ticket content is untrusted.** It can contain prompt injection, HTML, links and attacker-controlled instructions. 2. **Knowledge files are trusted operator content.** Only reviewed files should be mounted into `knowledge/`. 3. **The LLM is advisory.** It never receives a callable GLPI tool. All writes are performed by deterministic Go code after policy checks. 4. **GLPI is the source of truth.** The ticket and followups are re-read immediately before writes. 5. **Operational context is read-only and treated as data.** Change descriptions, incident text, asset names and monitoring messages may still contain untrusted text and never become executable instructions. 6. **Uptime Kuma credentials stay in the connector.** API keys are used only for the HTTP request and are never included in the LLM prompt or audit payload. ## Auto-reply gates An automatic response is only possible when all of these are true: - `DRY_RUN=false` - `AUTO_REPLY=true` - no followup existed at the first check - the model explicitly selects a knowledge ID - the knowledge ID was in the retrieval result - `knowledge.auto_reply=true` - global and per-document similarity thresholds pass - configured category restrictions pass - reply confidence passes - the ticket has not changed during inference (including requester/item relations relevant to context) - enabled context sources completed successfully when `CONTEXT_BLOCK_AUTO_REPLY_ON_ERRORS=true` - no relevant central Major Incident/Uptime outage is present when `CONTEXT_BLOCK_AUTO_REPLY_ON_INCIDENT=true` - a second followup check immediately before POST is still empty The actual user-facing answer comes from the reviewed knowledge JSON, not generated free text. ## Known concurrency boundary Without a GLPI API primitive that atomically combines "no followup exists" and "create followup", a small race remains between the final GET and POST. The application minimizes this using a per-ticket process lock and a final followup recheck. Run one active application replica unless you replace the local queue/state/lock with distributed coordination. ## Deployment checklist - Use a dedicated GLPI service account and least privileges. - Use HTTPS for GLPI; plain HTTP requires an explicit unsafe override. - Keep the dashboard bound to localhost/private networks behind TLS. - Use strong Basic Auth credentials or put the dashboard behind your SSO reverse proxy. - Keep `/metrics` and health endpoints on a trusted network. - Keep `.env` outside source control and restrict filesystem permissions. - Start with `DRY_RUN=true`, then category-only, then explicitly approved auto-replies. - Review `data/runs.jsonl` and GLPI audit logs regularly. ## Kommunikations- und Quellenpolicy - `KNOWLEDGE_ALLOWED_SOURCES` ist eine fail-closed Allowlist. Nur Dokumente mit einem dort genannten `source`-Label werden geladen, indexiert oder an das LLM übergeben. - `KNOWLEDGE_AUTO_REPLY_SOURCES` ist eine zusätzliche Teilmengen-Allowlist für automatische Antworten. Eine Quelle darf also recherchierbar sein, ohne Schreibrechte auszulösen. - Knowledge-Dokumente ohne `source` werden beim Start abgelehnt. - Auto-Replies erfordern passende `language`- und `communication_style`-Metadaten. Die sicheren Defaults sind `de-DE` und `formal`. - Anrede, Grußformel und Signatur werden außerhalb des LLM in der Go-Policy zusammengesetzt. Das Modell kann diese Werte nicht verändern. - Die Metadaten sind eine fachliche Freigabeerklärung. Ein falsch als `de-DE/formal` gekennzeichneter Text wird nicht semantisch durch einen zweiten externen Dienst überprüft; deshalb müssen Auto-Reply-Dokumente weiterhin redaktionell geprüft werden. ## Operational context policy - Change Calendar, Major Incident, Uptime Kuma and user/device integrations are **read-only**. They do not expand GLPI write capabilities. - A configured context-source failure is fail-closed for automatic replies by default. This prevents the agent from sending an individual troubleshooting answer while central-service context is unavailable. - Relevant Major Incidents and Uptime Kuma outages suppress normal Auto-Replies by default. They do not automatically close, merge or reassign tickets. - `GLPI_MAJOR_INCIDENT_FILTER` is operator-controlled. Keep `MAJOR_INCIDENTS_ENABLED=false` until the query has been verified against the target GLPI instance. - Asset lookup paths and filters are operator-controlled and validated where possible against GLPI's generated OpenAPI route list. Field/filter semantics still need Shadow-Mode verification on the real instance. - Prefer Uptime Kuma `UPTIME_KUMA_MODE=metrics` for private monitoring. Store `UPTIME_KUMA_API_KEY` as a secret and give the key only the access needed for metrics. `status_page` mode should be used only for information safe to publish on that status page. - Do not place passwords, tokens, personal secrets or raw diagnostic dumps into Change/Incident descriptions merely because the agent can read them; relevant text may be passed to the local Ollama model.