Vendor-neutral · self-hosted · open-source security correlation

Four alerts. One incident. Every claim cited.

SignalArray is the reasoning layer between your detection products and your incident response. It takes the findings you already have, correlates them with deterministic, replayable rules, and investigates each candidate case with a bounded, read-only agent that must cite its evidence. The output isn’t another alert. It’s a reviewable case: what belongs together, why, what happened, and what to do about it.

SPECIFICATION DRAFT · CONTRACTS UNDER REVIEW · NO IMPLEMENTATION YET

  • Deterministic correlation
  • Conservative identity
  • Cited evidence
  • Read-only investigator
  • Durable Temporal workflows
  • Vendor-neutral adapters
  • Default-deny response
The problem

Security teams don’t lack signals.

They lack a reliable way to know when signals from different systems describe the same event, gather the evidence, and explain what probably happened. Today the correlation engine is an analyst with six tabs open.

FAULT 01

Four queues, one incident

A cloud-security finding, an odd identity session, a suspicious process tree, and an outbound network alert may be one intrusion. They arrive as four unrelated queues of work, in four products, with four notions of “host.”

FAULT 02

The lookalike merge

A shared IP, a reused hostname, a display name that resembles another. Consoles that correlate on names merge things that aren’t the same, and one false merge contaminates every conclusion downstream.

FAULT 03

The model on the firehose

Pointing an LLM at raw telemetry is expensive, unsafe, and impossible to evaluate. Every log line, process argument, and issue description becomes a candidate instruction aimed at the model.

FAULT 04

Confidence as authority

A fluent report with a score at the top starts to look like permission. But a score without evidence is not a finding, and a finding without a policy decision is not authorization to touch production.

SignalArray’s answer isn’t a smarter detector. It’s a case: deterministic software decides what belongs together, a bounded investigator explains it with citations, and nothing on the page authorizes a mutation.

The layers

Three jobs. Three correctness bars.

Detection, correlation, and investigation need different data volumes, permissions, and failure semantics. SignalArray keeps them apart on purpose, and only the last one involves a model.

Layer A — the canonical signal

Vendor payloads stop at the adapter

Every finding becomes one versioned contract with provenance intact, and nothing downstream ever sees the native shape:

schema_version  signalarray.signal/v1alpha1
source          adapter · instance · native_id · native_version
times           occurred_at · observed_at · ingested_at — three distinct facts
entities        (namespace, scope, value) — scoped keys, never names
evidence        evidence_id · reference · content_sha256
dedupe key      (workspace, adapter, instance, type, id, version)

Redelivery of the same version returns the same signal_id. A meaningful update is a new immutable version linked to the last, never an overwrite of evidence a case already used.

Layer B — the correlation rule

Membership is a proof, not a hunch

Rules are data, not scripts. Each immutable version declares what it needs and records why it matched:

  • required predicates that no pile of weak hints can outvote
  • weighted corroborators and explicit exclusions, with the arithmetic stored
  • a rule-specific window — five to fifteen minutes to start, never one global constant
  • accepted identity levels: exact, asserted, or rule-authorized probable only
  • an explanation template populated with the matched fact IDs
  • positive, negative, boundary, duplicate, and false-merge fixtures

Only then does a model see anything. Layer C is the investigator: it receives a bounded case snapshot, not the event store; it may ask for evidence through registered read-only tools or complete a report, and nothing else. It returns incident, benign, or inconclusive, and uncertainty is a supported result, not a failure.

The investigation

Validate. Page. Then expand.

