{"key":"glpi_bot_runner_implementation_2026_03_22","title":"GLPI Bot Runner Implementation","content":"# GLPI Bot Runner Implementation\n\nImplemented a v1 GLPI bot workflow on `svc-auto` with a trusted execution backend and live GLPI, docs, and `brain` integration.\n\n## Deployment\n- Host: `svc-auto`\n- Path: `/home/svc-admin/docker/glpi-bot-runner`\n- Service: `glpi-bot-runner`\n- Architecture doc: `docs/architecture/glpi-bot-runner.md`\n\n## What it does\n- Authenticates to GLPI v2 with OAuth password grant\n- Polls GLPI tickets in category `Automation > Homelab Bot`\n- Requires `homelab-bot` assignment via TeamMember role `assigned`\n- Posts a claimed follow-up\n- Moves the ticket to `In Progress`\n- Parses a structured YAML bot spec from the ticket body\n- Executes only trusted built-in actions\n- Writes a Markdown artifact into the homelab documentation repo\n- Stores a matching memory in `brain`\n- Posts a professional completion-style follow-up\n- Moves the ticket to `Solved` on success or `Pending` on blocked/invalid work\n\n## Current execution mode\n`EXECUTOR_MODE=trusted_dispatch`\n\nSupported actions now verified in live tickets:\n- `http_check`\n- `docker_compose_remote`\n- `path_exists`\n- `docker_container_check`\n- `systemd_remote`\n\nThe dispatcher does not execute arbitrary shell from ticket text. `docker_compose_remote` is constrained by host, path, and action allowlists.\n\n## Files\n- `/home/svc-admin/docker/glpi-bot-runner/docker-compose.yml`\n- `/home/svc-admin/docker/glpi-bot-runner/.env`\n- `/home/svc-admin/docker/glpi-bot-runner/app/`\n- `/home/svc-admin/docker/glpi-bot-runner/templates/`\n- `/home/svc-admin/homelab-doc-sync/homelab-documentation-system/docs/architecture/glpi-bot-runner.md`\n\n## GLPI structure created\n- Category: `Automation`\n- Category: `Automation > Homelab Bot`\n- Followup template: `Bot Claimed - Homelab`\n- Followup template: `Bot Blocked - Homelab`\n- Followup template: `Bot Completion - Homelab`\n\n## Operational decisions and fixes\n- GLPI v2 ticket creation needs `category: {id: 2}`; using `itilcategories_id` did not populate the category field the runner filters on.\n- `GLPI_ALLOWED_STATUS_IDS` was tightened to `1` so already-claimed tickets are not reprocessed every poll cycle.\n- `path_exists` and `systemd_remote` now force host execution over SSH instead of using the local-container fast path.\n- `systemd_remote` uses `sudo -n` and `systemctl --no-pager` for unattended execution.\n- `svc-auto` needed `22/tcp` allowed from the runner bridge subnet `172.23.0.0/16` so SSH-based same-host actions could reach the host from the container.\n- `svc-auto` also needed its local `~/.ssh/id_ed25519.pub` added to `authorized_keys` so the runner container's mounted key could authenticate back to the host.\n- `workflow.py` was fixed to import `ExecutionResult` in the exception path.\n\n## Validation\nValidated live against GLPI and the runner.\n- Ticket `3` proved the lifecycle and artifact path in pending mode.\n- Ticket `4` proved invalid specs are blocked cleanly.\n- Ticket `5` executed a real `http_check` action, posted follow-ups, wrote `docs/generated/glpi-bot/ticket-5.md`, stored a `brain` memory, and moved to `Solved`.\n- Ticket `11` executed `docker_compose_remote` successfully and moved to `Solved`.\n- Ticket `12` executed `path_exists` successfully and moved to `Solved`.\n- Ticket `14` executed `docker_container_check` successfully and moved to `Solved`.\n- Ticket `15` executed `systemd_remote` successfully and moved to `Solved`.\n- Ticket `13` captured the pre-fix `systemd_remote` failure mode and remains a useful artifact for the earlier local-container/SSH routing issue.\n\n## Next step\nAdd more trusted actions as explicit handlers rather than allowing arbitrary command execution from ticket text.","summary":"# GLPI Bot Runner Implementation\n\nImplemented a v1 GLPI bot workflow on `svc-auto` with a trusted execution backend and live GLPI, docs, and `brain` integration.\n\n## Deployment\n- Host: `svc-auto`\n- Path: `/home/svc-admin/docker/glpi-bot-runner`\n- Service: `glpi-bot-runner`\n- Architecture doc: `docs/architecture/glpi-bot-runner.md`\n\n## What it does\n- Authenticates to GLPI v2 with OAuth password grant\n- Polls GLPI tickets in category `Automation > Homelab Bot`\n- Requires `homelab-bot` assignment via TeamMember role `assigned`\n- Posts a claimed follow-up\n- Moves the ticket to `In Progress`\n- Parses a structured YAML bot spec from the ticket body\n- Executes only trusted built-in actions\n- Writes a Markdown artifact into the homelab documentation repo\n- Stores a matching memory in `brain`\n- Posts a professional completion-style follow-up\n- Moves the ticket to `Solved` on success or `Pending` on blocked/invalid work\n\n## Current execution mode\n`EXECUTOR_MODE=trusted_dispatch`\n\nSupported actions now verified in live tickets:\n- `http_check`\n- `docker_compose_remote`\n- `path_exists`\n- `docker_container_check`\n- `systemd_remote`\n\nThe dispatcher does not execute arbitrary shell from ticket text. `docker_compose_remote` is constrained by host, path, and action allowlists.\n\n## Files\n- `/home/svc-admin/docker/glpi-bot-runner/docker-compose.yml`\n- `/home/svc-admin/docker/glpi-bot-runner/.env`\n- `/home/svc-admin/docker/glpi-bot-runner/app/`\n- `/home/svc-admin/docker/glpi-bot-runner/templates/`\n- `/home/svc-admin/homelab-doc-sync/homelab-documentation-system/docs/architecture/glpi-bot-runner.md`\n\n## GLPI structure created\n- Category: `Automation`\n- Category: `Automation > Homelab Bot`\n- Followup template: `Bot Claimed - Homelab`\n- Followup template: `Bot Blocked - Homelab`\n- Followup template: `Bot Completion - Homelab`\n\n## Operational decisions and fixes\n- GLPI v2 ticket creation needs `category: {id: 2}`; using `itilcategories_id` did not populate the category field the runner filters on.\n- `GLPI_ALLOWED_STATUS_IDS` was tightened to `1` so already-claimed tickets are not reprocessed every poll cycle.\n- `path_exists` and `systemd_remote` now force host execution over SSH instead of using the local-container fast path.\n- `systemd_remote` uses `sudo -n` and `systemctl --no-pager` for unattended execution.\n- `svc-auto` needed `22/tcp` allowed from the runner bridge subnet `172.23.0.0/16` so SSH-based same-host actions could reach the host from the container.\n- `svc-auto` also needed its local `~/.ssh/id_ed25519.pub` added to `authorized_keys` so the runner container's mounted key could authenticate back to the host.\n- `workflow.py` was fixed to import `ExecutionResult` in the exception path.\n\n## Validation\nValidated live against GLPI and the runner.\n- Ticket `3` proved the lifecycle and artifact path in pending mode.\n- Ticket `4` proved invalid specs are blocked cleanly.\n- Ticket `5` executed a real `http_check` action, posted follow-ups, wrote `docs/generated/glpi-bot/ticket-5.md`, stored a `brain` memory, and moved to `Solved`.\n- Ticket `11` executed `docker_compose_remote` successfully and moved to `Solved`.\n- Ticket `12` executed `path_exists` successfully and moved to `Solved`.\n- Ticket `14` executed `docker_container_check` successfully and moved to `Solved`.\n- Ticket `15` executed `systemd_remote` successfully and moved to `Solved`.\n- Ticket `13` captured the pre-fix `systemd_remote` failure mode and remains a useful artifact for the earlier local-container/SSH routing issue.\n\n## Next step\nAdd more trusted actions as explicit handlers rather than allowing arbitrary command execution from ticket text.","status":"active","namespace":"glpi-task-history","namespace_name":"glpi-task-history","namespace_tier":"shared","tags":[]}