LandfallDocs
Reference

Canvas widgets

The war room's canvas is built by the investigator agent from what it reads. Every card is one of the widget types below, rendered from validated data, and every query-backed card re-reads its source for the window you choose.

Widget types

The same catalog drives the agent's add_widget tool, the bridge's share_with_room widget argument, the hosted connector's describe_widget_types read and the canvas renderer. Adding a type anywhere means adding it here.

The pictures of the first seven types were captured before the card face was simplified. They show the older face, with chips for the window, source, pin or freshness and a provenance line. Those now sit behind the status dot, the ⋯ menu and the info view.

Stat tile stat

One current number with its direction and baseline, for a headline metric.

  • current error rate
  • p99 latency now
  • healthy host count
  • requests per second
  • any single KPI

Can be backed by a signed query that re-reads live. Follows the canvas time window.

app.landfalls.ai · War room · Canvas · Stat tile
A pinned Stat tile reading 6.7 % with an up 22× badge, baseline 0.3% and a red sparkline.
One value, how far it sits above its baseline, and a sparkline of the window.

Data shape

{ value: number, unit?, decimals?, delta?: number, deltaLabel?, trend?: "up"|"down"|"flat", tone?: "good"|"warning"|"serious"|"critical"|"neutral", baseline?: number, baselineLabel?, spark?: number[] }

Example

{
  "value": 6.7,
  "unit": "%",
  "decimals": 1,
  "delta": 6.4,
  "deltaLabel": "↑ 22×",
  "trend": "up",
  "tone": "critical",
  "baseline": 0.3,
  "baselineLabel": "baseline 0.3%",
  "spark": [
    0.3,
    0.3,
    0.4,
    0.3,
    2.1,
    5.8,
    6.4,
    6.7
  ]
}

Time series chart

One or more metrics over time on a shared clock axis, with optional thresholds and deploy markers.

  • error rate over the incident
  • latency trend
  • traffic volume
  • one metric split by region, zone or service
  • comparing a metric before and after a change

Can be backed by a signed query that re-reads live. Follows the canvas time window. Up to 8 series; the rest fold into one "other".

app.landfalls.ai · War room · Canvas · Time series
A Time series card titled 5XX ERROR RATE FOR DISTRIBUTION E123ABC, with a spike between about 14:10 and 14:30.
The 5xx error rate of one CloudFront distribution over the incident window, read from CloudWatch.

Data shape

{ series: [{ label, unit?, decimals?, points: [{ t: ISO-8601, v: number }] }] (max 8), yAxis?: { min?, max?, unit?, label? }, thresholds?: [{ value, label?, tone? }], markers?: [{ t: ISO-8601, label, kind? }] }

Example

{
  "series": [
    {
      "label": "eu-west-1",
      "unit": "%",
      "points": [
        {
          "t": "2026-09-04T14:00:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:15:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:30:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:35:00Z",
          "v": 9.8
        },
        {
          "t": "2026-09-04T14:45:00Z",
          "v": 12.4
        }
      ]
    },
    {
      "label": "us-east-1",
      "unit": "%",
      "points": [
        {
          "t": "2026-09-04T14:00:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:15:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:30:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:35:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:45:00Z",
          "v": 0.4
        }
      ]
    }
  ],
  "thresholds": [
    {
      "value": 5,
      "label": "alert · 5%",
      "tone": "warning"
    }
  ],
  "markers": [
    {
      "t": "2026-09-04T14:32:00Z",
      "label": "deploy #4127",
      "kind": "deploy"
    }
  ]
}

Table table

Ranked rows with typed columns: status codes as pills, shares as bars, numbers aligned.

  • top error URLs
  • slowest endpoints
  • hosts by error count
  • targets and their health
  • anything ranked

Can be backed by a signed query that re-reads live. Follows the canvas time window.