Any High or Critical signal starts a fast, narrowly budgeted Validation Investigation, even alone. Exactly one result suppresses the page. Everything else, including timeouts and failures, alerts a human and unlocks the full investigation.

  1. A signal lands, once. The adapter authenticates the source, validates the payload, derives the idempotency key, and normalizes. Redelivery returns the original signal_id; malformed input is quarantined, never patched with invented fields.

  2. Identity is resolved conservatively. Scoped keys, source-asserted aliases, and versioned probable mappings can join. Resemblance cannot. Ambiguity is represented, not collapsed.

  3. Rules append membership events. Crossing a creation threshold starts one workflow with a deterministic ID: signalarray:case:{workspace_id}:{case_id}. Starting it twice signals the existing run.

  4. Validation, fast and separately budgeted. The minimum evidence needed to decide whether the claimed severity is credible. It emits a cited validation record, never a stand-in for the full report.

  5. Escalate by default. Anything but affirmative benign at high confidence writes an immutable validation_escalated event and durably enqueues the on-call alert. Full Investigation and playbook selection start without waiting for delivery or acknowledgement.

  6. A bounded hypothesis loop. Each turn returns exactly one schema-valid action: request_evidence with a registered tool and the hypothesis it would distinguish, or complete_report. Budgets end the loop as a normal stop, named in the report.

  7. Validate citations, publish, wait for a human. Every cited evidence_id must exist and have been visible to that turn; failed tool calls cannot masquerade as evidence. Reports are immutable versions. Disposition is recorded with actor, reason, and time.

Correlation decisions

Every grouping shows its arithmetic.

A candidate case comes with a proof of why the signals were grouped, and every decision replays identically against the same input and rule version. Open a row to read the evaluation.

Case Condition Decision
Same accepted workload entity in both signals; occurrence times ten minutes apart Decision: ATTACHED
required: shared entity at level exact ✓ · required: within rule window ✓ · corroborating: identity assumed a role touching that workload (+w) · exclusions: none — match record stores inputs, weights, and rule_id@version.
Display names resemble each other; no shared scoped identifier Decision: NOT MERGED
resolution level is possible, which may guide enrichment but cannot satisfy an identity join. The entities remain distinct until evidence justifies a relationship; a false merge would corrupt the entire investigation.
Outbound traffic matches an approved scanner window Decision: EXCLUDED
exclusion predicate fires; score reduced below the attach threshold. The suppression is itself a recorded fact, so a later rule version cannot quietly rewrite what this one decided.
Same source version delivered a second time Decision: DEDUPED
canonical key (workspace, adapter, instance, type, id, version) already exists → the original signal_id is returned. No second membership evaluation, no second investigation, no duplicate case transition.
The investigator concludes another signal belongs in this case Decision: DENIED
a model cannot add a signal to a case. It may say so in the report; only a later deterministic rule or an audited human correction can change membership.

Scores prioritize and gate explicit evidence. They are not calibrated incident probability, and the specification says so out loud, because a number that looks like a probability gets treated like one.

The gates

Every tool call passes five gates.

Nothing here is enforced by a prompt. Each gate is a deterministic check in the activity that runs the call, evaluated independently of anything the model said.

  • Gate 01
    Scope

    A case can only ask about itself.

    • workspace matches the case
    • entity in case or one allowed hop
    • time range inside policy
    Mechanism: SCOPED
  • Gate 02
    Schema

    Free-form tool execution is not an action.

    • registered read-only operation
    • exact argument schema
    • e.g. cloud_security.get_attack_paths
    Mechanism: TYPED
  • Gate 03
    Budget

    Exhaustion is a normal stop, not an error.

    • turns · calls · duplicates
    • wall clock · tokens · cost
    • separate per phase, never borrowed
    Mechanism: BOUNDED
  • Gate 04
    Citation

    Absence of evidence is never evidence.

    • every material claim cites evidence_id
    • cited evidence visible to that turn
    • failed call ≠ retrieved evidence
    Mechanism: CITED
  • Gate 05
    Redaction

    The model never holds a credential.

    • secrets stripped before context
    • sensitivity class per evidence record
    • context manifest hashed and audited
    Mechanism: REDACTED

Validation failure comes back as a structured denial and is audited. The investigator cannot negotiate around it through prose, and quoted source content is labeled as untrusted data in every excerpt it sees.

The response plane

Confidence is not authorization.

Automated response is optional, separate, and default deny. A scenario-specific Response Playbook runs as a durable Response Run under its own agent, credentials, and budgets. Operators author it through a guided UI with safe presets and plain-language review. The UI compiles to an immutable revision you can diff, replay, and audit.

recommend_only

Record the match and the proposed action. Request nothing, execute nothing. Also the result of every unmatched, conflicting, expired, or invalid policy.

approval_required

A bounded action proceeds only after an authorized human records a separate approval with actor, scope, revision, and expiry. A page acknowledgement does not count.

