---
module: devices.agent-scripts
title: Agent Scripts
tab: Claude
order: 40
audience: dev
---

> Act-without-guessing reference. Only confirmed facts (hiveops-devices source, 2026-07-01).

## Owner
- **Service:** `hiveops-devices` (Spring Boot, port `8096`, DB `hiveiq_devices`).
- Served under `/api/fleet/scripts` **but owned by devices, NOT hiveops-fleet.**
- SPA: `hiveops-devices/frontend` → `components/Settings/AgentScripts.svelte`, `lib/api.ts` → `agentScriptAPI` on `devicesApi` (base `window.__APP_CONFIG__.apiUrl` else `http://localhost:8096`).

## Endpoints (all `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`)
| Method | Path | Result |
|--------|------|--------|
| GET | `/api/fleet/scripts` | list; optional `?institutionKey=` |
| POST | `/api/fleet/scripts` | 400 if name/content blank, else 201 |
| PUT | `/api/fleet/scripts/{id}` | 404 if missing |
| DELETE | `/api/fleet/scripts/{id}` | 204 (hard delete) |
| POST | `/api/fleet/scripts/{id}/push` | **STUB → 200 + `[]`, does nothing** |

## Data
- **Table:** `agent_scripts` (Flyway `V15`). Cols: `id`, `name` VARCHAR(200), `description` TEXT, `content` TEXT, `institution_key` VARCHAR(50), `created_at`, `updated_at`. Index: `idx_agent_scripts_institution_key`.
- **Entity/Repo/Service/Controller:** `AgentScript` / `AgentScriptRepository` / `AgentScriptService` / `AgentScriptController` (pkg `com.hiveops.devices.*`).
- Repo methods: `findAllByOrderByNameAsc`, `findByInstitutionKeyOrderByNameAsc`.

## Kafka / topics
- **None.** This module produces/consumes nothing.

## Signed delivery (lives elsewhere, NOT wired here)
- hiveops-fleet: `FleetTaskKind.UPDATE_SCRIPT` + `ScriptSigningService` (`SHA256withRSA`, key `script.signing.private-key` / env `SCRIPT_SIGNING_PRIVATE_KEY`).
- agent: `com.hiveops.filemgmt.ProcessScriptUpdate` verifies `SHA256withRSA`, needs patch keys `scriptName` + `scriptContent` (base64) + `scriptSignature`.

## Gotchas
- Devices Push button is a **no-op**; SPA still shows a success toast. Never treat a push as delivered.
- Path says `fleet` but the backend is **devices** — route to `api.bcos.cloud/devices`, not `/fleet`.
- Name extension check (`.cmd/.sh/.ps1`) is **client-side only**; backend accepts any non-blank name.
- SPA `getAll()` never sends `institutionKey` → lists ALL institutions; `create()` never sends it → rows saved with `institution_key = NULL`.
- Edit locks `name` (SPA sends only `{description, content}` on PUT).
- Fleet signer writes patch key `signature` over raw `script`; agent reads `scriptSignature` + base64 `scriptContent` — key/format mismatch (see uncertainties).

## Do NOT
- Do NOT claim scripts reach ATMs via this module's Push endpoint — it's a stub.
- Do NOT look for a Kafka topic or `device_summary` mirror for scripts — none exist.
- Do NOT expect institution scoping from the UI — it lists/creates unscoped.
- Do NOT search hiveops-fleet for `/api/fleet/scripts` — that path is a devices controller.
- Do NOT rely on backend name-extension validation.
