diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index df31d3c7471..92d5d311d25 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -24,6 +24,7 @@
/packages/airlock_digital @elastic/security-service-integrations @elastic/sit-crest-contractors
/packages/akamai @elastic/security-service-integrations @elastic/sit-crest-contractors
/packages/amazon_security_lake @elastic/security-service-integrations @elastic/sit-crest-contractors
+/packages/anduril_lattice @elastic/security-service-integrations
/packages/anthropic @elastic/integration-experience
/packages/anthropic_metrics @elastic/obs-infraobs-integrations
/packages/apache @elastic/obs-infraobs-integrations
diff --git a/packages/anduril_lattice/_dev/build/build.yml b/packages/anduril_lattice/_dev/build/build.yml
new file mode 100644
index 00000000000..ac76b327e47
--- /dev/null
+++ b/packages/anduril_lattice/_dev/build/build.yml
@@ -0,0 +1,3 @@
+dependencies:
+ ecs:
+ reference: "git@v9.4.0"
diff --git a/packages/anduril_lattice/_dev/build/docs/README.md b/packages/anduril_lattice/_dev/build/docs/README.md
new file mode 100644
index 00000000000..69cc2d1434b
--- /dev/null
+++ b/packages/anduril_lattice/_dev/build/docs/README.md
@@ -0,0 +1,142 @@
+{{- generatedHeader }}
+# Anduril Lattice Integration for Elastic
+
+## Overview
+
+The Anduril Lattice integration for Elastic collects entity lifecycle events from the [Anduril Lattice](https://www.anduril.com/lattice/) command and control (C2) platform. Lattice fuses data from heterogeneous sensor networks — radar, ADS-B, AIS, RF/EW, optical, and Anduril hardware — into a Common Operational Picture (COP). Every tracked or managed item is an **Entity**: aircraft, surface vessels, ground vehicles, UAS, fixed sensors, geospatial zones, and signals of interest.
+
+This integration collects all entity lifecycle events (created, updated, deleted, preexisting snapshot) and ships them to Elasticsearch for real-time situational awareness, threat monitoring, and asset tracking.
+
+### Compatibility
+
+Compatible with the Anduril Lattice REST API v1 (`/api/v1/entities/events`). Tested against Anduril Lattice SDK v4.0.0.
+
+### How it works
+
+The integration polls the Lattice long-poll API endpoint (`POST /api/v1/entities/events`) using a session-token cursor. Each poll returns a batch of entity lifecycle events. The session token is persisted between polls so the integration resumes from where it left off.
+
+On the first poll (empty session token) the Lattice server delivers a snapshot of all currently live entities as `EVENT_TYPE_PREEXISTING` events, then transitions to streaming ongoing changes. Subsequent polls receive `EVENT_TYPE_CREATED`, `EVENT_TYPE_UPDATE`, and `EVENT_TYPE_DELETED` events as the operational picture evolves.
+
+Two authentication modes are supported:
+- **Static bearer token** — supply a single token; rotation is manual.
+- **OAuth2 client credentials** — supply a client ID and secret; the integration fetches and refreshes access tokens automatically (30-minute lifetime).
+
+For Anduril sandbox/developer environments, an additional sandbox authorization token is required.
+
+## What data does this integration collect?
+
+The Anduril Lattice integration collects entity lifecycle events from the Lattice long-poll API.
+
+### Supported use cases
+
+- **Real-time situational awareness** — track friendly, hostile, and neutral entities across air, surface, land, and sub-surface domains.
+- **Asset health monitoring** — monitor connection status and battery/power state for Anduril hardware assets (towers, sensors).
+- **Track analysis** — correlate track quality, sensor hit count, and kinematic data (position, velocity, heading) for sensor-detected contacts.
+- **Threat detection** — alert on `DISPOSITION_HOSTILE` or `DISPOSITION_SUSPICIOUS` entity classifications.
+- **Geospatial analysis** — visualize entity positions on Kibana Maps using the `anduril_lattice.entity.location.geo` geo_point field.
+
+## What do I need to use this integration?
+
+- **Anduril Lattice environment** — a production environment, or a sandbox via the [Anduril developer program](https://developer.anduril.com/guides/getting-started/set-up).
+- **Credentials** — either a static bearer token, or an OAuth2 client ID and client secret generated from the Lattice admin console.
+- **Network connectivity** — the Elastic Agent host must be able to reach the Lattice API over HTTPS (port 443).
+
+## How do I deploy this integration?
+
+### Agent-based deployment
+
+Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). You can install only one Elastic Agent per host.
+
+Elastic Agent polls the Lattice long-poll API and ships events to Elastic, where they are processed by the integration's ingest pipeline.
+
+### Set up steps in Anduril Lattice
+
+1. Log in to the Lattice admin console for your environment.
+2. Navigate to **Integrations** and create a new integration to generate OAuth2 credentials (`client_id` and `client_secret`), or obtain a static bearer token from your Lattice administrator.
+3. Note your Lattice API base URL (for example, `https://lattice.yourdomain.com`).
+4. For sandbox environments, also obtain the `Anduril-Sandbox-Authorization` token from the [Lattice sandbox documentation](https://developer.anduril.com/guides/developer-tools/sandboxes).
+5. Ensure the Elastic Agent host has HTTPS/443 access to the Lattice server.
+
+#### Vendor resources
+
+- [Anduril Lattice developer portal](https://developer.anduril.com)
+- [Long-poll entity events API reference](https://developer.anduril.com/reference/rest/entities/long-poll-entity-events)
+- [Getting started / authentication](https://developer.anduril.com/guides/getting-started/quickstart)
+- [Lattice sandbox environments](https://developer.anduril.com/guides/developer-tools/sandboxes)
+
+### Set up steps in Kibana
+
+1. In Kibana, navigate to **Fleet** → **Integrations** and search for **Anduril Lattice**.
+2. Click **Add Anduril Lattice** and configure the integration:
+ - **Lattice API URL** — the base URL of your Lattice environment (for example, `https://lattice.example.com`).
+ - **Authentication** — provide either a static **Bearer Token**, or an **OAuth2 Client ID** and **Client Secret** for automatic token management.
+ - **Sandbox Token** — leave empty for production; provide the sandbox token for developer environments.
+ - **Interval** — how often to poll for new events (default: `5s`).
+3. Save and deploy the policy to the Elastic Agent.
+
+### Validation
+
+After deploying the integration, verify data is flowing:
+
+1. Open **Kibana** → **Discover**.
+2. Select the `logs-anduril_lattice.entity-*` index pattern.
+3. Check that events appear with `event.dataset: anduril_lattice.entity`.
+4. Confirm entity fields such as `anduril_lattice.entity.entity_id`, `anduril_lattice.entity.ontology.template`, and `anduril_lattice.entity.mil_view.disposition` are populated.
+5. Open **Kibana Maps** and add a layer using the `anduril_lattice.entity.location.geo` field to visualize entity positions.
+
+## Troubleshooting
+
+- No data collected: Verify the Lattice API URL is reachable from the Elastic Agent host and that the bearer token or OAuth2 credentials are valid.
+- Authentication failures: For OAuth2, ensure the token URL follows the pattern `{base_url}/api/v1/oauth/token` and that the client credentials have the correct permissions in the Lattice admin console.
+- Self-signed certificates: If the Lattice environment uses a private CA, configure the `SSL Configuration` field with the custom `certificate_authorities` path.
+- Sandbox environments: Ensure the `Sandbox Authorization Token` field is populated; the `Anduril-Sandbox-Authorization` header is required for developer sandboxes.
+- Session token loss on restart: The CEL input persists the session token in agent state. On cold restart the integration re-delivers a full entity snapshot as `EVENT_TYPE_PREEXISTING` events.
+
+## Performance and scaling
+
+The Lattice long-poll API returns all entities in the environment with no server-side filtering. In large environments with many active entities, the initial snapshot might produce thousands of events across multiple polling cycles. Tune `Batch Size` (default 100, max 2000) and `Interval` (default 5s) for your environment's entity density.
+
+For more information on architectures that can be used for scaling this integration, check the [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation.
+
+## Reference
+
+### Inputs used
+{{ inputDocs }}
+
+### API usage
+
+These APIs are used with this integration:
+
+- `POST /api/v1/entities/events` — [Long-poll entity events](https://developer.anduril.com/reference/rest/entities/long-poll-entity-events): returns batches of entity lifecycle events with a session-token cursor for incremental collection.
+- `POST /api/v1/oauth/token` — OAuth2 token endpoint: used to obtain and refresh bearer tokens when OAuth2 client credentials are configured.
+
+### Vendor documentation links
+
+- [Anduril Lattice developer portal](https://developer.anduril.com)
+- [Lattice API overview](https://developer.anduril.com/reference/overview/overview)
+- [Go SDK (public)](https://github.com/anduril/lattice-sdk-go)
+
+### Data streams
+
+#### entity
+
+The `entity` data stream collects entity lifecycle events from the Anduril Lattice long-poll API. Each event represents a state change for a tracked entity in the Lattice Common Operational Picture — creation, update, deletion, or preexisting snapshot on session start.
+
+Entity sub-types (distinguished by `anduril_lattice.entity.ontology.template`):
+- `TEMPLATE_TRACK` — sensor-tracked transient contacts (aircraft, vessels, UAVs)
+- `TEMPLATE_ASSET` — persistent managed assets (sensors, towers, Anduril hardware)
+- `TEMPLATE_GEO` — geospatial zones (keep-in, keep-out, engagement zones)
+- `TEMPLATE_SENSOR_POINT_OF_INTEREST` — sensor-detected points of interest
+- `TEMPLATE_SIGNAL_OF_INTEREST` — RF/EW signal entities
+
+##### entity fields
+
+{{ fields "entity" }}
+
+##### entity sample event
+
+{{ event "entity" }}
+
+{{ ilm }}
+
+{{ transform }}
diff --git a/packages/anduril_lattice/_dev/deploy/docker/docker-compose.yml b/packages/anduril_lattice/_dev/deploy/docker/docker-compose.yml
new file mode 100644
index 00000000000..676badd1461
--- /dev/null
+++ b/packages/anduril_lattice/_dev/deploy/docker/docker-compose.yml
@@ -0,0 +1,14 @@
+services:
+ anduril_lattice:
+ image: docker.elastic.co/observability/stream:v0.20.0
+ hostname: anduril_lattice
+ ports:
+ - 8090
+ volumes:
+ - ./files:/files:ro
+ environment:
+ PORT: '8090'
+ command:
+ - http-server
+ - --addr=:8090
+ - --config=/files/config-entity.yml
diff --git a/packages/anduril_lattice/_dev/deploy/docker/files/config-entity.yml b/packages/anduril_lattice/_dev/deploy/docker/files/config-entity.yml
new file mode 100644
index 00000000000..6cdd7a57589
--- /dev/null
+++ b/packages/anduril_lattice/_dev/deploy/docker/files/config-entity.yml
@@ -0,0 +1,72 @@
+rules:
+ # OAuth2 token endpoint - returns access token for OAuth2 auth mode
+ - path: /api/v1/oauth/token
+ methods: [POST]
+ request_headers:
+ Content-Type:
+ - "application/json"
+ responses:
+ - status_code: 200
+ headers:
+ Content-Type:
+ - "application/json"
+ body: >-
+ {"access_token":"test-access-token-xxxx","token_type":"Bearer","expires_in":1800}
+ # Page 1: new session (empty sessionToken) — returns TEMPLATE_TRACK entity event
+ # Matches both Python json.dumps (space after colon) and CEL encode_json (no space)
+ - path: /api/v1/entities/events
+ methods: [POST]
+ request_headers:
+ Content-Type:
+ - "application/json"
+ request_body: '/.*"sessionToken":? *"".*/'
+ responses:
+ - status_code: 200
+ headers:
+ Content-Type:
+ - "application/json"
+ body: >-
+ {"sessionToken":"mock-cursor-page-1","entityEvents":[{"eventType":"EVENT_TYPE_PREEXISTING","time":"2025-12-17T15:32:42Z","entity":{"entityId":"15af4024-05ac-44a3-a756-638e161bd977","description":"Sanctuary","isLive":true,"location":{"position":{"latitudeDegrees":42.35423678341084,"longitudeDegrees":-71.04721146609882,"altitudeHaeMeters":0},"velocityEnu":{"e":4.86,"n":-5.05,"u":-7.67e-07},"speedMps":7.005,"attitudeEnu":{"x":2.14e-08,"y":5.04e-08,"z":-0.391,"w":0.920}},"aliases":{"name":"Sanctuary Passenger Ship"},"milView":{"disposition":"DISPOSITION_ASSUMED_FRIENDLY","environment":"ENVIRONMENT_SURFACE"},"ontology":{"platformType":"SURFACE_VESSEL","template":"TEMPLATE_TRACK"},"provenance":{"integrationName":"legacy_integration","dataType":"ais","sourceUpdateTime":"2025-12-17T15:32:42Z"},"tracked":{"trackQualityWrapper":9,"sensorHits":1},"indicators":{"simulated":true},"signal":{"frequencyCenter":{"frequencyHz":{"value":9.4e9}},"frequencyRange":{"minimumFrequencyHz":{"frequencyHz":{"value":9.0e9}},"maximumFrequencyHz":{"frequencyHz":{"value":9.8e9}}},"bandwidthHz":8.0e8,"signalToNoiseRatio":14.5,"pulseWidthS":2.5e-6,"scanCharacteristics":{"scanType":"SCAN_TYPE_CIRCULAR","scanPeriodS":3.0},"emitterNotations":["EN-001","EN-002"]},"transponderCodes":{"mode3":5421,"modeS":{"id":"ABX1234","address":11189196}},"targetPriority":{"highValueTarget":{"isHighValueTarget":true,"targetPriority":2,"isHighPayoffTarget":false},"threat":{"isThreat":false}},"createdTime":"2025-12-17T14:51:52Z","expiryTime":"2025-12-17T15:32:52Z"}}]}
+ # Page 2: continuation with page-1 cursor — returns TEMPLATE_ASSET entity event
+ - path: /api/v1/entities/events
+ methods: [POST]
+ request_headers:
+ Content-Type:
+ - "application/json"
+ request_body: '/.*"sessionToken":? *"mock-cursor-page-1".*/'
+ responses:
+ - status_code: 200
+ headers:
+ Content-Type:
+ - "application/json"
+ body: >-
+ {"sessionToken":"mock-cursor-page-2","entityEvents":[{"eventType":"EVENT_TYPE_UPDATE","time":"2025-12-17T15:30:00Z","entity":{"entityId":"tower-45d9bf21-0001-0001-0001-000000000001","isLive":true,"aliases":{"name":"Tower 45d9bf21"},"milView":{"disposition":"DISPOSITION_FRIENDLY","environment":"ENVIRONMENT_LAND"},"ontology":{"platformType":"FIXED_SENSOR","template":"TEMPLATE_ASSET"},"location":{"position":{"latitudeDegrees":34.05223,"longitudeDegrees":-118.24368,"altitudeHaeMeters":85.0}},"health":{"connectionStatus":"CONNECTION_STATUS_ONLINE","healthStatus":"HEALTH_STATUS_HEALTHY","updateTime":"2025-12-17T15:30:00Z","activeAlerts":[{"alertCode":"ALERT_LOW_STORAGE","level":"ALERT_LEVEL_WARNING","activatedTime":"2025-12-17T15:00:00Z","description":"Storage capacity below 15 percent"}]},"geoShape":{"polygon":{"rings":[{"positions":[{"position":{"latitudeDegrees":34.053,"longitudeDegrees":-118.245},"heightM":0},{"position":{"latitudeDegrees":34.053,"longitudeDegrees":-118.242},"heightM":0},{"position":{"latitudeDegrees":34.051,"longitudeDegrees":-118.242},"heightM":0},{"position":{"latitudeDegrees":34.051,"longitudeDegrees":-118.245},"heightM":0}]}]}},"sensors":{"sensors":[{"sensorId":"sensor-001","operationalState":"OPERATIONAL_STATE_OPERATIONAL","sensorType":"SENSOR_TYPE_EO","sensorDescription":"Electro-optical camera","lastDetectionTimestamp":"2025-12-17T15:29:55Z","fieldsOfView":[{"projectedFrustum":{"upperLeft":{"latitudeDegrees":34.060,"longitudeDegrees":-118.252},"upperRight":{"latitudeDegrees":34.060,"longitudeDegrees":-118.237},"bottomRight":{"latitudeDegrees":34.050,"longitudeDegrees":-118.237},"bottomLeft":{"latitudeDegrees":34.050,"longitudeDegrees":-118.252}}}]}]},"powerState":{"sourceIdToState":{"Battery":{"powerStatus":"POWER_STATUS_DISCHARGING","powerType":"POWER_TYPE_BATTERY","powerLevel":{"percentRemaining":87.5,"voltage":31.84}}}},"provenance":{"integrationName":"anduril_tower","dataType":"anduril","sourceUpdateTime":"2025-12-17T15:30:00Z"},"indicators":{"simulated":true},"createdTime":"2025-12-17T10:00:00Z"}}]}
+ # Terminal page: cursor-page-2 token — entityEvents is null (no more events)
+ - path: /api/v1/entities/events
+ methods: [POST]
+ request_headers:
+ Content-Type:
+ - "application/json"
+ request_body: '/.*"sessionToken":? *"mock-cursor-page-2".*/'
+ responses:
+ - status_code: 200
+ headers:
+ Content-Type:
+ - "application/json"
+ body: >-
+ {"sessionToken":"mock-cursor-final","entityEvents":null}
+ # Second-round resume: same final cursor — returns null (simulates ongoing polling)
+ # Verifies cursor persistence: program must NOT reset sessionToken to "" between intervals
+ - path: /api/v1/entities/events
+ methods: [POST]
+ request_headers:
+ Content-Type:
+ - "application/json"
+ request_body: '/.*"sessionToken":? *"mock-cursor-final".*/'
+ responses:
+ - status_code: 200
+ headers:
+ Content-Type:
+ - "application/json"
+ body: >-
+ {"sessionToken":"mock-cursor-final","entityEvents":null}
diff --git a/packages/anduril_lattice/changelog.yml b/packages/anduril_lattice/changelog.yml
new file mode 100644
index 00000000000..4da433be812
--- /dev/null
+++ b/packages/anduril_lattice/changelog.yml
@@ -0,0 +1,6 @@
+# later versions go on top
+- version: "0.1.0"
+ changes:
+ - description: Initial release of the Anduril Lattice integration.
+ type: enhancement
+ link: https://github.com/elastic/integrations/pull/20021
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log
new file mode 100644
index 00000000000..adbef5df815
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log
@@ -0,0 +1 @@
+{"eventType":"EVENT_TYPE_UPDATE","time":"2025-12-17T15:30:00Z","entity":{"entityId":"tower-45d9bf21-0001-0001-0001-000000000001","isLive":true,"aliases":{"name":"Tower 45d9bf21"},"milView":{"disposition":"DISPOSITION_FRIENDLY","environment":"ENVIRONMENT_LAND"},"ontology":{"platformType":"FIXED_SENSOR","template":"TEMPLATE_ASSET"},"location":{"position":{"latitudeDegrees":34.05223,"longitudeDegrees":-118.24368,"altitudeHaeMeters":85.0}},"health":{"connectionStatus":"CONNECTION_STATUS_ONLINE","healthStatus":"HEALTH_STATUS_HEALTHY","updateTime":"2025-12-17T15:30:00Z","activeAlerts":[{"alertCode":"ALERT_LOW_STORAGE","level":"ALERT_LEVEL_WARNING","activatedTime":"2025-12-17T15:00:00Z","description":"Storage capacity below 15 percent"}]},"geoShape":{"polygon":{"rings":[{"positions":[{"position":{"latitudeDegrees":34.053,"longitudeDegrees":-118.245},"heightM":0},{"position":{"latitudeDegrees":34.053,"longitudeDegrees":-118.242},"heightM":0},{"position":{"latitudeDegrees":34.051,"longitudeDegrees":-118.242},"heightM":0},{"position":{"latitudeDegrees":34.051,"longitudeDegrees":-118.245},"heightM":0}]}]}},"sensors":{"sensors":[{"sensorId":"sensor-001","operationalState":"OPERATIONAL_STATE_OPERATIONAL","sensorType":"SENSOR_TYPE_EO","sensorDescription":"Electro-optical camera","lastDetectionTimestamp":"2025-12-17T15:29:55Z","fieldsOfView":[{"projectedFrustum":{"upperLeft":{"latitudeDegrees":34.060,"longitudeDegrees":-118.252},"upperRight":{"latitudeDegrees":34.060,"longitudeDegrees":-118.237},"bottomRight":{"latitudeDegrees":34.050,"longitudeDegrees":-118.237},"bottomLeft":{"latitudeDegrees":34.050,"longitudeDegrees":-118.252}}}]}]},"powerState":{"sourceIdToState":{"Battery":{"powerStatus":"POWER_STATUS_DISCHARGING","powerType":"POWER_TYPE_BATTERY","powerLevel":{"percentRemaining":87.5,"voltage":31.84}}}},"provenance":{"integrationName":"anduril_tower","dataType":"anduril","sourceUpdateTime":"2025-12-17T15:30:00Z"},"indicators":{"simulated":true},"createdTime":"2025-12-17T10:00:00Z"}}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log-expected.json b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log-expected.json
new file mode 100644
index 00000000000..9e5af95c84f
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-asset.log-expected.json
@@ -0,0 +1,162 @@
+{
+ "expected": [
+ {
+ "@timestamp": "2025-12-17T15:30:00.000Z",
+ "anduril_lattice": {
+ "entity": {
+ "aliases": {
+ "name": "Tower 45d9bf21"
+ },
+ "entity_id": "tower-45d9bf21-0001-0001-0001-000000000001",
+ "event_type": "EVENT_TYPE_UPDATE",
+ "geo_shape": {
+ "coordinates": [
+ [
+ [
+ -118.245,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.053
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ },
+ "health": {
+ "active_alerts": {
+ "activated_time": [
+ "2025-12-17T15:00:00Z"
+ ],
+ "alert_code": [
+ "ALERT_LOW_STORAGE"
+ ],
+ "description": [
+ "Storage capacity below 15 percent"
+ ],
+ "level": [
+ "ALERT_LEVEL_WARNING"
+ ]
+ },
+ "connection_status": "CONNECTION_STATUS_ONLINE",
+ "health_status": "HEALTH_STATUS_HEALTHY",
+ "update_time": "2025-12-17T15:30:00.000Z"
+ },
+ "indicators": {
+ "simulated": true
+ },
+ "is_live": true,
+ "location": {
+ "altitude_hae_meters": 85.0,
+ "geo": "34.05223,-118.24368"
+ },
+ "mil_view": {
+ "disposition": "DISPOSITION_FRIENDLY",
+ "environment": "ENVIRONMENT_LAND"
+ },
+ "ontology": {
+ "platform_type": "FIXED_SENSOR",
+ "template": "TEMPLATE_ASSET"
+ },
+ "power_state": {
+ "sourceIdToState": {
+ "Battery": {
+ "powerLevel": {
+ "percentRemaining": 87.5,
+ "voltage": 31.84
+ },
+ "powerStatus": "POWER_STATUS_DISCHARGING",
+ "powerType": "POWER_TYPE_BATTERY"
+ }
+ }
+ },
+ "provenance": {
+ "data_type": "anduril"
+ },
+ "sensors": {
+ "fields_of_view": {
+ "geo": [
+ {
+ "coordinates": [
+ [
+ [
+ -118.252,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.06
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ }
+ ]
+ },
+ "last_detection_timestamp": [
+ "2025-12-17T15:29:55Z"
+ ],
+ "operational_state": [
+ "OPERATIONAL_STATE_OPERATIONAL"
+ ],
+ "sensor_description": [
+ "Electro-optical camera"
+ ],
+ "sensor_id": [
+ "sensor-001"
+ ],
+ "sensor_type": [
+ "SENSOR_TYPE_EO"
+ ]
+ }
+ }
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "event": {
+ "category": [
+ "host"
+ ],
+ "created": "2025-12-17T15:30:00.000Z",
+ "kind": "event",
+ "original": "{\"eventType\":\"EVENT_TYPE_UPDATE\",\"time\":\"2025-12-17T15:30:00Z\",\"entity\":{\"entityId\":\"tower-45d9bf21-0001-0001-0001-000000000001\",\"isLive\":true,\"aliases\":{\"name\":\"Tower 45d9bf21\"},\"milView\":{\"disposition\":\"DISPOSITION_FRIENDLY\",\"environment\":\"ENVIRONMENT_LAND\"},\"ontology\":{\"platformType\":\"FIXED_SENSOR\",\"template\":\"TEMPLATE_ASSET\"},\"location\":{\"position\":{\"latitudeDegrees\":34.05223,\"longitudeDegrees\":-118.24368,\"altitudeHaeMeters\":85.0}},\"health\":{\"connectionStatus\":\"CONNECTION_STATUS_ONLINE\",\"healthStatus\":\"HEALTH_STATUS_HEALTHY\",\"updateTime\":\"2025-12-17T15:30:00Z\",\"activeAlerts\":[{\"alertCode\":\"ALERT_LOW_STORAGE\",\"level\":\"ALERT_LEVEL_WARNING\",\"activatedTime\":\"2025-12-17T15:00:00Z\",\"description\":\"Storage capacity below 15 percent\"}]},\"geoShape\":{\"polygon\":{\"rings\":[{\"positions\":[{\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.245},\"heightM\":0},{\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.242},\"heightM\":0},{\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.242},\"heightM\":0},{\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.245},\"heightM\":0}]}]}},\"sensors\":{\"sensors\":[{\"sensorId\":\"sensor-001\",\"operationalState\":\"OPERATIONAL_STATE_OPERATIONAL\",\"sensorType\":\"SENSOR_TYPE_EO\",\"sensorDescription\":\"Electro-optical camera\",\"lastDetectionTimestamp\":\"2025-12-17T15:29:55Z\",\"fieldsOfView\":[{\"projectedFrustum\":{\"upperLeft\":{\"latitudeDegrees\":34.060,\"longitudeDegrees\":-118.252},\"upperRight\":{\"latitudeDegrees\":34.060,\"longitudeDegrees\":-118.237},\"bottomRight\":{\"latitudeDegrees\":34.050,\"longitudeDegrees\":-118.237},\"bottomLeft\":{\"latitudeDegrees\":34.050,\"longitudeDegrees\":-118.252}}}]}]},\"powerState\":{\"sourceIdToState\":{\"Battery\":{\"powerStatus\":\"POWER_STATUS_DISCHARGING\",\"powerType\":\"POWER_TYPE_BATTERY\",\"powerLevel\":{\"percentRemaining\":87.5,\"voltage\":31.84}}}},\"provenance\":{\"integrationName\":\"anduril_tower\",\"dataType\":\"anduril\",\"sourceUpdateTime\":\"2025-12-17T15:30:00Z\"},\"indicators\":{\"simulated\":true},\"createdTime\":\"2025-12-17T10:00:00Z\"}}",
+ "start": "2025-12-17T10:00:00.000Z",
+ "type": [
+ "change"
+ ]
+ },
+ "observer": {
+ "name": "anduril_tower"
+ },
+ "tags": [
+ "preserve_original_event"
+ ]
+ }
+ ]
+}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-common-config.yml b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-common-config.yml
new file mode 100644
index 00000000000..4da22641654
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-common-config.yml
@@ -0,0 +1,3 @@
+fields:
+ tags:
+ - preserve_original_event
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log
new file mode 100644
index 00000000000..da00d65935a
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log
@@ -0,0 +1 @@
+{"eventType":"EVENT_TYPE_CREATED","time":"2025-12-17T16:00:00Z","entity":{"entityId":"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b","isLive":true,"ontology":{"template":"TEMPLATE_TRACK","platformType":"UAV"},"milView":{"disposition":"DISPOSITION_HOSTILE","environment":"ENVIRONMENT_AIR"},"createdTime":"2025-12-17T15:59:00Z"}}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log-expected.json b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log-expected.json
new file mode 100644
index 00000000000..13a6493c280
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-created.log-expected.json
@@ -0,0 +1,39 @@
+{
+ "expected": [
+ {
+ "@timestamp": "2025-12-17T16:00:00.000Z",
+ "anduril_lattice": {
+ "entity": {
+ "entity_id": "89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b",
+ "event_type": "EVENT_TYPE_CREATED",
+ "is_live": true,
+ "mil_view": {
+ "disposition": "DISPOSITION_HOSTILE",
+ "environment": "ENVIRONMENT_AIR"
+ },
+ "ontology": {
+ "platform_type": "UAV",
+ "template": "TEMPLATE_TRACK"
+ }
+ }
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "event": {
+ "category": [
+ "host"
+ ],
+ "kind": "event",
+ "original": "{\"eventType\":\"EVENT_TYPE_CREATED\",\"time\":\"2025-12-17T16:00:00Z\",\"entity\":{\"entityId\":\"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b\",\"isLive\":true,\"ontology\":{\"template\":\"TEMPLATE_TRACK\",\"platformType\":\"UAV\"},\"milView\":{\"disposition\":\"DISPOSITION_HOSTILE\",\"environment\":\"ENVIRONMENT_AIR\"},\"createdTime\":\"2025-12-17T15:59:00Z\"}}",
+ "start": "2025-12-17T15:59:00.000Z",
+ "type": [
+ "start"
+ ]
+ },
+ "tags": [
+ "preserve_original_event"
+ ]
+ }
+ ]
+}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log
new file mode 100644
index 00000000000..15cdb58d02f
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log
@@ -0,0 +1 @@
+{"eventType":"EVENT_TYPE_DELETED","time":"2025-12-17T16:01:00Z","entity":{"entityId":"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b","isLive":false,"ontology":{"template":"TEMPLATE_TRACK","platformType":"UAV"},"createdTime":"2025-12-17T15:59:00Z","expiryTime":"2025-12-17T16:01:00Z"}}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log-expected.json b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log-expected.json
new file mode 100644
index 00000000000..7d6811cb296
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-deleted.log-expected.json
@@ -0,0 +1,36 @@
+{
+ "expected": [
+ {
+ "@timestamp": "2025-12-17T16:01:00.000Z",
+ "anduril_lattice": {
+ "entity": {
+ "entity_id": "89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b",
+ "event_type": "EVENT_TYPE_DELETED",
+ "is_live": false,
+ "ontology": {
+ "platform_type": "UAV",
+ "template": "TEMPLATE_TRACK"
+ }
+ }
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "event": {
+ "category": [
+ "host"
+ ],
+ "end": "2025-12-17T16:01:00.000Z",
+ "kind": "event",
+ "original": "{\"eventType\":\"EVENT_TYPE_DELETED\",\"time\":\"2025-12-17T16:01:00Z\",\"entity\":{\"entityId\":\"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b\",\"isLive\":false,\"ontology\":{\"template\":\"TEMPLATE_TRACK\",\"platformType\":\"UAV\"},\"createdTime\":\"2025-12-17T15:59:00Z\",\"expiryTime\":\"2025-12-17T16:01:00Z\"}}",
+ "start": "2025-12-17T15:59:00.000Z",
+ "type": [
+ "end"
+ ]
+ },
+ "tags": [
+ "preserve_original_event"
+ ]
+ }
+ ]
+}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log
new file mode 100644
index 00000000000..7fd835e645d
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log
@@ -0,0 +1 @@
+{"eventType":"EVENT_TYPE_POST_EXPIRY_OVERRIDE","time":"2025-12-17T16:02:00Z","entity":{"entityId":"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b","isLive":false,"ontology":{"template":"TEMPLATE_TRACK"},"createdTime":"2025-12-17T15:59:00Z"}}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log-expected.json b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log-expected.json
new file mode 100644
index 00000000000..dcff6d7818d
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-post-expiry.log-expected.json
@@ -0,0 +1,34 @@
+{
+ "expected": [
+ {
+ "@timestamp": "2025-12-17T16:02:00.000Z",
+ "anduril_lattice": {
+ "entity": {
+ "entity_id": "89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b",
+ "event_type": "EVENT_TYPE_POST_EXPIRY_OVERRIDE",
+ "is_live": false,
+ "ontology": {
+ "template": "TEMPLATE_TRACK"
+ }
+ }
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "event": {
+ "category": [
+ "host"
+ ],
+ "kind": "event",
+ "original": "{\"eventType\":\"EVENT_TYPE_POST_EXPIRY_OVERRIDE\",\"time\":\"2025-12-17T16:02:00Z\",\"entity\":{\"entityId\":\"89a1d5c1-2b3e-4f67-8a9b-0c1d2e3f4a5b\",\"isLive\":false,\"ontology\":{\"template\":\"TEMPLATE_TRACK\"},\"createdTime\":\"2025-12-17T15:59:00Z\"}}",
+ "start": "2025-12-17T15:59:00.000Z",
+ "type": [
+ "change"
+ ]
+ },
+ "tags": [
+ "preserve_original_event"
+ ]
+ }
+ ]
+}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log
new file mode 100644
index 00000000000..ff3161180af
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log
@@ -0,0 +1 @@
+{"eventType":"EVENT_TYPE_PREEXISTING","time":"2025-12-17T15:32:42Z","entity":{"entityId":"15af4024-05ac-44a3-a756-638e161bd977","description":"Sanctuary","isLive":true,"location":{"position":{"latitudeDegrees":42.35423678341084,"longitudeDegrees":-71.04721146609882,"altitudeHaeMeters":0},"velocityEnu":{"e":4.86,"n":-5.05,"u":-7.67e-07},"speedMps":7.005,"attitudeEnu":{"x":2.14e-08,"y":5.04e-08,"z":-0.391,"w":0.920}},"aliases":{"name":"Sanctuary Passenger Ship"},"milView":{"disposition":"DISPOSITION_ASSUMED_FRIENDLY","environment":"ENVIRONMENT_SURFACE"},"ontology":{"platformType":"SURFACE_VESSEL","template":"TEMPLATE_TRACK"},"provenance":{"integrationName":"legacy_integration","dataType":"ais","sourceUpdateTime":"2025-12-17T15:32:42Z"},"tracked":{"trackQualityWrapper":9,"sensorHits":1},"indicators":{"simulated":true},"signal":{"frequencyCenter":{"frequencyHz":{"value":9400000000.0}},"frequencyRange":{"minimumFrequencyHz":{"frequencyHz":{"value":9000000000.0}},"maximumFrequencyHz":{"frequencyHz":{"value":9800000000.0}}},"bandwidthHz":800000000.0,"signalToNoiseRatio":14.5,"pulseWidthS":2.5e-6,"scanCharacteristics":{"scanType":"SCAN_TYPE_CIRCULAR","scanPeriodS":3.0},"emitterNotations":["EN-001","EN-002"]},"transponderCodes":{"mode3":5421,"modeS":{"id":"ABX1234","address":11189196}},"targetPriority":{"highValueTarget":{"isHighValueTarget":true,"targetPriority":2,"isHighPayoffTarget":false},"threat":{"isThreat":false}},"createdTime":"2025-12-17T14:51:52Z","expiryTime":"2025-12-17T15:32:52Z"}}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log-expected.json b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log-expected.json
new file mode 100644
index 00000000000..6c545485b75
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/pipeline/test-track.log-expected.json
@@ -0,0 +1,99 @@
+{
+ "expected": [
+ {
+ "@timestamp": "2025-12-17T15:32:42.000Z",
+ "anduril_lattice": {
+ "entity": {
+ "aliases": {
+ "name": "Sanctuary Passenger Ship"
+ },
+ "entity_id": "15af4024-05ac-44a3-a756-638e161bd977",
+ "event_type": "EVENT_TYPE_PREEXISTING",
+ "indicators": {
+ "simulated": true
+ },
+ "is_live": true,
+ "location": {
+ "altitude_hae_meters": 0,
+ "attitude_enu": {
+ "w": 0.92,
+ "x": 2.14E-8,
+ "y": 5.04E-8,
+ "z": -0.391
+ },
+ "geo": "42.35423678341084,-71.04721146609882",
+ "speed_mps": 7.005,
+ "velocity_enu": {
+ "e": 4.86,
+ "n": -5.05,
+ "u": -7.67E-7
+ }
+ },
+ "mil_view": {
+ "disposition": "DISPOSITION_ASSUMED_FRIENDLY",
+ "environment": "ENVIRONMENT_SURFACE"
+ },
+ "ontology": {
+ "platform_type": "SURFACE_VESSEL",
+ "template": "TEMPLATE_TRACK"
+ },
+ "provenance": {
+ "data_type": "ais"
+ },
+ "signal": {
+ "bandwidth_hz": 8.0E8,
+ "emitter_notations": [
+ "EN-001",
+ "EN-002"
+ ],
+ "frequency_center_hz": 9.4E9,
+ "frequency_max_hz": 9.8E9,
+ "frequency_min_hz": 9.0E9,
+ "pulse_width_s": 2.5E-6,
+ "scan_period_s": 3.0,
+ "scan_type": "SCAN_TYPE_CIRCULAR",
+ "signal_to_noise_ratio": 14.5
+ },
+ "target_priority": {
+ "is_high_payoff_target": false,
+ "is_high_value_target": true,
+ "is_threat": false,
+ "priority": 2
+ },
+ "tracked": {
+ "sensor_hits": 1,
+ "track_quality": 9
+ },
+ "transponder_codes": {
+ "mode3": 5421,
+ "mode_s_address": 11189196,
+ "mode_s_id": "ABX1234"
+ }
+ }
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "event": {
+ "category": [
+ "host"
+ ],
+ "created": "2025-12-17T15:32:42.000Z",
+ "end": "2025-12-17T15:32:52.000Z",
+ "kind": "state",
+ "original": "{\"eventType\":\"EVENT_TYPE_PREEXISTING\",\"time\":\"2025-12-17T15:32:42Z\",\"entity\":{\"entityId\":\"15af4024-05ac-44a3-a756-638e161bd977\",\"description\":\"Sanctuary\",\"isLive\":true,\"location\":{\"position\":{\"latitudeDegrees\":42.35423678341084,\"longitudeDegrees\":-71.04721146609882,\"altitudeHaeMeters\":0},\"velocityEnu\":{\"e\":4.86,\"n\":-5.05,\"u\":-7.67e-07},\"speedMps\":7.005,\"attitudeEnu\":{\"x\":2.14e-08,\"y\":5.04e-08,\"z\":-0.391,\"w\":0.920}},\"aliases\":{\"name\":\"Sanctuary Passenger Ship\"},\"milView\":{\"disposition\":\"DISPOSITION_ASSUMED_FRIENDLY\",\"environment\":\"ENVIRONMENT_SURFACE\"},\"ontology\":{\"platformType\":\"SURFACE_VESSEL\",\"template\":\"TEMPLATE_TRACK\"},\"provenance\":{\"integrationName\":\"legacy_integration\",\"dataType\":\"ais\",\"sourceUpdateTime\":\"2025-12-17T15:32:42Z\"},\"tracked\":{\"trackQualityWrapper\":9,\"sensorHits\":1},\"indicators\":{\"simulated\":true},\"signal\":{\"frequencyCenter\":{\"frequencyHz\":{\"value\":9400000000.0}},\"frequencyRange\":{\"minimumFrequencyHz\":{\"frequencyHz\":{\"value\":9000000000.0}},\"maximumFrequencyHz\":{\"frequencyHz\":{\"value\":9800000000.0}}},\"bandwidthHz\":800000000.0,\"signalToNoiseRatio\":14.5,\"pulseWidthS\":2.5e-6,\"scanCharacteristics\":{\"scanType\":\"SCAN_TYPE_CIRCULAR\",\"scanPeriodS\":3.0},\"emitterNotations\":[\"EN-001\",\"EN-002\"]},\"transponderCodes\":{\"mode3\":5421,\"modeS\":{\"id\":\"ABX1234\",\"address\":11189196}},\"targetPriority\":{\"highValueTarget\":{\"isHighValueTarget\":true,\"targetPriority\":2,\"isHighPayoffTarget\":false},\"threat\":{\"isThreat\":false}},\"createdTime\":\"2025-12-17T14:51:52Z\",\"expiryTime\":\"2025-12-17T15:32:52Z\"}}",
+ "start": "2025-12-17T14:51:52.000Z",
+ "type": [
+ "info"
+ ]
+ },
+ "message": "Sanctuary",
+ "observer": {
+ "name": "legacy_integration"
+ },
+ "tags": [
+ "preserve_original_event"
+ ]
+ }
+ ]
+}
diff --git a/packages/anduril_lattice/data_stream/entity/_dev/test/system/test-default-config.yml b/packages/anduril_lattice/data_stream/entity/_dev/test/system/test-default-config.yml
new file mode 100644
index 00000000000..7dbeaf1f895
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/_dev/test/system/test-default-config.yml
@@ -0,0 +1,13 @@
+wait_for_data_timeout: 1m
+input: cel
+service: anduril_lattice
+vars:
+ url: http://{{Hostname}}:{{Port}}
+ token: test-bearer-token-xxxx
+data_stream:
+ vars:
+ interval: 2s
+ batch_size: 100
+ preserve_original_event: true
+assert:
+ hit_count: 2
diff --git a/packages/anduril_lattice/data_stream/entity/agent/stream/cel.yml.hbs b/packages/anduril_lattice/data_stream/entity/agent/stream/cel.yml.hbs
new file mode 100644
index 00000000000..1a512e9c4e2
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/agent/stream/cel.yml.hbs
@@ -0,0 +1,136 @@
+interval: {{interval}}
+resource.tracer:
+ enabled: {{enable_request_tracer}}
+ filename: "../../logs/cel/http-request-trace-*.ndjson"
+ maxbackups: 5
+{{#if proxy_url}}
+resource.proxy_url: {{proxy_url}}
+{{/if}}
+{{#if ssl}}
+resource.ssl: {{ssl}}
+{{/if}}
+{{#if http_client_timeout}}
+resource.timeout: {{http_client_timeout}}
+{{/if}}
+resource.url: {{url}}
+state:
+ batch_size: {{batch_size}}
+ token: {{token}}
+ client_id: {{client_id}}
+ client_secret: {{client_secret}}
+ sandbox_token: {{sandbox_token}}
+redact:
+ fields:
+ - token
+ - client_secret
+ - sandbox_token
+program: |-
+ state.with(
+ has(state.client_id) ?
+ (
+ has(state.?next.expiry) && timestamp(state.next.expiry) > now ?
+ {"token": state.next.token, "next": state.next}
+ :
+ post_request(
+ state.url.trim_right("/") + "/api/v1/oauth/token",
+ "application/json",
+ {
+ "client_id": state.client_id,
+ "client_secret": state.client_secret,
+ }.encode_json()
+ ).do_request().as(tok_resp,
+ (tok_resp.StatusCode == 200) ?
+ tok_resp.Body.decode_json().as(tok_body,
+ {
+ "token": tok_body.access_token,
+ "next": {
+ "token": tok_body.access_token,
+ "expiry": string(now + duration("29m")),
+ },
+ }
+ )
+ :
+ {
+ "events": {
+ "error": {
+ "code": string(tok_resp.StatusCode),
+ "id": string(tok_resp.Status),
+ "message": "POST /api/v1/oauth/token: " + string(tok_resp.Body),
+ },
+ },
+ "want_more": false,
+ }
+ )
+ )
+ :
+ {?"token": state.?token}
+ ).as(state,
+ has(state.?events.error) ?
+ state
+ :
+ state.with(
+ request(
+ "POST",
+ state.url.trim_right("/") + "/api/v1/entities/events"
+ ).with(
+ {
+ "Header": {
+ "Content-Type": ["application/json"],
+ ?"Authorization": (state.?token.orValue("") != "") ?
+ optional.of(["Bearer " + state.token])
+ :
+ optional.none(),
+ ?"Anduril-Sandbox-Authorization": state.?sandbox_token.optMap(t, ["Bearer " + t]),
+ },
+ "Body": {
+ "sessionToken": state.?cursor.session_token.orValue(""),
+ "batchSize": int(state.batch_size),
+ }.encode_json(),
+ }
+ ).do_request().as(resp,
+ (resp.StatusCode == 200) ?
+ resp.Body.decode_json().as(body,
+ ((body.?entityEvents.orValue(null) != null) ? body.entityEvents : []).as(events,
+ (size(events) > 0) ?
+ {
+ "events": events.map(e, {"message": e.encode_json()}),
+ "cursor": {"session_token": body.sessionToken},
+ "want_more": size(events) >= int(state.batch_size),
+ }
+ :
+ {
+ "events": [{"retry": true}],
+ "cursor": {"session_token": body.sessionToken},
+ "want_more": false,
+ }
+ )
+ )
+ :
+ {
+ "events": {
+ "error": {
+ "code": string(resp.StatusCode),
+ "id": string(resp.Status),
+ "message": "POST /api/v1/entities/events: " + ((size(resp.Body) != 0) ? string(resp.Body) : string(resp.Status)),
+ },
+ },
+ "want_more": false,
+ }
+ )
+ )
+ )
+tags:
+{{#if preserve_original_event}}
+ - preserve_original_event
+{{/if}}
+{{#each tags as |tag|}}
+ - {{tag}}
+{{/each}}
+{{#contains "forwarded" tags}}
+publisher_pipeline.disable_host: true
+{{/contains}}
+processors:
+- drop_event.when.equals.retry: true
+{{#if processors}}
+{{processors}}
+{{/if}}
diff --git a/packages/anduril_lattice/data_stream/entity/elasticsearch/ingest_pipeline/default.yml b/packages/anduril_lattice/data_stream/entity/elasticsearch/ingest_pipeline/default.yml
new file mode 100644
index 00000000000..06ff6c35667
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/elasticsearch/ingest_pipeline/default.yml
@@ -0,0 +1,1600 @@
+---
+description: Pipeline for processing Anduril Lattice entity events.
+processors:
+ - set:
+ field: ecs.version
+ tag: set_ecs_version
+ value: '9.4.0'
+ - remove:
+ field:
+ - organization
+ - division
+ - team
+ ignore_missing: true
+ if: ctx.organization instanceof String && ctx.division instanceof String && ctx.team instanceof String
+ tag: remove_agentless_tags
+ description: >-
+ Removes the fields added by Agentless as metadata,
+ as they can collide with ECS fields.
+ - terminate:
+ tag: data_collection_error
+ if: ctx.error?.message != null && ctx.message == null && ctx.event?.original == null
+ description: error message set and no data to process.
+ - rename:
+ field: message
+ tag: rename_message_to_event_original
+ target_field: event.original
+ ignore_missing: true
+ description: >-
+ Renames the original `message` field to `event.original` to store a
+ copy of the original message. The `event.original` field is not touched
+ if the document already has one; it may happen when Logstash sends the
+ document.
+ if: ctx.event?.original == null
+ - remove:
+ field: message
+ tag: remove_message
+ ignore_missing: true
+ description: >-
+ The `message` field is no longer required if the document has an
+ `event.original` field.
+ if: ctx.event?.original != null
+ - json:
+ field: event.original
+ target_field: json
+ tag: parse_json
+ if: ctx.event?.original != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_parse_json
+ value: '{{{_ingest.on_failure_message}}}'
+ allow_duplicates: false
+ - date:
+ field: json.time
+ target_field: '@timestamp'
+ formats:
+ - ISO8601
+ tag: parse_timestamp
+ if: ctx.json?.time != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_parse_timestamp
+ value: >-
+ Processor {{{_ingest.on_failure_processor_type}}}
+ with tag '{{{_ingest.on_failure_processor_tag}}}'
+ failed: {{{_ingest.on_failure_message}}}
+ allow_duplicates: false
+ - date:
+ field: json.entity.provenance.sourceUpdateTime
+ target_field: event.created
+ formats:
+ - ISO8601
+ tag: parse_event_created
+ if: ctx.json?.entity?.provenance?.sourceUpdateTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_parse_event_created
+ value: >-
+ Processor {{{_ingest.on_failure_processor_type}}}
+ with tag '{{{_ingest.on_failure_processor_tag}}}'
+ failed: {{{_ingest.on_failure_message}}}
+ allow_duplicates: false
+ - date:
+ field: json.entity.createdTime
+ target_field: event.start
+ formats:
+ - ISO8601
+ tag: parse_event_start
+ if: ctx.json?.entity?.createdTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_parse_event_start
+ value: >-
+ Processor {{{_ingest.on_failure_processor_type}}}
+ with tag '{{{_ingest.on_failure_processor_tag}}}'
+ failed: {{{_ingest.on_failure_message}}}
+ allow_duplicates: false
+ - date:
+ field: json.entity.expiryTime
+ target_field: event.end
+ formats:
+ - ISO8601
+ tag: parse_event_end
+ if: ctx.json?.entity?.expiryTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_parse_event_end
+ value: >-
+ Processor {{{_ingest.on_failure_processor_type}}}
+ with tag '{{{_ingest.on_failure_processor_tag}}}'
+ failed: {{{_ingest.on_failure_message}}}
+ allow_duplicates: false
+ - rename:
+ field: json.entity.description
+ target_field: message
+ ignore_missing: true
+ tag: rename_description_to_message
+ if: ctx.json?.entity?.description != null
+ - rename:
+ field: json.entity.provenance.integrationName
+ target_field: observer.name
+ ignore_missing: true
+ tag: rename_integration_name_to_observer_name
+ if: ctx.json?.entity?.provenance?.integrationName != null
+ - set:
+ field: event.kind
+ tag: set_event_kind_created
+ value: event
+ if: ctx.json?.eventType == 'EVENT_TYPE_CREATED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_event_kind_created
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.category
+ tag: append_event_category_created
+ value: host
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_CREATED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_category_created
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.type
+ tag: append_event_type_created
+ value: start
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_CREATED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_type_created
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - set:
+ field: event.kind
+ tag: set_event_kind_update
+ value: event
+ if: ctx.json?.eventType == 'EVENT_TYPE_UPDATE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_event_kind_update
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.category
+ tag: append_event_category_update
+ value: host
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_UPDATE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_category_update
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.type
+ tag: append_event_type_update
+ value: change
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_UPDATE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_type_update
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - set:
+ field: event.kind
+ tag: set_event_kind_deleted
+ value: event
+ if: ctx.json?.eventType == 'EVENT_TYPE_DELETED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_event_kind_deleted
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.category
+ tag: append_event_category_deleted
+ value: host
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_DELETED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_category_deleted
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.type
+ tag: append_event_type_deleted
+ value: end
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_DELETED'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_type_deleted
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - set:
+ field: event.kind
+ tag: set_event_kind_preexisting
+ value: state
+ if: ctx.json?.eventType == 'EVENT_TYPE_PREEXISTING'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_event_kind_preexisting
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.category
+ tag: append_event_category_preexisting
+ value: host
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_PREEXISTING'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_category_preexisting
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.type
+ tag: append_event_type_preexisting
+ value: info
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_PREEXISTING'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_type_preexisting
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - set:
+ field: event.kind
+ tag: set_event_kind_post_expiry
+ value: event
+ if: ctx.json?.eventType == 'EVENT_TYPE_POST_EXPIRY_OVERRIDE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_event_kind_post_expiry
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.category
+ tag: append_event_category_post_expiry
+ value: host
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_POST_EXPIRY_OVERRIDE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_category_post_expiry
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - append:
+ field: event.type
+ tag: append_event_type_post_expiry
+ value: change
+ allow_duplicates: false
+ if: ctx.json?.eventType == 'EVENT_TYPE_POST_EXPIRY_OVERRIDE'
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_event_type_post_expiry
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - rename:
+ field: json.eventType
+ target_field: anduril_lattice.entity.event_type
+ ignore_missing: true
+ tag: rename_event_type
+ if: ctx.json?.eventType != null
+ - rename:
+ field: json.entity.entityId
+ target_field: anduril_lattice.entity.entity_id
+ ignore_missing: true
+ tag: rename_entity_id
+ if: ctx.json?.entity?.entityId != null
+ - rename:
+ field: json.entity.isLive
+ target_field: anduril_lattice.entity.is_live
+ ignore_missing: true
+ tag: rename_is_live
+ if: ctx.json?.entity?.isLive != null
+ - rename:
+ field: json.entity.noExpiry
+ target_field: anduril_lattice.entity.no_expiry
+ ignore_missing: true
+ tag: rename_no_expiry
+ if: ctx.json?.entity?.noExpiry != null
+ - rename:
+ field: json.entity.aliases.name
+ target_field: anduril_lattice.entity.aliases.name
+ ignore_missing: true
+ tag: rename_aliases_name
+ if: ctx.json?.entity?.aliases?.name != null
+ - rename:
+ field: json.entity.milView.disposition
+ target_field: anduril_lattice.entity.mil_view.disposition
+ ignore_missing: true
+ tag: rename_mil_view_disposition
+ if: ctx.json?.entity?.milView?.disposition != null
+ - rename:
+ field: json.entity.milView.environment
+ target_field: anduril_lattice.entity.mil_view.environment
+ ignore_missing: true
+ tag: rename_mil_view_environment
+ if: ctx.json?.entity?.milView?.environment != null
+ - rename:
+ field: json.entity.milView.nationality
+ target_field: anduril_lattice.entity.mil_view.nationality
+ ignore_missing: true
+ tag: rename_mil_view_nationality
+ if: ctx.json?.entity?.milView?.nationality != null
+ - rename:
+ field: json.entity.ontology.template
+ target_field: anduril_lattice.entity.ontology.template
+ ignore_missing: true
+ tag: rename_ontology_template
+ if: ctx.json?.entity?.ontology?.template != null
+ - rename:
+ field: json.entity.ontology.platformType
+ target_field: anduril_lattice.entity.ontology.platform_type
+ ignore_missing: true
+ tag: rename_ontology_platform_type
+ if: ctx.json?.entity?.ontology?.platformType != null
+ - rename:
+ field: json.entity.ontology.specificType
+ target_field: anduril_lattice.entity.ontology.specific_type
+ ignore_missing: true
+ tag: rename_ontology_specific_type
+ if: ctx.json?.entity?.ontology?.specificType != null
+ - set:
+ field: anduril_lattice.entity.location.geo
+ tag: set_location_geo
+ value: '{{{json.entity.location.position.latitudeDegrees}}},{{{json.entity.location.position.longitudeDegrees}}}'
+ if: ctx.json?.entity?.location?.position?.latitudeDegrees != null && ctx.json?.entity?.location?.position?.longitudeDegrees != null
+ - rename:
+ field: json.entity.location.position.altitudeHaeMeters
+ target_field: anduril_lattice.entity.location.altitude_hae_meters
+ ignore_missing: true
+ tag: rename_altitude_hae_meters
+ if: ctx.json?.entity?.location?.position?.altitudeHaeMeters != null
+ - rename:
+ field: json.entity.location.speedMps
+ target_field: anduril_lattice.entity.location.speed_mps
+ ignore_missing: true
+ tag: rename_speed_mps
+ if: ctx.json?.entity?.location?.speedMps != null
+ - rename:
+ field: json.entity.location.velocityEnu.e
+ target_field: anduril_lattice.entity.location.velocity_enu.e
+ ignore_missing: true
+ tag: rename_velocity_enu_e
+ if: ctx.json?.entity?.location?.velocityEnu?.e != null
+ - rename:
+ field: json.entity.location.velocityEnu.n
+ target_field: anduril_lattice.entity.location.velocity_enu.n
+ ignore_missing: true
+ tag: rename_velocity_enu_n
+ if: ctx.json?.entity?.location?.velocityEnu?.n != null
+ - rename:
+ field: json.entity.location.velocityEnu.u
+ target_field: anduril_lattice.entity.location.velocity_enu.u
+ ignore_missing: true
+ tag: rename_velocity_enu_u
+ if: ctx.json?.entity?.location?.velocityEnu?.u != null
+ - rename:
+ field: json.entity.tracked.trackQualityWrapper
+ target_field: anduril_lattice.entity.tracked.track_quality
+ ignore_missing: true
+ tag: rename_track_quality
+ if: ctx.json?.entity?.tracked?.trackQualityWrapper != null
+ - rename:
+ field: json.entity.tracked.sensorHits
+ target_field: anduril_lattice.entity.tracked.sensor_hits
+ ignore_missing: true
+ tag: rename_sensor_hits
+ if: ctx.json?.entity?.tracked?.sensorHits != null
+ - rename:
+ field: json.entity.provenance.dataType
+ target_field: anduril_lattice.entity.provenance.data_type
+ ignore_missing: true
+ tag: rename_provenance_data_type
+ if: ctx.json?.entity?.provenance?.dataType != null
+ - rename:
+ field: json.entity.indicators.simulated
+ target_field: anduril_lattice.entity.indicators.simulated
+ ignore_missing: true
+ tag: rename_indicators_simulated
+ if: ctx.json?.entity?.indicators?.simulated != null
+ - rename:
+ field: json.entity.indicators.exercise
+ target_field: anduril_lattice.entity.indicators.exercise
+ ignore_missing: true
+ tag: rename_indicators_exercise
+ if: ctx.json?.entity?.indicators?.exercise != null
+ - rename:
+ field: json.entity.indicators.emergency
+ target_field: anduril_lattice.entity.indicators.emergency
+ ignore_missing: true
+ tag: rename_indicators_emergency
+ if: ctx.json?.entity?.indicators?.emergency != null
+ - rename:
+ field: json.entity.health.connectionStatus
+ target_field: anduril_lattice.entity.health.connection_status
+ ignore_missing: true
+ tag: rename_health_connection_status
+ if: ctx.json?.entity?.health?.connectionStatus != null
+ - rename:
+ field: json.entity.powerState
+ target_field: anduril_lattice.entity.power_state
+ ignore_missing: true
+ tag: rename_power_state
+ if: ctx.json?.entity?.powerState != null
+ - rename:
+ field: json.entity.relationships
+ target_field: anduril_lattice.entity.relationships
+ ignore_missing: true
+ tag: rename_relationships
+ if: ctx.json?.entity?.relationships != null
+ - rename:
+ field: json.entity.status.platformActivity
+ target_field: anduril_lattice.entity.status.platform_activity
+ ignore_missing: true
+ tag: rename_status_platform_activity
+ if: ctx.json?.entity?.status?.platformActivity != null
+ - rename:
+ field: json.entity.status.role
+ target_field: anduril_lattice.entity.status.role
+ ignore_missing: true
+ tag: rename_status_role
+ if: ctx.json?.entity?.status?.role != null
+ - rename:
+ field: json.entity.location.position.altitudeAglMeters
+ target_field: anduril_lattice.entity.location.altitude_agl_meters
+ ignore_missing: true
+ tag: rename_altitude_agl_meters
+ if: ctx.json?.entity?.location?.position?.altitudeAglMeters != null
+ - rename:
+ field: json.entity.location.position.altitudeAsfMeters
+ target_field: anduril_lattice.entity.location.altitude_asf_meters
+ ignore_missing: true
+ tag: rename_altitude_asf_meters
+ if: ctx.json?.entity?.location?.position?.altitudeAsfMeters != null
+ - rename:
+ field: json.entity.location.position.pressureDepthMeters
+ target_field: anduril_lattice.entity.location.pressure_depth_meters
+ ignore_missing: true
+ tag: rename_pressure_depth_meters
+ if: ctx.json?.entity?.location?.position?.pressureDepthMeters != null
+ - rename:
+ field: json.entity.location.acceleration.e
+ target_field: anduril_lattice.entity.location.acceleration_enu.e
+ ignore_missing: true
+ tag: rename_acceleration_enu_e
+ if: ctx.json?.entity?.location?.acceleration?.e != null
+ - rename:
+ field: json.entity.location.acceleration.n
+ target_field: anduril_lattice.entity.location.acceleration_enu.n
+ ignore_missing: true
+ tag: rename_acceleration_enu_n
+ if: ctx.json?.entity?.location?.acceleration?.n != null
+ - rename:
+ field: json.entity.location.acceleration.u
+ target_field: anduril_lattice.entity.location.acceleration_enu.u
+ ignore_missing: true
+ tag: rename_acceleration_enu_u
+ if: ctx.json?.entity?.location?.acceleration?.u != null
+ - rename:
+ field: json.entity.location.attitudeEnu.x
+ target_field: anduril_lattice.entity.location.attitude_enu.x
+ ignore_missing: true
+ tag: rename_attitude_enu_x
+ if: ctx.json?.entity?.location?.attitudeEnu?.x != null
+ - rename:
+ field: json.entity.location.attitudeEnu.y
+ target_field: anduril_lattice.entity.location.attitude_enu.y
+ ignore_missing: true
+ tag: rename_attitude_enu_y
+ if: ctx.json?.entity?.location?.attitudeEnu?.y != null
+ - rename:
+ field: json.entity.location.attitudeEnu.z
+ target_field: anduril_lattice.entity.location.attitude_enu.z
+ ignore_missing: true
+ tag: rename_attitude_enu_z
+ if: ctx.json?.entity?.location?.attitudeEnu?.z != null
+ - rename:
+ field: json.entity.location.attitudeEnu.w
+ target_field: anduril_lattice.entity.location.attitude_enu.w
+ ignore_missing: true
+ tag: rename_attitude_enu_w
+ if: ctx.json?.entity?.location?.attitudeEnu?.w != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.mxx
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.mxx
+ ignore_missing: true
+ tag: rename_pos_enu_cov_mxx
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.mxx != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.mxy
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.mxy
+ ignore_missing: true
+ tag: rename_pos_enu_cov_mxy
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.mxy != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.mxz
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.mxz
+ ignore_missing: true
+ tag: rename_pos_enu_cov_mxz
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.mxz != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.myy
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.myy
+ ignore_missing: true
+ tag: rename_pos_enu_cov_myy
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.myy != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.myz
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.myz
+ ignore_missing: true
+ tag: rename_pos_enu_cov_myz
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.myz != null
+ - rename:
+ field: json.entity.locationUncertainty.positionEnuCov.mzz
+ target_field: anduril_lattice.entity.location_uncertainty.position_enu_cov.mzz
+ ignore_missing: true
+ tag: rename_pos_enu_cov_mzz
+ if: ctx.json?.entity?.locationUncertainty?.positionEnuCov?.mzz != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.mxx
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxx
+ ignore_missing: true
+ tag: rename_vel_enu_cov_mxx
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.mxx != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.mxy
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxy
+ ignore_missing: true
+ tag: rename_vel_enu_cov_mxy
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.mxy != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.mxz
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxz
+ ignore_missing: true
+ tag: rename_vel_enu_cov_mxz
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.mxz != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.myy
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.myy
+ ignore_missing: true
+ tag: rename_vel_enu_cov_myy
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.myy != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.myz
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.myz
+ ignore_missing: true
+ tag: rename_vel_enu_cov_myz
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.myz != null
+ - rename:
+ field: json.entity.locationUncertainty.velocityEnuCov.mzz
+ target_field: anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mzz
+ ignore_missing: true
+ tag: rename_vel_enu_cov_mzz
+ if: ctx.json?.entity?.locationUncertainty?.velocityEnuCov?.mzz != null
+ - rename:
+ field: json.entity.locationUncertainty.positionErrorEllipse.probability
+ target_field: anduril_lattice.entity.location_uncertainty.position_error_ellipse.probability
+ ignore_missing: true
+ tag: rename_pos_err_ellipse_probability
+ if: ctx.json?.entity?.locationUncertainty?.positionErrorEllipse?.probability != null
+ - rename:
+ field: json.entity.locationUncertainty.positionErrorEllipse.semiMajorAxisM
+ target_field: anduril_lattice.entity.location_uncertainty.position_error_ellipse.semi_major_axis_m
+ ignore_missing: true
+ tag: rename_pos_err_ellipse_semi_major
+ if: ctx.json?.entity?.locationUncertainty?.positionErrorEllipse?.semiMajorAxisM != null
+ - rename:
+ field: json.entity.locationUncertainty.positionErrorEllipse.semiMinorAxisM
+ target_field: anduril_lattice.entity.location_uncertainty.position_error_ellipse.semi_minor_axis_m
+ ignore_missing: true
+ tag: rename_pos_err_ellipse_semi_minor
+ if: ctx.json?.entity?.locationUncertainty?.positionErrorEllipse?.semiMinorAxisM != null
+ - rename:
+ field: json.entity.locationUncertainty.positionErrorEllipse.orientationD
+ target_field: anduril_lattice.entity.location_uncertainty.position_error_ellipse.orientation_d
+ ignore_missing: true
+ tag: rename_pos_err_ellipse_orientation
+ if: ctx.json?.entity?.locationUncertainty?.positionErrorEllipse?.orientationD != null
+ - script:
+ tag: set_geo_shape
+ description: >-
+ Convert the geoShape one-of union to a GeoJSON geo_shape. Handles point,
+ line, and polygon geometry types. Ellipse and ellipsoid store scalars only.
+ lang: painless
+ if: ctx.json?.entity?.geoShape != null
+ source: |
+ def gs = ctx.json.entity.geoShape;
+ if (gs.point != null) {
+ def pt = gs.point;
+ def coords = new ArrayList();
+ coords.add(pt.longitudeDegrees);
+ coords.add(pt.latitudeDegrees);
+ if (pt.altitudeHaeMeters != null) { coords.add(pt.altitudeHaeMeters); }
+ def shape = [:];
+ shape.type = "Point";
+ shape.coordinates = coords;
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.geo_shape = shape;
+ } else if (gs.line != null && gs.line.positions != null) {
+ def coordList = new ArrayList();
+ for (def pos : gs.line.positions) {
+ def c = new ArrayList();
+ c.add(pos.longitudeDegrees);
+ c.add(pos.latitudeDegrees);
+ coordList.add(c);
+ }
+ def shape = [:];
+ shape.type = "LineString";
+ shape.coordinates = coordList;
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.geo_shape = shape;
+ } else if (gs.polygon != null && gs.polygon.rings != null && gs.polygon.rings.size() > 0) {
+ def ring = gs.polygon.rings[0];
+ def ringCoords = new ArrayList();
+ if (ring.positions != null) {
+ for (def posEntry : ring.positions) {
+ def pos = posEntry.position != null ? posEntry.position : posEntry;
+ def c = new ArrayList();
+ c.add(pos.longitudeDegrees);
+ c.add(pos.latitudeDegrees);
+ ringCoords.add(c);
+ }
+ }
+ if (ringCoords.size() > 0) {
+ def first = ringCoords.get(0);
+ def last = ringCoords.get(ringCoords.size() - 1);
+ if (!first.equals(last)) { ringCoords.add(first); }
+ }
+ def rings = new ArrayList();
+ rings.add(ringCoords);
+ def shape = [:];
+ shape.type = "Polygon";
+ shape.coordinates = rings;
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.geo_shape = shape;
+ } else if (gs.ellipse != null) {
+ def e = gs.ellipse;
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.geo_shape_ellipse = [:];
+ if (e.semiMajorAxisM != null) { ctx.anduril_lattice.entity.geo_shape_ellipse.semi_major_axis_m = e.semiMajorAxisM; }
+ if (e.semiMinorAxisM != null) { ctx.anduril_lattice.entity.geo_shape_ellipse.semi_minor_axis_m = e.semiMinorAxisM; }
+ if (e.orientationD != null) { ctx.anduril_lattice.entity.geo_shape_ellipse.orientation_d = e.orientationD; }
+ if (e.heightM != null) { ctx.anduril_lattice.entity.geo_shape_ellipse.height_m = e.heightM; }
+ } else if (gs.ellipsoid != null) {
+ def e = gs.ellipsoid;
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.geo_shape_ellipsoid = [:];
+ if (e.forwardAxisM != null) { ctx.anduril_lattice.entity.geo_shape_ellipsoid.forward_axis_m = e.forwardAxisM; }
+ if (e.sideAxisM != null) { ctx.anduril_lattice.entity.geo_shape_ellipsoid.side_axis_m = e.sideAxisM; }
+ if (e.upAxisM != null) { ctx.anduril_lattice.entity.geo_shape_ellipsoid.up_axis_m = e.upAxisM; }
+ }
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_geo_shape
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - rename:
+ field: json.entity.geoDetails.type
+ target_field: anduril_lattice.entity.geo_details.type
+ ignore_missing: true
+ tag: rename_geo_details_type
+ if: ctx.json?.entity?.geoDetails?.type != null
+ - rename:
+ field: json.entity.geoDetails.controlArea.type
+ target_field: anduril_lattice.entity.geo_details.control_area_type
+ ignore_missing: true
+ tag: rename_geo_details_control_area_type
+ if: ctx.json?.entity?.geoDetails?.controlArea?.type != null
+ - rename:
+ field: json.entity.geoDetails.acm.acmType
+ target_field: anduril_lattice.entity.geo_details.acm.type
+ ignore_missing: true
+ tag: rename_geo_details_acm_type
+ if: ctx.json?.entity?.geoDetails?.acm?.acmType != null
+ - rename:
+ field: json.entity.geoDetails.acm.acmDescription
+ target_field: anduril_lattice.entity.geo_details.acm.description
+ ignore_missing: true
+ tag: rename_geo_details_acm_description
+ if: ctx.json?.entity?.geoDetails?.acm?.acmDescription != null
+ - foreach:
+ field: json.entity.aliases.alternateIds
+ ignore_missing: true
+ tag: foreach_alternate_ids
+ if: ctx.json?.entity?.aliases?.alternateIds instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.aliases.alternate_ids
+ tag: append_alternate_id
+ value: '{{{_ingest._value.id}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.aliases.alternateIds
+ ignore_missing: true
+ tag: foreach_alternate_id_types
+ if: ctx.json?.entity?.aliases?.alternateIds instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.aliases.alternate_id_types
+ tag: append_alternate_id_type
+ value: '{{{_ingest._value.type}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - rename:
+ field: json.entity.tracked.numberOfObjects.lowerBound
+ target_field: anduril_lattice.entity.tracked.number_of_objects.lower_bound
+ ignore_missing: true
+ tag: rename_tracked_num_objects_lower
+ if: ctx.json?.entity?.tracked?.numberOfObjects?.lowerBound != null
+ - rename:
+ field: json.entity.tracked.numberOfObjects.upperBound
+ target_field: anduril_lattice.entity.tracked.number_of_objects.upper_bound
+ ignore_missing: true
+ tag: rename_tracked_num_objects_upper
+ if: ctx.json?.entity?.tracked?.numberOfObjects?.upperBound != null
+ - rename:
+ field: json.entity.tracked.radarCrossSection
+ target_field: anduril_lattice.entity.tracked.radar_cross_section
+ ignore_missing: true
+ tag: rename_tracked_radar_cross_section
+ if: ctx.json?.entity?.tracked?.radarCrossSection != null
+ - date:
+ field: json.entity.tracked.lastMeasurementTime
+ target_field: anduril_lattice.entity.tracked.last_measurement_time
+ formats:
+ - ISO8601
+ tag: parse_tracked_last_measurement_time
+ if: ctx.json?.entity?.tracked?.lastMeasurementTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_tracked_last_measurement_time
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - rename:
+ field: json.entity.tracked.lineOfBearing.rangeEstimateM.value
+ target_field: anduril_lattice.entity.tracked.line_of_bearing.range_estimate_m
+ ignore_missing: true
+ tag: rename_lob_range_estimate_m
+ if: ctx.json?.entity?.tracked?.lineOfBearing?.rangeEstimateM?.value != null
+ - rename:
+ field: json.entity.tracked.lineOfBearing.maxRangeM.value
+ target_field: anduril_lattice.entity.tracked.line_of_bearing.max_range_m
+ ignore_missing: true
+ tag: rename_lob_max_range_m
+ if: ctx.json?.entity?.tracked?.lineOfBearing?.maxRangeM?.value != null
+ - rename:
+ field: json.entity.indicators.c2
+ target_field: anduril_lattice.entity.indicators.c2
+ ignore_missing: true
+ tag: rename_indicators_c2
+ if: ctx.json?.entity?.indicators?.c2 != null
+ - rename:
+ field: json.entity.indicators.egressable
+ target_field: anduril_lattice.entity.indicators.egressable
+ ignore_missing: true
+ tag: rename_indicators_egressable
+ if: ctx.json?.entity?.indicators?.egressable != null
+ - rename:
+ field: json.entity.indicators.starred
+ target_field: anduril_lattice.entity.indicators.starred
+ ignore_missing: true
+ tag: rename_indicators_starred
+ if: ctx.json?.entity?.indicators?.starred != null
+ - rename:
+ field: json.entity.provenance.sourceId
+ target_field: anduril_lattice.entity.provenance.source_id
+ ignore_missing: true
+ tag: rename_provenance_source_id
+ if: ctx.json?.entity?.provenance?.sourceId != null
+ - rename:
+ field: json.entity.provenance.sourceDescription
+ target_field: anduril_lattice.entity.provenance.source_description
+ ignore_missing: true
+ tag: rename_provenance_source_description
+ if: ctx.json?.entity?.provenance?.sourceDescription != null
+ - rename:
+ field: json.entity.targetPriority.highValueTarget.isHighValueTarget
+ target_field: anduril_lattice.entity.target_priority.is_high_value_target
+ ignore_missing: true
+ tag: rename_target_priority_hvt
+ if: ctx.json?.entity?.targetPriority?.highValueTarget?.isHighValueTarget != null
+ - rename:
+ field: json.entity.targetPriority.highValueTarget.targetPriority
+ target_field: anduril_lattice.entity.target_priority.priority
+ ignore_missing: true
+ tag: rename_target_priority_priority
+ if: ctx.json?.entity?.targetPriority?.highValueTarget?.targetPriority != null
+ - rename:
+ field: json.entity.targetPriority.highValueTarget.isHighPayoffTarget
+ target_field: anduril_lattice.entity.target_priority.is_high_payoff_target
+ ignore_missing: true
+ tag: rename_target_priority_hpt
+ if: ctx.json?.entity?.targetPriority?.highValueTarget?.isHighPayoffTarget != null
+ - rename:
+ field: json.entity.targetPriority.threat.isThreat
+ target_field: anduril_lattice.entity.target_priority.is_threat
+ ignore_missing: true
+ tag: rename_target_priority_is_threat
+ if: ctx.json?.entity?.targetPriority?.threat?.isThreat != null
+ - rename:
+ field: json.entity.signal.frequencyCenter.frequencyHz.value
+ target_field: anduril_lattice.entity.signal.frequency_center_hz
+ ignore_missing: true
+ tag: rename_signal_frequency_center_hz
+ if: ctx.json?.entity?.signal?.frequencyCenter?.frequencyHz?.value != null
+ - rename:
+ field: json.entity.signal.frequencyRange.minimumFrequencyHz.frequencyHz.value
+ target_field: anduril_lattice.entity.signal.frequency_min_hz
+ ignore_missing: true
+ tag: rename_signal_frequency_min_hz
+ if: ctx.json?.entity?.signal?.frequencyRange?.minimumFrequencyHz?.frequencyHz?.value != null
+ - rename:
+ field: json.entity.signal.frequencyRange.maximumFrequencyHz.frequencyHz.value
+ target_field: anduril_lattice.entity.signal.frequency_max_hz
+ ignore_missing: true
+ tag: rename_signal_frequency_max_hz
+ if: ctx.json?.entity?.signal?.frequencyRange?.maximumFrequencyHz?.frequencyHz?.value != null
+ - rename:
+ field: json.entity.signal.bandwidthHz
+ target_field: anduril_lattice.entity.signal.bandwidth_hz
+ ignore_missing: true
+ tag: rename_signal_bandwidth_hz
+ if: ctx.json?.entity?.signal?.bandwidthHz != null
+ - rename:
+ field: json.entity.signal.signalToNoiseRatio
+ target_field: anduril_lattice.entity.signal.signal_to_noise_ratio
+ ignore_missing: true
+ tag: rename_signal_snr
+ if: ctx.json?.entity?.signal?.signalToNoiseRatio != null
+ - rename:
+ field: json.entity.signal.pulseWidthS
+ target_field: anduril_lattice.entity.signal.pulse_width_s
+ ignore_missing: true
+ tag: rename_signal_pulse_width_s
+ if: ctx.json?.entity?.signal?.pulseWidthS != null
+ - rename:
+ field: json.entity.signal.scanCharacteristics.scanType
+ target_field: anduril_lattice.entity.signal.scan_type
+ ignore_missing: true
+ tag: rename_signal_scan_type
+ if: ctx.json?.entity?.signal?.scanCharacteristics?.scanType != null
+ - rename:
+ field: json.entity.signal.scanCharacteristics.scanPeriodS
+ target_field: anduril_lattice.entity.signal.scan_period_s
+ ignore_missing: true
+ tag: rename_signal_scan_period_s
+ if: ctx.json?.entity?.signal?.scanCharacteristics?.scanPeriodS != null
+ - foreach:
+ field: json.entity.signal.emitterNotations
+ ignore_missing: true
+ tag: foreach_signal_emitter_notations
+ if: ctx.json?.entity?.signal?.emitterNotations instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.signal.emitter_notations
+ tag: append_signal_emitter_notation
+ value: '{{{_ingest._value}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - rename:
+ field: json.entity.transponderCodes.mode1
+ target_field: anduril_lattice.entity.transponder_codes.mode1
+ ignore_missing: true
+ tag: rename_transponder_mode1
+ if: ctx.json?.entity?.transponderCodes?.mode1 != null
+ - rename:
+ field: json.entity.transponderCodes.mode2
+ target_field: anduril_lattice.entity.transponder_codes.mode2
+ ignore_missing: true
+ tag: rename_transponder_mode2
+ if: ctx.json?.entity?.transponderCodes?.mode2 != null
+ - rename:
+ field: json.entity.transponderCodes.mode3
+ target_field: anduril_lattice.entity.transponder_codes.mode3
+ ignore_missing: true
+ tag: rename_transponder_mode3
+ if: ctx.json?.entity?.transponderCodes?.mode3 != null
+ - rename:
+ field: json.entity.transponderCodes.modeCAltitudeFt
+ target_field: anduril_lattice.entity.transponder_codes.mode_c_altitude_ft
+ ignore_missing: true
+ tag: rename_transponder_mode_c_altitude_ft
+ if: ctx.json?.entity?.transponderCodes?.modeCAltitudeFt != null
+ - rename:
+ field: json.entity.transponderCodes.modeS.id
+ target_field: anduril_lattice.entity.transponder_codes.mode_s_id
+ ignore_missing: true
+ tag: rename_transponder_mode_s_id
+ if: ctx.json?.entity?.transponderCodes?.modeS?.id != null
+ - rename:
+ field: json.entity.transponderCodes.modeS.address
+ target_field: anduril_lattice.entity.transponder_codes.mode_s_address
+ ignore_missing: true
+ tag: rename_transponder_mode_s_address
+ if: ctx.json?.entity?.transponderCodes?.modeS?.address != null
+ - rename:
+ field: json.entity.transponderCodes.mode5.mode5
+ target_field: anduril_lattice.entity.transponder_codes.mode5
+ ignore_missing: true
+ tag: rename_transponder_mode5
+ if: ctx.json?.entity?.transponderCodes?.mode5?.mode5 != null
+ - rename:
+ field: json.entity.transponderCodes.mode5.mode5PlatformId
+ target_field: anduril_lattice.entity.transponder_codes.mode5_platform_id
+ ignore_missing: true
+ tag: rename_transponder_mode5_platform_id
+ if: ctx.json?.entity?.transponderCodes?.mode5?.mode5PlatformId != null
+ - rename:
+ field: json.entity.dataClassification.default.level
+ target_field: anduril_lattice.entity.data_classification.level
+ ignore_missing: true
+ tag: rename_data_classification_level
+ if: ctx.json?.entity?.dataClassification?.default?.level != null
+ - foreach:
+ field: json.entity.dataClassification.default.caveats
+ ignore_missing: true
+ tag: foreach_data_classification_caveats
+ if: ctx.json?.entity?.dataClassification?.default?.caveats instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.data_classification.caveats
+ tag: append_data_classification_caveat
+ value: '{{{_ingest._value}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - rename:
+ field: json.entity.health.healthStatus
+ target_field: anduril_lattice.entity.health.health_status
+ ignore_missing: true
+ tag: rename_health_status
+ if: ctx.json?.entity?.health?.healthStatus != null
+ - date:
+ field: json.entity.health.updateTime
+ target_field: anduril_lattice.entity.health.update_time
+ formats:
+ - ISO8601
+ tag: parse_health_update_time
+ if: ctx.json?.entity?.health?.updateTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_health_update_time
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - foreach:
+ field: json.entity.health.activeAlerts
+ ignore_missing: true
+ tag: foreach_health_active_alerts_code
+ if: ctx.json?.entity?.health?.activeAlerts instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.health.active_alerts.alert_code
+ tag: append_health_alert_code
+ value: '{{{_ingest._value.alertCode}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.health.activeAlerts
+ ignore_missing: true
+ tag: foreach_health_active_alerts_level
+ if: ctx.json?.entity?.health?.activeAlerts instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.health.active_alerts.level
+ tag: append_health_alert_level
+ value: '{{{_ingest._value.level}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.health.activeAlerts
+ ignore_missing: true
+ tag: foreach_health_active_alerts_description
+ if: ctx.json?.entity?.health?.activeAlerts instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.health.active_alerts.description
+ tag: append_health_alert_description
+ value: '{{{_ingest._value.description}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.health.activeAlerts
+ ignore_missing: true
+ tag: foreach_health_active_alerts_activated_time
+ if: ctx.json?.entity?.health?.activeAlerts instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.health.active_alerts.activated_time
+ tag: append_health_alert_activated_time
+ value: '{{{_ingest._value.activatedTime}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - rename:
+ field: json.entity.correlation.primary.secondaryEntityIds
+ target_field: anduril_lattice.entity.correlation.primary_secondary_entity_ids
+ ignore_missing: true
+ tag: rename_correlation_primary_secondary_ids
+ if: ctx.json?.entity?.correlation?.primary?.secondaryEntityIds != null
+ - rename:
+ field: json.entity.correlation.secondary.primaryEntityId
+ target_field: anduril_lattice.entity.correlation.secondary_primary_entity_id
+ ignore_missing: true
+ tag: rename_correlation_secondary_primary_id
+ if: ctx.json?.entity?.correlation?.secondary?.primaryEntityId != null
+ - rename:
+ field: json.entity.correlation.membership.correlationSetId
+ target_field: anduril_lattice.entity.correlation.membership_set_id
+ ignore_missing: true
+ tag: rename_correlation_membership_set_id
+ if: ctx.json?.entity?.correlation?.membership?.correlationSetId != null
+ - rename:
+ field: json.entity.symbology.milStd2525C.sidc
+ target_field: anduril_lattice.entity.symbology.mil_std_2525c_sidc
+ ignore_missing: true
+ tag: rename_symbology_sidc
+ if: ctx.json?.entity?.symbology?.milStd2525C?.sidc != null
+ - date:
+ field: json.entity.orbit.orbitMeanElements.meanKeplerianElements.epoch
+ target_field: anduril_lattice.entity.orbit.epoch
+ formats:
+ - ISO8601
+ tag: parse_orbit_epoch
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.meanKeplerianElements?.epoch != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_orbit_epoch
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - rename:
+ field: json.entity.orbit.orbitMeanElements.meanKeplerianElements.semiMajorAxisKm
+ target_field: anduril_lattice.entity.orbit.semi_major_axis_km
+ ignore_missing: true
+ tag: rename_orbit_semi_major_axis_km
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.meanKeplerianElements?.semiMajorAxisKm != null
+ - rename:
+ field: json.entity.orbit.orbitMeanElements.meanKeplerianElements.eccentricity
+ target_field: anduril_lattice.entity.orbit.eccentricity
+ ignore_missing: true
+ tag: rename_orbit_eccentricity
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.meanKeplerianElements?.eccentricity != null
+ - rename:
+ field: json.entity.orbit.orbitMeanElements.meanKeplerianElements.inclinationDeg
+ target_field: anduril_lattice.entity.orbit.inclination_deg
+ ignore_missing: true
+ tag: rename_orbit_inclination_deg
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.meanKeplerianElements?.inclinationDeg != null
+ - rename:
+ field: json.entity.orbit.orbitMeanElements.tleParameters.noradCatId
+ target_field: anduril_lattice.entity.orbit.norad_cat_id
+ ignore_missing: true
+ tag: rename_orbit_norad_cat_id
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.tleParameters?.noradCatId != null
+ - rename:
+ field: json.entity.orbit.orbitMeanElements.tleParameters.bstar
+ target_field: anduril_lattice.entity.orbit.bstar
+ ignore_missing: true
+ tag: rename_orbit_bstar
+ if: ctx.json?.entity?.orbit?.orbitMeanElements?.tleParameters?.bstar != null
+ - rename:
+ field: json.entity.dimensions.lengthM
+ target_field: anduril_lattice.entity.dimensions.length_m
+ ignore_missing: true
+ tag: rename_dimensions_length_m
+ if: ctx.json?.entity?.dimensions?.lengthM != null
+ - rename:
+ field: json.entity.routeDetails.destinationName
+ target_field: anduril_lattice.entity.route_details.destination_name
+ ignore_missing: true
+ tag: rename_route_details_destination_name
+ if: ctx.json?.entity?.routeDetails?.destinationName != null
+ - date:
+ field: json.entity.routeDetails.estimatedArrivalTime
+ target_field: anduril_lattice.entity.route_details.estimated_arrival_time
+ formats:
+ - ISO8601
+ tag: parse_route_estimated_arrival_time
+ if: ctx.json?.entity?.routeDetails?.estimatedArrivalTime != null
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_route_estimated_arrival_time
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - rename:
+ field: json.entity.visualDetails.rangeRings.minDistanceM
+ target_field: anduril_lattice.entity.visual_details.range_rings.min_distance_m
+ ignore_missing: true
+ tag: rename_visual_details_range_rings_min
+ if: ctx.json?.entity?.visualDetails?.rangeRings?.minDistanceM != null
+ - rename:
+ field: json.entity.visualDetails.rangeRings.maxDistanceM
+ target_field: anduril_lattice.entity.visual_details.range_rings.max_distance_m
+ ignore_missing: true
+ tag: rename_visual_details_range_rings_max
+ if: ctx.json?.entity?.visualDetails?.rangeRings?.maxDistanceM != null
+ - rename:
+ field: json.entity.visualDetails.rangeRings.ringCount
+ target_field: anduril_lattice.entity.visual_details.range_rings.ring_count
+ ignore_missing: true
+ tag: rename_visual_details_range_rings_count
+ if: ctx.json?.entity?.visualDetails?.rangeRings?.ringCount != null
+ - rename:
+ field: json.entity.groupDetails.echelon.armyEchelon
+ target_field: anduril_lattice.entity.group_details.army_echelon
+ ignore_missing: true
+ tag: rename_group_details_army_echelon
+ if: ctx.json?.entity?.groupDetails?.echelon?.armyEchelon != null
+ - foreach:
+ field: json.entity.taskCatalog.taskDefinitions
+ ignore_missing: true
+ tag: foreach_task_catalog_task_definitions
+ if: ctx.json?.entity?.taskCatalog?.taskDefinitions instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.task_catalog.task_specification_urls
+ tag: append_task_specification_url
+ value: '{{{_ingest._value.taskSpecificationUrl}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.media.media
+ ignore_missing: true
+ tag: foreach_media_item_identifier
+ if: ctx.json?.entity?.media?.media instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.media.item_identifier
+ tag: append_media_item_identifier
+ value: '{{{_ingest._value.itemIdentifier}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.media.media
+ ignore_missing: true
+ tag: foreach_media_type
+ if: ctx.json?.entity?.media?.media instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.media.type
+ tag: append_media_type
+ value: '{{{_ingest._value.type}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.media.media
+ ignore_missing: true
+ tag: foreach_media_relative_path
+ if: ctx.json?.entity?.media?.media instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.media.relative_path
+ tag: append_media_relative_path
+ value: '{{{_ingest._value.relativePath}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.munitions
+ ignore_missing: true
+ tag: foreach_supplies_munition_id
+ if: ctx.json?.entity?.supplies?.munitions instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.munition_id
+ tag: append_supplies_munition_id
+ value: '{{{_ingest._value.munitionId}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.munitions
+ ignore_missing: true
+ tag: foreach_supplies_munition_name
+ if: ctx.json?.entity?.supplies?.munitions instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.munition_name
+ tag: append_supplies_munition_name
+ value: '{{{_ingest._value.name}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.munitions
+ ignore_missing: true
+ tag: foreach_supplies_munition_quantity_units
+ if: ctx.json?.entity?.supplies?.munitions instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.munition_quantity_units
+ tag: append_supplies_munition_quantity_units
+ value: '{{{_ingest._value.quantityUnits}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.fuel
+ ignore_missing: true
+ tag: foreach_supplies_fuel_id
+ if: ctx.json?.entity?.supplies?.fuel instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.fuel_id
+ tag: append_supplies_fuel_id
+ value: '{{{_ingest._value.fuelId}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.fuel
+ ignore_missing: true
+ tag: foreach_supplies_fuel_name
+ if: ctx.json?.entity?.supplies?.fuel instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.fuel_name
+ tag: append_supplies_fuel_name
+ value: '{{{_ingest._value.name}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.fuel
+ ignore_missing: true
+ tag: foreach_supplies_fuel_amount_gallons
+ if: ctx.json?.entity?.supplies?.fuel instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.fuel_amount_gallons
+ tag: append_supplies_fuel_amount_gallons
+ value: '{{{_ingest._value.amountGallons}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.supplies.fuel
+ ignore_missing: true
+ tag: foreach_supplies_fuel_max_capacity_gallons
+ if: ctx.json?.entity?.supplies?.fuel instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.supplies.fuel_max_authorized_capacity_gallons
+ tag: append_supplies_fuel_max_capacity_gallons
+ value: '{{{_ingest._value.maxAuthorizedCapacityGallons}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.payloads.payloadConfigurations
+ ignore_missing: true
+ tag: foreach_payload_capability_id
+ if: ctx.json?.entity?.payloads?.payloadConfigurations instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.payloads.capability_id
+ tag: append_payload_capability_id
+ value: '{{{_ingest._value.config.capabilityId}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.payloads.payloadConfigurations
+ ignore_missing: true
+ tag: foreach_payload_operational_state
+ if: ctx.json?.entity?.payloads?.payloadConfigurations instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.payloads.operational_state
+ tag: append_payload_operational_state
+ value: '{{{_ingest._value.config.payloadOperationalState}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.payloads.payloadConfigurations
+ ignore_missing: true
+ tag: foreach_payload_description
+ if: ctx.json?.entity?.payloads?.payloadConfigurations instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.payloads.description
+ tag: append_payload_description
+ value: '{{{_ingest._value.config.payloadDescription}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.payloads.payloadConfigurations
+ ignore_missing: true
+ tag: foreach_payload_quantity
+ if: ctx.json?.entity?.payloads?.payloadConfigurations instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.payloads.quantity
+ tag: append_payload_quantity
+ value: '{{{_ingest._value.config.quantity}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.overrides
+ ignore_missing: true
+ tag: foreach_overrides_request_id
+ if: ctx.json?.entity?.overrides instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.overrides.request_ids
+ tag: append_overrides_request_id
+ value: '{{{_ingest._value.requestId}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.overrides
+ ignore_missing: true
+ tag: foreach_overrides_field_path
+ if: ctx.json?.entity?.overrides instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.overrides.field_paths
+ tag: append_overrides_field_path
+ value: '{{{_ingest._value.fieldPath}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.overrides
+ ignore_missing: true
+ tag: foreach_overrides_status
+ if: ctx.json?.entity?.overrides instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.overrides.statuses
+ tag: append_overrides_status
+ value: '{{{_ingest._value.status}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.overrides
+ ignore_missing: true
+ tag: foreach_overrides_type
+ if: ctx.json?.entity?.overrides instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.overrides.types
+ tag: append_overrides_type
+ value: '{{{_ingest._value.type}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.overrides
+ ignore_missing: true
+ tag: foreach_overrides_request_timestamp
+ if: ctx.json?.entity?.overrides instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.overrides.request_timestamps
+ tag: append_overrides_request_timestamp
+ value: '{{{_ingest._value.requestTimestamp}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.sensors.sensors
+ ignore_missing: true
+ tag: foreach_sensors_sensor_id
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.sensors.sensor_id
+ tag: append_sensors_sensor_id
+ value: '{{{_ingest._value.sensorId}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.sensors.sensors
+ ignore_missing: true
+ tag: foreach_sensors_operational_state
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.sensors.operational_state
+ tag: append_sensors_operational_state
+ value: '{{{_ingest._value.operationalState}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.sensors.sensors
+ ignore_missing: true
+ tag: foreach_sensors_sensor_type
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.sensors.sensor_type
+ tag: append_sensors_sensor_type
+ value: '{{{_ingest._value.sensorType}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.sensors.sensors
+ ignore_missing: true
+ tag: foreach_sensors_sensor_description
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.sensors.sensor_description
+ tag: append_sensors_sensor_description
+ value: '{{{_ingest._value.sensorDescription}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - foreach:
+ field: json.entity.sensors.sensors
+ ignore_missing: true
+ tag: foreach_sensors_last_detection_timestamp
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ processor:
+ append:
+ field: anduril_lattice.entity.sensors.last_detection_timestamp
+ tag: append_sensors_last_detection_timestamp
+ value: '{{{_ingest._value.lastDetectionTimestamp}}}'
+ allow_duplicates: false
+ ignore_failure: true
+ - script:
+ tag: set_sensors_fov_geo
+ description: >-
+ Build geo_shape Polygon footprints from sensor fieldsOfView projectedFrustum corners
+ (upperLeft, upperRight, bottomRight, bottomLeft). Appends one Polygon per FoV across
+ all sensors into anduril_lattice.entity.sensors.fields_of_view.geo.
+ lang: painless
+ if: ctx.json?.entity?.sensors?.sensors instanceof List
+ source: |
+ def fovGeoList = new ArrayList();
+ for (def sensor : ctx.json.entity.sensors.sensors) {
+ if (sensor.fieldsOfView == null) { continue; }
+ for (def fov : sensor.fieldsOfView) {
+ def fr = fov.projectedFrustum;
+ if (fr == null) { continue; }
+ def ul = fr.upperLeft;
+ def ur = fr.upperRight;
+ def br = fr.bottomRight;
+ def bl = fr.bottomLeft;
+ if (ul == null || ur == null || br == null || bl == null) { continue; }
+ def ring = new ArrayList();
+ def c0 = new ArrayList(); c0.add(ul.longitudeDegrees); c0.add(ul.latitudeDegrees); ring.add(c0);
+ def c1 = new ArrayList(); c1.add(ur.longitudeDegrees); c1.add(ur.latitudeDegrees); ring.add(c1);
+ def c2 = new ArrayList(); c2.add(br.longitudeDegrees); c2.add(br.latitudeDegrees); ring.add(c2);
+ def c3 = new ArrayList(); c3.add(bl.longitudeDegrees); c3.add(bl.latitudeDegrees); ring.add(c3);
+ ring.add(c0);
+ def rings = new ArrayList(); rings.add(ring);
+ def poly = [:]; poly.type = "Polygon"; poly.coordinates = rings;
+ fovGeoList.add(poly);
+ }
+ }
+ if (!fovGeoList.isEmpty()) {
+ ctx.anduril_lattice = ctx.anduril_lattice ?: [:];
+ ctx.anduril_lattice.entity = ctx.anduril_lattice.entity ?: [:];
+ ctx.anduril_lattice.entity.sensors = ctx.anduril_lattice.entity.sensors ?: [:];
+ ctx.anduril_lattice.entity.sensors.fields_of_view = ctx.anduril_lattice.entity.sensors.fields_of_view ?: [:];
+ ctx.anduril_lattice.entity.sensors.fields_of_view.geo = fovGeoList;
+ }
+ on_failure:
+ - append:
+ field: error.message
+ tag: append_error_set_sensors_fov_geo
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{ _ingest.on_failure_message }}}'
+ allow_duplicates: false
+ - remove:
+ field: json
+ ignore_missing: true
+ tag: cleanup_json
+ description: Remove the temporary json parse target.
+ - append:
+ field: tags
+ tag: append_preserve_on_collector_error
+ value: preserve_original_event
+ allow_duplicates: false
+ if: ctx.error?.message != null
+on_failure:
+ - append:
+ field: error.message
+ tag: append_error_message
+ value: >-
+ Processor '{{{ _ingest.on_failure_processor_type }}}'
+ {{{#_ingest.on_failure_processor_tag}}}with tag '{{{ _ingest.on_failure_processor_tag }}}'
+ {{{/_ingest.on_failure_processor_tag}}}in pipeline '{{{ _ingest.pipeline }}}'
+ failed with message '{{{ _ingest.on_failure_message }}}'
+ - set:
+ field: event.kind
+ tag: set_pipeline_error_to_event_kind
+ value: pipeline_error
+ - append:
+ field: tags
+ tag: append_preserve_original_event_on_failure
+ value: preserve_original_event
+ allow_duplicates: false
diff --git a/packages/anduril_lattice/data_stream/entity/fields/base-fields.yml b/packages/anduril_lattice/data_stream/entity/fields/base-fields.yml
new file mode 100644
index 00000000000..6a1bc42425e
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/fields/base-fields.yml
@@ -0,0 +1,16 @@
+- name: data_stream.type
+ external: ecs
+- name: data_stream.dataset
+ external: ecs
+- name: data_stream.namespace
+ external: ecs
+- name: event.module
+ external: ecs
+ type: constant_keyword
+ value: anduril_lattice
+- name: event.dataset
+ external: ecs
+ type: constant_keyword
+ value: anduril_lattice.entity
+- name: '@timestamp'
+ external: ecs
diff --git a/packages/anduril_lattice/data_stream/entity/fields/beats.yml b/packages/anduril_lattice/data_stream/entity/fields/beats.yml
new file mode 100644
index 00000000000..4084f1dc7f5
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/fields/beats.yml
@@ -0,0 +1,6 @@
+- name: input.type
+ type: keyword
+ description: Type of filebeat input.
+- name: log.offset
+ type: long
+ description: Log offset.
diff --git a/packages/anduril_lattice/data_stream/entity/fields/ecs.yml b/packages/anduril_lattice/data_stream/entity/fields/ecs.yml
new file mode 100644
index 00000000000..7742ead09c8
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/fields/ecs.yml
@@ -0,0 +1,24 @@
+- name: ecs.version
+ external: ecs
+- name: event.kind
+ external: ecs
+- name: event.category
+ external: ecs
+- name: event.type
+ external: ecs
+- name: event.created
+ external: ecs
+- name: event.start
+ external: ecs
+- name: event.end
+ external: ecs
+- name: event.original
+ external: ecs
+- name: message
+ external: ecs
+- name: observer.name
+ external: ecs
+- name: error.message
+ external: ecs
+- name: tags
+ external: ecs
diff --git a/packages/anduril_lattice/data_stream/entity/fields/fields.yml b/packages/anduril_lattice/data_stream/entity/fields/fields.yml
new file mode 100644
index 00000000000..5573ff708ff
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/fields/fields.yml
@@ -0,0 +1,660 @@
+- name: anduril_lattice
+ type: group
+ fields:
+ - name: entity
+ type: group
+ description: Anduril Lattice entity event fields.
+ fields:
+ - name: event_type
+ type: keyword
+ description: >-
+ Type of entity lifecycle event. One of: EVENT_TYPE_CREATED, EVENT_TYPE_UPDATE, EVENT_TYPE_PREEXISTING, EVENT_TYPE_DELETED, EVENT_TYPE_POST_EXPIRY_OVERRIDE.
+ - name: entity_id
+ type: keyword
+ description: Unique identifier for the entity.
+ - name: is_live
+ type: boolean
+ description: Whether the entity is currently live and active.
+ - name: no_expiry
+ type: boolean
+ description: Whether the entity has no expiry time (persistent asset).
+ - name: aliases
+ type: group
+ description: Alias information for the entity.
+ fields:
+ - name: name
+ type: keyword
+ description: Human-readable alias name for the entity.
+ - name: alternate_ids
+ type: keyword
+ description: Alternate identifier values extracted from alternateIds array.
+ - name: alternate_id_types
+ type: keyword
+ description: Alternate identifier type labels extracted from alternateIds array.
+ - name: mil_view
+ type: group
+ description: Military classification and environment of the entity.
+ fields:
+ - name: disposition
+ type: keyword
+ description: >-
+ Military disposition of the entity. Examples: DISPOSITION_FRIENDLY, DISPOSITION_ASSUMED_FRIENDLY, DISPOSITION_HOSTILE, DISPOSITION_NEUTRAL, DISPOSITION_SUSPECT, DISPOSITION_UNKNOWN.
+ - name: environment
+ type: keyword
+ description: >-
+ Operational environment. Examples: ENVIRONMENT_SURFACE, ENVIRONMENT_LAND, ENVIRONMENT_AIR, ENVIRONMENT_SUBSURFACE, ENVIRONMENT_SPACE.
+ - name: nationality
+ type: keyword
+ description: Nationality code of the entity.
+ - name: ontology
+ type: group
+ description: Entity classification and template type.
+ fields:
+ - name: template
+ type: keyword
+ description: >-
+ Entity template type determining which fields are populated. Examples: TEMPLATE_TRACK, TEMPLATE_ASSET, TEMPLATE_SIGNAL, TEMPLATE_ALERT, TEMPLATE_GEO_ENTITY, TEMPLATE_EM_ENTITY.
+ - name: platform_type
+ type: keyword
+ description: >-
+ Platform type of the entity. Examples: SURFACE_VESSEL, FIXED_SENSOR, GROUND_VEHICLE, AIRCRAFT, SUBMARINE.
+ - name: specific_type
+ type: keyword
+ description: More granular platform type classification.
+ - name: status
+ type: group
+ description: Current operational status of the entity.
+ fields:
+ - name: platform_activity
+ type: keyword
+ description: Platform activity state of the entity.
+ - name: role
+ type: keyword
+ description: Operational role of the entity.
+ - name: location
+ type: group
+ description: Geospatial location and motion of the entity.
+ fields:
+ - name: geo
+ type: geo_point
+ description: >-
+ Geographic position of the entity as a geo_point derived from latitudeDegrees and longitudeDegrees.
+ - name: geo.coordinates
+ type: object
+ object_type: double
+ description: Coordinates of the geo_point as [lon, lat].
+ - name: geo.type
+ type: keyword
+ description: GeoJSON type of the geo_point (always "Point").
+ - name: altitude_hae_meters
+ type: double
+ description: Altitude above WGS-84 ellipsoid in meters.
+ - name: altitude_agl_meters
+ type: float
+ description: Altitude above ground level in meters.
+ - name: altitude_asf_meters
+ type: float
+ description: Altitude above sea floor in meters.
+ - name: pressure_depth_meters
+ type: float
+ description: Depth derived from pressure in meters.
+ - name: speed_mps
+ type: double
+ description: Speed over ground in meters per second.
+ - name: velocity_enu
+ type: group
+ description: Velocity vector in East-North-Up coordinates (m/s).
+ fields:
+ - name: e
+ type: double
+ description: East component of velocity in m/s.
+ - name: n
+ type: double
+ description: North component of velocity in m/s.
+ - name: u
+ type: double
+ description: Up component of velocity in m/s.
+ - name: acceleration_enu
+ type: group
+ description: Acceleration vector in East-North-Up coordinates (m/s²).
+ fields:
+ - name: e
+ type: float
+ description: East component of acceleration in m/s².
+ - name: n
+ type: float
+ description: North component of acceleration in m/s².
+ - name: u
+ type: float
+ description: Up component of acceleration in m/s².
+ - name: attitude_enu
+ type: group
+ description: Attitude quaternion in East-North-Up frame.
+ fields:
+ - name: x
+ type: float
+ description: X component of attitude quaternion.
+ - name: y
+ type: float
+ description: Y component of attitude quaternion.
+ - name: z
+ type: float
+ description: Z component of attitude quaternion.
+ - name: w
+ type: float
+ description: W (scalar) component of attitude quaternion.
+ - name: location_uncertainty
+ type: group
+ description: Uncertainty estimates for position and velocity.
+ fields:
+ - name: position_enu_cov
+ type: group
+ description: Position covariance matrix in ENU frame (upper triangle, meters²).
+ fields:
+ - name: mxx
+ type: float
+ description: Position covariance mxx.
+ - name: mxy
+ type: float
+ description: Position covariance mxy.
+ - name: mxz
+ type: float
+ description: Position covariance mxz.
+ - name: myy
+ type: float
+ description: Position covariance myy.
+ - name: myz
+ type: float
+ description: Position covariance myz.
+ - name: mzz
+ type: float
+ description: Position covariance mzz.
+ - name: velocity_enu_cov
+ type: group
+ description: Velocity covariance matrix in ENU frame (upper triangle, (m/s)²).
+ fields:
+ - name: mxx
+ type: float
+ description: Velocity covariance mxx.
+ - name: mxy
+ type: float
+ description: Velocity covariance mxy.
+ - name: mxz
+ type: float
+ description: Velocity covariance mxz.
+ - name: myy
+ type: float
+ description: Velocity covariance myy.
+ - name: myz
+ type: float
+ description: Velocity covariance myz.
+ - name: mzz
+ type: float
+ description: Velocity covariance mzz.
+ - name: position_error_ellipse
+ type: group
+ description: 2D error ellipse for horizontal position uncertainty.
+ fields:
+ - name: probability
+ type: float
+ description: Probability level of the error ellipse (0–1).
+ - name: semi_major_axis_m
+ type: float
+ description: Semi-major axis of the position error ellipse in meters.
+ - name: semi_minor_axis_m
+ type: float
+ description: Semi-minor axis of the position error ellipse in meters.
+ - name: orientation_d
+ type: float
+ description: Orientation of the error ellipse semi-major axis in degrees from North.
+ - name: geo_shape
+ type: geo_shape
+ description: >-
+ Entity declared geometry as a GeoJSON shape derived from geoShape (point, line, or polygon).
+ - name: geo_shape.coordinates
+ type: object
+ object_type: double
+ description: Coordinates of the geo_shape geometry.
+ - name: geo_shape.type
+ type: keyword
+ description: 'GeoJSON geometry type (for example, "Polygon," "MultiPolygon.")'
+ - name: geo_shape_ellipse
+ type: group
+ description: Scalar fields for ellipse geometry (no GeoJSON equivalent).
+ fields:
+ - name: semi_major_axis_m
+ type: float
+ description: Semi-major axis of the ellipse in meters.
+ - name: semi_minor_axis_m
+ type: float
+ description: Semi-minor axis of the ellipse in meters.
+ - name: orientation_d
+ type: float
+ description: Orientation of the ellipse semi-major axis in degrees from North.
+ - name: height_m
+ type: float
+ description: Height of the ellipse in meters.
+ - name: geo_shape_ellipsoid
+ type: group
+ description: Scalar fields for ellipsoid geometry (no GeoJSON equivalent).
+ fields:
+ - name: forward_axis_m
+ type: float
+ description: Forward (x) semi-axis of the ellipsoid in meters.
+ - name: side_axis_m
+ type: float
+ description: Side (y) semi-axis of the ellipsoid in meters.
+ - name: up_axis_m
+ type: float
+ description: Up (z) semi-axis of the ellipsoid in meters.
+ - name: geo_details
+ type: group
+ description: Geo entity classification and area control details.
+ fields:
+ - name: type
+ type: keyword
+ description: Geo entity type.
+ - name: control_area_type
+ type: keyword
+ description: Control area type for the geo entity.
+ - name: acm
+ type: group
+ description: Airspace Control Measure details.
+ fields:
+ - name: type
+ type: keyword
+ description: ACM type.
+ - name: description
+ type: keyword
+ description: ACM description.
+ - name: tracked
+ type: group
+ description: Track quality and measurement information for TEMPLATE_TRACK entities.
+ fields:
+ - name: track_quality
+ type: long
+ description: Track quality score (0-9 scale).
+ - name: sensor_hits
+ type: long
+ description: Number of sensors contributing to this track.
+ - name: number_of_objects
+ type: group
+ description: Estimated number of objects in a group track.
+ fields:
+ - name: lower_bound
+ type: integer
+ description: Lower bound of the object count estimate.
+ - name: upper_bound
+ type: integer
+ description: Upper bound of the object count estimate.
+ - name: radar_cross_section
+ type: float
+ description: Radar cross section estimate in square meters.
+ - name: last_measurement_time
+ type: date
+ description: Time of the last sensor measurement contributing to this track.
+ - name: line_of_bearing
+ type: group
+ description: Line-of-bearing range estimates.
+ fields:
+ - name: range_estimate_m
+ type: float
+ description: Range estimate along line of bearing in meters.
+ - name: max_range_m
+ type: float
+ description: Maximum range along line of bearing in meters.
+ - name: provenance
+ type: group
+ description: Origin metadata for the entity data.
+ fields:
+ - name: data_type
+ type: keyword
+ description: Data type or sensor type of the entity source.
+ - name: source_id
+ type: keyword
+ description: Source system identifier.
+ - name: source_description
+ type: keyword
+ description: Human-readable description of the source.
+ - name: indicators
+ type: group
+ description: Contextual indicator flags for the entity.
+ fields:
+ - name: simulated
+ type: boolean
+ description: Whether this entity is part of a simulation or exercise.
+ - name: exercise
+ type: boolean
+ description: Whether this entity is part of a live exercise.
+ - name: emergency
+ type: boolean
+ description: Whether this entity is in an emergency state.
+ - name: c2
+ type: boolean
+ description: Whether this entity is a command and control node.
+ - name: egressable
+ type: boolean
+ description: Whether this entity can be egressed to external systems.
+ - name: starred
+ type: boolean
+ description: Whether this entity has been starred/bookmarked by an operator.
+ - name: target_priority
+ type: group
+ description: Target priority assessments.
+ fields:
+ - name: is_high_value_target
+ type: boolean
+ description: Whether this entity is designated as a high-value target.
+ - name: priority
+ type: integer
+ description: Numeric target priority rank.
+ - name: is_high_payoff_target
+ type: boolean
+ description: Whether this entity is designated as a high-payoff target.
+ - name: is_threat
+ type: boolean
+ description: Whether this entity is assessed as a threat.
+ - name: signal
+ type: group
+ description: Signal intelligence fields for RF/EM emitters.
+ fields:
+ - name: frequency_center_hz
+ type: float
+ description: Center frequency of the detected signal in Hz.
+ - name: frequency_min_hz
+ type: float
+ description: Minimum frequency of the signal range in Hz.
+ - name: frequency_max_hz
+ type: float
+ description: Maximum frequency of the signal range in Hz.
+ - name: bandwidth_hz
+ type: float
+ description: Signal bandwidth in Hz.
+ - name: signal_to_noise_ratio
+ type: float
+ description: Signal-to-noise ratio in dB.
+ - name: pulse_width_s
+ type: float
+ description: Pulse width in seconds.
+ - name: scan_type
+ type: keyword
+ description: Radar/signal scan type.
+ - name: scan_period_s
+ type: float
+ description: Scan period in seconds.
+ - name: emitter_notations
+ type: keyword
+ description: Emitter notation identifiers associated with this signal.
+ - name: transponder_codes
+ type: group
+ description: IFF/SSR transponder code fields.
+ fields:
+ - name: mode1
+ type: integer
+ description: Mode 1 IFF code.
+ - name: mode2
+ type: integer
+ description: Mode 2 IFF code.
+ - name: mode3
+ type: integer
+ description: Mode 3/A IFF code.
+ - name: mode_c_altitude_ft
+ type: integer
+ description: Mode C altitude in feet.
+ - name: mode_s_id
+ type: keyword
+ description: Mode S ICAO aircraft identifier string.
+ - name: mode_s_address
+ type: long
+ description: Mode S ICAO 24-bit address.
+ - name: mode5
+ type: long
+ description: Mode 5 IFF code.
+ - name: mode5_platform_id
+ type: long
+ description: Mode 5 platform identifier.
+ - name: data_classification
+ type: group
+ description: Data classification markings.
+ fields:
+ - name: level
+ type: keyword
+ description: Classification level (for example, UNCLASSIFIED, SECRET).
+ - name: caveats
+ type: keyword
+ description: Classification caveats or handling instructions.
+ - name: health
+ type: group
+ description: Health and alert status for TEMPLATE_ASSET entities.
+ fields:
+ - name: connection_status
+ type: keyword
+ description: >-
+ Asset connection status. Examples: CONNECTION_STATUS_ONLINE, CONNECTION_STATUS_OFFLINE, CONNECTION_STATUS_DEGRADED.
+ - name: health_status
+ type: keyword
+ description: >-
+ Overall health status. Examples: HEALTH_STATUS_HEALTHY, HEALTH_STATUS_DEGRADED, HEALTH_STATUS_CRITICAL.
+ - name: update_time
+ type: date
+ description: Time of the last health status update.
+ - name: active_alerts
+ type: group
+ description: Active alert details extracted from the activeAlerts array.
+ fields:
+ - name: alert_code
+ type: keyword
+ description: Alert code identifiers.
+ - name: level
+ type: keyword
+ description: Alert severity levels.
+ - name: description
+ type: keyword
+ description: Alert descriptions.
+ - name: activated_time
+ type: keyword
+ description: ISO8601 timestamps when each alert was activated (stored as keyword).
+ - name: correlation
+ type: group
+ description: Entity correlation membership and cross-references.
+ fields:
+ - name: primary_secondary_entity_ids
+ type: keyword
+ description: Secondary entity IDs associated with this primary entity.
+ - name: secondary_primary_entity_id
+ type: keyword
+ description: Primary entity ID that this secondary entity is correlated to.
+ - name: membership_set_id
+ type: keyword
+ description: Correlation set identifier for group membership.
+ - name: symbology
+ type: group
+ description: Military symbology codes.
+ fields:
+ - name: mil_std_2525c_sidc
+ type: keyword
+ description: MIL-STD-2525C Symbol Identification Code.
+ - name: orbit
+ type: group
+ description: Orbital elements for space objects.
+ fields:
+ - name: epoch
+ type: date
+ description: Epoch time of the mean orbital elements.
+ - name: semi_major_axis_km
+ type: float
+ description: Semi-major axis in kilometers.
+ - name: eccentricity
+ type: float
+ description: Orbital eccentricity (dimensionless).
+ - name: inclination_deg
+ type: float
+ description: Orbital inclination in degrees.
+ - name: norad_cat_id
+ type: long
+ description: NORAD catalog number.
+ - name: bstar
+ type: float
+ description: BSTAR drag term from TLE.
+ - name: dimensions
+ type: group
+ description: Physical dimensions of the entity.
+ fields:
+ - name: length_m
+ type: float
+ description: Length of the entity in meters.
+ - name: route_details
+ type: group
+ description: Route and navigation details.
+ fields:
+ - name: destination_name
+ type: keyword
+ description: Name of the destination waypoint or location.
+ - name: estimated_arrival_time
+ type: date
+ description: Estimated time of arrival at the destination.
+ - name: visual_details
+ type: group
+ description: Visual display parameters.
+ fields:
+ - name: range_rings
+ type: group
+ description: Range ring display configuration.
+ fields:
+ - name: min_distance_m
+ type: float
+ description: Minimum range ring distance in meters.
+ - name: max_distance_m
+ type: float
+ description: Maximum range ring distance in meters.
+ - name: ring_count
+ type: integer
+ description: Number of range rings to display.
+ - name: group_details
+ type: group
+ description: Group and formation details.
+ fields:
+ - name: army_echelon
+ type: keyword
+ description: Army echelon designation (for example, ARMY_ECHELON_PLATOON).
+ - name: task_catalog
+ type: group
+ description: Task catalog entries available for this entity.
+ fields:
+ - name: task_specification_urls
+ type: keyword
+ description: Task specification URLs from the task catalog.
+ - name: media
+ type: group
+ description: Media items associated with the entity.
+ fields:
+ - name: item_identifier
+ type: keyword
+ description: Media item identifiers.
+ - name: type
+ type: keyword
+ description: Media types (for example, IMAGE, VIDEO).
+ - name: relative_path
+ type: keyword
+ description: Relative paths to media items.
+ - name: supplies
+ type: group
+ description: Supply and logistics information.
+ fields:
+ - name: munition_id
+ type: keyword
+ description: Munition identifiers.
+ - name: munition_name
+ type: keyword
+ description: Munition names.
+ - name: munition_quantity_units
+ type: keyword
+ description: Munition quantity units (e.g. ROUNDS, MISSILES).
+ - name: fuel_id
+ type: keyword
+ description: Fuel type identifiers.
+ - name: fuel_name
+ type: keyword
+ description: Fuel type names.
+ - name: fuel_amount_gallons
+ type: float
+ description: Current fuel amounts in gallons.
+ - name: fuel_max_authorized_capacity_gallons
+ type: float
+ description: Maximum authorized fuel capacity in gallons.
+ - name: payloads
+ type: group
+ description: Payload configuration information.
+ fields:
+ - name: capability_id
+ type: keyword
+ description: Payload capability identifiers.
+ - name: operational_state
+ type: keyword
+ description: Payload operational state values.
+ - name: description
+ type: keyword
+ description: Payload descriptions.
+ - name: quantity
+ type: integer
+ description: Payload quantities.
+ - name: overrides
+ type: group
+ description: Field override requests applied to this entity.
+ fields:
+ - name: request_ids
+ type: keyword
+ description: Override request identifiers.
+ - name: field_paths
+ type: keyword
+ description: Field paths targeted by overrides.
+ - name: statuses
+ type: keyword
+ description: Override request statuses.
+ - name: types
+ type: keyword
+ description: Override types.
+ - name: request_timestamps
+ type: keyword
+ description: ISO8601 timestamps when override requests were submitted (stored as keyword).
+ - name: sensors
+ type: group
+ description: Sensor suite information.
+ fields:
+ - name: sensor_id
+ type: keyword
+ description: Sensor identifiers.
+ - name: operational_state
+ type: keyword
+ description: Sensor operational states.
+ - name: sensor_type
+ type: keyword
+ description: Sensor types.
+ - name: sensor_description
+ type: keyword
+ description: Sensor descriptions.
+ - name: last_detection_timestamp
+ type: keyword
+ description: ISO8601 timestamps of the last detection per sensor (stored as keyword).
+ - name: fields_of_view
+ type: group
+ description: Sensor field-of-view footprints.
+ fields:
+ - name: geo
+ type: geo_shape
+ description: >-
+ Sensor field-of-view footprint polygons derived from projectedFrustum corners. Stored as an array of GeoJSON Polygon objects.
+ - name: geo.coordinates
+ type: object
+ object_type: double
+ description: Coordinates of the geo_shape geometry.
+ - name: geo.type
+ type: keyword
+ description: 'GeoJSON geometry type (for example, "Polygon," "MultiPolygon.")'
+ - name: power_state
+ type: flattened
+ description: >-
+ Power state information keyed by power source ID. The map structure uses arbitrary string keys and is stored as a flattened object.
+ - name: relationships
+ type: flattened
+ description: Entity relationship data stored as a flattened object.
diff --git a/packages/anduril_lattice/data_stream/entity/manifest.yml b/packages/anduril_lattice/data_stream/entity/manifest.yml
new file mode 100644
index 00000000000..f2da09012c6
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/manifest.yml
@@ -0,0 +1,79 @@
+title: "Entity"
+type: logs
+streams:
+ - input: cel
+ title: "Collect entity events via Lattice long-poll API"
+ description: >-
+ Collect entity events from the Anduril Lattice long-poll API. Each poll returns entity lifecycle events (created, updated, deleted) for all live entities in the Lattice environment.
+ template_path: cel.yml.hbs
+ vars:
+ - name: interval
+ type: text
+ title: Interval
+ description: >-
+ How often to poll the Lattice API for new entity events. Short intervals reduce latency; the API supports continuous long-polling. Supports duration strings such as 1s, 5s, 30s, 1m, 5m.
+ required: true
+ show_user: true
+ default: 5s
+ - name: batch_size
+ type: integer
+ title: Batch Size
+ description: >-
+ Maximum number of entity events returned per poll request (1–2000). Set higher values for environments with dense entity activity.
+ required: true
+ show_user: false
+ default: 100
+ - name: http_client_timeout
+ type: text
+ title: HTTP Client Timeout
+ description: >-
+ Duration before declaring the HTTP client connection timed out. Default is 30s. Increase for slow or high-latency Lattice environments.
+ required: false
+ show_user: false
+ default: 30s
+ - name: proxy_url
+ type: text
+ title: Proxy URL
+ description: >-
+ URL of an HTTP proxy to route Lattice API requests through, in the form http[s]://[user:pass@]host:port.
+ required: false
+ show_user: false
+ - name: ssl
+ type: yaml
+ title: SSL Configuration
+ description: >-
+ TLS settings for connecting to the Lattice API — certificate_authorities, verification_mode, and so on. See Filebeat SSL docs for available options.
+ required: false
+ show_user: false
+ multi: false
+ - name: enable_request_tracer
+ type: bool
+ title: Enable Request Tracer
+ description: >-
+ Log HTTP requests and responses to the agent's local file system for debugging. Enabling this traces compromises security; use only for debugging.
+ required: false
+ show_user: false
+ default: false
+ - name: tags
+ type: text
+ title: Tags
+ multi: true
+ required: true
+ show_user: false
+ default:
+ - forwarded
+ - name: preserve_original_event
+ type: bool
+ title: Preserve Original Event
+ description: >-
+ If enabled, the raw API response is preserved in the event.original field.
+ required: true
+ show_user: true
+ default: false
+ - name: processors
+ type: yaml
+ title: Processors
+ description: >-
+ Processors to apply to events before they are sent to Elasticsearch. See Beats processors documentation for available options.
+ required: false
+ show_user: false
diff --git a/packages/anduril_lattice/data_stream/entity/sample_event.json b/packages/anduril_lattice/data_stream/entity/sample_event.json
new file mode 100644
index 00000000000..6fef300193b
--- /dev/null
+++ b/packages/anduril_lattice/data_stream/entity/sample_event.json
@@ -0,0 +1,169 @@
+{
+ "@timestamp": "2025-12-17T15:30:00.000Z",
+ "agent": {
+ "ephemeral_id": "f7b5c7cb-12fc-48c8-95d4-26127cebee89",
+ "id": "f819c1fc-36c0-4432-848b-9aeb48f482d2",
+ "name": "elastic-agent-44681",
+ "type": "filebeat",
+ "version": "9.4.1"
+ },
+ "anduril_lattice": {
+ "entity": {
+ "aliases": {
+ "name": "Tower 45d9bf21"
+ },
+ "entity_id": "tower-45d9bf21-0001-0001-0001-000000000001",
+ "event_type": "EVENT_TYPE_UPDATE",
+ "geo_shape": {
+ "coordinates": [
+ [
+ [
+ -118.245,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.053
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ },
+ "health": {
+ "active_alerts": {
+ "activated_time": "2025-12-17T15:00:00Z",
+ "alert_code": "ALERT_LOW_STORAGE",
+ "description": "Storage capacity below 15 percent",
+ "level": "ALERT_LEVEL_WARNING"
+ },
+ "connection_status": "CONNECTION_STATUS_ONLINE",
+ "health_status": "HEALTH_STATUS_HEALTHY",
+ "update_time": "2025-12-17T15:30:00.000Z"
+ },
+ "indicators": {
+ "simulated": true
+ },
+ "is_live": true,
+ "location": {
+ "altitude_hae_meters": 85,
+ "geo": {
+ "coordinates": [
+ -118.24368003755808,
+ 34.05222997069359
+ ],
+ "type": "Point"
+ }
+ },
+ "mil_view": {
+ "disposition": "DISPOSITION_FRIENDLY",
+ "environment": "ENVIRONMENT_LAND"
+ },
+ "ontology": {
+ "platform_type": "FIXED_SENSOR",
+ "template": "TEMPLATE_ASSET"
+ },
+ "power_state": {
+ "sourceIdToState": {
+ "Battery": {
+ "powerLevel": {
+ "percentRemaining": "87.5",
+ "voltage": "31.84"
+ },
+ "powerStatus": "POWER_STATUS_DISCHARGING",
+ "powerType": "POWER_TYPE_BATTERY"
+ }
+ }
+ },
+ "provenance": {
+ "data_type": "anduril"
+ },
+ "sensors": {
+ "fields_of_view": {
+ "geo": {
+ "coordinates": [
+ [
+ [
+ -118.252,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.06
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ }
+ },
+ "last_detection_timestamp": "2025-12-17T15:29:55Z",
+ "operational_state": "OPERATIONAL_STATE_OPERATIONAL",
+ "sensor_description": "Electro-optical camera",
+ "sensor_id": "sensor-001",
+ "sensor_type": "SENSOR_TYPE_EO"
+ }
+ }
+ },
+ "data_stream": {
+ "dataset": "anduril_lattice.entity",
+ "namespace": "93766",
+ "type": "logs"
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "elastic_agent": {
+ "id": "f819c1fc-36c0-4432-848b-9aeb48f482d2",
+ "snapshot": false,
+ "version": "9.4.1"
+ },
+ "event": {
+ "agent_id_status": "verified",
+ "category": [
+ "host"
+ ],
+ "created": "2025-12-17T15:30:00.000Z",
+ "dataset": "anduril_lattice.entity",
+ "ingested": "2026-07-10T18:12:09Z",
+ "kind": "event",
+ "module": "anduril_lattice",
+ "original": "{\"entity\":{\"aliases\":{\"name\":\"Tower 45d9bf21\"},\"createdTime\":\"2025-12-17T10:00:00Z\",\"entityId\":\"tower-45d9bf21-0001-0001-0001-000000000001\",\"geoShape\":{\"polygon\":{\"rings\":[{\"positions\":[{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.245}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.242}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.242}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.245}}]}]}},\"health\":{\"activeAlerts\":[{\"activatedTime\":\"2025-12-17T15:00:00Z\",\"alertCode\":\"ALERT_LOW_STORAGE\",\"description\":\"Storage capacity below 15 percent\",\"level\":\"ALERT_LEVEL_WARNING\"}],\"connectionStatus\":\"CONNECTION_STATUS_ONLINE\",\"healthStatus\":\"HEALTH_STATUS_HEALTHY\",\"updateTime\":\"2025-12-17T15:30:00Z\"},\"indicators\":{\"simulated\":true},\"isLive\":true,\"location\":{\"position\":{\"altitudeHaeMeters\":85,\"latitudeDegrees\":34.05223,\"longitudeDegrees\":-118.24368}},\"milView\":{\"disposition\":\"DISPOSITION_FRIENDLY\",\"environment\":\"ENVIRONMENT_LAND\"},\"ontology\":{\"platformType\":\"FIXED_SENSOR\",\"template\":\"TEMPLATE_ASSET\"},\"powerState\":{\"sourceIdToState\":{\"Battery\":{\"powerLevel\":{\"percentRemaining\":87.5,\"voltage\":31.84},\"powerStatus\":\"POWER_STATUS_DISCHARGING\",\"powerType\":\"POWER_TYPE_BATTERY\"}}},\"provenance\":{\"dataType\":\"anduril\",\"integrationName\":\"anduril_tower\",\"sourceUpdateTime\":\"2025-12-17T15:30:00Z\"},\"sensors\":{\"sensors\":[{\"fieldsOfView\":[{\"projectedFrustum\":{\"bottomLeft\":{\"latitudeDegrees\":34.05,\"longitudeDegrees\":-118.252},\"bottomRight\":{\"latitudeDegrees\":34.05,\"longitudeDegrees\":-118.237},\"upperLeft\":{\"latitudeDegrees\":34.06,\"longitudeDegrees\":-118.252},\"upperRight\":{\"latitudeDegrees\":34.06,\"longitudeDegrees\":-118.237}}}],\"lastDetectionTimestamp\":\"2025-12-17T15:29:55Z\",\"operationalState\":\"OPERATIONAL_STATE_OPERATIONAL\",\"sensorDescription\":\"Electro-optical camera\",\"sensorId\":\"sensor-001\",\"sensorType\":\"SENSOR_TYPE_EO\"}]}},\"eventType\":\"EVENT_TYPE_UPDATE\",\"time\":\"2025-12-17T15:30:00Z\"}",
+ "start": "2025-12-17T10:00:00.000Z",
+ "type": [
+ "change"
+ ]
+ },
+ "input": {
+ "type": "cel"
+ },
+ "observer": {
+ "name": "anduril_tower"
+ },
+ "tags": [
+ "preserve_original_event",
+ "forwarded"
+ ]
+}
diff --git a/packages/anduril_lattice/docs/README.md b/packages/anduril_lattice/docs/README.md
new file mode 100644
index 00000000000..3c9ed73e429
--- /dev/null
+++ b/packages/anduril_lattice/docs/README.md
@@ -0,0 +1,523 @@
+
+
+# Anduril Lattice Integration for Elastic
+
+## Overview
+
+The Anduril Lattice integration for Elastic collects entity lifecycle events from the [Anduril Lattice](https://www.anduril.com/lattice/) command and control (C2) platform. Lattice fuses data from heterogeneous sensor networks — radar, ADS-B, AIS, RF/EW, optical, and Anduril hardware — into a Common Operational Picture (COP). Every tracked or managed item is an **Entity**: aircraft, surface vessels, ground vehicles, UAS, fixed sensors, geospatial zones, and signals of interest.
+
+This integration collects all entity lifecycle events (created, updated, deleted, preexisting snapshot) and ships them to Elasticsearch for real-time situational awareness, threat monitoring, and asset tracking.
+
+### Compatibility
+
+Compatible with the Anduril Lattice REST API v1 (`/api/v1/entities/events`). Tested against Anduril Lattice SDK v4.0.0.
+
+### How it works
+
+The integration polls the Lattice long-poll API endpoint (`POST /api/v1/entities/events`) using a session-token cursor. Each poll returns a batch of entity lifecycle events. The session token is persisted between polls so the integration resumes from where it left off.
+
+On the first poll (empty session token) the Lattice server delivers a snapshot of all currently live entities as `EVENT_TYPE_PREEXISTING` events, then transitions to streaming ongoing changes. Subsequent polls receive `EVENT_TYPE_CREATED`, `EVENT_TYPE_UPDATE`, and `EVENT_TYPE_DELETED` events as the operational picture evolves.
+
+Two authentication modes are supported:
+- **Static bearer token** — supply a single token; rotation is manual.
+- **OAuth2 client credentials** — supply a client ID and secret; the integration fetches and refreshes access tokens automatically (30-minute lifetime).
+
+For Anduril sandbox/developer environments, an additional sandbox authorization token is required.
+
+## What data does this integration collect?
+
+The Anduril Lattice integration collects entity lifecycle events from the Lattice long-poll API.
+
+### Supported use cases
+
+- **Real-time situational awareness** — track friendly, hostile, and neutral entities across air, surface, land, and sub-surface domains.
+- **Asset health monitoring** — monitor connection status and battery/power state for Anduril hardware assets (towers, sensors).
+- **Track analysis** — correlate track quality, sensor hit count, and kinematic data (position, velocity, heading) for sensor-detected contacts.
+- **Threat detection** — alert on `DISPOSITION_HOSTILE` or `DISPOSITION_SUSPICIOUS` entity classifications.
+- **Geospatial analysis** — visualize entity positions on Kibana Maps using the `anduril_lattice.entity.location.geo` geo_point field.
+
+## What do I need to use this integration?
+
+- **Anduril Lattice environment** — a production environment, or a sandbox via the [Anduril developer program](https://developer.anduril.com/guides/getting-started/set-up).
+- **Credentials** — either a static bearer token, or an OAuth2 client ID and client secret generated from the Lattice admin console.
+- **Network connectivity** — the Elastic Agent host must be able to reach the Lattice API over HTTPS (port 443).
+
+## How do I deploy this integration?
+
+### Agent-based deployment
+
+Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html). You can install only one Elastic Agent per host.
+
+Elastic Agent polls the Lattice long-poll API and ships events to Elastic, where they are processed by the integration's ingest pipeline.
+
+### Set up steps in Anduril Lattice
+
+1. Log in to the Lattice admin console for your environment.
+2. Navigate to **Integrations** and create a new integration to generate OAuth2 credentials (`client_id` and `client_secret`), or obtain a static bearer token from your Lattice administrator.
+3. Note your Lattice API base URL (for example, `https://lattice.yourdomain.com`).
+4. For sandbox environments, also obtain the `Anduril-Sandbox-Authorization` token from the [Lattice sandbox documentation](https://developer.anduril.com/guides/developer-tools/sandboxes).
+5. Ensure the Elastic Agent host has HTTPS/443 access to the Lattice server.
+
+#### Vendor resources
+
+- [Anduril Lattice developer portal](https://developer.anduril.com)
+- [Long-poll entity events API reference](https://developer.anduril.com/reference/rest/entities/long-poll-entity-events)
+- [Getting started / authentication](https://developer.anduril.com/guides/getting-started/quickstart)
+- [Lattice sandbox environments](https://developer.anduril.com/guides/developer-tools/sandboxes)
+
+### Set up steps in Kibana
+
+1. In Kibana, navigate to **Fleet** → **Integrations** and search for **Anduril Lattice**.
+2. Click **Add Anduril Lattice** and configure the integration:
+ - **Lattice API URL** — the base URL of your Lattice environment (for example, `https://lattice.example.com`).
+ - **Authentication** — provide either a static **Bearer Token**, or an **OAuth2 Client ID** and **Client Secret** for automatic token management.
+ - **Sandbox Token** — leave empty for production; provide the sandbox token for developer environments.
+ - **Interval** — how often to poll for new events (default: `5s`).
+3. Save and deploy the policy to the Elastic Agent.
+
+### Validation
+
+After deploying the integration, verify data is flowing:
+
+1. Open **Kibana** → **Discover**.
+2. Select the `logs-anduril_lattice.entity-*` index pattern.
+3. Check that events appear with `event.dataset: anduril_lattice.entity`.
+4. Confirm entity fields such as `anduril_lattice.entity.entity_id`, `anduril_lattice.entity.ontology.template`, and `anduril_lattice.entity.mil_view.disposition` are populated.
+5. Open **Kibana Maps** and add a layer using the `anduril_lattice.entity.location.geo` field to visualize entity positions.
+
+## Troubleshooting
+
+- No data collected: Verify the Lattice API URL is reachable from the Elastic Agent host and that the bearer token or OAuth2 credentials are valid.
+- Authentication failures: For OAuth2, ensure the token URL follows the pattern `{base_url}/api/v1/oauth/token` and that the client credentials have the correct permissions in the Lattice admin console.
+- Self-signed certificates: If the Lattice environment uses a private CA, configure the `SSL Configuration` field with the custom `certificate_authorities` path.
+- Sandbox environments: Ensure the `Sandbox Authorization Token` field is populated; the `Anduril-Sandbox-Authorization` header is required for developer sandboxes.
+- Session token loss on restart: The CEL input persists the session token in agent state. On cold restart the integration re-delivers a full entity snapshot as `EVENT_TYPE_PREEXISTING` events.
+
+## Performance and scaling
+
+The Lattice long-poll API returns all entities in the environment with no server-side filtering. In large environments with many active entities, the initial snapshot might produce thousands of events across multiple polling cycles. Tune `Batch Size` (default 100, max 2000) and `Interval` (default 5s) for your environment's entity density.
+
+For more information on architectures that can be used for scaling this integration, check the [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation.
+
+## Reference
+
+### Inputs used
+These inputs can be used with this integration:
+
+cel
+
+## Setup
+
+For more details about the CEL input settings, check the [Filebeat documentation](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-cel.html).
+
+Before configuring the CEL input, make sure you have:
+- Network connectivity to the target API endpoint
+- Valid authentication credentials (API keys, tokens, or certificates as required)
+- Appropriate permissions to read from the target data source
+
+### Collecting logs from CEL
+
+To configure the CEL input, you must specify the `request.url` value pointing to the API endpoint. The interval parameter controls how frequently requests are made and is the primary way to balance data freshness with API rate limits and costs. Authentication is often configured through the `request.headers` section using the appropriate method for the service.
+
+NOTE: To access the API service, make sure you have the necessary API credentials and that the Filebeat instance can reach the endpoint URL. Some services may require IP whitelisting or VPN access.
+
+To collect logs via API endpoint, configure the following parameters:
+
+- API Endpoint URL
+- API credentials (tokens, keys, or username/password)
+- Request interval (how often to fetch data)
+
+
+
+### API usage
+
+These APIs are used with this integration:
+
+- `POST /api/v1/entities/events` — [Long-poll entity events](https://developer.anduril.com/reference/rest/entities/long-poll-entity-events): returns batches of entity lifecycle events with a session-token cursor for incremental collection.
+- `POST /api/v1/oauth/token` — OAuth2 token endpoint: used to obtain and refresh bearer tokens when OAuth2 client credentials are configured.
+
+### Vendor documentation links
+
+- [Anduril Lattice developer portal](https://developer.anduril.com)
+- [Lattice API overview](https://developer.anduril.com/reference/overview/overview)
+- [Go SDK (public)](https://github.com/anduril/lattice-sdk-go)
+
+### Data streams
+
+#### entity
+
+The `entity` data stream collects entity lifecycle events from the Anduril Lattice long-poll API. Each event represents a state change for a tracked entity in the Lattice Common Operational Picture — creation, update, deletion, or preexisting snapshot on session start.
+
+Entity sub-types (distinguished by `anduril_lattice.entity.ontology.template`):
+- `TEMPLATE_TRACK` — sensor-tracked transient contacts (aircraft, vessels, UAVs)
+- `TEMPLATE_ASSET` — persistent managed assets (sensors, towers, Anduril hardware)
+- `TEMPLATE_GEO` — geospatial zones (keep-in, keep-out, engagement zones)
+- `TEMPLATE_SENSOR_POINT_OF_INTEREST` — sensor-detected points of interest
+- `TEMPLATE_SIGNAL_OF_INTEREST` — RF/EW signal entities
+
+##### entity fields
+
+**Exported fields**
+
+| Field | Description | Type |
+|---|---|---|
+| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date |
+| anduril_lattice.entity.aliases.alternate_id_types | Alternate identifier type labels extracted from alternateIds array. | keyword |
+| anduril_lattice.entity.aliases.alternate_ids | Alternate identifier values extracted from alternateIds array. | keyword |
+| anduril_lattice.entity.aliases.name | Human-readable alias name for the entity. | keyword |
+| anduril_lattice.entity.correlation.membership_set_id | Correlation set identifier for group membership. | keyword |
+| anduril_lattice.entity.correlation.primary_secondary_entity_ids | Secondary entity IDs associated with this primary entity. | keyword |
+| anduril_lattice.entity.correlation.secondary_primary_entity_id | Primary entity ID that this secondary entity is correlated to. | keyword |
+| anduril_lattice.entity.data_classification.caveats | Classification caveats or handling instructions. | keyword |
+| anduril_lattice.entity.data_classification.level | Classification level (for example, UNCLASSIFIED, SECRET). | keyword |
+| anduril_lattice.entity.dimensions.length_m | Length of the entity in meters. | float |
+| anduril_lattice.entity.entity_id | Unique identifier for the entity. | keyword |
+| anduril_lattice.entity.event_type | Type of entity lifecycle event. One of: EVENT_TYPE_CREATED, EVENT_TYPE_UPDATE, EVENT_TYPE_PREEXISTING, EVENT_TYPE_DELETED, EVENT_TYPE_POST_EXPIRY_OVERRIDE. | keyword |
+| anduril_lattice.entity.geo_details.acm.description | ACM description. | keyword |
+| anduril_lattice.entity.geo_details.acm.type | ACM type. | keyword |
+| anduril_lattice.entity.geo_details.control_area_type | Control area type for the geo entity. | keyword |
+| anduril_lattice.entity.geo_details.type | Geo entity type. | keyword |
+| anduril_lattice.entity.geo_shape | Entity declared geometry as a GeoJSON shape derived from geoShape (point, line, or polygon). | geo_shape |
+| anduril_lattice.entity.geo_shape.coordinates | Coordinates of the geo_shape geometry. | object |
+| anduril_lattice.entity.geo_shape.type | GeoJSON geometry type (for example, "Polygon," "MultiPolygon.") | keyword |
+| anduril_lattice.entity.geo_shape_ellipse.height_m | Height of the ellipse in meters. | float |
+| anduril_lattice.entity.geo_shape_ellipse.orientation_d | Orientation of the ellipse semi-major axis in degrees from North. | float |
+| anduril_lattice.entity.geo_shape_ellipse.semi_major_axis_m | Semi-major axis of the ellipse in meters. | float |
+| anduril_lattice.entity.geo_shape_ellipse.semi_minor_axis_m | Semi-minor axis of the ellipse in meters. | float |
+| anduril_lattice.entity.geo_shape_ellipsoid.forward_axis_m | Forward (x) semi-axis of the ellipsoid in meters. | float |
+| anduril_lattice.entity.geo_shape_ellipsoid.side_axis_m | Side (y) semi-axis of the ellipsoid in meters. | float |
+| anduril_lattice.entity.geo_shape_ellipsoid.up_axis_m | Up (z) semi-axis of the ellipsoid in meters. | float |
+| anduril_lattice.entity.group_details.army_echelon | Army echelon designation (for example, ARMY_ECHELON_PLATOON). | keyword |
+| anduril_lattice.entity.health.active_alerts.activated_time | ISO8601 timestamps when each alert was activated (stored as keyword). | keyword |
+| anduril_lattice.entity.health.active_alerts.alert_code | Alert code identifiers. | keyword |
+| anduril_lattice.entity.health.active_alerts.description | Alert descriptions. | keyword |
+| anduril_lattice.entity.health.active_alerts.level | Alert severity levels. | keyword |
+| anduril_lattice.entity.health.connection_status | Asset connection status. Examples: CONNECTION_STATUS_ONLINE, CONNECTION_STATUS_OFFLINE, CONNECTION_STATUS_DEGRADED. | keyword |
+| anduril_lattice.entity.health.health_status | Overall health status. Examples: HEALTH_STATUS_HEALTHY, HEALTH_STATUS_DEGRADED, HEALTH_STATUS_CRITICAL. | keyword |
+| anduril_lattice.entity.health.update_time | Time of the last health status update. | date |
+| anduril_lattice.entity.indicators.c2 | Whether this entity is a command and control node. | boolean |
+| anduril_lattice.entity.indicators.egressable | Whether this entity can be egressed to external systems. | boolean |
+| anduril_lattice.entity.indicators.emergency | Whether this entity is in an emergency state. | boolean |
+| anduril_lattice.entity.indicators.exercise | Whether this entity is part of a live exercise. | boolean |
+| anduril_lattice.entity.indicators.simulated | Whether this entity is part of a simulation or exercise. | boolean |
+| anduril_lattice.entity.indicators.starred | Whether this entity has been starred/bookmarked by an operator. | boolean |
+| anduril_lattice.entity.is_live | Whether the entity is currently live and active. | boolean |
+| anduril_lattice.entity.location.acceleration_enu.e | East component of acceleration in m/s². | float |
+| anduril_lattice.entity.location.acceleration_enu.n | North component of acceleration in m/s². | float |
+| anduril_lattice.entity.location.acceleration_enu.u | Up component of acceleration in m/s². | float |
+| anduril_lattice.entity.location.altitude_agl_meters | Altitude above ground level in meters. | float |
+| anduril_lattice.entity.location.altitude_asf_meters | Altitude above sea floor in meters. | float |
+| anduril_lattice.entity.location.altitude_hae_meters | Altitude above WGS-84 ellipsoid in meters. | double |
+| anduril_lattice.entity.location.attitude_enu.w | W (scalar) component of attitude quaternion. | float |
+| anduril_lattice.entity.location.attitude_enu.x | X component of attitude quaternion. | float |
+| anduril_lattice.entity.location.attitude_enu.y | Y component of attitude quaternion. | float |
+| anduril_lattice.entity.location.attitude_enu.z | Z component of attitude quaternion. | float |
+| anduril_lattice.entity.location.geo | Geographic position of the entity as a geo_point derived from latitudeDegrees and longitudeDegrees. | geo_point |
+| anduril_lattice.entity.location.geo.coordinates | Coordinates of the geo_point as [lon, lat]. | object |
+| anduril_lattice.entity.location.geo.type | GeoJSON type of the geo_point (always "Point"). | keyword |
+| anduril_lattice.entity.location.pressure_depth_meters | Depth derived from pressure in meters. | float |
+| anduril_lattice.entity.location.speed_mps | Speed over ground in meters per second. | double |
+| anduril_lattice.entity.location.velocity_enu.e | East component of velocity in m/s. | double |
+| anduril_lattice.entity.location.velocity_enu.n | North component of velocity in m/s. | double |
+| anduril_lattice.entity.location.velocity_enu.u | Up component of velocity in m/s. | double |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.mxx | Position covariance mxx. | float |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.mxy | Position covariance mxy. | float |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.mxz | Position covariance mxz. | float |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.myy | Position covariance myy. | float |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.myz | Position covariance myz. | float |
+| anduril_lattice.entity.location_uncertainty.position_enu_cov.mzz | Position covariance mzz. | float |
+| anduril_lattice.entity.location_uncertainty.position_error_ellipse.orientation_d | Orientation of the error ellipse semi-major axis in degrees from North. | float |
+| anduril_lattice.entity.location_uncertainty.position_error_ellipse.probability | Probability level of the error ellipse (0–1). | float |
+| anduril_lattice.entity.location_uncertainty.position_error_ellipse.semi_major_axis_m | Semi-major axis of the position error ellipse in meters. | float |
+| anduril_lattice.entity.location_uncertainty.position_error_ellipse.semi_minor_axis_m | Semi-minor axis of the position error ellipse in meters. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxx | Velocity covariance mxx. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxy | Velocity covariance mxy. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mxz | Velocity covariance mxz. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.myy | Velocity covariance myy. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.myz | Velocity covariance myz. | float |
+| anduril_lattice.entity.location_uncertainty.velocity_enu_cov.mzz | Velocity covariance mzz. | float |
+| anduril_lattice.entity.media.item_identifier | Media item identifiers. | keyword |
+| anduril_lattice.entity.media.relative_path | Relative paths to media items. | keyword |
+| anduril_lattice.entity.media.type | Media types (for example, IMAGE, VIDEO). | keyword |
+| anduril_lattice.entity.mil_view.disposition | Military disposition of the entity. Examples: DISPOSITION_FRIENDLY, DISPOSITION_ASSUMED_FRIENDLY, DISPOSITION_HOSTILE, DISPOSITION_NEUTRAL, DISPOSITION_SUSPECT, DISPOSITION_UNKNOWN. | keyword |
+| anduril_lattice.entity.mil_view.environment | Operational environment. Examples: ENVIRONMENT_SURFACE, ENVIRONMENT_LAND, ENVIRONMENT_AIR, ENVIRONMENT_SUBSURFACE, ENVIRONMENT_SPACE. | keyword |
+| anduril_lattice.entity.mil_view.nationality | Nationality code of the entity. | keyword |
+| anduril_lattice.entity.no_expiry | Whether the entity has no expiry time (persistent asset). | boolean |
+| anduril_lattice.entity.ontology.platform_type | Platform type of the entity. Examples: SURFACE_VESSEL, FIXED_SENSOR, GROUND_VEHICLE, AIRCRAFT, SUBMARINE. | keyword |
+| anduril_lattice.entity.ontology.specific_type | More granular platform type classification. | keyword |
+| anduril_lattice.entity.ontology.template | Entity template type determining which fields are populated. Examples: TEMPLATE_TRACK, TEMPLATE_ASSET, TEMPLATE_SIGNAL, TEMPLATE_ALERT, TEMPLATE_GEO_ENTITY, TEMPLATE_EM_ENTITY. | keyword |
+| anduril_lattice.entity.orbit.bstar | BSTAR drag term from TLE. | float |
+| anduril_lattice.entity.orbit.eccentricity | Orbital eccentricity (dimensionless). | float |
+| anduril_lattice.entity.orbit.epoch | Epoch time of the mean orbital elements. | date |
+| anduril_lattice.entity.orbit.inclination_deg | Orbital inclination in degrees. | float |
+| anduril_lattice.entity.orbit.norad_cat_id | NORAD catalog number. | long |
+| anduril_lattice.entity.orbit.semi_major_axis_km | Semi-major axis in kilometers. | float |
+| anduril_lattice.entity.overrides.field_paths | Field paths targeted by overrides. | keyword |
+| anduril_lattice.entity.overrides.request_ids | Override request identifiers. | keyword |
+| anduril_lattice.entity.overrides.request_timestamps | ISO8601 timestamps when override requests were submitted (stored as keyword). | keyword |
+| anduril_lattice.entity.overrides.statuses | Override request statuses. | keyword |
+| anduril_lattice.entity.overrides.types | Override types. | keyword |
+| anduril_lattice.entity.payloads.capability_id | Payload capability identifiers. | keyword |
+| anduril_lattice.entity.payloads.description | Payload descriptions. | keyword |
+| anduril_lattice.entity.payloads.operational_state | Payload operational state values. | keyword |
+| anduril_lattice.entity.payloads.quantity | Payload quantities. | integer |
+| anduril_lattice.entity.power_state | Power state information keyed by power source ID. The map structure uses arbitrary string keys and is stored as a flattened object. | flattened |
+| anduril_lattice.entity.provenance.data_type | Data type or sensor type of the entity source. | keyword |
+| anduril_lattice.entity.provenance.source_description | Human-readable description of the source. | keyword |
+| anduril_lattice.entity.provenance.source_id | Source system identifier. | keyword |
+| anduril_lattice.entity.relationships | Entity relationship data stored as a flattened object. | flattened |
+| anduril_lattice.entity.route_details.destination_name | Name of the destination waypoint or location. | keyword |
+| anduril_lattice.entity.route_details.estimated_arrival_time | Estimated time of arrival at the destination. | date |
+| anduril_lattice.entity.sensors.fields_of_view.geo | Sensor field-of-view footprint polygons derived from projectedFrustum corners. Stored as an array of GeoJSON Polygon objects. | geo_shape |
+| anduril_lattice.entity.sensors.fields_of_view.geo.coordinates | Coordinates of the geo_shape geometry. | object |
+| anduril_lattice.entity.sensors.fields_of_view.geo.type | GeoJSON geometry type (for example, "Polygon," "MultiPolygon.") | keyword |
+| anduril_lattice.entity.sensors.last_detection_timestamp | ISO8601 timestamps of the last detection per sensor (stored as keyword). | keyword |
+| anduril_lattice.entity.sensors.operational_state | Sensor operational states. | keyword |
+| anduril_lattice.entity.sensors.sensor_description | Sensor descriptions. | keyword |
+| anduril_lattice.entity.sensors.sensor_id | Sensor identifiers. | keyword |
+| anduril_lattice.entity.sensors.sensor_type | Sensor types. | keyword |
+| anduril_lattice.entity.signal.bandwidth_hz | Signal bandwidth in Hz. | float |
+| anduril_lattice.entity.signal.emitter_notations | Emitter notation identifiers associated with this signal. | keyword |
+| anduril_lattice.entity.signal.frequency_center_hz | Center frequency of the detected signal in Hz. | float |
+| anduril_lattice.entity.signal.frequency_max_hz | Maximum frequency of the signal range in Hz. | float |
+| anduril_lattice.entity.signal.frequency_min_hz | Minimum frequency of the signal range in Hz. | float |
+| anduril_lattice.entity.signal.pulse_width_s | Pulse width in seconds. | float |
+| anduril_lattice.entity.signal.scan_period_s | Scan period in seconds. | float |
+| anduril_lattice.entity.signal.scan_type | Radar/signal scan type. | keyword |
+| anduril_lattice.entity.signal.signal_to_noise_ratio | Signal-to-noise ratio in dB. | float |
+| anduril_lattice.entity.status.platform_activity | Platform activity state of the entity. | keyword |
+| anduril_lattice.entity.status.role | Operational role of the entity. | keyword |
+| anduril_lattice.entity.supplies.fuel_amount_gallons | Current fuel amounts in gallons. | float |
+| anduril_lattice.entity.supplies.fuel_id | Fuel type identifiers. | keyword |
+| anduril_lattice.entity.supplies.fuel_max_authorized_capacity_gallons | Maximum authorized fuel capacity in gallons. | float |
+| anduril_lattice.entity.supplies.fuel_name | Fuel type names. | keyword |
+| anduril_lattice.entity.supplies.munition_id | Munition identifiers. | keyword |
+| anduril_lattice.entity.supplies.munition_name | Munition names. | keyword |
+| anduril_lattice.entity.supplies.munition_quantity_units | Munition quantity units (e.g. ROUNDS, MISSILES). | keyword |
+| anduril_lattice.entity.symbology.mil_std_2525c_sidc | MIL-STD-2525C Symbol Identification Code. | keyword |
+| anduril_lattice.entity.target_priority.is_high_payoff_target | Whether this entity is designated as a high-payoff target. | boolean |
+| anduril_lattice.entity.target_priority.is_high_value_target | Whether this entity is designated as a high-value target. | boolean |
+| anduril_lattice.entity.target_priority.is_threat | Whether this entity is assessed as a threat. | boolean |
+| anduril_lattice.entity.target_priority.priority | Numeric target priority rank. | integer |
+| anduril_lattice.entity.task_catalog.task_specification_urls | Task specification URLs from the task catalog. | keyword |
+| anduril_lattice.entity.tracked.last_measurement_time | Time of the last sensor measurement contributing to this track. | date |
+| anduril_lattice.entity.tracked.line_of_bearing.max_range_m | Maximum range along line of bearing in meters. | float |
+| anduril_lattice.entity.tracked.line_of_bearing.range_estimate_m | Range estimate along line of bearing in meters. | float |
+| anduril_lattice.entity.tracked.number_of_objects.lower_bound | Lower bound of the object count estimate. | integer |
+| anduril_lattice.entity.tracked.number_of_objects.upper_bound | Upper bound of the object count estimate. | integer |
+| anduril_lattice.entity.tracked.radar_cross_section | Radar cross section estimate in square meters. | float |
+| anduril_lattice.entity.tracked.sensor_hits | Number of sensors contributing to this track. | long |
+| anduril_lattice.entity.tracked.track_quality | Track quality score (0-9 scale). | long |
+| anduril_lattice.entity.transponder_codes.mode1 | Mode 1 IFF code. | integer |
+| anduril_lattice.entity.transponder_codes.mode2 | Mode 2 IFF code. | integer |
+| anduril_lattice.entity.transponder_codes.mode3 | Mode 3/A IFF code. | integer |
+| anduril_lattice.entity.transponder_codes.mode5 | Mode 5 IFF code. | long |
+| anduril_lattice.entity.transponder_codes.mode5_platform_id | Mode 5 platform identifier. | long |
+| anduril_lattice.entity.transponder_codes.mode_c_altitude_ft | Mode C altitude in feet. | integer |
+| anduril_lattice.entity.transponder_codes.mode_s_address | Mode S ICAO 24-bit address. | long |
+| anduril_lattice.entity.transponder_codes.mode_s_id | Mode S ICAO aircraft identifier string. | keyword |
+| anduril_lattice.entity.visual_details.range_rings.max_distance_m | Maximum range ring distance in meters. | float |
+| anduril_lattice.entity.visual_details.range_rings.min_distance_m | Minimum range ring distance in meters. | float |
+| anduril_lattice.entity.visual_details.range_rings.ring_count | Number of range rings to display. | integer |
+| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword |
+| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword |
+| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword |
+| ecs.version | ECS version this event conforms to. `ecs.version` is a required field and must exist in all events. When querying across multiple indices -- which may conform to slightly different ECS versions -- this field lets integrations adjust to the schema version of the events. | keyword |
+| error.message | Error message. | match_only_text |
+| event.category | This is one of four ECS Categorization Fields, and indicates the second level in the ECS category hierarchy. `event.category` represents the "big buckets" of ECS categories. For example, filtering on `event.category:process` yields all events relating to process activity. This field is closely related to `event.type`, which is used as a subcategory. This field is an array. This will allow proper categorization of some events that fall in multiple categories. | keyword |
+| event.created | `event.created` contains the date/time when the event was first read by an agent, or by your pipeline. This field is distinct from `@timestamp` in that `@timestamp` typically contain the time extracted from the original event. In most situations, these two timestamps will be slightly different. The difference can be used to calculate the delay between your source generating an event, and the time when your agent first processed it. This can be used to monitor your agent's or pipeline's ability to keep up with your event source. In case the two timestamps are identical, `@timestamp` should be used. | date |
+| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword |
+| event.end | `event.end` contains the date when the event ended or when the activity was last observed. | date |
+| event.kind | This is one of four ECS Categorization Fields, and indicates the highest level in the ECS category hierarchy. `event.kind` gives high-level information about what type of information the event contains, without being specific to the contents of the event. For example, values of this field distinguish alert events from metric events. The value of this field can be used to inform how these kinds of events should be handled. They may warrant different retention, different access control, it may also help understand whether the data is coming in at a regular interval or not. | keyword |
+| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword |
+| event.original | Raw text message of entire event. Used to demonstrate log integrity or where the full log message (before splitting it up in multiple parts) may be required, e.g. for reindex. This field is not indexed and doc_values are disabled. It cannot be searched, but it can be retrieved from `_source`. If users wish to override this and index this field, please see `Field data types` in the `Elasticsearch Reference`. | keyword |
+| event.start | `event.start` contains the date when the event started or when the activity was first observed. | date |
+| event.type | This is one of four ECS Categorization Fields, and indicates the third level in the ECS category hierarchy. `event.type` represents a categorization "sub-bucket" that, when used along with the `event.category` field values, enables filtering events down to a level appropriate for single visualization. This field is an array. This will allow proper categorization of some events that fall in multiple event types. | keyword |
+| input.type | Type of filebeat input. | keyword |
+| log.offset | Log offset. | long |
+| message | For log events the message field contains the log message, optimized for viewing in a log viewer. For structured logs without an original message field, other fields can be concatenated to form a human-readable summary of the event. If multiple messages exist, they can be combined into one message. | match_only_text |
+| observer.name | Custom name of the observer. This is a name that can be given to an observer. This can be helpful for example if multiple firewalls of the same model are used in an organization. If no custom name is needed, the field can be left empty. | keyword |
+| tags | List of keywords used to tag each event. | keyword |
+
+
+##### entity sample event
+
+An example event for `entity` looks as following:
+
+```json
+{
+ "@timestamp": "2025-12-17T15:30:00.000Z",
+ "agent": {
+ "ephemeral_id": "f7b5c7cb-12fc-48c8-95d4-26127cebee89",
+ "id": "f819c1fc-36c0-4432-848b-9aeb48f482d2",
+ "name": "elastic-agent-44681",
+ "type": "filebeat",
+ "version": "9.4.1"
+ },
+ "anduril_lattice": {
+ "entity": {
+ "aliases": {
+ "name": "Tower 45d9bf21"
+ },
+ "entity_id": "tower-45d9bf21-0001-0001-0001-000000000001",
+ "event_type": "EVENT_TYPE_UPDATE",
+ "geo_shape": {
+ "coordinates": [
+ [
+ [
+ -118.245,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.053
+ ],
+ [
+ -118.242,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.051
+ ],
+ [
+ -118.245,
+ 34.053
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ },
+ "health": {
+ "active_alerts": {
+ "activated_time": "2025-12-17T15:00:00Z",
+ "alert_code": "ALERT_LOW_STORAGE",
+ "description": "Storage capacity below 15 percent",
+ "level": "ALERT_LEVEL_WARNING"
+ },
+ "connection_status": "CONNECTION_STATUS_ONLINE",
+ "health_status": "HEALTH_STATUS_HEALTHY",
+ "update_time": "2025-12-17T15:30:00.000Z"
+ },
+ "indicators": {
+ "simulated": true
+ },
+ "is_live": true,
+ "location": {
+ "altitude_hae_meters": 85,
+ "geo": {
+ "coordinates": [
+ -118.24368003755808,
+ 34.05222997069359
+ ],
+ "type": "Point"
+ }
+ },
+ "mil_view": {
+ "disposition": "DISPOSITION_FRIENDLY",
+ "environment": "ENVIRONMENT_LAND"
+ },
+ "ontology": {
+ "platform_type": "FIXED_SENSOR",
+ "template": "TEMPLATE_ASSET"
+ },
+ "power_state": {
+ "sourceIdToState": {
+ "Battery": {
+ "powerLevel": {
+ "percentRemaining": "87.5",
+ "voltage": "31.84"
+ },
+ "powerStatus": "POWER_STATUS_DISCHARGING",
+ "powerType": "POWER_TYPE_BATTERY"
+ }
+ }
+ },
+ "provenance": {
+ "data_type": "anduril"
+ },
+ "sensors": {
+ "fields_of_view": {
+ "geo": {
+ "coordinates": [
+ [
+ [
+ -118.252,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.06
+ ],
+ [
+ -118.237,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.05
+ ],
+ [
+ -118.252,
+ 34.06
+ ]
+ ]
+ ],
+ "type": "Polygon"
+ }
+ },
+ "last_detection_timestamp": "2025-12-17T15:29:55Z",
+ "operational_state": "OPERATIONAL_STATE_OPERATIONAL",
+ "sensor_description": "Electro-optical camera",
+ "sensor_id": "sensor-001",
+ "sensor_type": "SENSOR_TYPE_EO"
+ }
+ }
+ },
+ "data_stream": {
+ "dataset": "anduril_lattice.entity",
+ "namespace": "93766",
+ "type": "logs"
+ },
+ "ecs": {
+ "version": "9.4.0"
+ },
+ "elastic_agent": {
+ "id": "f819c1fc-36c0-4432-848b-9aeb48f482d2",
+ "snapshot": false,
+ "version": "9.4.1"
+ },
+ "event": {
+ "agent_id_status": "verified",
+ "category": [
+ "host"
+ ],
+ "created": "2025-12-17T15:30:00.000Z",
+ "dataset": "anduril_lattice.entity",
+ "ingested": "2026-07-10T18:12:09Z",
+ "kind": "event",
+ "module": "anduril_lattice",
+ "original": "{\"entity\":{\"aliases\":{\"name\":\"Tower 45d9bf21\"},\"createdTime\":\"2025-12-17T10:00:00Z\",\"entityId\":\"tower-45d9bf21-0001-0001-0001-000000000001\",\"geoShape\":{\"polygon\":{\"rings\":[{\"positions\":[{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.245}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.053,\"longitudeDegrees\":-118.242}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.242}},{\"heightM\":0,\"position\":{\"latitudeDegrees\":34.051,\"longitudeDegrees\":-118.245}}]}]}},\"health\":{\"activeAlerts\":[{\"activatedTime\":\"2025-12-17T15:00:00Z\",\"alertCode\":\"ALERT_LOW_STORAGE\",\"description\":\"Storage capacity below 15 percent\",\"level\":\"ALERT_LEVEL_WARNING\"}],\"connectionStatus\":\"CONNECTION_STATUS_ONLINE\",\"healthStatus\":\"HEALTH_STATUS_HEALTHY\",\"updateTime\":\"2025-12-17T15:30:00Z\"},\"indicators\":{\"simulated\":true},\"isLive\":true,\"location\":{\"position\":{\"altitudeHaeMeters\":85,\"latitudeDegrees\":34.05223,\"longitudeDegrees\":-118.24368}},\"milView\":{\"disposition\":\"DISPOSITION_FRIENDLY\",\"environment\":\"ENVIRONMENT_LAND\"},\"ontology\":{\"platformType\":\"FIXED_SENSOR\",\"template\":\"TEMPLATE_ASSET\"},\"powerState\":{\"sourceIdToState\":{\"Battery\":{\"powerLevel\":{\"percentRemaining\":87.5,\"voltage\":31.84},\"powerStatus\":\"POWER_STATUS_DISCHARGING\",\"powerType\":\"POWER_TYPE_BATTERY\"}}},\"provenance\":{\"dataType\":\"anduril\",\"integrationName\":\"anduril_tower\",\"sourceUpdateTime\":\"2025-12-17T15:30:00Z\"},\"sensors\":{\"sensors\":[{\"fieldsOfView\":[{\"projectedFrustum\":{\"bottomLeft\":{\"latitudeDegrees\":34.05,\"longitudeDegrees\":-118.252},\"bottomRight\":{\"latitudeDegrees\":34.05,\"longitudeDegrees\":-118.237},\"upperLeft\":{\"latitudeDegrees\":34.06,\"longitudeDegrees\":-118.252},\"upperRight\":{\"latitudeDegrees\":34.06,\"longitudeDegrees\":-118.237}}}],\"lastDetectionTimestamp\":\"2025-12-17T15:29:55Z\",\"operationalState\":\"OPERATIONAL_STATE_OPERATIONAL\",\"sensorDescription\":\"Electro-optical camera\",\"sensorId\":\"sensor-001\",\"sensorType\":\"SENSOR_TYPE_EO\"}]}},\"eventType\":\"EVENT_TYPE_UPDATE\",\"time\":\"2025-12-17T15:30:00Z\"}",
+ "start": "2025-12-17T10:00:00.000Z",
+ "type": [
+ "change"
+ ]
+ },
+ "input": {
+ "type": "cel"
+ },
+ "observer": {
+ "name": "anduril_tower"
+ },
+ "tags": [
+ "preserve_original_event",
+ "forwarded"
+ ]
+}
+```
+
+
+### Data streams using ILM policies
+
+
+
diff --git a/packages/anduril_lattice/img/anduril-logo.svg b/packages/anduril_lattice/img/anduril-logo.svg
new file mode 100644
index 00000000000..7b04de19baf
--- /dev/null
+++ b/packages/anduril_lattice/img/anduril-logo.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/packages/anduril_lattice/img/entity-dashboard-distributions.png b/packages/anduril_lattice/img/entity-dashboard-distributions.png
new file mode 100644
index 00000000000..4f6444f9b5a
Binary files /dev/null and b/packages/anduril_lattice/img/entity-dashboard-distributions.png differ
diff --git a/packages/anduril_lattice/img/entity-dashboard-map_kpis.png b/packages/anduril_lattice/img/entity-dashboard-map_kpis.png
new file mode 100644
index 00000000000..9f7f5715be1
Binary files /dev/null and b/packages/anduril_lattice/img/entity-dashboard-map_kpis.png differ
diff --git a/packages/anduril_lattice/kibana/dashboard/anduril_lattice-153d9e91-df65-45b8-9de4-9aaf86ef3f72.json b/packages/anduril_lattice/kibana/dashboard/anduril_lattice-153d9e91-df65-45b8-9de4-9aaf86ef3f72.json
new file mode 100644
index 00000000000..fb8550e2da7
--- /dev/null
+++ b/packages/anduril_lattice/kibana/dashboard/anduril_lattice-153d9e91-df65-45b8-9de4-9aaf86ef3f72.json
@@ -0,0 +1,1979 @@
+{
+ "attributes": {
+ "description": "",
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": {
+ "query": {
+ "language": "kuery",
+ "query": ""
+ }
+ }
+ },
+ "optionsJSON": {
+ "autoApplyFilters": true,
+ "hidePanelBorders": false,
+ "hidePanelTitles": false,
+ "syncColors": false,
+ "syncCursor": true,
+ "syncTooltips": false,
+ "useMargins": true
+ },
+ "panelsJSON": [
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "79c3a153-e53f-4d69-a0d5-fe99bbcbbbdd": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.indicators.emergency == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.indicators.emergency == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "layerId": "79c3a153-e53f-4d69-a0d5-fe99bbcbbbdd",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Emergency Entities"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "dba3be53-7f5a-4296-aaaa-11ae017f7f1b",
+ "w": 5,
+ "x": 38,
+ "y": 0
+ },
+ "panelIndex": "dba3be53-7f5a-4296-aaaa-11ae017f7f1b",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "0e4d208b-5cfe-4b82-bad4-00452053ec43": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.ontology.template == \"TEMPLATE_TRACK\"\n | EVAL quality_tier = CASE(\n anduril_lattice.entity.tracked.track_quality <= 3, \"Poor (0-3)\",\n anduril_lattice.entity.tracked.track_quality <= 6, \"Moderate (4-6)\",\n \"High (7-9)\"\n )\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY quality_tier\n | SORT entity_count DESC"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.ontology.template == \"TEMPLATE_TRACK\"\n | EVAL quality_tier = CASE(\n anduril_lattice.entity.tracked.track_quality <= 3, \"Poor (0-3)\",\n anduril_lattice.entity.tracked.track_quality <= 6, \"Moderate (4-6)\",\n \"High (7-9)\"\n )\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY quality_tier\n | SORT entity_count DESC"
+ },
+ "visualization": {
+ "layerId": "0e4d208b-5cfe-4b82-bad4-00452053ec43",
+ "layerType": "data",
+ "metricAccessor": "entity_count",
+ "palette": {
+ "name": "custom",
+ "params": {
+ "colorStops": [
+ {
+ "color": "#F6726A",
+ "stop": null
+ },
+ {
+ "color": "#fcd883",
+ "stop": 4
+ },
+ {
+ "color": "#24C292",
+ "stop": 7
+ }
+ ],
+ "continuity": "all",
+ "maxSteps": 5,
+ "name": "custom",
+ "progression": "fixed",
+ "rangeMax": null,
+ "rangeMin": null,
+ "rangeType": "number",
+ "reverse": false,
+ "steps": 3,
+ "stops": [
+ {
+ "color": "#F6726A",
+ "stop": 4
+ },
+ {
+ "color": "#fcd883",
+ "stop": 7
+ },
+ {
+ "color": "#24C292",
+ "stop": 8
+ }
+ ]
+ },
+ "type": "palette"
+ }
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "description": "Poor (0-3), Moderate (4-6), and High (7-9)",
+ "title": "Track Quality"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "b7dd7a59-7c1d-401f-bd0e-eefc7b271989",
+ "w": 5,
+ "x": 43,
+ "y": 0
+ },
+ "panelIndex": "b7dd7a59-7c1d-401f-bd0e-eefc7b271989",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "layerListJSON": [
+ {
+ "alpha": 1,
+ "id": "fa4d755e-5388-48f0-af5a-43135a27857e",
+ "includeInFitToBounds": true,
+ "locale": "autoselect",
+ "maxZoom": 24,
+ "minZoom": 0,
+ "sourceDescriptor": {
+ "isAutoSelect": true,
+ "lightModeDefault": "road_map_desaturated_v9",
+ "type": "EMS_TMS"
+ },
+ "style": {
+ "color": "",
+ "type": "EMS_VECTOR_TILE"
+ },
+ "type": "EMS_VECTOR_TILE",
+ "visible": true
+ },
+ {
+ "alpha": 1,
+ "disableTooltips": false,
+ "id": "3372f243-3a8a-4083-8a64-c5272270b899",
+ "includeInFitToBounds": true,
+ "joins": [],
+ "label": "Track Path",
+ "maxZoom": 24,
+ "minZoom": 0,
+ "sourceDescriptor": {
+ "applyForceRefresh": true,
+ "applyGlobalQuery": true,
+ "applyGlobalTime": true,
+ "geoField": "anduril_lattice.entity.location.geo",
+ "groupByTimeseries": false,
+ "id": "9a88f3c3-0391-4ad7-8e0a-44b417f55ff9",
+ "indexPatternRefName": "layer_1_source_index_pattern",
+ "lineSimplificationSize": 500,
+ "metrics": [
+ {
+ "type": "count"
+ }
+ ],
+ "query": {
+ "language": "kuery",
+ "query": "data_stream.dataset : \"anduril_lattice.entity\""
+ },
+ "sortField": "@timestamp",
+ "splitField": "anduril_lattice.entity.entity_id",
+ "type": "ES_GEO_LINE"
+ },
+ "style": {
+ "isTimeAware": true,
+ "properties": {
+ "fillColor": {
+ "options": {
+ "color": "#16C5C0"
+ },
+ "type": "STATIC"
+ },
+ "icon": {
+ "options": {
+ "value": "marker"
+ },
+ "type": "STATIC"
+ },
+ "iconOrientation": {
+ "options": {
+ "orientation": 0
+ },
+ "type": "STATIC"
+ },
+ "iconSize": {
+ "options": {
+ "size": 6
+ },
+ "type": "STATIC"
+ },
+ "labelBorderColor": {
+ "options": {
+ "color": "#FFFFFF"
+ },
+ "type": "STATIC"
+ },
+ "labelBorderSize": {
+ "options": {
+ "size": "SMALL"
+ }
+ },
+ "labelColor": {
+ "options": {
+ "color": "#000000"
+ },
+ "type": "STATIC"
+ },
+ "labelPosition": {
+ "options": {
+ "position": "CENTER"
+ }
+ },
+ "labelSize": {
+ "options": {
+ "size": 14
+ },
+ "type": "STATIC"
+ },
+ "labelText": {
+ "options": {
+ "value": ""
+ },
+ "type": "STATIC"
+ },
+ "labelZoomRange": {
+ "options": {
+ "maxZoom": 24,
+ "minZoom": 0,
+ "useLayerZoomRange": true
+ }
+ },
+ "lineColor": {
+ "options": {
+ "color": "#5a5a5a"
+ },
+ "type": "STATIC"
+ },
+ "lineWidth": {
+ "options": {
+ "size": 2
+ },
+ "type": "STATIC"
+ },
+ "symbolizeAs": {
+ "options": {
+ "value": "circle"
+ }
+ }
+ },
+ "type": "VECTOR"
+ },
+ "type": "GEOJSON_VECTOR",
+ "visible": true
+ },
+ {
+ "alpha": 0.75,
+ "disableTooltips": false,
+ "id": "bd807981-c1d4-4263-b636-60275a2d018d",
+ "includeInFitToBounds": true,
+ "joins": [],
+ "label": "Entities",
+ "maxZoom": 24,
+ "minZoom": 0,
+ "sourceDescriptor": {
+ "applyForceRefresh": true,
+ "applyGlobalQuery": true,
+ "applyGlobalTime": true,
+ "filterByMapBounds": true,
+ "geoField": "anduril_lattice.entity.location.geo",
+ "id": "79200959-5ab7-4a88-afee-f7468f77d270",
+ "indexPatternRefName": "layer_2_source_index_pattern",
+ "query": {
+ "language": "kuery",
+ "query": "data_stream.dataset : \"anduril_lattice.entity\""
+ },
+ "scalingType": "TOP_HITS",
+ "sortField": "@timestamp",
+ "sortOrder": "desc",
+ "tooltipProperties": [
+ "anduril_lattice.entity.entity_id",
+ "@timestamp"
+ ],
+ "topHitsGroupByTimeseries": false,
+ "topHitsSize": 1,
+ "topHitsSplitField": "anduril_lattice.entity.entity_id",
+ "type": "ES_SEARCH"
+ },
+ "style": {
+ "isTimeAware": true,
+ "properties": {
+ "fillColor": {
+ "options": {
+ "color": "Blues",
+ "colorCategory": "palette_0",
+ "customColorPalette": [
+ {
+ "color": "#80B3CB",
+ "stop": "DISPOSITION_ASSUMED_FRIENDLY"
+ },
+ {
+ "color": "#006B96",
+ "stop": "DISPOSITION_FRIENDLY"
+ },
+ {
+ "color": "#00A651",
+ "stop": "DISPOSITION_NEUTRAL"
+ },
+ {
+ "color": "#F4591D",
+ "stop": "DISPOSITION_SUSPICIOUS"
+ },
+ {
+ "color": "#C8102E",
+ "stop": "DISPOSITION_HOSTILE"
+ },
+ {
+ "color": "#FFD700",
+ "stop": "DISPOSITION_UNKNOWN"
+ }
+ ],
+ "field": {
+ "name": "anduril_lattice.entity.mil_view.disposition",
+ "origin": "source"
+ },
+ "fieldMetaOptions": {
+ "isEnabled": true,
+ "sigma": 3
+ },
+ "type": "CATEGORICAL",
+ "useCustomColorPalette": true
+ },
+ "type": "DYNAMIC"
+ },
+ "icon": {
+ "options": {
+ "value": "marker"
+ },
+ "type": "STATIC"
+ },
+ "iconOrientation": {
+ "options": {
+ "orientation": 0
+ },
+ "type": "STATIC"
+ },
+ "iconSize": {
+ "options": {
+ "size": 6
+ },
+ "type": "STATIC"
+ },
+ "labelBorderColor": {
+ "options": {
+ "color": "#FFFFFF"
+ },
+ "type": "STATIC"
+ },
+ "labelBorderSize": {
+ "options": {
+ "size": "SMALL"
+ }
+ },
+ "labelColor": {
+ "options": {
+ "color": "#000000"
+ },
+ "type": "STATIC"
+ },
+ "labelPosition": {
+ "options": {
+ "position": "CENTER"
+ }
+ },
+ "labelSize": {
+ "options": {
+ "size": 14
+ },
+ "type": "STATIC"
+ },
+ "labelText": {
+ "options": {
+ "field": {
+ "isUnsupported": false,
+ "label": "anduril_lattice.entity.aliases.name",
+ "name": "anduril_lattice.entity.aliases.name",
+ "origin": "source",
+ "supportsAutoDomain": true,
+ "type": "string"
+ }
+ },
+ "type": "DYNAMIC"
+ },
+ "labelZoomRange": {
+ "options": {
+ "maxZoom": 24,
+ "minZoom": 0,
+ "useLayerZoomRange": true
+ }
+ },
+ "lineColor": {
+ "options": {
+ "color": "#75bab8"
+ },
+ "type": "STATIC"
+ },
+ "lineWidth": {
+ "options": {
+ "size": 0
+ },
+ "type": "STATIC"
+ },
+ "symbolizeAs": {
+ "options": {
+ "value": "circle"
+ }
+ }
+ },
+ "type": "VECTOR"
+ },
+ "type": "GEOJSON_VECTOR",
+ "visible": true
+ }
+ ],
+ "mapStateJSON": {
+ "center": {
+ "lat": 34.14908,
+ "lon": 152.43072
+ },
+ "filters": [],
+ "query": {
+ "language": "kuery",
+ "query": "data_stream.dataset : \"anduril_lattice.entity\" and anduril_lattice.entity.is_live : true "
+ },
+ "refreshConfig": {
+ "interval": 60000,
+ "isPaused": true
+ },
+ "settings": {
+ "autoFitToDataBounds": false,
+ "backgroundColor": "transparent",
+ "browserLocation": {
+ "zoom": 2
+ },
+ "customIcons": [],
+ "disableInteractive": false,
+ "disableTooltipControl": false,
+ "fixedLocation": {
+ "lat": 0,
+ "lon": 0,
+ "zoom": 2
+ },
+ "hideLayerControl": false,
+ "hideToolbarOverlay": false,
+ "hideViewControl": false,
+ "initialLocation": "LAST_SAVED_LOCATION",
+ "keydownScrollZoom": false,
+ "maxZoom": 24,
+ "minZoom": 0,
+ "projection": "globeInterpolate",
+ "showScaleControl": false,
+ "showSpatialFilters": true,
+ "showTimesliderToggleButton": true,
+ "spatialFiltersAlpa": 0.3,
+ "spatialFiltersFillColor": "#DA8B45",
+ "spatialFiltersLineColor": "#DA8B45"
+ },
+ "timeFilters": {
+ "from": "now-1h",
+ "to": "now"
+ },
+ "zoom": 3.08
+ },
+ "title": "Entity Map",
+ "uiStateJSON": {
+ "isLayerTOCOpen": true,
+ "openTOCDetails": [
+ "3372f243-3a8a-4083-8a64-c5272270b899",
+ "bd807981-c1d4-4263-b636-60275a2d018d"
+ ]
+ }
+ },
+ "hiddenLayers": [],
+ "isLayerTOCOpen": false,
+ "mapBuffer": {
+ "maxLat": 66.51326,
+ "maxLon": 0,
+ "minLat": -21.94305,
+ "minLon": -202.5
+ },
+ "mapCenter": {
+ "lat": 32.22232,
+ "lon": -105.90101,
+ "zoom": 3.11
+ },
+ "openTOCDetails": [
+ "3372f243-3a8a-4083-8a64-c5272270b899"
+ ]
+ },
+ "gridData": {
+ "h": 26,
+ "i": "20f1d0e2-34a5-4bb3-8d0b-e86232228ed6",
+ "w": 48,
+ "x": 0,
+ "y": 8
+ },
+ "panelIndex": "20f1d0e2-34a5-4bb3-8d0b-e86232228ed6",
+ "type": "map"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "b551d14f-510f-4eaf-9dcd-b06b5202e455": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": "Count",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ },
+ {
+ "columnId": "anduril_lattice.entity.ontology.platform_type",
+ "customLabel": false,
+ "fieldName": "anduril_lattice.entity.ontology.platform_type",
+ "label": "anduril_lattice.entity.ontology.platform_type",
+ "meta": {
+ "esType": "keyword",
+ "type": "string"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.ontology.platform_type\n | SORT entity_count DESC\n | LIMIT 10"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.ontology.platform_type\n | SORT entity_count DESC\n | LIMIT 10"
+ },
+ "visualization": {
+ "axisTitlesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "fittingFunction": "Linear",
+ "gridlinesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "labelsOrientation": {
+ "x": 0,
+ "yLeft": 0,
+ "yRight": 0
+ },
+ "layers": [
+ {
+ "accessors": [
+ "entity_count"
+ ],
+ "colorMapping": {
+ "assignments": [],
+ "colorMode": {
+ "type": "categorical"
+ },
+ "paletteId": "default",
+ "specialAssignments": [
+ {
+ "color": {
+ "type": "loop"
+ },
+ "rules": [
+ {
+ "type": "other"
+ }
+ ],
+ "touched": false
+ }
+ ]
+ },
+ "layerId": "b551d14f-510f-4eaf-9dcd-b06b5202e455",
+ "layerType": "data",
+ "seriesType": "bar_stacked",
+ "xAccessor": "anduril_lattice.entity.ontology.platform_type"
+ }
+ ],
+ "legend": {
+ "isVisible": true,
+ "position": "right"
+ },
+ "preferredSeriesType": "bar_stacked",
+ "tickLabelsVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "valueLabels": "hide"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsXY"
+ },
+ "title": "Platform Type Distribution"
+ },
+ "gridData": {
+ "h": 17,
+ "i": "ec5fc749-dd38-4084-9672-87eb5ef9217c",
+ "w": 24,
+ "x": 0,
+ "y": 34
+ },
+ "panelIndex": "ec5fc749-dd38-4084-9672-87eb5ef9217c",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "2cbf9443-36d9-4c86-ad67-59cdf086cde3": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": "Count",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ },
+ {
+ "columnId": "anduril_lattice.entity.mil_view.disposition",
+ "customLabel": false,
+ "fieldName": "anduril_lattice.entity.mil_view.disposition",
+ "label": "anduril_lattice.entity.mil_view.disposition",
+ "meta": {
+ "esType": "keyword",
+ "type": "string"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.mil_view.disposition\n | SORT entity_count DESC"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.mil_view.disposition\n | SORT entity_count DESC"
+ },
+ "visualization": {
+ "axisTitlesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "fittingFunction": "Linear",
+ "gridlinesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "labelsOrientation": {
+ "x": 0,
+ "yLeft": 0,
+ "yRight": 0
+ },
+ "layers": [
+ {
+ "accessors": [
+ "entity_count"
+ ],
+ "colorMapping": {
+ "assignments": [],
+ "colorMode": {
+ "type": "categorical"
+ },
+ "paletteId": "default",
+ "specialAssignments": [
+ {
+ "color": {
+ "type": "loop"
+ },
+ "rules": [
+ {
+ "type": "other"
+ }
+ ],
+ "touched": false
+ }
+ ]
+ },
+ "layerId": "2cbf9443-36d9-4c86-ad67-59cdf086cde3",
+ "layerType": "data",
+ "seriesType": "bar_stacked",
+ "xAccessor": "anduril_lattice.entity.mil_view.disposition"
+ }
+ ],
+ "legend": {
+ "isVisible": true,
+ "position": "right"
+ },
+ "preferredSeriesType": "bar_stacked",
+ "tickLabelsVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "valueLabels": "hide"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsXY"
+ },
+ "title": "Disposition Distribution"
+ },
+ "gridData": {
+ "h": 17,
+ "i": "007a87ad-7272-490e-a6f3-879271dd95d6",
+ "w": 24,
+ "x": 24,
+ "y": 34
+ },
+ "panelIndex": "007a87ad-7272-490e-a6f3-879271dd95d6",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "99a66aca-c867-487c-9f54-abc0a34f62ff": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": "Count",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ },
+ {
+ "columnId": "anduril_lattice.entity.health.connection_status",
+ "customLabel": false,
+ "fieldName": "anduril_lattice.entity.health.connection_status",
+ "label": "anduril_lattice.entity.health.connection_status",
+ "meta": {
+ "esType": "keyword",
+ "type": "string"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.ontology.template == \"TEMPLATE_ASSET\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.health.connection_status\n | SORT entity_count DESC"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.ontology.template == \"TEMPLATE_ASSET\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.health.connection_status\n | SORT entity_count DESC"
+ },
+ "visualization": {
+ "axisTitlesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "fittingFunction": "Linear",
+ "gridlinesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "labelsOrientation": {
+ "x": 0,
+ "yLeft": 0,
+ "yRight": 0
+ },
+ "layers": [
+ {
+ "accessors": [
+ "entity_count"
+ ],
+ "colorMapping": {
+ "assignments": [],
+ "colorMode": {
+ "type": "categorical"
+ },
+ "paletteId": "default",
+ "specialAssignments": [
+ {
+ "color": {
+ "type": "loop"
+ },
+ "rules": [
+ {
+ "type": "other"
+ }
+ ],
+ "touched": false
+ }
+ ]
+ },
+ "layerId": "99a66aca-c867-487c-9f54-abc0a34f62ff",
+ "layerType": "data",
+ "seriesType": "bar_stacked",
+ "xAccessor": "anduril_lattice.entity.health.connection_status"
+ }
+ ],
+ "legend": {
+ "isVisible": true,
+ "position": "right"
+ },
+ "preferredSeriesType": "bar_stacked",
+ "tickLabelsVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "valueLabels": "hide"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsXY"
+ },
+ "title": "Asset Connection Status"
+ },
+ "gridData": {
+ "h": 15,
+ "i": "1a17b1ad-0227-4a07-8fbe-b1a790a39d80",
+ "w": 24,
+ "x": 0,
+ "y": 51
+ },
+ "panelIndex": "1a17b1ad-0227-4a07-8fbe-b1a790a39d80",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "699c9f3a-fbaf-4132-a7af-204786e4e1ee": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": "Count",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ },
+ {
+ "columnId": "anduril_lattice.entity.mil_view.environment",
+ "customLabel": false,
+ "fieldName": "anduril_lattice.entity.mil_view.environment",
+ "label": "anduril_lattice.entity.mil_view.environment",
+ "meta": {
+ "esType": "keyword",
+ "type": "string"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.mil_view.environment\n | SORT entity_count DESC"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id) BY anduril_lattice.entity.mil_view.environment\n | SORT entity_count DESC"
+ },
+ "visualization": {
+ "axisTitlesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "fittingFunction": "Linear",
+ "gridlinesVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "labelsOrientation": {
+ "x": 0,
+ "yLeft": 0,
+ "yRight": 0
+ },
+ "layers": [
+ {
+ "accessors": [
+ "entity_count"
+ ],
+ "colorMapping": {
+ "assignments": [],
+ "colorMode": {
+ "type": "categorical"
+ },
+ "paletteId": "default",
+ "specialAssignments": [
+ {
+ "color": {
+ "type": "loop"
+ },
+ "rules": [
+ {
+ "type": "other"
+ }
+ ],
+ "touched": false
+ }
+ ]
+ },
+ "layerId": "699c9f3a-fbaf-4132-a7af-204786e4e1ee",
+ "layerType": "data",
+ "seriesType": "bar_stacked",
+ "xAccessor": "anduril_lattice.entity.mil_view.environment"
+ }
+ ],
+ "legend": {
+ "isVisible": true,
+ "position": "right"
+ },
+ "preferredSeriesType": "bar_stacked",
+ "tickLabelsVisibilitySettings": {
+ "x": true,
+ "yLeft": true,
+ "yRight": true
+ },
+ "valueLabels": "hide"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsXY"
+ },
+ "title": "Environment Distribution"
+ },
+ "gridData": {
+ "h": 15,
+ "i": "ec16f05a-e086-446c-9532-5912b9cd3d7c",
+ "w": 24,
+ "x": 24,
+ "y": 51
+ },
+ "panelIndex": "ec16f05a-e086-446c-9532-5912b9cd3d7c",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "grid": {
+ "columns": {
+ "@timestamp": {
+ "width": 202
+ },
+ "anduril_lattice.entity.aliases.name": {
+ "width": 258
+ }
+ }
+ },
+ "selectedTabId": "f2441f42-44a4-4a6a-b743-dcfbd6803b88"
+ },
+ "gridData": {
+ "h": 12,
+ "i": "68ede175-a9bd-4ce7-a79c-f96aad593989",
+ "w": 48,
+ "x": 0,
+ "y": 66
+ },
+ "panelIndex": "68ede175-a9bd-4ce7-a79c-f96aad593989",
+ "type": "discover_session"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "58418e59-8819-4a31-bf13-8fe5c38dd567": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.target_priority.is_high_value_target == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.target_priority.is_high_value_target == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#ffffff",
+ "layerId": "58418e59-8819-4a31-bf13-8fe5c38dd567",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "High Value Targets"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "a563964b-3d00-48e4-b297-b03e7a8853ec",
+ "w": 6,
+ "x": 26,
+ "y": 0
+ },
+ "panelIndex": "a563964b-3d00-48e4-b297-b03e7a8853ec",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "58418e59-8819-4a31-bf13-8fe5c38dd567": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.target_priority.is_high_payoff_target == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.target_priority.is_high_payoff_target == true\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#ffffff",
+ "layerId": "58418e59-8819-4a31-bf13-8fe5c38dd567",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "High Payoff Targets"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "10d36753-3e1c-4179-84ab-2e1c8bbe986c",
+ "w": 6,
+ "x": 32,
+ "y": 0
+ },
+ "panelIndex": "10d36753-3e1c-4179-84ab-2e1c8bbe986c",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "58418e59-8819-4a31-bf13-8fe5c38dd567": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.health.connection_status == \"CONNECTION_STATUS_OFFLINE\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": "FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.health.connection_status == \"CONNECTION_STATUS_OFFLINE\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#ffffff",
+ "layerId": "58418e59-8819-4a31-bf13-8fe5c38dd567",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Assets Offline"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "3fd67705-3d5e-4906-950d-fa945de63d13",
+ "w": 5,
+ "x": 21,
+ "y": 0
+ },
+ "panelIndex": "3fd67705-3d5e-4906-950d-fa945de63d13",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "58418e59-8819-4a31-bf13-8fe5c38dd567": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition IN (\"DISPOSITION_SUSPICIOUS\", \"DISPOSITION_SUSPECT\")\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition IN (\"DISPOSITION_SUSPICIOUS\", \"DISPOSITION_SUSPECT\")\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#EAAE01",
+ "layerId": "58418e59-8819-4a31-bf13-8fe5c38dd567",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Suspicious"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "c5442a20-9d20-40fa-8564-6d8d2332e989",
+ "w": 5,
+ "x": 16,
+ "y": 0
+ },
+ "panelIndex": "c5442a20-9d20-40fa-8564-6d8d2332e989",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "58418e59-8819-4a31-bf13-8fe5c38dd567": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition == \"DISPOSITION_HOSTILE\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition == \"DISPOSITION_HOSTILE\"\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#F6726A",
+ "layerId": "58418e59-8819-4a31-bf13-8fe5c38dd567",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Hostiles"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "e7e9a51a-b8cb-4967-bdda-aaec73577c1e",
+ "w": 5,
+ "x": 11,
+ "y": 0
+ },
+ "panelIndex": "e7e9a51a-b8cb-4967-bdda-aaec73577c1e",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [],
+ "state": {
+ "adHocDataViews": {
+ "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f": {
+ "allowHidden": false,
+ "allowNoIndex": false,
+ "fieldFormats": {},
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "managed": false,
+ "name": "logs-anduril_lattice.entity-*",
+ "runtimeFieldMap": {},
+ "sourceFilters": [],
+ "timeFieldName": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*",
+ "type": "esql"
+ }
+ },
+ "datasourceStates": {
+ "textBased": {
+ "indexPatternRefs": [
+ {
+ "id": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "timeField": "@timestamp",
+ "title": "logs-anduril_lattice.entity-*"
+ }
+ ],
+ "layers": {
+ "86eb25ba-34f1-4308-9a15-f5b2298d8c52": {
+ "columns": [
+ {
+ "columnId": "entity_count",
+ "customLabel": true,
+ "fieldName": "entity_count",
+ "inMetricDimension": true,
+ "label": " ",
+ "meta": {
+ "esType": "long",
+ "type": "number"
+ }
+ }
+ ],
+ "index": "178ae00165c16f7c9419466b0d8a3e1f7c185148df5e9b700f873d77cc0bdc4f",
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition IN (\"DISPOSITION_FRIENDLY\", \"DISPOSITION_ASSUMED_FRIENDLY\")\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "timeField": "@timestamp"
+ }
+ }
+ }
+ },
+ "filters": [],
+ "needsRefresh": false,
+ "query": {
+ "esql": " FROM logs-anduril_lattice.entity-*\n | WHERE anduril_lattice.entity.is_live == true\n | WHERE anduril_lattice.entity.mil_view.disposition IN (\"DISPOSITION_FRIENDLY\", \"DISPOSITION_ASSUMED_FRIENDLY\")\n | STATS entity_count = COUNT_DISTINCT(anduril_lattice.entity.entity_id)"
+ },
+ "visualization": {
+ "color": "#61A2FF",
+ "layerId": "86eb25ba-34f1-4308-9a15-f5b2298d8c52",
+ "layerType": "data",
+ "metricAccessor": "entity_count"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Friendlies"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "e4d31076-2e7d-4783-8436-fba39386808d",
+ "w": 5,
+ "x": 6,
+ "y": 0
+ },
+ "panelIndex": "e4d31076-2e7d-4783-8436-fba39386808d",
+ "type": "vis"
+ },
+ {
+ "embeddableConfig": {
+ "attributes": {
+ "references": [
+ {
+ "id": "logs-*",
+ "name": "indexpattern-datasource-layer-001588cf-07e3-47f2-95fe-f74f97ff8f3e",
+ "type": "index-pattern"
+ }
+ ],
+ "state": {
+ "adHocDataViews": {},
+ "datasourceStates": {
+ "formBased": {
+ "layers": {
+ "001588cf-07e3-47f2-95fe-f74f97ff8f3e": {
+ "columnOrder": [
+ "79ea0ee4-825f-49ed-bc48-33aab1c5c2fc"
+ ],
+ "columns": {
+ "79ea0ee4-825f-49ed-bc48-33aab1c5c2fc": {
+ "customLabel": true,
+ "dataType": "number",
+ "isBucketed": false,
+ "label": " ",
+ "operationType": "unique_count",
+ "params": {
+ "emptyAsNull": true
+ },
+ "sourceField": "anduril_lattice.entity.entity_id"
+ }
+ },
+ "ignoreGlobalFilters": false,
+ "incompleteColumns": {},
+ "sampling": 1
+ }
+ }
+ },
+ "indexpattern": {
+ "layers": {}
+ },
+ "textBased": {
+ "layers": {}
+ }
+ },
+ "filters": [
+ {
+ "$state": {
+ "store": "appState"
+ },
+ "meta": {
+ "alias": null,
+ "disabled": false,
+ "key": "data_stream.dataset",
+ "negate": false,
+ "params": {
+ "query": "anduril_lattice.entity"
+ },
+ "type": "phrase"
+ },
+ "query": {
+ "match_phrase": {
+ "data_stream.dataset": "anduril_lattice.entity"
+ }
+ }
+ }
+ ],
+ "internalReferences": [],
+ "query": {
+ "language": "kuery",
+ "query": "anduril_lattice.entity.is_live : true "
+ },
+ "visualization": {
+ "layerId": "001588cf-07e3-47f2-95fe-f74f97ff8f3e",
+ "layerType": "data",
+ "metricAccessor": "79ea0ee4-825f-49ed-bc48-33aab1c5c2fc"
+ }
+ },
+ "title": "",
+ "version": 2,
+ "visualizationType": "lnsMetric"
+ },
+ "title": "Total Live Entities"
+ },
+ "gridData": {
+ "h": 8,
+ "i": "5b8f0f60-7e93-4d06-afe6-5f0ec2698c55",
+ "w": 6,
+ "x": 0,
+ "y": 0
+ },
+ "panelIndex": "5b8f0f60-7e93-4d06-afe6-5f0ec2698c55",
+ "type": "vis"
+ }
+ ],
+ "pinned_panels": {
+ "panels": {
+ "168f4a58-9ba4-455d-b3ac-4594a34776ad": {
+ "config": {
+ "dataViewRefName": "168f4a58-9ba4-455d-b3ac-4594a34776ad:optionsListDataView",
+ "exclude": false,
+ "exists_selected": false,
+ "field_name": "anduril_lattice.entity.mil_view.disposition",
+ "ignore_validations": false,
+ "run_past_timeout": false,
+ "search_technique": "wildcard",
+ "selected_options": [],
+ "single_select": false,
+ "sort": {
+ "by": "_count",
+ "direction": "desc"
+ },
+ "title": "Disposition",
+ "use_global_filters": true
+ },
+ "grow": true,
+ "order": 0,
+ "type": "options_list_control",
+ "width": "small"
+ },
+ "39dd1684-29df-4835-aa91-2e06709ef8d8": {
+ "config": {
+ "dataViewRefName": "39dd1684-29df-4835-aa91-2e06709ef8d8:optionsListDataView",
+ "exclude": false,
+ "exists_selected": false,
+ "field_name": "anduril_lattice.entity.mil_view.environment",
+ "ignore_validations": false,
+ "run_past_timeout": false,
+ "search_technique": "wildcard",
+ "selected_options": [],
+ "single_select": false,
+ "sort": {
+ "by": "_count",
+ "direction": "desc"
+ },
+ "title": "Environment",
+ "use_global_filters": true
+ },
+ "grow": false,
+ "order": 2,
+ "type": "options_list_control",
+ "width": "small"
+ },
+ "c9684877-4e55-4f58-b8ab-69e235d4c94c": {
+ "config": {
+ "dataViewRefName": "c9684877-4e55-4f58-b8ab-69e235d4c94c:optionsListDataView",
+ "exclude": false,
+ "exists_selected": false,
+ "field_name": "anduril_lattice.entity.entity_id",
+ "ignore_validations": false,
+ "run_past_timeout": false,
+ "search_technique": "wildcard",
+ "selected_options": [],
+ "single_select": false,
+ "sort": {
+ "by": "_count",
+ "direction": "desc"
+ },
+ "title": "Entity ID",
+ "use_global_filters": true
+ },
+ "grow": false,
+ "order": 3,
+ "type": "options_list_control",
+ "width": "medium"
+ },
+ "dee9fcb4-57d2-47c6-ab7b-ac11960d85e6": {
+ "config": {
+ "dataViewRefName": "dee9fcb4-57d2-47c6-ab7b-ac11960d85e6:optionsListDataView",
+ "exclude": false,
+ "exists_selected": false,
+ "field_name": "anduril_lattice.entity.aliases.name",
+ "ignore_validations": false,
+ "run_past_timeout": false,
+ "search_technique": "wildcard",
+ "selected_options": [],
+ "single_select": false,
+ "sort": {
+ "by": "_count",
+ "direction": "desc"
+ },
+ "title": "Entity Name",
+ "use_global_filters": true
+ },
+ "grow": false,
+ "order": 4,
+ "type": "options_list_control",
+ "width": "medium"
+ },
+ "fac4fec0-3b66-445a-9a62-2f74a390adbf": {
+ "config": {
+ "dataViewRefName": "fac4fec0-3b66-445a-9a62-2f74a390adbf:optionsListDataView",
+ "exclude": false,
+ "exists_selected": false,
+ "field_name": "anduril_lattice.entity.ontology.platform_type",
+ "ignore_validations": false,
+ "run_past_timeout": false,
+ "search_technique": "wildcard",
+ "selected_options": [],
+ "single_select": false,
+ "sort": {
+ "by": "_count",
+ "direction": "desc"
+ },
+ "title": "Platform Type",
+ "use_global_filters": true
+ },
+ "grow": false,
+ "order": 1,
+ "type": "options_list_control",
+ "width": "medium"
+ }
+ }
+ },
+ "timeRestore": false,
+ "title": "[Logs Anduril Lattice] Entities Overview"
+ },
+ "coreMigrationVersion": "8.8.0",
+ "created_at": "2026-07-07T16:03:19.396Z",
+ "id": "anduril_lattice-153d9e91-df65-45b8-9de4-9aaf86ef3f72",
+ "references": [
+ {
+ "id": "logs-*",
+ "name": "20f1d0e2-34a5-4bb3-8d0b-e86232228ed6:layer_1_source_index_pattern",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "20f1d0e2-34a5-4bb3-8d0b-e86232228ed6:layer_2_source_index_pattern",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "5b8f0f60-7e93-4d06-afe6-5f0ec2698c55:indexpattern-datasource-layer-001588cf-07e3-47f2-95fe-f74f97ff8f3e",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "168f4a58-9ba4-455d-b3ac-4594a34776ad:optionsListDataView",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "fac4fec0-3b66-445a-9a62-2f74a390adbf:optionsListDataView",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "39dd1684-29df-4835-aa91-2e06709ef8d8:optionsListDataView",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "c9684877-4e55-4f58-b8ab-69e235d4c94c:optionsListDataView",
+ "type": "index-pattern"
+ },
+ {
+ "id": "logs-*",
+ "name": "dee9fcb4-57d2-47c6-ab7b-ac11960d85e6:optionsListDataView",
+ "type": "index-pattern"
+ }
+ ],
+ "type": "dashboard",
+ "typeMigrationVersion": "10.3.0"
+}
diff --git a/packages/anduril_lattice/manifest.yml b/packages/anduril_lattice/manifest.yml
new file mode 100644
index 00000000000..e608eed84e2
--- /dev/null
+++ b/packages/anduril_lattice/manifest.yml
@@ -0,0 +1,79 @@
+format_version: "3.6.3"
+name: anduril_lattice
+title: "Anduril Lattice"
+version: 0.1.0
+source:
+ license: "Elastic-2.0"
+description: >-
+ Collect entity events from Anduril Lattice — a software-defined command and control platform — using Elastic Agent for real-time situational awareness, threat monitoring, and asset tracking.
+type: integration
+categories:
+ - security
+ - threat_intel
+conditions:
+ kibana:
+ version: "^8.19.0 || ^9.1.0"
+ elastic:
+ subscription: "basic"
+screenshots:
+ - src: /img/entity-dashboard-map_kpis.png
+ title: Sample screenshot
+ size: 600x600
+ type: image/png
+ - src: /img/entity-dashboard-distributions.png
+ title: Sample screenshot
+ size: 600x600
+ type: image/png
+icons:
+ - src: /img/anduril-logo.svg
+ title: Sample logo
+ size: 32x32
+ type: image/svg+xml
+policy_templates:
+ - name: anduril_lattice
+ title: Anduril Lattice
+ description: Collect entity events from Anduril Lattice
+ inputs:
+ - type: cel
+ title: Collect entity events via REST API
+ description: Collect entity events from the Anduril Lattice long-poll API
+ vars:
+ - name: url
+ type: url
+ title: Lattice API URL
+ description: Base URL of the Anduril Lattice API (for example, https://lattice.example.com)
+ required: true
+ show_user: true
+ - name: token
+ type: password
+ title: Lattice Bearer Token
+ description: >-
+ Static bearer token for authentication. Used as Authorization: Bearer . Provide client_id and client_secret instead for OAuth2.
+ required: false
+ show_user: true
+ secret: true
+ - name: client_id
+ type: text
+ title: OAuth2 Client ID
+ description: >-
+ OAuth2 client ID for automatic token management (30-minute tokens, auto-refreshed). Use instead of token for OAuth2.
+ required: false
+ show_user: true
+ - name: client_secret
+ type: password
+ title: OAuth2 Client Secret
+ description: OAuth2 client secret for automatic token management.
+ required: false
+ show_user: true
+ secret: true
+ - name: sandbox_token
+ type: password
+ title: Sandbox Authorization Token
+ description: >-
+ Token for Anduril sandbox environments. Sent as Anduril-Sandbox-Authorization: Bearer . Leave empty for production.
+ required: false
+ show_user: true
+ secret: true
+owner:
+ github: elastic/security-service-integrations
+ type: elastic