Skip to content

feat(deployment): add behavioural workload signals with replay tooling - #3983

Open
baktun14 wants to merge 4 commits into
feat/deployment-probe-accelerator-evidencefrom
feat/deployment-workload-behavioural-signals
Open

baktun14 wants to merge 4 commits into
feat/deployment-probe-accelerator-evidencefrom
feat/deployment-workload-behavioural-signals

Conversation

@baktun14

Copy link
Copy Markdown
Contributor

Why

Ref CON-978

Stacked on #3982, which is where the evidence rows these signals read come from. Review that one first.

String matching only catches a workload we have already seen. These two signals describe a shape instead, so the probe has something to record about a workload that matches nothing. They record and count findings, nothing else: no verdict moves, and both stay off until the flag is set.

What

  • Two pure signal modules over one evidence row: one for a workload that holds the accelerator while carrying nothing large on disk, one for a workload with nothing established in either direction, past our own endpoints. Either alone has a benign population, so only the pair counts as a candidate.
  • The handler records the signals that fire on the rows it just wrote, logs them per service and counts them by signal. Verdicts are untouched.
  • npm run console -- replay-behavioural-signals re-scores recorded evidence for a window, or a corpus of fixture shapes, and reports per deployment what fired, what each agreement length would have reached, and how the counts move when the thresholds move. It reads and never writes.
  • Five fixture shapes ship with the repo so the signals are pinned in CI from the start, including two that deliberately stop short of a candidate.
  • Tests: specs for both signals and the combination, the replay service, the evidence service and the handler, plus integration coverage of the findings landing on the row with the flag on and staying off without it.

@baktun14
baktun14 requested a review from a team as a code owner September 20, 2026 10:51
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: akash-network/console/.coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: 3501168f-385f-4910-be69-7ff9107d312c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@baktun14
baktun14 force-pushed the feat/deployment-probe-accelerator-evidence branch from bd62327 to 14c8627 Compare September 20, 2026 11:01
@baktun14
baktun14 force-pushed the feat/deployment-workload-behavioural-signals branch 3 times, most recently from ea3c697 to fd2b01f Compare September 20, 2026 11:02

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the inline findings, I also checked the shared evidenceWriteFailures counter that both the pre-existing evidence-write failure path and the new recordBehaviouralFindings write failure (probe-evidence.service.ts) now increment — confirmed they do conflate under one unlabeled metric, but this is an observability gap rather than a functional bug, so it doesn't add a blocking concern beyond what's already flagged inline.

Extended reasoning...

