Skip to Content

Signals

Where: Signals in the sidebar (#/signals).

Signals with the Sources panel (GitHub “Connected · read-only verified”, ArgoCD “Reporting”, SARIF upload) above the findings list, one finding selected showing the six-step governed loop.
Save as public/guide/signals.png

Signals is where security findings meet the governed delivery loop. TruStacks is not a scanner and does not own the fix. Findings come from the tools you already run (Snyk, Trivy, Dependabot, GitHub Advanced Security, a SARIF file), or are observed in GitHub by your runner’s read-only MCP Signals source. TruStacks governs, validates and ships the fix through your pipeline. You approve, always. TruStacks re-proposes; it never auto-merges.

Sources

A Sources panel sits at the top of the screen. It lists every place findings and observations come from, each with the status your runner last reported. With no report, it says Not connected or No reports yet, never “connected”.

SourceWhat it readsStatus shown
GitHub, read-onlyDependabot, code-scanning and secret-scanning alerts, and CI runs, read by your runner with a read-only tokenNot connected; Connected · read-only verified · last sweep …; Refused (the server offered a tool we do not allow); On, but its Secret is missing in the runner’s namespace; Last sweep failed
ArgoCD deploy statusWhether a merged change synced and became healthy, read by your runnerNo reports yet or Reporting · last report …
SARIF uploadAny scanner’s SARIF output (CodeQL, Semgrep, Trivy, and so on)Upload a file any time

A source that is not reporting yet has a Connect button; SARIF has Upload. Connect a source at the top of the panel opens the same wizard with a source chooser first.

Connect a source

Connect a source dialog, first step: the three source cards (GitHub, read-only · ArgoCD deploy status · SARIF upload).
Save as public/guide/signals-connect-choose.png
Connect a source, GitHub: the runner picker (runner id · version), Runner namespace and Helm release filled in.
Save as public/guide/signals-connect-runner.png
Connect a source, GitHub: the commands step with the token scope (repo names, read-only permissions), the kubectl secret command and the version-pinned helm upgrade.
Save as public/guide/signals-connect-commands.png
Connect a source, GitHub: the result “Connected · read-only verified · last sweep 0m ago · N observations”.
Save as public/guide/signals-connect-connected.png

The wizard never asks for a credential. TruStacks writes the commands; you run them on your own cluster.

  1. Choose a source: GitHub, read-only; ArgoCD deploy status; or SARIF upload.
  2. Pick the runner. Choose one of your connected runners, then enter its Runner namespace and Helm release (default trustacks-runner). For ArgoCD, also enter the namespace your ArgoCD Applications live in (default argocd). These values only fill in the commands; they are not sent anywhere. If no runner is connected, the wizard sends you to enroll one first. The GitHub source needs runner 0.2.14-rc27 or later; an older runner is stopped here with a prompt to upgrade it from Runners.
  3. Run the commands.
    • For GitHub: create a fine-grained personal access token scoped to the repos you have connected, with read-only repository permissions only (Actions, Contents, Metadata, Pull requests, Issues, Dependabot alerts, Code scanning alerts, Secret scanning alerts). Store it with the generated kubectl command. It reads the token with read -rs, so it never appears on screen or in your shell history, and pipes it to kubectl on standard input. printf is a shell builtin, so the token never becomes a process argument; --from-literal would put it in kubectl’s arguments, where anyone who can list processes (ps) could read it:

      read -rs GH_TOKEN && \ printf '%s' "$GH_TOKEN" | kubectl -n <runner-namespace> create secret generic trustacks-mcp-github \ --from-file=token=/dev/stdin && unset GH_TOKEN

      Then turn the source on. The --version is pinned to the version that runner runs now, so the upgrade neither up- nor downgrades it:

      helm upgrade <release> oci://ghcr.io/trustacks/charts/runner --version <runner-version> -n <runner-namespace> \ --reset-then-reuse-values \ --set mcpSignals.enabled=true \ --set mcpSignals.sources.github.enabled=true

      The runner needs HTTPS egress to api.github.com.

    • For ArgoCD: the same helm upgrade with --set observer.enabled=true --set observer.argocdNamespace=<namespace>. The chart grants the runner read-only get, list, watch on ArgoCD Applications and nothing else.

  4. Wait for the report. After I’ve run them, the wizard waits for that runner’s own report and shows exactly what came back: Connected · read-only verified, Refused, the Secret missing, or Last sweep failed. If nothing arrives within 10 minutes, it tells you to check that the runner pod restarted and to look in its logs.

How findings arrive without you

Most findings never need a manual upload to Signals. The read-only GitHub source reads code-scanning alerts, and from release 0.2.15-rc6, when your EnvironmentProfile declares a scanner that writes SARIF (Trivy, Semgrep), the DevOps Engineer’s CI workflow uploads that scanner’s results to GitHub code scanning. Your CI runs the scanner, GitHub stores the results, and the next sweep brings them here. See the Signals workshop.

Upload a SARIF file

Connect a source, SARIF upload: the file picker and the “Uploaded. N findings created.” result.
Save as public/guide/signals-sarif-upload.png

For a scanner whose results never reach GitHub. SARIF (Static Analysis Results Interchange Format) is the standard JSON report most scanners can write. Choose SARIF upload (or Upload on its row) and pick a .sarif or .json file. The file is posted to the findings intake; each result becomes a finding, and the list refreshes. The wizard reports how many findings were created, or that the file had no results. The file is read as data, never executed.

Findings

No findings yet

When nothing has reported a finding to your workspace, the screen shows No findings yet and lists how findings arrive: GitHub, read-only through your runner, and any scanner by SARIF upload. If the findings list fails to load, the screen says so (“Couldn’t load findings”), rather than showing an empty list.

Your findings

When at least one finding exists, a green strip reads Live · N from your sources.

  • Incoming findings (left): each with a severity chip (CRIT, HIGH, MED, LOW), title, source and age. A finding an MCP source observed shows its source as MCP feed · github.
  • The selected finding (right):
    • a header card: the finding’s id, source, observed by (for example mcp:github, for a finding seen by a read-only source in your runner and re-checked every sweep), fix source (if any) and when it was detected;
    • actions: Triage on a new finding; Propose a fix on a triaged finding whose repo is connected; Dismiss on anything not finished. Finished findings show Validated or Dismissed instead;
    • The governed loop: six steps (Finding detected, Coordinator triages, Crew proposes fix, Constitution decides, You approve, ArgoCD ships + validates) with the current one highlighted;
    • if the finding’s repo is not governed by TruStacks yet, This repo isn’t governed by TruStacks yet with Connect this repo →;
    • Proposed fix: before a fix is proposed, what the finding’s stage means and what moves it on. Once Propose a fix has run, the card shows that proposal (see below);
    • Transition history: every state change, oldest first.

The Proposed fix card

A finding’s Proposed fix card after Propose a fix: the DevOps Engineer’s one-line summary, “Constitution: allowed. Every rule passed.”, “The change · 6 files” with the file list, “How the crew got here”, and the green Review & merge the PR button.
Save as public/guide/signals-fix-card.png

After Propose a fix, the card follows the real proposal:

  • While it drafts: The DevOps Engineer is drafting the fix…, and the stepper advances on its own.
  • The summary: the DevOps Engineer’s one-line description, with The DevOps Engineer’s explanation to expand when there is more.
  • The constitution’s verdict:
    • allowed (green);
    • denied (red), listing each rule that refused it, linked to the rule, with No pull request was opened;
    • Not checked (amber) if the policy check didn’t run. That is never shown as allowed.
  • The change: every file the fix adds or changes, in full; click a file to expand it. The pull request has the line-by-line diff.
  • How the crew got here: the proposal’s run log.
  • Review & merge the PR: opens the real pull request. You approve by merging it on GitHub, and TruStacks sees the merge within about a minute and moves the finding to shipping. Once ArgoCD reports the app synced and healthy, it becomes validated. A merged or closed PR says so on the card.

There is no approve button in TruStacks: approving is merging, in the tool where you review code.

What it means

  • Triage says a human has looked at the finding and it is real.
  • Propose a fix starts a governed proposal for the service the finding belongs to: the DevOps Engineer drafts the change, it is validated and judged by the constitution, and a PR opens on your platform repo. It only works when the finding’s repo is connected as a service in an Application, and that service has been analyzed. Otherwise the app says to connect the repo and run an analysis first.
  • Dismiss closes the finding with no further action. It stays in the history.

Findings are not a second policy. A proposed fix gets the same validation, constitution check and human review as any other proposal.

What to do here

  1. Triage new findings.
  2. For a real issue in a connected service, Propose a fix. Watch the card. If the constitution allowed it, check the change, then Review & merge the PR (or close it if you don’t want it). If it denied it, no pull request was opened: fix the cause the card names, or the rule, and propose again. Open the proposal shows the full run.
  3. Dismiss noise, so the Overview queue only shows what needs you.

How it connects

  • Untriaged findings and fixes awaiting approval appear on the Overview queue.
  • A proposed fix is a normal proposal.
  • Connect this repo → opens the connect wizard.

Beta limits

  • Two intake paths. Findings arrive from the read-only GitHub source (open Dependabot, code-scanning and secret-scanning alerts on repos connected to an Application) and from SARIF uploads, plus the API (a SARIF endpoint and a generic findings endpoint). Each GitHub alert enters Signals once, however many sweeps see it. Repos added only through extraRepos never produce findings. Snyk and Trivy integrations are direction, not shipped; their output arrives today as SARIF.
  • The pull request doesn’t name the finding yet. A fix opened from Signals addresses the finding, but the PR title and body don’t say which finding it resolves.
  • The card finds the proposal among your 100 most recent proposals. In a very busy workspace an older fix may not show; it is still on the service’s Proposals tab.
  • A denied fix leaves the finding at “Constitution decides”. Fix the cause (or the rule) and propose again.
  • Before release 0.2.15-rc5, a just-uploaded or just-triaged finding could show Connect this repo with Propose a fix hidden until you reloaded the page. Reload if you see that on an older release.
Last updated on