Documentation

Decision Record

The versioned record every Orthalon control point writes for an AI interaction: what was attempted, what policy decided, what the sensor could see and whether enforcement was confirmed.

Voir le Markdown

Every browser, desktop, gateway, MCP and mobile event is described by the same record, version 1.0. It is what the console shows, what the event export contains and what SIEM streaming delivers. It never contains a prompt, a file, a matched value or a session title: detected values appear only as placeholders such as <AWS_KEY_1>, and every reason is an upper-case code rather than text.

What the fields mean

Enforcement outcome

The decision says what policy asked for. The outcome says what became of it.

OutcomeMeaning
NOT_REQUIREDNothing had to be stopped: the interaction was allowed, monitored, or sent after a coaching notice.
ATTEMPTEDThe control point tried, but could not see enough of the interaction to say it worked. A partially inspected or disconnected event is never reported as a successful block.
ENFORCEDThe control point applied the control in the path it owns. A browser block is enforced: the page may have other paths to the network.
CONFIRMEDThe control point prevented the action and knows it did not happen. Only an in-path control can say this: the AI gateway or MCP runtime refusing to forward a request, or the Windows host acknowledging that it replaced the clipboard. It requires full coverage.
FAILEDThe control point tried and the control did not take effect, for example a clipboard replacement the operating system refused.

An empty outcome means the event came from a sensor version that predates the record. It means not recorded, never "succeeded".

Coverage

CoverageMeaning
FULLEverything the decision depends on was inspected.
PARTIALPart of it was not, with a reason: FILE_TOO_LARGE, FILE_TYPE_UNSUPPORTED, FILE_INSPECTION_PENDING, ATTACHMENT_NOT_INSPECTED, AGENT_ACTIONS_NOT_OBSERVED, or the file-analysis service's own code.
NOT_OBSERVEDThe interaction happened where the sensor cannot see content: DESTINATION_ONLY (mobile), CONTENT_NOT_READ (a file another application opened).
UNSUPPORTEDThe sensor knows it cannot cover this interaction.

Not observed and partial coverage are limits of what the sensor could see. They are never a finding of no risk.

Fail mode

failMode names the rule that applied when something could not be checked: FAIL_OPEN (let through, labelled) or FAIL_CLOSED (refused), with failModeReason. NONE means nothing failed. A policy bypass caused by a downstream error is always labelled; it is never recorded as a clean allow.

Actor origin

OriginEvidenceTypical source
HUMANUSER_ACTIVATION, STICKY_ACTIVATION, OS_INPUTThe browser page had user activation; a clipboard transfer through the operating system.
AGENTTOOL_CALL, DECLARED_BY_CLIENTAn MCP tool call; a gateway caller that declared an agent id (not verified).
MIXED—Reserved for sensors that observe both.
UNKNOWNNONE, AGENTIC_CLIENTGateway calls without a declared agent, desktop application requests, events in a known agentic browser.

Confidence is between 0 and 1. A human origin is never certain: input dispatched through browser automation also activates a page, so the browser's evidence stays below 1.

Account class