app.landfalls.ai · War room · Canvas · Table
A pinned Table card titled TOP ERROR URLS with two rows, /api/checkout/session and /api/cart, each with code 502, a five-minute count and a share bar.
The URLs returning the most errors, with each row’s share of the total drawn as a bar.

Data shape

{ columns: [{ key, label, type: "string"|"number"|"time"|"status"|"share" }], rows: [{ [key]: string | number | { v, tone? } }], highlightKey? }

Example

{
  "columns": [
    {
      "key": "path",
      "label": "Path",
      "type": "string"
    },
    {
      "key": "code",
      "label": "Code",
      "type": "status"
    },
    {
      "key": "count",
      "label": "Count 5m",
      "type": "number"
    },
    {
      "key": "share",
      "label": "Share",
      "type": "share"
    }
  ],
  "rows": [
    {
      "path": "/api/checkout/session",
      "code": 502,
      "count": 4812,
      "share": 18.2
    },
    {
      "path": "/api/cart",
      "code": 502,
      "count": 3109,
      "share": 14.7
    }
  ]
}

Log view logView

Raw log lines in the window, colored by level, with timestamps.

  • origin error lines
  • the first errors after a deploy
  • a filtered stream from one service

Can be backed by a signed query that re-reads live. Follows the canvas time window.

app.landfalls.ai · War room · Canvas · Log view
The Investigation status card: monospace lines with the phase, the findings so far, the current hypothesis and the time it was updated.
The investigation status card uses the log view type, one line per fact. A log view of real log lines also shows a timestamp and a level colour on each line.

Data shape

{ lines: [{ t?: ISO-8601, level?: "error"|"warn"|"info"|"debug", message, fields? }], truncated?: boolean }

Example

{
  "lines": [
    {
      "t": "2026-09-04T14:33:02Z",
      "level": "error",
      "message": "CloudFront origin 502 Bad Gateway path=/api/checkout edge=eu-west-1"
    },
    {
      "t": "2026-09-04T14:33:05Z",
      "level": "warn",
      "message": "target i-0a1 draining (2/6 healthy)"
    }
  ]
}

Timeline timeline

Discrete events in time order, each with a kind badge; a correlated one is highlighted.

  • recent deploys and config changes
  • feature-flag flips
  • alarms as they fired
  • what changed before the incident

Can be backed by a signed query that re-reads live. Follows the canvas time window.

app.landfalls.ai · War room · Canvas · Timeline
A pinned Timeline card titled RECENT CHANGES: a deploy at 17:32 marked correlated 0.94, and a flag change at 17:18, checkout-v2 rollout 25% to 50%.
Recent changes in time order. The deploy row carries the correlated · 0.94 marker.

Data shape

{ events: [{ t: ISO-8601, label, kind?: "deploy"|"config"|"flag"|"alarm"|string, detail?, correlated?: number|boolean, tone? }] }

Example

{
  "events": [
    {
      "t": "2026-09-04T14:32:00Z",
      "label": "web-edge #4127 · task def :47",
      "kind": "deploy",
      "correlated": 0.94
    },
    {
      "t": "2026-09-04T14:18:00Z",
      "label": "checkout-v2 rollout 25% → 50%",
      "kind": "flag"
    }
  ]
}

World map geo

Regions or points of presence on a world map: affected places stand out in their status color, healthy ones stay quiet, to show WHERE an incident is.

  • error rate by region
  • edge locations affected
  • latency by point of presence
  • which regions are healthy
  • any value keyed by a place

Can be backed by a signed query that re-reads live. Follows the canvas time window. Up to 60 series; the rest fold into one "other".

app.landfalls.ai · War room · Canvas · World map
A World map card titled 5XX ERROR RATE BY REGION FOR DISTRIBUTION E123ABC, with eu-west-1 annotated as peak 8.48 at 11:24 UTC and a legend of five regions.
A CloudFront 5xx rate by region. The two regions that peaked in the window, eu-west-1 and eu-central-1, are circled, and the legend gives every region’s value.

