// ============================================================================
// attack_graph_local.h — T1 Local Self-Diagnosis Attack Graph
//
// C++ port of the LOCAL self-diagnosis subset of:
//   pdl-engine/pdl_platform/redcell/attack_graph.py
//   (6-node compromise-probability graph for on-device health monitoring)
//
// Models 6 firmware assets and tracks their individual compromise probability
// based on observed security events.  Pure rule-based update: no networkx,
// no heap, no STL.  Decays 1% per minute when no events are seen.
//
// Nodes (asset IDs 0–5):
//   NODE_BOOTLOADER     = 0
//   NODE_FIRMWARE       = 1
//   NODE_MODELS         = 2
//   NODE_MESH_KEY       = 3
//   NODE_BLUE_FORCE_LIST= 4
//   NODE_AUTH_PUBKEY    = 5
//
// Event types:
//   EVT_SIG_FAIL          — signature verification failure
//   EVT_OOB_TIME          — out-of-bounds timing anomaly
//   EVT_MISSING_HEARTBEAT — expected heartbeat not received
//   EVT_OTA_REJECT        — OTA update rejected / integrity failure
//   EVT_PEC_DEVIATION     — PEC model confidence deviation
//   EVT_AUTH_FAIL         — authentication attempt failed
//   EVT_REPLAY_DETECT     — replay-attack pattern detected
//   EVT_MESH_INJECT       — suspected mesh packet injection
//
// Per-node weights (static const matrix):
//   s_event_weight[event_type][node_id] ∈ [0, 1]
//   Applied as: new_prob = clamp(old_prob + weight * event_weight_param, 0, 1)
//
// Decay: once per call to attackgraph_observe(), elapsed time is used to
//        decay all nodes by 1%/min (approximated per call if timestamp supplied,
//        or approximated at 1%/call-batch for callers without a clock).
//
// Failsafe threshold: any node > 0.85 → attackgraph_should_failsafe() = true.
//
// Static memory only.  <cstdint> <cstring> <cmath> only.
//
// PDL Consulting LLC — Trade Secret.  See license header in attack_graph_local.cpp.
// ============================================================================

#ifndef ATTACK_GRAPH_LOCAL_H
#define ATTACK_GRAPH_LOCAL_H

#include <cstdint>

// ---------------------------------------------------------------------------
// Node IDs
// ---------------------------------------------------------------------------
enum AttackGraphNode : uint8_t {
    NODE_BOOTLOADER      = 0,
    NODE_FIRMWARE        = 1,
    NODE_MODELS          = 2,
    NODE_MESH_KEY        = 3,
    NODE_BLUE_FORCE_LIST = 4,
    NODE_AUTH_PUBKEY     = 5,
    AG_NODE_COUNT        = 6   // sentinel
};

// ---------------------------------------------------------------------------
// Event types
// ---------------------------------------------------------------------------
enum AttackGraphEvent : uint8_t {
    EVT_SIG_FAIL          = 0,
    EVT_OOB_TIME          = 1,
    EVT_MISSING_HEARTBEAT = 2,
    EVT_OTA_REJECT        = 3,
    EVT_PEC_DEVIATION     = 4,
    EVT_AUTH_FAIL         = 5,
    EVT_REPLAY_DETECT     = 6,
    EVT_MESH_INJECT       = 7,
    AG_EVENT_COUNT        = 8  // sentinel
};

// ---------------------------------------------------------------------------
// Failsafe threshold (any node above this → should_failsafe = true)
// ---------------------------------------------------------------------------
static const float AG_FAILSAFE_THRESHOLD = 0.85f;

// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------

/**
 * attackgraph_init — reset all node probabilities to 0 and clear decay timer.
 * Must be called before any other attackgraph_* function.
 */
void attackgraph_init(void);

/**
 * attackgraph_observe — record a security event and update node probabilities.
 *
 * @param node_id    Target node (AttackGraphNode).  If >= AG_NODE_COUNT, call is ignored.
 * @param event_type Event type (AttackGraphEvent). If >= AG_EVENT_COUNT, call is ignored.
 * @param weight     Caller-supplied event weight ∈ [0, 1].  Multiplied by the
 *                   static per-(event,node) weight to produce the probability delta.
 *                   Pass 1.0f for a fully-weighted event; lower values for soft signals.
 */
void attackgraph_observe(uint8_t node_id, uint8_t event_type, float weight);

/**
 * attackgraph_node_risk — return the current compromise probability for a node.
 *
 * @param node_id  AttackGraphNode.
 * @return float ∈ [0, 1].  Returns 0.0f for invalid node_id.
 */
float attackgraph_node_risk(uint8_t node_id);

/**
 * attackgraph_should_failsafe — returns true when ANY node's compromise
 * probability exceeds AG_FAILSAFE_THRESHOLD (0.85).
 *
 * Integrator action when true:
 *   - Publish MSG_TYPE_BEHAVIORAL_NLL with reason byte set to 0xFF
 *   - If attackgraph_node_risk(NODE_AUTH_PUBKEY) > 0.95: wipe NVS + reboot
 */
bool attackgraph_should_failsafe(void);

/**
 * attackgraph_decay — apply time-based decay to all node probabilities.
 *
 * Called automatically by attackgraph_observe().  Can also be called from the
 * main loop tick if no events arrive, to ensure decay happens continuously.
 *
 * @param elapsed_ms  Milliseconds since last call.  Decay = 1% per 60 000 ms.
 */
void attackgraph_decay(uint32_t elapsed_ms);

/**
 * attackgraph_highest_risk_node — returns the node_id with the highest
 * compromise probability, or 0xFF if all are 0.
 */
uint8_t attackgraph_highest_risk_node(void);

#endif // ATTACK_GRAPH_LOCAL_H
