feat: RMM Overshell, IT Glue audit/write-back, LogLift, link-aware bundles, dashboard overhaul
- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift) - LogLift evidence pipeline (migration 078): upload webhook, B2 storage client, receiver/matcher, EventLogCollector PowerShell script - IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket xrefs, applications/configurations browse pages + apply/revert/audit endpoints - Link-aware analyzer bundles (migration 073) + provider toggle (migration 074): link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion panels, analyze-bundle endpoint - Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts admin page, reconciler service, resolve endpoints - Dashboard overhaul: integration-health service + alerts, overview/health endpoints - Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
378e68ad8a
commit
1112a06afe
132 changed files with 21352 additions and 743 deletions
88
migrations/077_rmm_overshell.sql
Normal file
88
migrations/077_rmm_overshell.sql
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
-- Phase 4.2 — Datto RMM Overshell evidence pipeline.
|
||||
--
|
||||
-- Two tables:
|
||||
-- 1. rmm_settings — singleton row caching the discovered Overshell
|
||||
-- component_uid + variable_name. Avoids re-discovering on every dispatch.
|
||||
-- 2. rmm_executions — full lifecycle of every Overshell job Pulse triggers.
|
||||
-- Forever-retained: stdout/stderr (redacted), parsed evidence, audit
|
||||
-- linkage, target/asset linkage.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rmm_settings (
|
||||
id BOOLEAN PRIMARY KEY DEFAULT true CHECK (id),
|
||||
overshell_component_uid TEXT,
|
||||
overshell_component_name TEXT,
|
||||
-- The variable name the Overshell component expects the script body in.
|
||||
-- Default 'CommandLine' matches the Datto-provided "Run Command" component;
|
||||
-- Wulf's custom Overshell may use a different name (e.g. 'Script') —
|
||||
-- adjustable via /admin/rmm-overshell.
|
||||
overshell_variable_name TEXT NOT NULL DEFAULT 'CommandLine',
|
||||
discovered_at TIMESTAMPTZ,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
INSERT INTO rmm_settings (id) VALUES (true) ON CONFLICT DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rmm_executions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
-- Script library identifiers (script bodies are version-controlled in code).
|
||||
script_id TEXT NOT NULL,
|
||||
script_version INT NOT NULL DEFAULT 1,
|
||||
-- Target resolution.
|
||||
target_type TEXT NOT NULL
|
||||
CHECK (target_type IN ('site_anchor','asset_self')),
|
||||
target_device_uid TEXT NOT NULL,
|
||||
target_hostname TEXT,
|
||||
target_company_id BIGINT,
|
||||
-- Optional links back to the audit / asset the user clicked from.
|
||||
triggered_by_audit_id UUID REFERENCES itglue_asset_audits(id) ON DELETE SET NULL,
|
||||
asset_type TEXT
|
||||
CHECK (asset_type IS NULL OR asset_type IN ('flexible_asset','configuration')),
|
||||
asset_id BIGINT,
|
||||
-- Datto job tracking.
|
||||
job_uid TEXT,
|
||||
job_name TEXT NOT NULL,
|
||||
variables JSONB NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'queued'
|
||||
CHECK (status IN ('queued','running','complete','failed','timeout')),
|
||||
exit_code INT,
|
||||
raw_stdout TEXT,
|
||||
raw_stderr TEXT,
|
||||
parsed_evidence JSONB,
|
||||
parse_error TEXT,
|
||||
error_message TEXT,
|
||||
performed_by_user_id TEXT REFERENCES "user"(id) ON DELETE SET NULL,
|
||||
queued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
-- Hard timeout marker. The poller will mark a still-running execution as
|
||||
-- timeout once NOW() > timeout_at and stop polling.
|
||||
timeout_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '5 minutes'
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_status
|
||||
ON rmm_executions (status, queued_at);
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_target_device
|
||||
ON rmm_executions (target_device_uid, queued_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_company
|
||||
ON rmm_executions (target_company_id, queued_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_audit
|
||||
ON rmm_executions (triggered_by_audit_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_asset
|
||||
ON rmm_executions (asset_type, asset_id, queued_at DESC)
|
||||
WHERE asset_type IS NOT NULL;
|
||||
|
||||
-- The audit-context loader pulls the latest successful execution per
|
||||
-- (company, script). Partial index keeps the lookup fast even as the table
|
||||
-- grows.
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_latest_success
|
||||
ON rmm_executions (target_company_id, script_id, completed_at DESC)
|
||||
WHERE status = 'complete';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_rmm_executions_user_window
|
||||
ON rmm_executions (performed_by_user_id, queued_at)
|
||||
WHERE performed_by_user_id IS NOT NULL;
|
||||
|
||||
COMMENT ON TABLE rmm_executions IS
|
||||
'Every Overshell job Pulse dispatched to Datto RMM. status: queued (we '
|
||||
'inserted the row but have not yet called runQuickJob), running (job_uid '
|
||||
'returned by Datto), complete (poller saw stdout), failed (exit_code != 0 '
|
||||
'or HTTP failure), timeout (still running past timeout_at).';
|
||||
Loading…
Add table
Add a link
Reference in a new issue