Data shape

{ points: [{ place: "eu-west-1"|"DUB"|"Frankfurt"|"Brazil"|…, label?, lat?, lon?, value?, unit?, tone?, pulse?, detail?, peakTone? }], unit?, legend? }. Coordinates are filled from the place name when omitted; only warning/serious/critical places are highlighted, peakTone draws a ring for a place that WAS affected in the window

Example

{
  "unit": "%",
  "points": [
    {
      "place": "eu-west-1",
      "value": 12.4,
      "tone": "critical",
      "pulse": true,
      "label": "eu-west-1 · 12.4% 5xx"
    },
    {
      "place": "eu-central-1",
      "value": 3.2,
      "tone": "warning"
    },
    {
      "place": "us-east-1",
      "value": 0.4,
      "tone": "good",
      "label": "us-east-1 · 0.4%"
    },
    {
      "place": "ap-southeast-1",
      "value": 0.3,
      "tone": "good"
    }
  ]
}

Code finding codeFinding

A code snippet pinned to a commit, with a permalink, captured when the finding was made.

  • the exact lines a deploy changed
  • a suspicious configuration value in source
  • evidence read from a repository

Data only: captured once, never re-read.

app.landfalls.ai · War room · Canvas · Code finding
A pinned Code finding card showing lines 41 and 42 of src/origin.ts, with a GitHub chip for acme/web-edge:src/origin.ts#L41-44.
The exact lines, captured when the finding was made, with a link to the file at that commit.

Data shape

{ codeRef: { owner, repo, ref, path?, lineStart?, lineEnd?, pullRequestNumber?, permalink }, snippet: { lines: string[], startLine } }

Example

{
  "codeRef": {
    "provider": "github",
    "owner": "acme",
    "repo": "web-edge",
    "ref": "9f3c1e2a",
    "path": "src/origin.ts",
    "lineStart": 41,
    "lineEnd": 44,
    "permalink": "https://github.com/acme/web-edge/blob/9f3c1e2a/src/origin.ts#L41-L44"
  },
  "snippet": {
    "startLine": 41,
    "lines": [
      "const ttl = 120;",
      "export const origin = alb(\"web-edge-tg\", { ttl });"
    ]
  }
}

Audit trail events

Control-plane and audit events with the actor and the target as first-class values: who did what, to which resource, and whether it succeeded. Use it whenever the question is who changed something, rather than what a number did.

  • CloudTrail management events in the incident window
  • who changed a configuration, and whether the call succeeded
  • failed or denied API calls by one principal
  • IAM and policy changes around the time an incident opened
  • deploys and control-plane actions attributed to a person or a role

Can be backed by a signed query that re-reads live. Follows the canvas time window.

An audit trail is for a control-plane or audit read, where the interesting part of each row is who acted and on what. The actor, the action, the target resource and whether the call succeeded are separate values rather than a line of text, so you can group the card by actor and click a target to open its resource page. A principal that appears only once in the events on the card is marked as such. That marker is about what is on the card, not a claim about the person's history.

app.landfalls.ai · War room · Canvas · Audit trail
An Audit trail card titled CONTROL-PLANE CHANGES with three events: the deploy-ci role ran UpdateDistribution and CreateInvalidation on distribution E123ABC, both successful, and the user sam was denied PutBucketPolicy on bucket checkout-assets with AccessDenied.
Each row names the actor, the action, the target and the outcome, with Group by actor above the rows. The note under sam’s row reads only appearance in this window. 203.0.113.42 is a documentation address.

Data shape

{ events: [{ t, actor: { kind, id, label? }, action, target?: { kind, id, label? }, outcome?: "success"|"failure"|"denied"|"unknown", sourceIp?, userAgent?, errorCode?, detail? }], truncated?, window? }. Newest first; actor.kind is a lower-case token (user, role, service, account, federated, unknown are the named ones, the vocabulary is open); target is an entity, so it links to that resource page and joins the canvas cross-highlight

