// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract HeartbeatCapabilityRegistry { struct Entry { address agent; bytes32 endpoint; uint64 expiration; } mapping(bytes4 => Entry) private entries; event CapabilityRegistered(bytes4 indexed capability, address indexed agent, bytes32 endpoint, uint256 expiration); event CapabilityRemoved(bytes4 indexed capability, address indexed agent); error BadExpiry(); error NotAgent(); error NotRemovable(); error NotActive(); function set(bytes4 capability, bytes32 endpoint, uint256 expiration) external { if (!(expiration > block.timestamp && expiration <= block.timestamp + 90 days)) revert BadExpiry(); Entry storage entry = entries[capability]; if (!(entry.agent == address(0) || entry.expiration <= block.timestamp || entry.agent == msg.sender)) revert NotAgent(); entry.agent = msg.sender; entry.endpoint = endpoint; entry.expiration = uint64(expiration); emit CapabilityRegistered(capability, msg.sender, endpoint, expiration); } function remove(bytes4 capability) external { Entry storage entry = entries[capability]; if (!(entry.agent != address(0) && entry.expiration <= block.timestamp)) revert NotRemovable(); emit CapabilityRemoved(capability, entry.agent); delete entries[capability]; } function get(bytes4 capability) external view returns (address agent, bytes32 endpoint, uint256 expiration) { Entry storage entry = entries[capability]; if (!(entry.expiration > block.timestamp)) revert NotActive(); return (entry.agent, entry.endpoint, uint256(entry.expiration)); } }