Per-country history needs stored indicator history, which the engine does not keep yet. Live indicators are shown on the globe and in the detection ticker.
HISTORICAL STATISTICS · PER COUNTRY
{{ p.label }}
MOST ATTACKED · SELECT
{{ c.rank }}{{ c.n }}{{ c.total }}
{{ gtSel.name }} {{ gtSel.code }}
GLOBAL RANK {{ gtSel.rank }} · PERIOD {{ gtSel.period }}
{{ gtSel.total }}
DETECTIONS
{{ b.val }}
{{ b.label }}
BY DETECTION TYPE
{{ t.k }}{{ t.cnt }}
Advanced analytics overview
Risk-scored users and entities derived from 142 behavior models against rolling 90-day baselines and peer-group norms.
Multi-panel views over your indexed data. Each dashboard declares its base searches once and every panel transforms that same result set, so a nine-panel dashboard is one trip to the store rather than nine.
{{ dashListErrMsg }}
No dashboards yet
Build one here, or run a search and use Save As → Save as Dashboard to start from a query. Documents are stored as JSON on the engine host, one file per dashboard.
{{ d.title }}
{{ d.description }}
{{ d.meta }}
{{ dashStoreNote }}
{{ dashDraftHeading }}
Declare the base searches once, then describe each panel as a transform of one of them. Panels are packed left to right and wrap at 12 columns, so you set a width rather than a position.
NOT READY TO SAVE
{{ b.text }}
{{ dashDraftMsg }}
TITLE
DESCRIPTION
Base searches
Each one runs as a single job. Every panel that names it shares those rows, so nine panels over one base is one trip to the store.
{{ s.num }}
Panels
A panel is a base search plus a transform — | stats count by user, | timechart span=1h count, | top 10 src_ip.
{{ p.num }}
{{ p.postErr }}
CHART
BASEpick a base search
WIDTH / 12
HEIGHT
DRILLDOWN TOKEN
OPTIONS
TIME OVERRIDE
RIGHT AXIS
TRELLIS BY
SHOW ONLY IF SET
HIDE IF SET
Inputs
Optional. An input sets a $token$ that base searches interpolate, so one control filters every panel at once.
{{ i.num }}
No inputs. Every panel runs its base search exactly as written.
{{ dashTitle }}
{{ dashDesc }}
{{ dashRunNote }}
{{ p.title }}{{ p.stamp }}{{ p.badge }}
{{ p.pendingMsg }}
{{ p.singleValue }}
{{ p.singleLabel }}
{{ p.bandLabel }}
{{ b.label }}{{ b.value }}
L {{ p.axisLeft }} · {{ p.xFirst }}{{ p.peakNote }}{{ p.xLast }} · R {{ p.axisRight }}
{{ lg.label }}
{{ s.label }}{{ s.pct }}
{{ c }}
{{ c.peak }}{{ c.text }}
{{ tc.label }}{{ tc.total }}
{{ tb.label }}{{ tb.value }}
{{ e.time }}
{{ e.raw }}
{{ p.foot }}
{{ p.sizeHint }}
Alerts
A rule is a search, a condition and an action. The throttle decides how often one incident may interrupt somebody — it is the setting that determines whether these get read or filtered to a folder.
Alerting needs the backend
Rules are evaluated on a schedule by the engine, not in this browser — a dashboard nobody is looking at cannot fire an alert. Connect under Settings → Connections.
{{ alErr }}
{{ alDraftHeading }}
TITLE
SEVERITY
SEARCH
WINDOW
TRANSFORM
RUN EVERY
TRIGGER WHEN
number of results is
⚠ {{ alExprErr }}
Evaluated per row against the transformed results — same expression language as a panel's eval and where.
THROTTLE — HOW OFTEN ONE INCIDENT MAY INTERRUPT
SUPPRESS FOR (SECONDS)
SAME INCIDENT MEANS SAME…
NOTIFY
{{ alThrottleNote }}
WHEN IT FIRES
WEBHOOK URL
EMAIL TO
ALSO
{{ alMailNote }}
{{ alPreview }}
{{ alDraftMsg }}
No alert rules yet
Start from a search you already trust. A rule that fires on its first evaluation usually has the wrong threshold, not the right one.
Every action that changes something is recorded here with its undo, at the moment it runs. Dry runs never appear — they change nothing, so there is nothing to reverse.
{{ e.label }}{{ e.stateLabel }}
{{ e.preview }}
{{ e.meta }}
Settings
{{ soarSettingsNote }}
{{ c.title }}
{{ r.label }}{{ r.value }}
{{ c.note }}
{{ soarBuilderTitle }}
Settings
Trigger
{{ soarTriggerCount }} · one per workflow
{{ c.name }}
{{ c.desc }}
Add a step
{{ k.label }}
{{ k.desc }}
+
ACTIONS
{{ a.label }}
{{ a.category }}
{{ a.flag }}
{{ soarValidLabel }}
Pick a trigger to begin
Every workflow starts with exactly one trigger. Choose one on the left, then add steps and connect them.
{{ n.kindLabel }}{{ n.linkLabel }}
{{ n.label }}
{{ n.sub }}
{{ soarInspectorTitle }}✕
LABEL
CONDITION
Same expression language as dashboards and alerts. A condition that errors is treated as false, so a broken expression cannot let a destructive branch through.
LOOP OVER
PARAMETERS
{{ p.label }}
{{ soarSelActionNote }}
PROMPT SHOWN TO THE APPROVER
{{ soarProblemCount }}
{{ p }}
Create workflow✕
Create workflow from scratch
Start a workflow from a blank page
Import workflow
Upload a .yaml file to import a workflow
From playbook
Start from a configurable prebuilt workflow
Workflow Playbooks
Get started with configurable, prebuilt workflows for the most common use cases. New playbooks are released regularly.
Search workflows
Trigger ▾Action ▾Tag ▾Clear all
{{ p.name }}
{{ p.desc }}
NEW
Import an existing workflow✕
Upload a workflow .yaml file to import a workflow.
{{ activeMenu }}
Module workspace · provisioning in progress
SETTINGS · {{ settingsSection }}
{{ settingsTitle }}
{{ settingsDesc }}
{{ iamSyncLabel }}
BEHAVIORAL ENGINE ENDPOINT
{{ beLabel }}
⚠ {{ beErr }}
Point this at your deployed engine (e.g. an ngrok or LAN URL). Once connected, every module pulls live data and auto-syncs every 12s.
CTI ENGINE ENDPOINT
{{ ctiLabel }}
⚠ {{ ctiErr }}
Separate service from the behavioral engine (default port 8100). Feeds the four Global Threat Intelligence sections. While disconnected those pages show sample data so the layout stays reviewable.
SERVER · {{ srv.state }}{{ srv.detail }}
Read-only connection. Collection, demo data, the brand watchlist, executives, peers and threat news feeds are managed in the CTI Admin Console → Collectors, not from UEBA2.
Continuous collection{{ schedState }}
{{ schedNote }}
{{ schedLast }}
⚠ {{ schedErr }}
{{ ctiCycleMsg }}
Demo data{{ demoState }}
{{ demoNote }}
{{ demoSilent }}
{{ demoMsg }}
Interactive Common Information Model studio — browse the 206-field / 33-domain ECIM schema, and watch any of 63 vendor logs run parse → map → normalize → validate → enrich → ECIM output live.
SECTOR THREAT NEWS
The sector shown when you pick SECTOR THREAT NEWS in Threat Intelligence.
COUNTRY THREAT NEWS
The country shown when you pick COUNTRY THREAT NEWS in Threat Intelligence.
Current: {{ tiCurrentCountry }}
BRAND MONITORING · CTI ENGINE ROSTER
Monitored brand values, the watchlist, peers and executives belong to the CTI engine and are managed in the CTI Admin Console. UEBA2 only reads the results.
BRAND MONITORING
Domains and brand terms watched for look-alike certificates (crt.sh) and impersonation pages (URLScan). These populate the Brand category in Threat Intelligence.
CTI ENGINE — WHAT WE MONITOR
Every CTI detector is roster-driven: the engine only looks for what is named here. Permutation sweeps, look-alike scoring, wordmark and logo detection and executive impersonation all key off these three lists. Saved on the engine host under config/local/ and picked up on the next collection cycle — no restart.
{{ cfgOriginNote }}
Connect the CTI engine under Settings · Endpoint · Connections to edit the watchlist, peers and executive roster from here. Until then these lists can only be changed on the engine host.
Applies to every index without its own policy. Only frozen_days deletes — hot/warm/cold are reported tiers.
{{ f.label }}
{{ ixDefMsg }}
INDEX
EVENTS
SIZE
TIER SPREAD
TIME RANGE
RETENTION
{{ x.name }}
{{ x.sourceLabel }}
{{ x.eventsLabel }}
{{ x.sizeLabel }}
{{ x.tierLabel }}
{{ x.rangeLabel }}
{{ x.frozenLabel }}
{{ x.srcLabel }}
{{ x.editHint }}
{{ f.label }}
{{ x.msg }}
{{ ixEmptyMsg }}
{{ ixPruneMsg }}
⚠ {{ lkErr }}
{{ lkCountLabel }}
{{ lkDir }}
New lookup
FILE NAME
saved as {{ lkNewFile }}
COLUMNS · COMMA SEPARATED
the first column is the join key by convention
{{ lkNewMsg }}
FILE
ROWS
COLS
SIZE
MODIFIED
READ BY
{{ l.colPreview }}
{{ l.rows }}
{{ l.column_count }}
{{ l.sizeLabel }}
{{ l.modLabel }}
{{ l.useLabel }}
{{ lkEmptyMsg }}
{{ lkSel }}
{{ lkShapeLabel }}
Read by: {{ lkInUse }} — a save here changes what those screens show on the next request.
{{ lkMsg }}
{{ lkGridNote }}
#
{{ r.num }}
The whole file, header row first. Saving replaces it — the grid re-reads from what you save here.
{{ t.label }}
1 · SAMPLE→2 · PARSER→3 · DRY RUN→4 · INGEST
Parsers live on the engine
Each source is described by a parser file the backend reads from config/default/parsers and config/local/parsers. Connect the backend to list them, preview a record and bind one to an index.
{{ psrErr }}
SAMPLE RECORD
MATCHESNo parser recognises this record. Pick one manually, or override its map in config/local/parsers.
In the record but not in the parser's map. Add them as a local override and bump the version — no deploy.
Every field in the record is mapped.
REQUIRED ECIM FIELDS
{{ q.name }}{{ q.val }}
{{ psrStamp }}
✓ INGESTED
{{ psrDoneNote }}
REPARSE STORED EVENTSFixed a mapping? Re-derive events already stored — the raw is kept, so this is repeatable.
{{ rprMsg }}
{{ rprErr }}
{{ s.label }}
{{ s.value }}
{{ rprSkipped }} row(s) skipped — no parser stamped on them and no override given, so there is nothing to reparse them with.
{{ x.time }}{{ x.parser }}
+ {{ x.gained }}
− {{ x.lost }}
~ {{ x.altered }}
Connectors live on the engine
One connection per source, each with its own ingest token. It carries the index it may write, the parser applied to its data, and how its payloads are framed — so a collector needs no user account and cannot reach anything else.
CONNECTION CREATED · {{ tokSecretName }} → {{ tokSecretIndex }}
{{ tokSecretHeader }}
POST {{ tokSecretUrl }} · connection {{ tokSecretCid }}
Shown once. Only its fingerprint is stored, so this cannot be retrieved again — paste it into the collector's config now. Losing it costs a new token, not a support call.
{{ tokErr }}
Data connections
Status of connections
Total connections{{ tokTotal }}
Data ingest
{{ tokBarFirst }}amber = days with inferred timestamps{{ tokBarLast }}
No data received in the last 14 days
Avg. ingest per day
14-day average
{{ tokAvgDay }}
Daily ingest limit
Not set
quotas not enforced yet
Daily ingest
since 00:00 UTC
{{ tokToday }} today
Data connectors{{ catTotal }} items
{{ catNoneMsg }}
{{ catShownLabel }}Items per pagePage {{ catPage }} of {{ catPages }}
New connection details
Connector name
{{ catSel.mono }}{{ catSel.name }}
Vendor
{{ catSel.vendor }}
Connector author
{{ catSel.author }}
Destination
Delivery
Push over HTTPS with this connection's ingest token. The token is shown once after creation.
This source can also be pulled by a collector (API poller or S3/SQS). Collectors are configured on the collector host for now and deliver with the same token.
No dedicated parser for this connector yet. Events are stored with the generic normalizer and can be reparsed once a parser exists.
Framing · where one event ends
{{ tokErr }}
Additional resources
After you create it
Copy the token into the sender's config. It is shown once and only its fingerprint is kept, so a lost token means a new connection.
Check the parser first
Dry-run a sample on the Parsers tab to see which fields map before data starts arriving.
Timestamps
Events keep their own time. If the parser finds none, ingest time is used and the event is flagged, so backfilled data never lands silently in today.
NEW CONNECTION
FRAMING · WHERE ONE EVENT ENDS
Connections{{ tokItems }}
Status
Ingest (24h)
Connection name
Vendor
Product
Type
Parser
Index
Actions
No connections yet
Every source needs one. Until a connection exists, nothing can send data here except a paste on the Data Inputs tab.
No connections match these filters.
{{ t.status }}
{{ t.ingest24 }}
{{ t.vendor }}
{{ t.product }}
{{ t.type }}
{{ t.parser }}
{{ t.index }}
TOKEN
{{ t.prefix }}…
SOURCETYPE · FRAMING
{{ t.sourcetype }} · {{ t.framing }}
ALL-TIME VOLUME
{{ t.events }} ev · {{ t.bytes }}
LAST USED
{{ t.lastUsed }}
INFERRED TIMESTAMPS
{{ t.inferred }}
{{ t.inferred }} event(s) arrived with no time of their own and carry ingest time instead.
Connection
{{ dtl.name }}{{ dtl.status }}
{{ dtlConfirmText }}
Error history · last 30 days
Loading…
No parse errors or rejected events recorded.
Day
Events
Parse errors
Rejected
Inferred time
{{ d.day }}
{{ d.events }}
{{ d.parseErrors }}
{{ d.rejected }}
{{ d.inferred }}
Recent batches with errors
{{ e.at }}{{ e.count }} parse error(s)
{{ e.text }}
Endpoint
API URL
{{ dtl.apiUrl }}
HEC-compatible URL
{{ dtl.hecUrl }}
Auth header
{{ dtl.keyLine }}
{{ dtl.keyNote }}
Identity
Connection ID
{{ dtl.cid }}
Config file
connectors/{{ dtl.file }}
Created
{{ dtl.created }}
Last used
{{ dtl.lastUsed }}
Index · cannot be changed
{{ dtl.index }}
Binding
Framing
Usage · last 30 days
Events
{{ dtl.events }}
Bytes
{{ dtl.bytes }}
Inferred time
{{ dtl.inferred }}
Parse errors
{{ dtl.parseErrors }}
{{ dtlErr }}
{{ dtl.rotated }}
API key generated
{{ keyModalName }}
API key
{{ keyModalSecret }}
API URL
{{ keyModalUrl }}
Send it as the X-Ingest-Token header.
This key is shown once and is not stored. Any previous key for this connection has stopped working.
Collectors report through the engine
Each collector keeps a checkpoint of where it got to, so a restart resumes instead of duplicating or skipping. Connect the backend to see those positions.
{{ agtErr }}
{{ agtCount }}{{ agtDir }}
No collector has checked in yet
A collector appears here as soon as it commits its first position. Configure one, point it at an ingest token, and run it:
No fields could be detected automatically in this sample. That happens with positional data that carries no labels, or free text with no recognisable values. Use Highlight manually instead — select the text to the left of a value and name it.
Highlight a value, then name the field
Select the value itself — the label in front of it is found for you, and the pattern is shaped from what you highlighted so it generalises to other lines.
{{ extractRaw }}
SELECTED VALUE
{{ extractSelText }}
WILL CAPTURE AS
{{ extractSelCaptureWhy }} · anchored by {{ extractSelAnchorKind }}
FIELDS · {{ extractFieldCount }}
{{ c.name }}
{{ c.text }}
✕
Generated extraction rules
{{ r.name }}
{{ r.matchText }}
REGEX · EDITABLE
FIRST MATCH
{{ r.sampleText }}
{{ r.originText }}
First match is {{ r.sampleText }}, not the {{ r.selectedText }} you highlighted — an earlier line matched the same pattern. Usually fine if you want every occurrence; tighten the anchor if you meant only this one.
Name the sourcetype
Extractions are saved to extractions.conf under a [sourcetype] stanza on the backend.
WILL WRITE
[{{ extractSourcetype }}]
EXTRACT-{{ r.name }} = {{ r.regex }}
{{ extractSaveMsg }}
Saved to {{ extractSavedFile }}
Stanza [{{ extractSavedStanza }}] now has {{ extractSavedCount }} extraction(s).
INGESTED VOLUME · LAST 14 DAYS
Amber bars carry events with no time of their own.
{{ diExtractNote }} Data is stored to a file named after the index, with the original line under raw plus any extracted fields.
{{ diSaveMsg }}
Ingested to index {{ diSavedIndex }}
{{ diSavedEvents }} event(s) stored to {{ diSavedFile }} {{ diSavedApplied }} extraction rule(s) applied · fields: {{ diSavedFields }} {{ diSavedTotal }} total record(s) in index
{{ rolesCount }} ROLES · {{ rolesUserTotal }} MEMBERS
{{ r.name }}
{{ r.members }} members
{{ r.desc }}
{{ r.moduleLabel }}
{{ p }}
GRANTS ON THE API
{{ r.grantLabel }}
{{ roleModalTitle }}
ROLE NAME
DESCRIPTION
COLOR
MODULE & DASHBOARD ACCESS
+ VIEW ALLCLEAR
Type to find a module or dashboard, then pick it to grant access. New roles can view all by default.
{{ m.module }}+
No module matches — it may already be added.
No modules granted yet — this role can't open any dashboard. Add some above, or “+ VIEW ALL”.
{{ m.module }}✕
DATA & INDEX ACCESS
RESET TO FULLDENY ALL
Per index: Search runs queries and sees hit counts, View opens the full event body, Access exports raw records and reads unmasked fields. Indexes come from the live engine. A role reaches every index by default, new ones included — untick only what this role must not reach.
INDEXSEARCHVIEWACCESS
{{ d.label }}
{{ d.pattern }}
{{ c.mark }}
PERMISSIONS
{{ p.mark }}{{ p.perm }}
{{ usersCount }} USERS · {{ usersActiveCount }} ACTIVE
USER
ROLE
MFA
STATUS
LAST ACTIVE
ACTIONS
{{ u.initials }}
{{ u.name }}
{{ u.email }}
{{ u.mfa }}
{{ u.status }}
{{ u.lastActive }}
API keys
For collectors, schedulers and webhooks. A key carries a role, so it holds exactly that role's capabilities. Sent as X-API-Key.
NAME
ROLE
COPY IT NOW — IT IS HASHED ON SAVE AND CANNOT BE SHOWN AGAIN
{{ newKey }}
{{ k.name }}
{{ k.meta }}
Invite user
They'll receive an email to set a password and enrol MFA.
FULL NAME
EMAIL
ROLE
TEMPORARY PASSWORD · optional
Require change on first sign-in
User must set their own password the first time they log in.
SIGN-IN METHODS
{{ a.label }}
{{ a.desc }}
Single Sign-On configuration
PROTOCOL
{{ ssoIdpLabel }}
{{ ssoIssuerLabel }}
{{ ssoCertLabel }}
SERVICE-PROVIDER VALUES · give these to your IdP
ACS / Reply URL{{ ssoAcsUrl }}
SP Entity ID{{ ssoSpEntity }}
Multi-factor authentication
ALLOWED FACTORS
{{ m.label }}
{{ m.desc }}
⚠ Enable at least one factor or users cannot complete MFA.
ENFORCEMENT SCOPE
ENROLLMENT GRACE PERIOD
Trusted devices
TRUST DURATION
MAX DEVICES PER USER
Re-verify on new location or IP
Force MFA again if a trusted device connects from an unfamiliar network.
CURRENTLY TRUSTED · {{ trustDeviceCount }}
No trusted devices — all sessions will be prompted for MFA.
{{ d.name }}
{{ d.meta }} · {{ d.last }}
IP allow-list
ENFORCEMENT MODE
Exempt federated SSO sign-ins
{{ ipModeNote }}
ALLOWED RANGES · {{ ipRangeCount }}
⚠ No ranges defined — enforcement would lock everyone out. Add at least one range.
{{ r.cidr }}
{{ r.label }}
SESSION & PASSWORD POLICY
{{ p.label }}
{{ authStatusLabel }}
Your session
Credentials are required to reach any endpoint. Your capabilities come from the role assigned in Settings → Roles and are resolved on every request, so a role edit takes effect immediately.
{{ enfStore }}
SIGNED IN AS
{{ meSubject }}
{{ meRole }}
YOUR CAPABILITIES
{{ c }}
CURRENT PASSWORD
NEW PASSWORD
This account is on a temporary password — change it now.
{{ authMsg }}
No {{ settingsTitle }} configured yet
This workspace is ready — tell me how you want {{ settingsTitle }} to work.
Behavioral Analytics Engine
SENTINELGRID · SELF-HOSTED IP
Vendor-independent UEBA core — adaptive baselining, multi-model anomaly detection, weighted risk scoring, correlation, explainability and a plug-in SDK for new behavioural models.
ENSEMBLE MODELS
{{ engModelTotal }}
BEHAVIOURAL BASELINES
{{ engBaselineTotal }}
FEATURES / ENTITY
1,000+
PROCESSING PIPELINE · RAW TELEMETRY → RISK
{{ p.n }}
{{ p.t }}
{{ p.d }}
ML Ensemble Layer
Each model emits a confidence score — scores are fused, not voted. {{ engModelsOn }} of {{ engModelTotal }} active.
{{ m.name }}
{{ m.type }}
Scale-Out Stack
{{ s.t }}{{ s.d }}
Horizontally scalable · millions of events / sec
Detection Models
{{ engModelsOn }} of {{ engModelTotal }} enabled · toggle to include in the ensemble
{{ m.name }}
{{ m.desc }}
{{ m.type }}
Risk Score Weights
Σ {{ totW }}%
Weights feed the live Risk Simulator. Keep the total at 100%.
{{ f.label }}{{ f.wPct }}
Detection Plug-ins
Behavioural model packs · SDK-extensible
{{ pg.name }}{{ pg.meta }}
Behavioural Baselines
{{ engBaselineTotal }} baselines across {{ engBaselineGroups.length }} domains
{{ g.cat }}{{ g.count }}
{{ it }}
EVERY BASELINE SUPPORTS
{{ d }}
Composite Risk Score
Recomputes live from the weighted formula
{{ engScore }}
{{ engBandT }}
Time-decay factor{{ engDecayV }}%
Risk decays over time unless reinforced by new activity.
Risk = Σ ( weight × signal )
weights Σ {{ totW }}%
Drag each factor's live signal (0–100). Weights are set in the Admin Console.
{{ f.label }}w {{ f.wPct }}
signal {{ f.sig }} · +{{ f.contrib }} pts
TECHNICAL SPECIFICATION · v1.0
Behavioral Analytics Engine
A vendor-independent UEBA core delivering adaptive baselining, multi-model anomaly detection, weighted risk scoring, correlation, explainability and extensibility — implemented as owned IP rather than a copy of any proprietary platform.
{{ s.h }}
{{ s.b }}
SENTINELGRID · Self-hosted · {{ engModelTotal }} models · {{ engBaselineTotal }} baselines · 1,000+ features per entity
SENTINELGRID
{{ activeMenu }}
ACTIVE ALERTS · 24
Ransomware C2 beacon
Finance VLAN · 2m ago
Impossible travel login
UEBA · 11m ago
New S3 bucket exposed
Cloud-East · 24m ago
DATA
{{ s.label }}
ENDPOINT
{{ s.label }}
USERS AND AUTHENTICATION
{{ s.label }}
{{ profileInitials }}
{{ profileName }}
{{ profileRole }}
{{ profileEmail }}
My account
Sign out
Browsing demo data. Reload to sign in against the backend.
SENTINELGRID
MODULES
ALL SENSORS ONLINE
Brand Monitoring
Watch multiple domains and brand terms for look-alikes and impersonation.
No values monitored yet. Add a domain or brand term above.
{{ m.value }}
{{ m.statusText }}
✕
{{ brandMonitorMsg }}
{{ brandMonitorFootNote }}
{{ tiPickerKicker }}
{{ tiPickerTitle }}
{{ tiPickerHint }}
{{ cfgKicker }}
{{ cfgTitle }}
{{ cfgHint }}
{{ cfgFormula }}
{{ t.value }}
{{ cfgEmptyNote }}
ADD A PERSON
Only name is required. Handles and domains are their genuine accounts — the detector uses them as an allow-list, so an official account is never reported as an impersonation of itself. Leave them blank and every look-alike handle is a candidate, including the real one.
{{ p.name }}
{{ p.sub }}
{{ p.detail }}
No roster. Executive impersonation detection stays idle until somebody is named — it never discovers or profiles people on its own.
FINDINGS ACROSS ENGINES {{ entityCard.findingCount }}
{{ f.engine }}{{ f.type }}{{ f.sev }}
{{ f.summary }}
{{ entityCard.emptyFindingsNote }}
EVIDENCE TRAIL
{{ e.src }}{{ e.when }}{{ e.note }}
RELATIONSHIPS
{{ g.label }} · {{ g.count }}
{{ entityCard.emptyNeighboursNote }}
TIMELINE
{{ t.when }}
{{ t.kind }}
{{ t.note }}
ATTRIBUTES
{{ a.k }}{{ a.v }}
No attributes recorded.
{{ entityCard.footer }}{{ entityCard.subjectId }}
VERIFYING SESSION…
First-run setup
NO ACCOUNTS EXIST YET
Create the administrator account. It is granted every permission, and this screen closes permanently once it exists — every later account comes from Settings → Users or directory sync.