Example

{
  "window": {
    "from": "2026-09-21T01:00:00Z",
    "to": "2026-09-21T04:00:00Z"
  },
  "events": [
    {
      "t": "2026-09-21T03:12:44Z",
      "actor": {
        "kind": "role",
        "id": "deploy-ci",
        "label": "deploy-ci"
      },
      "action": "UpdateDistribution",
      "target": {
        "kind": "cloudfront_distribution",
        "id": "E123ABC"
      },
      "outcome": "success",
      "sourceIp": "203.0.113.42"
    },
    {
      "t": "2026-09-21T03:11:02Z",
      "actor": {
        "kind": "user",
        "id": "AIDAEXAMPLE",
        "label": "jordan"
      },
      "action": "PutBucketPolicy",
      "target": {
        "kind": "bucket",
        "id": "checkout-assets"
      },
      "outcome": "denied",
      "errorCode": "AccessDenied"
    }
  ]
}

Topology graph

What a resource connects to, drawn as a graph: what it depends on, what depends on it, and how sure Landfall is about each link. Use it to show blast radius or a dependency chain, rather than describing one in prose.

  • what depends on the failing service
  • blast radius of one resource
  • the dependency chain between an alert and its cause
  • which services share a data store
  • what a compromised host can reach

Data only: captured once, never re-read.

A topology card draws what a resource connects to: what it depends on, what depends on it, and how far each thing sits from the one the card is about. It is built from your organisation's architecture map rather than from a telemetry read, so it needs no query and no connected source. Each node is a resource chip, so hovering one highlights every other card looking at the same thing and clicking one opens its page.

A topology card tells you how much it believes itself. The architecture map is built partly by reading documents you upload, so some of what it holds was inferred rather than confirmed by a person. A link that was inferred is drawn dashed and faint, and the card says so underneath. Treat a dashed link as a lead, not a fact. A card shows the resources nearest the subject and states how many it is not drawing; open the architecture map to see the whole thing.

app.landfalls.ai · War room · Canvas · Topology
A Topology card titled WHAT CHECKOUT DEPENDS ON: the checkout service with a solid line to the orders database and a dashed line to the pricing service, which is marked inferred from documents.
The dashed line was inferred from architecture documents and has not been confirmed, as the note under the chips says. The last line says 4 more are not shown and points to the architecture map.

Data shape

{ nodes: [{ id, label, kind?, tone?, entity?: { kind, id, label? }, trust?: "confirmed"|"established"|"inferred", detail? }], edges: [{ from, to, label?, kind?, tone?, trust?, direction?: "forward"|"both"|"none" }], focus?, omitted?, legend? }. Every edge endpoint must name a node that exists; a node with an entity links to that resource page and joins the canvas cross-highlight; trust says whether a person confirmed the link or a model inferred it; the layout is chosen by the renderer, never by the payload

Example

{
  "focus": "checkout",
  "legend": "Dashed links were inferred from architecture documents and not confirmed.",
  "nodes": [
    {
      "id": "checkout",
      "label": "checkout",
      "entity": {
        "kind": "service",
        "id": "checkout"
      },
      "tone": "critical",
      "trust": "confirmed"
    },
    {
      "id": "orders-db",
      "label": "orders",
      "entity": {
        "kind": "database",
        "id": "orders"
      },
      "tone": "warning",
      "trust": "confirmed"
    },
    {
      "id": "cart",
      "label": "cart",
      "entity": {
        "kind": "service",
        "id": "cart"
      },
      "tone": "good",
      "trust": "established"
    },
    {
      "id": "pricing",
      "label": "pricing",
      "entity": {
        "kind": "service",
        "id": "pricing"
      },
      "tone": "neutral",
      "trust": "inferred"
    }
  ],
  "edges": [
    {
      "from": "checkout",
      "to": "orders-db",
      "kind": "depends_on",
      "trust": "confirmed",
      "tone": "critical"
    },
    {
      "from": "cart",
      "to": "orders-db",
      "kind": "depends_on",
      "trust": "confirmed"
    },
    {
      "from": "checkout",
      "to": "pricing",
      "kind": "depends_on",
      "trust": "inferred"
    }
  ],
  "omitted": 0
}

