Problem
The current delivery model couples dtc-inc/msp-script-library and NinjaRMM via raw URL strings. Ninja scripts have URLs pointing at raw.githubusercontent.com/.../main/..., and the mapping of "which Ninja script corresponds to which repo path" lives only in those URLs (and the Ninja UI). Drift between repo state and Ninja state is invisible.
Proposal — C: Sync main → NinjaRMM, link scripts via a Ninja custom field
Move the source-of-truth coupling out of URL strings and into an explicit sync layer.
Mechanics:
- Each
.ps1 in the repo gets a corresponding script entry in Ninja.
- A NinjaRMM custom field on the script entry holds the canonical repo path (e.g.
sec-huntress/HuntressAgentInstall.ps1) plus the version / SHA that was last synced.
- A GitHub Action (or scheduled job) on every push to
main walks the repo, finds the matching Ninja script via the custom field, and updates Ninja's script content via Ninja's API.
- Scripts deleted from the repo get flagged in Ninja (don't auto-delete ... operator decides).
What this unblocks:
- Explicit mapping ...
Ninja script -> repo path is queryable, not buried in URL strings.
- Ninja-side controls work normally ... Ninja's role-based access, scheduling, parameterization, monitoring all apply to the live script.
- Atomic deployments ... can stop the sync if a regression ships; rollback is
git revert + re-sync.
- Drift detection ... compare custom field SHA to current main HEAD ... mismatches are visible.
Trade-offs / risks
- NinjaRMM API capability ... need to confirm Ninja's API exposes "update script content" and "read/write custom fields on script entries." Worth checking before scoping further.
- Sync direction is one-way ... edits made in Ninja's UI get overwritten on next sync. That's the right default (repo is canonical) but operator habits may need to shift.
- Drift recovery ... if the sync job fails silently for a week, repo and Ninja diverge until someone notices. Need monitoring + alerting on the sync job.
- Mapping bootstrap ... someone has to stamp every existing Ninja script with the custom field once. One-off but tedious.
Scope
Relationship to issues A + B
- vs A (jsDelivr) ... C bypasses URL-based delivery entirely. They're mutually exclusive directions for the script-delivery model. C is heavier engineering up-front but better long-term observability + control.
- vs B (vendor-download integrity) ... orthogonal. B can ship inside whatever delivery model is chosen.
Branch / labels
- Branch prefix:
enhancement/ninja-sync
- Likely largest engineering effort of the three; can be staged across milestones.
Problem
The current delivery model couples
dtc-inc/msp-script-libraryand NinjaRMM via raw URL strings. Ninja scripts have URLs pointing atraw.githubusercontent.com/.../main/..., and the mapping of "which Ninja script corresponds to which repo path" lives only in those URLs (and the Ninja UI). Drift between repo state and Ninja state is invisible.Proposal — C: Sync
main→ NinjaRMM, link scripts via a Ninja custom fieldMove the source-of-truth coupling out of URL strings and into an explicit sync layer.
Mechanics:
.ps1in the repo gets a corresponding script entry in Ninja.sec-huntress/HuntressAgentInstall.ps1) plus the version / SHA that was last synced.mainwalks the repo, finds the matching Ninja script via the custom field, and updates Ninja's script content via Ninja's API.What this unblocks:
Ninja script -> repo pathis queryable, not buried in URL strings.git revert + re-sync.Trade-offs / risks
Scope
Relationship to issues A + B
Branch / labels
enhancement/ninja-sync