id: recorded_future
name: Recorded Future
version: 1.0.0
description: "Recorded Future ConnectAPI (v2) — risk reputation for IPs, domains, URLs, file hashes and vulnerabilities, full entity intelligence (risk rules, related entities, threat lists), and alert ingestion (search/lookup/rules)."
changelog: "1.0.0 — Initial release: ip/domain/url/file/cve reputation, entity intelligence, alert ingestion (search) with an OCSF mapper, alert lookup and alert-rule search."
category: enrichment

# Per-instance configuration. The ConnectAPI is authenticated with an
# Organization API token sent in the X-RFToken header.
config_schema:
  properties:
    server_url:
      type: string
      description: "Recorded Future API base URL"
      default: https://api.recordedfuture.com
    api_token:
      type: string
      description: "Recorded Future API token"
      x-soar-sensitive: true
  required:
    - api_token

auth:
  - id: token
    type: api_key
    in: header
    name: X-RFToken
    value_template: "{{secret}}"
    secret_field: api_token

commands:
  # ── Reputation ──────────────────────────────────────────────────────────────
  - id: ip
    name: recordedfuture-ip
    description: "Risk reputation for an IP address (risk score, level and triggered risk rules)."
    risk: read
    inputs_schema:
      properties:
        ip: { type: string, description: "IP address" }
      required: [ip]
    outputs_schema: { properties: {} }

  - id: domain
    name: recordedfuture-domain
    description: "Risk reputation for a domain (risk score, level and triggered risk rules)."
    risk: read
    inputs_schema:
      properties:
        domain: { type: string, description: "Domain name" }
      required: [domain]
    outputs_schema: { properties: {} }

  - id: url
    name: recordedfuture-url
    description: "Risk reputation for a URL (risk score, level and triggered risk rules)."
    risk: read
    inputs_schema:
      properties:
        url: { type: string, description: "URL" }
      required: [url]
    outputs_schema: { properties: {} }

  - id: file
    name: recordedfuture-file
    description: "Risk reputation for a file hash (MD5, SHA1, SHA256, SHA512)."
    risk: read
    inputs_schema:
      properties:
        file: { type: string, description: "File hash" }
      required: [file]
    outputs_schema: { properties: {} }

  - id: cve
    name: recordedfuture-cve
    description: "Risk reputation for a vulnerability (CVE)."
    risk: read
    inputs_schema:
      properties:
        cve: { type: string, description: "CVE identifier (e.g. CVE-2021-44228)" }
      required: [cve]
    outputs_schema: { properties: {} }

  - id: intelligence
    name: recordedfuture-intelligence
    description: "Full intelligence for a single entity: risk, triggered rules, related entities, metrics and threat lists."
    risk: read
    inputs_schema:
      properties:
        entity_type: { type: string, description: "Entity type: ip, domain, url, file or cve" }
        entity: { type: string, description: "Entity value (IP, domain, URL, hash or CVE)" }
      required: [entity_type, entity]
    outputs_schema: { properties: {} }

  # ── Alert ingestion ─────────────────────────────────────────────────────────
  - id: alerts
    name: recordedfuture-alerts
    description: "Search alerts. Used for ingestion: results path = data.results. Filter by triggered time, status and alert rule."
    risk: read
    inputs_schema:
      properties:
        triggered: { type: string, description: "Triggered-time filter. A bare timestamp/relative value is treated as the lower bound ('[<value>,]'); a range '[from,to]' is passed through. Incremental fetch watermark." }
        status: { type: string, description: "Review status (unassigned, assigned, pending, actionable, no-action, tuning)" }
        alert_rule: { type: string, description: "Alert rule ID to filter by" }
        freetext: { type: string, description: "Free-text search" }
        direction: { type: string, description: "Sort direction (asc, desc). Default desc." }
        limit: { type: number, description: "Maximum number of alerts (default 50)" }
      required: []
    outputs_schema: { properties: {} }
    ingest:
      results_path: data.results
      dedup_key: id
      incremental_field: triggered

  - id: alert_lookup
    name: recordedfuture-alert-lookup
    description: "Look up a single alert by ID."
    risk: read
    inputs_schema:
      properties:
        alert_id: { type: string, description: "Alert ID" }
      required: [alert_id]
    outputs_schema: { properties: {} }

  - id: alert_rules
    name: recordedfuture-alert-rules
    description: "Search alert rule IDs by name."
    risk: read
    inputs_schema:
      properties:
        rule_name: { type: string, description: "Rule name to search (partial allowed)" }
        limit: { type: number, description: "Maximum number of rules (default 10)" }
      required: []
    outputs_schema: { properties: {} }

  # ── Connectivity test ─────────────────────────────────────────────────────
  - id: test_connection
    name: recordedfuture-test-connection
    description: "Verify connectivity and credentials (used by the Test button)."
    risk: read
    inputs_schema:
      properties: {}
      required: []
    outputs_schema: { properties: {} }

ingestion:
  command: alerts
  mapper: alerts
  default_incident_type: "Recorded Future Alert"