automatic

An explicitly scoped, reversible action within strict target and blast-radius limits. Policy and live target facts are revalidated immediately before the mutation.

no matching active policy

The recommendation stays in the case and the alert. Nothing infers permission, widens a target, or falls back to a different action.

The Response Agent reasons only at declared decision steps and selects exactly one eligible playbook using cited evidence. Deterministic orchestration owns transitions, waits, approvals, policy calls, mutations, verification, and terminal state. A successful adapter request is not proof of containment; a verify step has to show it.

Boundaries

Never installed.

Not switched off. Not hidden behind a prompt. Absent. Each boundary below is a requirement with an adversarial test in the security model, not a configuration default.

Never lets a model decide case membership. Deduplication, identity, windows, and grouping are deterministic and replayable. The investigator reasons over a case; it doesn’t assemble one.

Never merges on a name. Hostnames, emails, IPs, and tags are aliases or observables. Only scoped identifiers, authoritative assertions, and versioned probable rules can join.

Never scans the firehose. SignalArray begins at signals. Upstream products keep doing high-volume collection and detection; a bounded investigation may query telemetry, but no model reads the stream.

Never gives the investigator a write path. Destructive or production-mutating tools are impossible to register in the v1 investigator role. The response plane does not exist in that runtime.

Never treats confidence as authorization. No threshold, including 100%, authorizes a mutation. Only an active, immutable policy revision matching the exact action, targets, environment, and bounds can.

Never treats an acknowledgement as approval. A page being seen or owned is a coordination fact. Human authorization is a distinct audited human_approval step with its own expiry.

Never lets source content steer the system. Log lines, issue descriptions, URLs, and documents remain quoted evidence. They never become workflow policy, tool permission, or playbook instruction.

Never fabricates evidence. A failed or denied tool call is an explicit gap. A report cannot describe it as retrieved, and cannot describe a recommended action as taken.

Never lets a vendor payload cross the adapter. Credentials, native shapes, and vendor errors stay inside the adapter. Core rules may not depend on an extensions field.

Never requires StarColony. The same SignalArray-owned workflow runs on a bundled Temporal or on StarColony. Evaluation, dogfood, and core operation stay standalone by default.

What a prompt-injected investigator can actually reach: a redacted case projection, registered read-only tools inside case scope, and a report schema that rejects uncited claims. That is the entire surface.

Site survey

What’s specified. What’s open.

SignalArray is being specified in the open, contract first. Present tense above means the specification; here is exactly what is settled and what is deliberately still a question.

Specified — decided and written down

  • Canonical signal contract with immutable provenance and a six-part deduplication key
  • Entity model with scoped keys and five resolution levels, exact through rejected
  • Correlation rule contract: predicates, weights, exclusions, windows, explanations, fixtures
  • Two-phase investigation workflow on Temporal, one portable implementation for standalone and StarColony runtimes
  • Recipient routing plane with Slack, on-call, signed webhook, and automation as reference destinations
  • Response playbooks and default-deny policy, authored in a guided UI and compiled to immutable revisions
  • Security model with an authority table and a required adversarial test list
  • One-command Docker Compose evaluation path; Kubernetes with Helm as the durable deployment

Stated plainly

No implementation exists yet. Every integration named on this page is a reference adapter or planned work. The specification is the product today.

Wiz and Datadog are reference adapters, not dependencies. They demonstrate two complementary signal sources. Core contracts may not contain logic that requires either.

SignalArray is not a SIEM, a detection console, or a managed SOC. It reduces cross-tool investigation toil for a small team that already runs several detectors and is willing to self-host.

Early access

Design partners, before the first signal lands.

We’re looking for a small set of security teams who already run Wiz, Datadog, or their equivalents, lose time reconstructing incidents across them, and would rather shape the contracts than inherit them.

Case manifest · design partner
STAGEspecification draft
SCOPEWiz + Datadog closed loop
RUNTIMETemporal · standalone or StarColony
OUTPUTa reviewable, cited case
Become a design partner

No invented logos, no fake metrics, no testimonials. A conversation about your detectors, your investigation toil, and our open questions.

Deterministic before agentic. Evidence before confidence.