Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function parseEvent(rawBody) {

- The key is the whole signing secret, `whsec_` prefix included, as UTF-8 bytes. The message is the raw body: re-serialized JSON does not match (for example, `&` arrives as `\u0026`).
- Delivery attempts have a 1-second timeout. Network errors, timeout, 429 and 5xx retry with backoff within a bounded window (8 failed sends or 15-minute retry age); worker/Redis waits can extend wall time. Retries preserve signed bytes and `event_id`, and duplicate deliveries remain possible. Verify the raw-body signature, durably store by signed `event_id` (legacy fallback: `data.request_id`), then acknowledge 2xx and process asynchronously. Redirects are not followed.
- Current Portal Test sends a complete `2026-10-06` Core-generated sample with fp21/HRE and a distinct event ID per click. Vendored historical Test fixtures retain their two missing flags as explicit legacy compatibility cases.
- Current Portal Test sends a complete `2026-10-07` Core-generated sample with HRE cluster references and a distinct event ID per click. Vendored historical Test fixtures retain their two missing flags as explicit legacy compatibility cases.
- A History row can be refined after its webhook was sent; the webhook is not sent again. Read the History API when you need the latest state.

### Read identifications from the History API
Expand Down Expand Up @@ -210,7 +210,7 @@ access the typed field.
## Compatibility

- OpenAPI 3.1.0; the JSON Schemas use JSON Schema 2020-12 and compile with a strict validator.
- `info.version` follows the package version (semantic versioning). Webhook payloads carry `schema_version` (`2026-10-06` current, `2026-06-01` legacy).
- `info.version` follows the package version (semantic versioning). Webhook payloads carry `schema_version` (`2026-10-07` current; `2026-10-06` and `2026-06-01` legacy).
- Parse tolerantly: ignore unknown fields, keep unknown values of string fields and accept other `schema_version` values. Response fields with a known set of values are open strings in the spec and in the JSON Schemas, so a value added later never fails validation.
- Tooling requires Node.js 20.19 or later; CI runs on Node.js 20, 22 and 24.

Expand Down
154 changes: 149 additions & 5 deletions dist/schemas/identification-scored-event.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,121 @@
"type": "object",
"additionalProperties": true
}
},
{
"if": {
"type": "object",
"required": [
"schema_version"
],
"properties": {
"schema_version": {
"const": "2026-10-07"
}
},
"additionalProperties": true
},
"then": {
"type": "object",
"required": [
"event_id"
],
"properties": {
"event_id": {
"type": "string",
"minLength": 1,
"description": "Logical site/request/final-result-version/type identity. Stable across retries and endpoints."
},
"data": {
"type": "object",
"required": [
"result_version",
"scoring_version",
"hre"
],
"properties": {
"result_version": {},
"scoring_version": {},
"risk_events": {},
"fingerprint": {},
"detection_flags": {
"type": "object",
"not": {
"type": "object",
"required": [
"os_mismatch2"
],
"properties": {
"os_mismatch2": {}
},
"additionalProperties": true
}
},
"hre": {
"type": "object",
"properties": {
"account_sharing": {
"type": "object",
"required": [
"cluster_id"
],
"properties": {
"cluster_id": {}
},
"additionalProperties": true
},
"account_takeover": {
"type": "object",
"required": [
"cluster_id"
],
"properties": {
"cluster_id": {}
},
"additionalProperties": true
},
"impossible_travel": {
"type": "object",
"required": [
"cluster_id"
],
"properties": {
"cluster_id": {}
},
"additionalProperties": true
}
}
}
},
"additionalProperties": true,
"not": {
"anyOf": [
{
"type": "object",
"required": [
"risk_events"
],
"properties": {
"risk_events": {}
},
"additionalProperties": true
},
{
"type": "object",
"required": [
"fingerprint"
],
"properties": {
"fingerprint": {}
},
"additionalProperties": true
}
]
}
}
},
"additionalProperties": true
}
}
],
"$defs": {
Expand Down Expand Up @@ -367,7 +482,7 @@
},
"os_mismatch": {
"type": "boolean",
"description": "The operating system seen on the network differs from the one the browser reports."
"description": "Either internal OS consistency check detected a mismatch. The public flag combines browser/network and TCP behaviour checks."
},
"os_not_detected": {
"type": "boolean",
Expand Down Expand Up @@ -413,9 +528,6 @@
"type": "boolean",
"description": "Part of the browser checks timed out, so the verdict rests on partial data. Informational."
},
"os_mismatch2": {
"type": "boolean"
},
"device_spoofing": {
"type": "boolean"
},
Expand All @@ -432,6 +544,11 @@
"ai_browser": {
"type": "boolean",
"description": "A browser is identified by separate verified browser infrastructure. A generic browser User-Agent or a verified provider alone is insufficient. Weight 0. Optional on older payloads; absence is not an evaluated negative."
},
"os_mismatch2": {
"type": "boolean",
"deprecated": true,
"description": "Legacy 2026-10-06 only; current payloads combine this check into os_mismatch."
}
}
},
Expand Down Expand Up @@ -511,12 +628,19 @@
"min_devices": {
"type": "integer",
"minimum": 1
},
"cluster_id": {
"type": [
"string",
"null"
],
"description": "Authoritative cluster ID for this HRE result. Null when no cluster was published for the result, including old stored verdicts; never a device ID. Reused on retries."
}
}
},
"IdentificationScoredData": {
"type": "object",
"description": "Final identification. risk_score is this scan only; no all-time entity risk. New extension fields are required by version 2026-10-06; legacy bodies remain accepted.",
"description": "Final identification. risk_score is this scan only. Version 2026-10-07 uses signals for score contributions, detection_flags for final decisions, and hre for account results. Older bodies remain accepted.",
"required": [
"request_id",
"visitor_id",
Expand Down Expand Up @@ -615,13 +739,33 @@
"description": "Core build source revision; core:unversioned on local builds."
},
"risk_events": {
"deprecated": true,
"description": "Legacy 2026-10-06 only; absent from current scored events.",
"type": "array",
"items": {
"$ref": "#/$defs/RiskEvent"
}
},
"hre": {
"$ref": "#/$defs/HRE"
},
"search_bot_owner": {
"type": "string",
"description": "Owner label from accepted search-bot detection; omitted when unknown or inactive.",
"examples": [
"Google"
]
},
"ai_bot_owner": {
"type": "string",
"description": "Provider company label from accepted AI-bot detection; omitted when unknown or inactive.",
"examples": [
"OpenAI"
]
},
"ai_browser_owner": {
"type": "string",
"description": "Owner label from accepted AI-browser detection; omitted when unknown or inactive."
}
}
},
Expand Down
10 changes: 6 additions & 4 deletions dist/schemas/identification.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@
},
"os_mismatch": {
"type": "boolean",
"description": "The operating system seen on the network differs from the one the browser reports."
"description": "Either internal OS consistency check detected a mismatch. The public flag combines browser/network and TCP behaviour checks."
},
"os_not_detected": {
"type": "boolean",
Expand Down Expand Up @@ -481,9 +481,6 @@
"type": "boolean",
"description": "Part of the browser checks timed out, so the verdict rests on partial data. Informational."
},
"os_mismatch2": {
"type": "boolean"
},
"device_spoofing": {
"type": "boolean"
},
Expand All @@ -500,6 +497,11 @@
"ai_browser": {
"type": "boolean",
"description": "A browser is identified by separate verified browser infrastructure. A generic browser User-Agent or a verified provider alone is insufficient. Weight 0. Optional on older payloads; absence is not an evaluated negative."
},
"os_mismatch2": {
"type": "boolean",
"deprecated": true,
"description": "Legacy 2026-10-06 only; current payloads combine this check into os_mismatch."
}
}
},
Expand Down
Loading
Loading