Time windows

app.landfalls.ai · War room · Canvas · Window and live controls
The canvas toolbar: a Window select on Incident window, the incident window label, a checked Live box with every 15s, a Refresh now button, and the status line updated 1s ago · 5 live widgets.
The window is the incident window, Live is on and refreshes every 15 seconds, and five widgets are in the refresh cycle.

One control row above the cards scopes every query-backed widget. The default is the incident window: from 30 minutes before the incident opened until now. A window can be at most 7 days; reversed or future ranges are refused with the reason.

  • Incident window (fixed start, slides while live)
  • Last 15 min (15m ending now, slides while live)
  • Last 1 hour (1h ending now, slides while live)
  • Last 3 hours (3h ending now, slides while live)
  • Last 6 hours (6h ending now, slides while live)
  • Last 24 hours (24h ending now, slides while live)
  • Custom: an absolute start and end.

An agent may give a widget its own default window (for example the five minutes it looked at); the card names it in its head and the canvas control overrides it while selected.

Freshness: the status dot and what it says

Each card carries exactly one status dot, and it never claims more than it knows. Its colour is the state; hover or focus it to read the words below, and the info view repeats them.

  • building…: the agent requested the widget and the build is still running.
  • live · updated Ns ago: the widget is in the refresh cycle and its last read succeeded. Live refreshes every 5, 15, 30 or 60 seconds, in one request for the whole canvas, and can be turned off.
  • zoomed · 01:37 → 03:28: the widget was read for its own narrower span (see Zoom into a time span).
  • stale · last good: the last refresh failed; the card keeps the data it last had and says why.
  • snapshot · HH:MM: data-only widgets (shared by an edge agent, the investigation status, a code finding) captured at that time and never re-read. With Live off, every query-backed card is a snapshot of its last read.
  • no data in this window: the source answered with no points for the selected window; try the incident window.
  • source unavailable: the card is empty because the source could not be read, which is a different fact from an empty window.
  • flagged wrong · content may be out of date: the card quotes a hypothesis or finding that has since been flagged wrong.
  • failed: the read failed and nothing good was ever shown for this window; the reason is on the card.

While a refresh is in flight the previous render stays visible, dimmed. The toolbar's Refresh now re-reads every widget; Refresh in a card's menu re-reads that one widget. Widgets survive a server restart: the durable record carries everything needed to rebuild them.

A card at rest shows its title, its data, one status dot and a ⋯ menu. The drag handle appears when you hover the card. Everything else is in the menu: Info, Refresh, Expand, pin or unpin for a shared widget, Copy link (a URL that opens the war room and highlights the card), Ask Beacon about this widget (puts a reference in the chat composer, sends nothing) and Hide, which removes the card from your own canvas only; a hidden (n) control beside the toolbar restores it. The investigation status and remediation cards cannot be hidden, and no agent can hide, remove or reorder a widget.

app.landfalls.ai · War room · Canvas · Card menu
The Acme 42 war room canvas with the ⋯ menu of the 5xx rate · eu-west-1 chart open: Info, Refresh, Expand, Copy link, Ask Beacon about this widget, Hide.
The ⋯ menu of the 5xx rate · eu-west-1 chart. Beside the chart is a table of the worst edges by 5xx, and below it the investigation status card, each with its own status dot and menu.

Info opens a panel docked beside the wall (an overlay when the canvas is narrow) with everything recorded about the widget: what it shows and why the agent built it, the resource and source, the exact query with its signed parameters (copy as JSON), freshness and trust (fetch time, sliding or fixed window, quarantine, the timeline entries it depends on, who created it), the data as a table with a CSV download, previous versions, and build details (module, hash, where it ran, the last source calls with any partial flag). Nothing in the panel is fetched from a source; it is the record.