account.class is CORPORATE, PERSONAL, EXTERNAL (an email domain that is neither your organization's nor a consumer domain) or UNKNOWN, with how it was established (account.source), a confidence and a reason code such as domain_not_verified or consumer_domain. A policy rule for unknown accounts also applies to external ones, so an external account is never treated more leniently than an unknown one unless a rule names EXTERNAL.

Identity and deduplication

  • eventId is unique per stored event. dedupKey is the same for every delivery of the same sensor event: a retry, an offline sensor sending its queue again, or a replay from the console. Drop repeats by dedupKey.
  • observedAt is when the sensor saw the interaction; receivedAt is when Orthalon stored it. An offline sensor's events arrive with an old observedAt.
  • provenance names the sensor, its version, the policy revision that decided and the sensor's own event id.
  • actor.pseudonym is a stable identifier for the person within your organization that does not reveal who they are. actor.email can be suppressed per destination.

Agentic browsers and AI sidebars

Orthalon lists the agentic browsers and AI sidebars it knows about and states, per action, what a sensor can see. An action that is not observed is reported as not observed, never as safe.

ClientKindTyped prompt, paste, upload on AI sitesBuilt-in assistant panelActions the built-in agent takes
Comet (Perplexity)Agentic browserObserved with the extension installedNot observedNot observed
ChatGPT Atlas (OpenAI)Agentic browserObserved with the extension installedNot observedNot observed
Dia (The Browser Company)Agentic browserObserved with the extension installedNot observedNot observed
Opera NeonAgentic browserObserved with the extension installedNot observedNot observed
Copilot in Microsoft EdgeAI sidebarObservedNot observedNot observed
Gemini in ChromeAI sidebarObservedNot observedNot observed
Brave LeoAI sidebarObservedNot observedNot observed

Browser extensions cannot read a browser's own assistant panel, and an agent driving pages through automation produces input that looks like a person's. Orthalon therefore does not guess these browsers from their user-agent string, which is Chromium's. When a sensor reports one of these clients, the event carries actor.agenticClient, its actor origin becomes UNKNOWN (even if the sensor saw user activation) and its coverage PARTIAL with AGENT_ACTIONS_NOT_OBSERVED. Today the desktop app recognizes Comet by its process for application blocking, but no sensor yet labels the browser events that come from inside an agentic browser; until one does, treat browser events from devices where these clients are installed with the limits in this table.

JSON Schema

The record as delivered to a webhook or Splunk (schemaVersion 1.0). Fields marked as suppressible arrive as null when an administrator keeps them out of a destination.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:orthalon:decision-record:1.0",
  "title": "Orthalon decision record",
  "type": "object",
  "required": ["schemaVersion", "recordType", "eventId", "dedupKey", "observedAt", "receivedAt", "tenant", "decision", "enforcement", "coverage"],
  "properties": {
    "id": { "type": "string", "description": "Same as eventId; kept for searches written before version 1.0." },
    "organizationId": { "type": "string" },
    "receivedAt": { "type": "string", "format": "date-time" },
    "occurredAt": { "type": "string", "format": "date-time", "description": "Same as observedAt." },
    "user": { "type": ["string", "null"], "description": "The user's email. Suppressible (userEmail)." },
    "appDomain": { "type": "string" },
    "decision": { "enum": ["ALLOWED", "REDACTED", "COACHED_SENT", "COACHED_CANCELLED", "BLOCKED", "APPROVAL_REQUESTED"] },
    "direction": { "enum": ["REQUEST", "RESPONSE"] },
    "contentSource": { "type": ["string", "null"], "description": "PROMPT, CLIPBOARD, CLIPBOARD_COPY, FILE_UPLOAD, FILE_DOWNLOAD, FILE_OPEN, PAGE_VISIT, DESKTOP_REQUEST, MCP_TOOL_CALL, MOBILE_DESTINATION, AI_SIDEBAR, AUTH_CONTEXT" },
    "accountType": { "enum": ["UNKNOWN", "PERSONAL", "CORPORATE", "EXTERNAL"] },
    "accountDomain": { "type": ["string", "null"] },
    "policyId": { "type": ["string", "null"] },
    "detectorCount": { "type": "integer", "minimum": 0 },
    "detections": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["type", "count"],
        "properties": {
          "type": { "type": "string" },
          "count": { "type": "integer", "minimum": 1 },
          "confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 1 }
        }
      }
    },
    "redactedExcerpt": { "type": ["string", "null"], "description": "Placeholders only, such as <AWS_KEY_1>." },
    "file": {
      "type": ["object", "null"],
      "properties": {
        "extension": { "type": ["string", "null"] },
        "sizeBytes": { "type": ["integer", "null"] },
        "inspection": { "type": ["string", "null"] },
        "failureCode": { "type": ["string", "null"] }
      }
    },
    "falsePositiveReported": { "type": "boolean" },
    "justificationReason": { "type": ["string", "null"] },
    "schemaVersion": { "const": "1.0" },
    "recordType": { "const": "orthalon.decision" },
    "eventId": { "type": "string" },
    "dedupKey": { "type": "string", "pattern": "^[0-9a-f]{32}$" },
    "observedAt": { "type": "string", "format": "date-time" },
    "tenant": { "type": "object", "required": ["id"], "properties": { "id": { "type": "string" } } },
    "sensor": {
      "type": "object",
      "properties": {
        "surface": { "enum": ["BROWSER", "DESKTOP", "GATEWAY", "MCP", "MOBILE", null] },
        "id": { "type": ["string", "null"] },
        "version": { "type": ["string", "null"] },
        "recordVersion": { "type": ["integer", "null"] },
        "browserContext": { "enum": ["private", "standard", null] }
      }
    },
    "actor": {
      "type": "object",
      "properties": {
        "pseudonym": { "type": ["string", "null"], "pattern": "^act_[0-9a-f]{32}$" },
        "email": { "type": ["string", "null"] },
        "origin": { "enum": ["HUMAN", "AGENT", "MIXED", "UNKNOWN", null] },
        "originConfidence": { "type": ["number", "null"], "minimum": 0, "maximum": 1 },
        "originEvidence": { "enum": ["USER_ACTIVATION", "STICKY_ACTIVATION", "TOOL_CALL", "DECLARED_BY_CLIENT", "AGENTIC_CLIENT", "OS_INPUT", "NONE", null] },
        "agenticClient": { "type": ["string", "null"] }
      }
    },
    "account": {
      "type": "object",
      "properties": {
        "class": { "enum": ["UNKNOWN", "PERSONAL", "CORPORATE", "EXTERNAL"] },
        "source": { "enum": ["MANAGED_POLICY", "EMAIL_DOMAIN", "WORKSPACE_LABEL", "ACCOUNT_LABEL", "IDP", "UNKNOWN", null] },
        "confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 1 },
        "reason": { "type": ["string", "null"], "pattern": "^[a-z][a-z0-9_]{2,63}$", "description": "Why the class was chosen, e.g. domain_not_verified, consumer_domain." },
        "domain": { "type": ["string", "null"] }
      }
    },
    "asset": {
      "type": "object",
      "properties": {
        "appDomain": { "type": "string" },
        "orgAiAppId": { "type": ["string", "null"] }
      }
    },
    "action": {
      "type": "object",
      "properties": {
        "type": { "type": ["string", "null"] },
        "direction": { "enum": ["REQUEST", "RESPONSE"] }
      }
    },
    "detectorCategories": { "type": "array", "items": { "type": "string" } },
    "policy": {
      "type": "object",
      "properties": {
        "id": { "type": ["string", "null"] },
        "ruleId": { "type": ["string", "null"] },
        "revision": { "type": ["string", "null"] }
      }
    },
    "enforcement": {
      "type": "object",
      "required": ["decision", "outcome"],
      "properties": {
        "decision": { "type": "string" },
        "outcome": { "enum": ["NOT_REQUIRED", "ATTEMPTED", "ENFORCED", "CONFIRMED", "FAILED", null], "description": "null: not recorded by the sensor version that sent the event." },
        "failMode": { "enum": ["NONE", "FAIL_OPEN", "FAIL_CLOSED", null] },
        "failModeReason": { "type": ["string", "null"], "pattern": "^[A-Z][A-Z0-9_]{2,63}$" }
      }
    },
    "coverage": {
      "type": "object",
      "required": ["state"],
      "properties": {
        "state": { "enum": ["FULL", "PARTIAL", "NOT_OBSERVED", "UNSUPPORTED", null] },
        "reason": { "type": ["string", "null"], "pattern": "^[A-Z][A-Z0-9_]{2,63}$" }
      }
    },
    "severity": { "enum": ["informational", "low", "medium", "high", "critical"], "description": "A triage hint. A failed or unconfirmed control on a credential ranks highest." },
    "provenance": {
      "type": "object",
      "properties": {
        "sensorId": { "type": ["string", "null"] },
        "sensorVersion": { "type": ["string", "null"] },
        "policyRevision": { "type": ["string", "null"] },
        "clientEventId": { "type": ["string", "null"] }
      }
    }
  }
}