Three confirmed bugs were already surfaced as inline comments on this PR (truncated-probe rows scored as fully scanned in probe-evidence.service.ts, the sensitivity report missing from the replay service's completion log, and IPv6 relay-endpoint string-equality mismatch in network-isolation.ts), so the PR already signals that human review is needed and I should not restate those. I independently verified the one ruled-out candidate issue in the task data by reading the actual diff: recordBehaviouralFindings in probe-evidence.service.ts calls this.instrumentation.recordEvidenceWriteFailure() on failure (line ~83), which is the exact same counter (workload_abuse_evidence_write_failures_total, no labels) incremented by the original evidence-insert failure path — confirmed via the diff to workload-abuse-instrumentation.service.ts, which added a separate labeled behaviouralFindings counter for successful findings but did not add a distinct failure counter/label for the new write path. This is a real but minor observability gap (alerting on evidence-write failures can no longer distinguish which write failed), not a correctness or security bug, consistent with it being ruled out as non-blocking.

Given three confirmed, non-trivial bugs already exist as inline comments, this PR clearly needs human attention regardless of what I add, so per the guidelines I should not approve and should not duplicate the inline findings in a top-level body. The narrow exception for speaking while findings exist is to note something concrete I separately examined and ruled out, which I have here (the shared-metric conflation), stated briefly and without implying it clears the PR or that no further review is needed.

Findings marked 🟡 are optional suggestions and need no follow-up push.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the inline findings, I also checked findCreatedBetween (workload-probe-evidence.repository.ts) for unbounded-result risk — it has no LIMIT, but it's only reachable from the new offline replay CLI over an operator-supplied window, not a request-path or untrusted-input query, so I ruled it out as a memory-exhaustion concern for this PR.

Extended reasoning...

This run's inline findings cover two confirmed bugs in BehaviouralSignalReplayService (unvalidated fixture parsing via JSON.parse(...) as BehaviouralReplayFixture, and the usesDatabase flag ignoring options.until when only that bound is supplied). Beyond those, I independently examined WorkloadProbeEvidenceRepository.findCreatedBetween for the same class of risk (unbounded query results) since it backs the same CLI tool, and ruled it out: it is invoked only by the read-only, operator-driven replay-behavioural-signals command over an explicit window, not by any API route or untrusted caller, so the blast radius of an unbounded read is limited to the operator's own tooling rather than a production or security concern.

Findings marked 🟡 are optional suggestions and need no follow-up push.

@baktun14
baktun14 force-pushed the feat/deployment-workload-behavioural-signals branch 2 times, most recently from 7f3f1a1 to c9013fa Compare September 20, 2026 12:22

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the inline finding, I also checked WorkloadProbeEvidenceRepository.findCreatedBetween (apps/api/src/workload-abuse/repositories/workload-probe-evidence/workload-probe-evidence.repository.ts:37-43) for an unbounded read — it has no .limit(), but it's only reached from the operator-run replay-behavioural-signals CLI (never a request path) and defaults to a 30-day window, so I didn't flag it as a bug.

Extended reasoning...

This run's confirmed finding (the usesDatabase fixture-load-failure fallback at behavioural-signal-replay.service.ts:66) is new and already going out as an inline comment, so it isn't restated here. I additionally traced findCreatedBetween's lack of a .limit() clause to see whether it posed the same kind of unbounded-scan risk as the confirmed issue, but concluded it doesn't warrant a finding: it's only invoked from the read-only, operator-triggered replay-behavioural-signals CLI path (not from any request handler), and the caller (#loadFromDatabase/#resolveWindow) always supplies a bounded window that defaults to 30 days when --since/--until are omitted, so this is an intentionally-open-ended offline tool rather than an unbounded production query.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request has been reviewed before and this review found new issues. Where they share a root cause, one fix may close them together.

Still open from earlier reviews (1):

  • Unresolved: 1 minor or pre-existing.

Comment thread apps/api/src/workload-abuse/config/env.config.ts
@baktun14
baktun14 force-pushed the feat/deployment-workload-behavioural-signals branch from c9013fa to 3894656 Compare September 20, 2026 13:00

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR again and found no new bugs. The commits pushed since my last review (bb2d2cf, fbfa6f1, 3894656) address all five previously raised findings in the code itself — not merely via self-resolved threads — plus the newly reported blank-env-var config crash. Because this is a large (1503-line) new abuse-detection subsystem with security implications, a human look is still worthwhile before merging.

What was reviewed:

  • Shell-status gating: evaluateBehaviouralSignals now returns no findings unless shellStatus === "completed", fixing the truncated-probe false positive.
  • IPv6 relay matching: normalizeHost now expands compressed IPv6 to match the probe's decoded fixed-width form.
  • Replay fixes: --until alone now triggers a database query, the threshold sweep is now logged, and per-fixture JSON is now schema-validated with per-file failure isolation.
  • Config fix: blank WORKLOAD_ABUSE_SIGNAL_RELAY_ENDPOINTS now falls back to its default instead of crashing config resolution.
Extended reasoning...

Overview

This is the fifth review pass on a PR that adds a new "behavioural signals" detection layer (accel-without-artifacts + network-isolation) to apps/api's workload-abuse module, plus a replay/CLI tool for tuning thresholds against fixtures or recorded evidence. Four commits (d115551, bb2d2cf, fbfa6f1, 3894656) landed since the base commit in this diff range, with the latter three specifically responding to five inline findings from my prior reviews plus one additional finding about a blank env var crashing config resolution.

Verification of prior findings

I independently re-read the current code (not relying on the author's thread self-resolutions, which are not evidence of a fix) for each previously raised issue: (1) the shell-status/truncation gating issue in probe-evidence.service.ts is now fixed via a shared evaluateBehaviouralSignals guard on shellStatus !== COMPLETE_SHELL_STATUS, applied identically in both the live path and the replay service; (2) the IPv6 relay-endpoint mismatch is fixed via a normalizeHost function that expands compressed IPv6 notation to the kernel's fixed-width hex form before comparison; (3) the usesDatabase logic in behavioural-signal-replay.service.ts was reworked to key off whether fixtures were explicitly requested (bundledFixtures || fixturePaths?.length) rather than whether the resulting fixture list ended up non-empty, which fixes both the --until-only case and the silent-fallback-on-bad-fixture-path case (the "nit 66" item that was still open in my last review); (4) the sensitivity sweep is now included in the BEHAVIOURAL_REPLAY_COMPLETED log; (5) fixture files are now validated against a real Zod schema (FIXTURE_SCHEMA.parse) with per-file try/catch so one malformed file no longer aborts the whole run; (6) the new WORKLOAD_ABUSE_SIGNAL_RELAY_ENDPOINTS env var now uses the same blankToUndefined preprocessing as its sibling field, so a blank value falls back to "[]" instead of throwing. All six are genuine code fixes, not just resolved GitHub threads.

Security risks

The module only records/counts findings and gates everything behind a feature flag (WORKLOAD_ABUSE_BEHAVIOURAL_SIGNALS_ENABLED) — no verdict or enforcement logic is touched, matching the PR description. No SQL injection, auth-bypass, or data-exposure concerns were apparent in the read-only replay service or the repository/controller changes.

Level of scrutiny and other factors

Despite no new findings this round, this remains a large, non-trivial addition (1503 insertions across 27 files) to a security/abuse-detection subsystem, including a new CLI surface, config surface, and persistence changes. Given the size and sensitivity, and consistent with my role's guidance to prefer deferring over approving large/security-adjacent changes even when no bugs are found, I'm recommending a human still take a look rather than approving outright, while noting that the concrete, previously-flagged issues have been resolved in code.

Two shape signals now run over the evidence rows a probe writes: one for a
workload that holds the accelerator while carrying nothing on disk, one for a
workload with nothing established in either direction. Both are recorded on the
row and counted, neither changes a verdict, and both stay off until the flag is
set.

A console command re-scores recorded evidence, or a corpus of fixture shapes,
and reports what each agreement length would have reached. It reads and never
writes.
…inished collecting

A section that stopped early looks exactly like a section with nothing in it,
and both signals read an absence as the thing worth noticing. Snapshots now
carry the status of the shell that produced them, and a collection that was cut
short supports no signal, in the live path and in the replay.

The replay honours a window given by its end alone, skips a fixture file it
cannot parse instead of losing the whole run with it, and logs the threshold
sweep it computes so an operator running the command actually sees it.

Relay addresses configured in the short form of an IPv6 address now match the
expanded form the probe decodes.
The evidence shape now names connections for what they are and keeps the
socket state with each one, so the signals and the replay corpus carry a half
open connection as such.
…nfig

A variable that is declared but left empty reached the JSON parse and turned
every resolution of the workload abuse config into a validation error. It now
falls back to the default the same way the sibling list does.

A replay that asked for fixtures and could read none of them reports nothing
rather than quietly scanning a month of recorded evidence instead.
@baktun14
baktun14 force-pushed the feat/deployment-workload-behavioural-signals branch from 3894656 to b7f7eb3 Compare September 20, 2026 13:21

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the latest commits and the seven issues raised across my earlier rounds on this PR (truncated-shell gating, IPv6 relay matching, until-only window handling, fixture parse failures, fixture-vs-database fallback, blank RELAY_ENDPOINTS config, and the missing sensitivity log) all now have corresponding code fixes with matching new test cases — I checked each one against the current source rather than just the commit messages. No new bugs were found this round. Given the size and abuse-detection sensitivity of this change, a human look is still worthwhile before merge.

Extended reasoning...

Overview

This diff adds a "behavioural signals" scoring layer to apps/api's workload-abuse trial-probe pipeline: two pure evaluators (accelerator-without-artifacts, network-isolation) combined into a candidate conjunction, new env-driven thresholds, persistence of findings via a new repository method, an OTel counter, and a read-only CLI replay tool with bundled JSON fixtures. This is round 6 of review on this PR; three new fix commits (d5f8fa7, db2cb44, b7f7eb3) landed after the last review round.

Security risks

No injection, auth-bypass, or data-exposure concerns. The feature only records/counts findings behind a disabled-by-default flag and does not alter enforcement verdicts. The main risk surface was correctness of the detection logic itself (false positives/negatives), which is what the prior review rounds focused on.

Level of scrutiny

I verified, by reading the current source directly (not the commit messages), that all seven previously-raised issues are fixed: evaluateBehaviouralSignals now gates on shellStatus === "completed" (types.ts/evaluate-behavioural-signals.ts), normalizeHost expands compressed IPv6 for relay matching (network-isolation.ts), usesDatabase in the replay service now considers until alone and distinguishes "no fixtures requested" from "fixtures requested but all failed to load," #readFixture wraps parsing in try/catch with parseReplayFixture doing real zod validation, WORKLOAD_ABUSE_SIGNAL_RELAY_ENDPOINTS is now wrapped in blankToUndefined, and the BEHAVIOURAL_REPLAY_COMPLETED log now includes sensitivity. Each fix has a corresponding new spec (probe-evidence.service.spec.ts:131, network-isolation.spec.ts IPv6 tests, several new cases in behavioural-signal-replay.service.spec.ts, env.config.spec.ts blank-string test), so these aren't just plausible-looking patches — they're exercised.

Other factors

Despite the fixes checking out, this remains an XL, multi-file feature in a security-relevant subsystem with a track record of five prior rounds each surfacing real bugs, and I was unable to execute the test suite in this sandboxed run (Bash was denied) to confirm green CI, relying instead on static reading of source and specs. That combination — scale, sensitivity, and no executed test confirmation — keeps this above the bar for silent auto-approval even though no new issues were found this round.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant