{title}
{body}
${escapeHtml(subtitle)}
Graph confidence
Findings
Handoffs
High confidence
Owners
npm run dev completed. Findings, graph, and remediation queue are visible for review.
npm run dev completed. Handoffs, graph, and remediation queue are visible for review.
- Northwall brings agents into security operations: triage alerts, build the investigation graph, draft the response plan, and send the work to the right owner. + Northwall builds an AppSec graph, dispatches specialist agents across code and ownership context, and sends approved remediation work to the right owner.
- GitHub is the first connector for code context and remediation work items. + GitHub is the first connector for source context and approved remediation work.
{eyebrow}
+{body}
} ++ Agentic AppSec orchestration +
+- Northwall runs specialist agents across source context, evidence, and ownership. Analysts approve the plan before issues are created. +
+ Northwall turns GitHub application context into approved AppSec work by building a knowledge graph, planning governed agent missions, and dispatching parallel MoE specialists across auth, dependencies, CI/CD, config, ownership, and threat context.
+{body}
+ It is not a passive code review bot. Northwall builds graph context from application evidence, proposes a mission plan, routes work to specialist security agents, streams execution, and creates owner-ready remediation handoffs after approval. +
+{body}
+{body}
+{body}
+{body}
++ That framing matters for security buyers. It says Northwall is practical today, extensible tomorrow, and careful about the difference between implemented surfaces and roadmap direction. +
+{faq.answer}
+Run a mission
+- Build context, assign agents, approve the response plan, then send the work to owners. + Build the AppSec graph, approve the specialist agent plan, run parallel investigation, then send the work to owners.
Agentic SOC
-Triage, investigation, response, and owner handoff in one run.
+Agentic AppSec
+Graph context, parallel agents, approval, and owner handoff in one mission.
| {head} | ))}
|---|
Current plan
-For teams running agent-assisted security operations every week.
+For teams running graph-backed, agent-assisted AppSec work every week.
{item}
))}Human approval is required before response actions run.
+Human approval is required before agent execution and owner handoff.
Request rate is capped at 30 rpm unless an admin lowers it.
Evidence retention is 365 days for paid workspaces.
-External systems require explicit scope approval.
+External systems require explicit scope approval before they enter the graph.
- Northwall gives security teams an agent crew for alert triage, investigation graphs, response plans, and owner handoff. + Northwall gives security teams a specialist agent crew for AppSec graph building, parallel investigation, approved execution, and owner handoff.
Human approval stays in the loop. Scope is checked before a run starts.
diff --git a/packages/frontend/src/hooks/use-sdk-stream.ts b/packages/frontend/src/hooks/use-sdk-stream.ts index 829a7df..5b23562 100644 --- a/packages/frontend/src/hooks/use-sdk-stream.ts +++ b/packages/frontend/src/hooks/use-sdk-stream.ts @@ -331,7 +331,7 @@ function processResult( state.feed.push({ kind: "result", status: "success", - summary: msg.result?.slice(0, 200) ?? "Assessment completed", + summary: msg.result?.slice(0, 200) ?? "Mission completed", costUsd: msg.total_cost_usd, durationMs: msg.duration_ms, turns: msg.num_turns, diff --git a/packages/frontend/src/lib/northwall-demo.ts b/packages/frontend/src/lib/northwall-demo.ts index 9f18292..6ced8d6 100644 --- a/packages/frontend/src/lib/northwall-demo.ts +++ b/packages/frontend/src/lib/northwall-demo.ts @@ -1,10 +1,10 @@ import type { AssessmentLoop, Finding, SystemGraph } from "@northwall/shared"; export const targetProfile = { - name: "AcmePay Security Operations", - type: "Owned SOC workspace", - stack: ["Microsoft Sentinel", "CrowdStrike", "GitHub", "Postgres", "Stripe webhooks", "Jira"], - scope: ["siem://acmepay", "edr://acmepay", "repo://acmepay", "jira://security"], + name: "AcmePay AppSec Orchestration", + type: "Owned AppSec mission workspace", + stack: ["GitHub", "Postgres", "Stripe webhooks", "Jira", "Microsoft Sentinel roadmap", "CrowdStrike roadmap"], + scope: ["repo://acmepay", "owner://acmepay", "jira://security", "siem://roadmap", "edr://roadmap"], budget: "35 min / human approval required", }; @@ -12,21 +12,21 @@ export const systemGraph: SystemGraph = { confidence: 94, lastUpdatedAt: 1_777_897_200_000, nodes: [ - { id: "siem", label: "SIEM incident queue", kind: "service", risk: "high" }, - { id: "edr", label: "Endpoint telemetry", kind: "integration", risk: "high" }, - { id: "identity", label: "Identity events", kind: "auth", risk: "critical" }, - { id: "cloud", label: "Cloud audit logs", kind: "service", risk: "medium" }, + { id: "repo", label: "GitHub source context", kind: "integration", risk: "medium" }, { id: "app", label: "Customer app", kind: "app", risk: "medium" }, - { id: "repo", label: "GitHub code context", kind: "integration", risk: "medium" }, + { id: "auth", label: "Auth boundary", kind: "auth", risk: "critical" }, + { id: "deps", label: "Dependency graph", kind: "package", risk: "high" }, + { id: "ci", label: "CI and release controls", kind: "integration", risk: "medium" }, + { id: "config", label: "Runtime configuration", kind: "service", risk: "medium" }, { id: "owners", label: "Service owners", kind: "service", risk: "low" }, - { id: "tickets", label: "Response work items", kind: "integration", risk: "low" }, + { id: "tickets", label: "Owner handoff work", kind: "integration", risk: "low" }, ], edges: [ - { id: "siem-edr", source: "siem", target: "edr", label: "alert evidence" }, - { id: "siem-identity", source: "siem", target: "identity", label: "user context" }, - { id: "identity-cloud", source: "identity", target: "cloud", label: "session activity" }, - { id: "cloud-app", source: "cloud", target: "app", label: "affected service" }, - { id: "app-repo", source: "app", target: "repo", label: "code owner lookup" }, + { id: "repo-app", source: "repo", target: "app", label: "source context" }, + { id: "app-auth", source: "app", target: "auth", label: "auth boundary" }, + { id: "repo-deps", source: "repo", target: "deps", label: "package evidence" }, + { id: "repo-ci", source: "repo", target: "ci", label: "release guardrails" }, + { id: "app-config", source: "app", target: "config", label: "runtime context" }, { id: "repo-owners", source: "repo", target: "owners", label: "ownership" }, { id: "owners-tickets", source: "owners", target: "tickets", label: "handoff" }, ], @@ -35,38 +35,38 @@ export const systemGraph: SystemGraph = { export const expertTeam = [ { name: "Nova", - role: "Incident Cartographer", - focus: "Maps alerts, entities, assets, owners, and investigation paths.", - status: "Investigation graph ready", + role: "System Cartographer", + focus: "Maps routes, packages, controls, owners, and remediation paths.", + status: "AppSec graph ready", }, { name: "Rhea", - role: "Alert Triage Agent", - focus: "Cuts duplicate signals, groups related alerts, and ranks urgency.", - status: "Triage complete", + role: "Auth Boundary Agent", + focus: "Reviews auth, tenant, session, middleware, and permission-sensitive paths.", + status: "Boundary review complete", }, { name: "Kade", - role: "Threat Investigator", - focus: "Checks identity, endpoint, cloud, and repo context for a coherent case.", - status: "Correlating evidence", + role: "Dependency Analyst", + focus: "Checks package evidence, lockfile exposure, ownership, and release risk.", + status: "Correlating package evidence", }, { name: "Mira", - role: "Response Planner", - focus: "Drafts response tasks with owners, approvals, and rollback notes.", + role: "CI/Config Analyst", + focus: "Reviews pipeline, runtime configuration, environment references, and guardrails.", status: "Plan ready", }, { name: "Ilya", role: "Control Verifier", - focus: "Checks whether compensating controls already reduced the risk.", + focus: "Checks whether compensating controls already reduce AppSec risk.", status: "Verification running", }, { name: "Vera", role: "Human Review Agent", - focus: "Prepares the analyst handoff and keeps risky actions behind approval.", + focus: "Prepares owner handoff and keeps risky actions behind approval.", status: "Preparing handoff", }, ]; @@ -74,32 +74,32 @@ export const expertTeam = [ export const loops: AssessmentLoop[] = [ { id: "loop-1", - title: "Map the incident", - strategy: "Correlate SIEM, EDR, identity, cloud, repo, and ownership context.", + title: "Map the AppSec graph", + strategy: "Correlate source, routes, auth, dependencies, CI, config, and ownership context.", agents: ["Nova", "Rhea"], findingsAdded: 1, graphChanges: 11, - nextHypothesis: "Identity event and endpoint alert point to the same privileged workflow.", + nextHypothesis: "Auth boundary and service ownership point to the same high-risk route.", status: "complete", }, { id: "loop-2", - title: "Triage likely blast radius", - strategy: "Separate noisy alerts from assets, users, and services with real exposure.", + title: "Run parallel specialists", + strategy: "Split auth, dependency, ownership, config, and CI work across focused agents.", agents: ["Rhea", "Mira", "Kade"], findingsAdded: 3, graphChanges: 6, - nextHypothesis: "Cloud session and service owner data can narrow response scope.", + nextHypothesis: "Dependency and CI context can narrow which owners need action.", status: "complete", }, { id: "loop-3", title: "Verify controls", - strategy: "Check safe evidence sources and existing controls before escalation.", + strategy: "Check safe source evidence and existing controls before escalation.", agents: ["Ilya", "Mira"], findingsAdded: 1, graphChanges: 3, - nextHypothesis: "Evidence supports two high-confidence response tasks.", + nextHypothesis: "Evidence supports two high-confidence owner handoffs.", status: "running", }, { @@ -109,7 +109,7 @@ export const loops: AssessmentLoop[] = [ agents: ["Vera"], findingsAdded: 0, graphChanges: 1, - nextHypothesis: "Stop after response plan generation unless new evidence appears.", + nextHypothesis: "Stop after owner handoff generation unless new evidence appears.", status: "queued", }, ]; @@ -117,38 +117,38 @@ export const loops: AssessmentLoop[] = [ export const findings: Finding[] = [ { id: "BG-104", - title: "Privileged session touched billing export path after unusual login", + title: "Billing export route crosses auth and ownership boundaries", severity: "high", confidence: "high", status: "open", owner: "Security Engineering", - affectedNodeIds: ["identity", "app", "repo"], + affectedNodeIds: ["auth", "app", "repo"], evidence: [ - "Identity events show a new device for an admin user.", - "Endpoint telemetry puts the same user on a managed laptop.", + "Auth middleware and billing export route sit in the same request path.", + "Tenant ownership checks are owned by Security Engineering.", "Code ownership maps the touched billing export path to the Payments team.", ], - businessImpact: "The case may be benign, but it crosses identity, endpoint, and sensitive billing code in one short window.", - fixPlan: "Ask the owner to verify the session, check device posture, and review the export route permissions before closing the case.", - verificationStep: "Attach identity, EDR, and code-owner evidence to the work item; require analyst approval before closure.", + businessImpact: "The path touches sensitive billing exports and shared auth logic, so weak ownership can delay remediation.", + fixPlan: "Ask the owner to verify tenant checks, route permissions, and billing export ownership before release.", + verificationStep: "Attach route, auth, and code-owner evidence to the work item; require analyst approval before closure.", cwe: "CWE-862", asvs: "ASVS 4.3.1", kev: false, }, { id: "BG-117", - title: "Payment webhook alert lacks owner and rollback path", + title: "Payment webhook route lacks owner and rollback path", severity: "high", confidence: "medium", status: "in_progress", owner: "Payments", - affectedNodeIds: ["siem", "app", "owners"], + affectedNodeIds: ["app", "config", "owners"], evidence: [ - "SIEM alert is tied to the Stripe webhook route.", + "Source inventory maps the Stripe webhook route.", "Service ownership points to Payments, not the platform queue.", "No rollback note is attached to the current ticket template.", ], - businessImpact: "A real payment incident can sit in the wrong queue while billing state changes continue.", + businessImpact: "A payment security issue can sit in the wrong queue while billing state changes continue.", fixPlan: "Create a Payments-owned response task with webhook replay checks, rollback owner, and customer-impact notes.", verificationStep: "Reviewer confirms owner assignment and rollback path before the work item is marked ready.", cwe: "CWE-345", @@ -157,18 +157,18 @@ export const findings: Finding[] = [ }, { id: "BG-122", - title: "Dependency signal affects service in active incident path", + title: "Dependency signal affects a service on the AppSec graph", severity: "medium", confidence: "high", status: "ready_for_review", owner: "Platform", - affectedNodeIds: ["repo", "cloud"], + affectedNodeIds: ["repo", "deps"], evidence: [ "Lockfile contains a vulnerable transitive package below the patched advisory range.", - "The package is pulled into the service linked to the active alert.", + "The package is pulled into a service on the approved mission graph.", "CISA KEV enrichment raised response priority.", ], - businessImpact: "The package issue is no longer just backlog hygiene because it sits on the current incident graph.", + businessImpact: "The package issue is no longer just backlog hygiene because it sits on the current AppSec graph.", fixPlan: "Update the parent package, regenerate the lockfile, and attach the SBOM diff to the response task.", verificationStep: "Confirm the affected package is absent from the production dependency graph.", cve: "CVE-2025-47281", @@ -178,17 +178,17 @@ export const findings: Finding[] = [ }, { id: "BG-131", - title: "Low-confidence alert kept out of the response queue", + title: "Low-confidence signal kept out of the owner queue", severity: "medium", confidence: "medium", status: "open", - owner: "SOC Analyst", - affectedNodeIds: ["siem", "edr"], + owner: "AppSec Reviewer", + affectedNodeIds: ["repo", "ci"], evidence: [ - "Alert pattern matched an older detection rule.", - "Endpoint and identity context did not support escalation.", + "Pattern matched an older dependency signal.", + "Graph and ownership context did not support escalation.", ], - businessImpact: "Without filtering, analysts waste time on a weak signal while higher-confidence work waits.", + businessImpact: "Without filtering, reviewers waste time on a weak signal while higher-confidence handoffs wait.", fixPlan: "Keep the evidence on the case, but do not create an owner task unless a second signal appears.", verificationStep: "Reviewer checks that no response task was created for the weak signal.", cwe: "CWE-1032", @@ -199,9 +199,9 @@ export const findings: Finding[] = [ export const evidenceTimeline = [ ["09:41", "Scope gate", "Owned systems confirmed; response actions require approval."], - ["09:43", "Graph update", "Mapped 8 nodes across SIEM, EDR, identity, cloud, app, repo, owners, and work items."], - ["09:47", "Agent handoff", "Triage Agent and Threat Investigator started parallel evidence review."], - ["09:52", "Finding", "BG-104 promoted to high confidence after identity and endpoint correlation."], - ["09:57", "Finding", "BG-117 kept at medium confidence pending Payments owner confirmation."], + ["09:43", "Graph update", "Mapped 8 nodes across repo, app, auth, dependencies, CI, config, owners, and work items."], + ["09:47", "Agent handoff", "Auth Boundary Agent and Dependency Analyst started parallel evidence review."], + ["09:52", "Handoff", "BG-104 promoted to high confidence after route and auth correlation."], + ["09:57", "Handoff", "BG-117 kept at medium confidence pending Payments owner confirmation."], ["10:04", "Owner handoff", "BG-122 moved to review with SBOM verification step."], ]; diff --git a/packages/shared/src/schemas/appsec.test.ts b/packages/shared/src/schemas/appsec.test.ts index cf41113..57e9a83 100644 --- a/packages/shared/src/schemas/appsec.test.ts +++ b/packages/shared/src/schemas/appsec.test.ts @@ -31,7 +31,7 @@ describe("AppSec scope gate", () => { }); expect(result.allowed).toBe(false); expect(result.reasons).toContain("Third-party targets are outside scope."); - expect(result.reasons).toContain("Destructive testing is disabled for safe SOC runs."); + expect(result.reasons).toContain("Destructive testing is disabled for safe AppSec missions."); }); it("requires allowed hosts for staging URL assessments", () => { diff --git a/packages/shared/src/schemas/appsec.ts b/packages/shared/src/schemas/appsec.ts index e6b0ea7..1b5cd60 100644 --- a/packages/shared/src/schemas/appsec.ts +++ b/packages/shared/src/schemas/appsec.ts @@ -112,7 +112,7 @@ export function validateScopeGate(scope: EngagementScope): ScopeGateResult { if (!scope.ownedEnvironment) reasons.push("Target must be an owned or explicitly authorized environment."); if (!scope.authorizationConfirmed) reasons.push("Authorization must be confirmed before execution."); if (scope.thirdPartyTargets) reasons.push("Third-party targets are outside scope."); - if (scope.destructiveTesting) reasons.push("Destructive testing is disabled for safe SOC runs."); + if (scope.destructiveTesting) reasons.push("Destructive testing is disabled for safe AppSec missions."); if (scope.targetType === "staging-url" && scope.allowedHosts.length === 0) { reasons.push("Staging URL runs require at least one allowed host."); } diff --git a/packages/shared/src/schemas/assessment.test.ts b/packages/shared/src/schemas/assessment.test.ts index 0b066ff..3a1cf0c 100644 --- a/packages/shared/src/schemas/assessment.test.ts +++ b/packages/shared/src/schemas/assessment.test.ts @@ -70,7 +70,7 @@ describe("GitHub issue payload", () => { }; const payload = buildGitHubIssuePayload(finding); - expect(payload.labels).toEqual(["northwall", "agentic-soc", "security-operations", "high", "backend"]); + expect(payload.labels).toEqual(["northwall", "agentic-appsec", "appsec-orchestration", "high", "backend"]); }); }); diff --git a/packages/shared/src/schemas/assessment.ts b/packages/shared/src/schemas/assessment.ts index 73771fb..91f8685 100644 --- a/packages/shared/src/schemas/assessment.ts +++ b/packages/shared/src/schemas/assessment.ts @@ -205,6 +205,6 @@ export function buildGitHubIssuePayload(finding: VulnerabilityFinding): { return { title: finding.issueTitle, body: finding.issueBody, - labels: Array.from(new Set(["northwall", "agentic-soc", "security-operations", finding.severity, finding.confidence, ...finding.labels])), + labels: Array.from(new Set(["northwall", "agentic-appsec", "appsec-orchestration", finding.severity, finding.confidence, ...finding.labels])), }; }