app.landfalls.ai · War room · Canvas · Info
The info panel docked to the right of the canvas for the 5xx rate · eu-west-1 chart, showing What it shows, Resource, the CloudWatch getMetricData query with Copy as JSON, and Freshness and trust.
The info view of a CloudFront 5xx chart: why the agent built it, the distribution it reads, the query with its connection, window, grouping and step, and who created it. 123456789012 is the placeholder AWS account used in these docs.

Zoom into a time span

Drag across a chart or a timeline to select a span; release, and that widget re-reads just that span, at finer resolution where the source allows it (a 24-hour CloudWatch window read at five-minute points becomes one-minute points for the hour you chose). The card's head shows the range with a ⟲ back control, and the dot reads zoomed · 01:37 → 03:28. Other widgets keep the canvas window until you choose Apply this range to canvas from the ⋯ menu, which makes it the toolbar's custom window for every widget. Escape, the back control or Zoom out restore the canvas window. A drag shorter than thirty seconds is just a hover. Keyboard: Tab to the plot, Left/Right move a crosshair, Shift+Left/Right select, Enter zooms. Only widgets Landfall can re-read are zoomable; a shared snapshot from a colleague's agent is not. Your zoom is yours: it is remembered in this browser and never written to the incident.

app.landfalls.ai · War room · Canvas · Zoom
A zoomed 5xx rate chart: the head shows 10:28 → 12:18 with a back control and the axis spans 10:30 to 12:00, while the neighbouring chart still shows the full day.
The left chart was zoomed to 10:28 → 12:18 and its head shows the range with the back control. The right chart still shows the canvas window.

Click a legend entry to hide or show that series (shift-click to show only that one); the y-axis rescales and every series keeps its colour. Hover a time on one chart and every other chart on the canvas draws its crosshair and values at the same instant. Copy link on a zoomed widget carries the range, so the person who opens it lands on the same minutes.

app.landfalls.ai · War room · Canvas · Shared hover
Two charts side by side, 5xx rate · eu-west-1 and Origin latency p99, both showing a crosshair and a tooltip at 7:05:03 AM.
Hovering 7:05:03 AM on one chart draws the same instant, with each series' value, on the other.

What a widget is looking at

When the agent builds a widget, Landfall works out what the read is about (a CloudFront distribution, an ALB target group, a log group, a service, a table or a queue) from the read itself: an ARN, a CloudWatch dimension, a log-group parameter, or a catalogued metric key. The Info view shows it as a chip; a read that cannot be pinned to one thing says so rather than guessing. Hovering the chip dims every card on the canvas that is looking at something else, so you can see at a glance which widgets share a resource.

Clicking the chip opens that resource's page for your organisation: the architecture element it matches, every incident that was triggered about it, and every incident in which a widget read it, with those widgets linking straight back to their cards. The same chip appears on an incident's alert line, so a resource is reachable from anywhere it is mentioned.

Agents

The investigator agent puts a widget on the canvas with the same source, operation, parameters and connection it read with, plus the window it looked at and a grouping hint when values split by region or zone. It picks the type from this catalog, which it can ask for at any time with describe_widget_types. Your own coding agent, connected through the bridge, shares data-only widgets of any type here with share_with_room; the bridge exposes the same catalog. The world map places regions, edge locations, cities and countries by name, so a widget only has to say eu-west-1 or DUB.

Reference

Widget types9: stat, chart, table, logView, timeline, geo, codeFinding, events, graph
Default windowIncident window: from 30 minutes before the incident opened until now
Longest window7 days
Live refreshEvery 5, 15, 30 or 60 seconds, or off
Catalog for agentsdescribe_widget_types
HideYour own canvas only; no agent can hide, remove or reorder a widget