OCSF mapping

A destination set to OCSF receives each record as an OCSF 1.9.0 Data Security Finding (class_uid 2006, category Findings, type_uid 200601, activity Create) with the security_control profile.

OCSF attributeFrom the record
timeobservedAt (milliseconds)
metadata.uid, finding_info.uideventId
metadata.correlation_uiddedupKey
metadata.logged_timereceivedAt
severity_idseverity (1 informational … 5 critical)
action_iddecision: 1 Allowed, 2 Denied (block, cancelled coaching), 4 Modified (redaction), 99 Other (approval)
disposition_idoutcome: 2 Blocked only when the block was enforced or confirmed; 11 Corrected (redaction), 14 Delayed (approval), 27 Error (failed), 99 "Attempted, not confirmed", 0 Unknown when not recorded
finding_info.typesdetectorCategories
finding_info.analytic.uidthe rule id, or the policy id
data_security.detection_system_id1 Endpoint (browser, desktop), 2 DLP Gateway, 10 Application-Level DLP (MCP)
data_security.data_lifecycle_state_id3 In Use (clipboard), otherwise 2 In Transit
actor.user.uid, actor.user.email_addractor.pseudonym, actor.email
dst_endpoint.hostnameappDomain
unmapped.orthalonthe full record, so coverage, actor origin and every original id travel with the finding