{
    "title": "Generic Ingest Edge",
    "description": "Defines an edge between two nodes in a generic graph ingestion system. Each edge specifies a start and end node using one of three matching strategies: by unique identifier (match_by: id), by name (match_by: name, deprecated), or by one or more property matchers (match_by: property). A kind is required to indicate the relationship type. Optional properties may include custom attributes. You may optionally constrain the start or end node to a specific kind using the kind field inside each reference.",
    "type": "object",
    "$defs": {
        "property_map": {
            "type": ["object", "null"],
            "description": "A key-value map of edge attributes. Values must not be objects. If a value is an array, it must contain only primitive types (e.g., strings, numbers, booleans) and must be homogeneous (all items must be of the same type).",
            "additionalProperties": {
                "anyOf": [
                    { "type": "string" },
                    { "type": "number" },
                    { "type": "boolean" },
                    {
                        "type": "array",
                        "anyOf": [
                            { "items": { "type": "string" } },
                            { "items": { "type": "number" } },
                            { "items": { "type": "boolean" } }
                        ]
                    }
                ]
            }
        },
        "endpoint": {
            "type": "object",
            "properties": {
                "match_by": {
                    "type": "string",
                    "enum": ["id", "name", "property"],
                    "default": "id",
                    "description": "Whether to match the start node by its unique object ID or by a series of property matches. Note that the name value here is deprecated and will be removed in future versions. Users are advised to use the multi-property match strategy moving forward."
                },
                "property_matchers": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "type": "object",
                        "properties": {
                            "key": {
                                "type": "string"
                            },
                            "operator": {
                                "type": "string",
                                "enum": ["equals"]
                            },
                            "value": {
                                "type": ["string", "number", "boolean"]
                            }
                        },
                        "required": ["key", "operator", "value"]
                    }
                },
                "value": {
                    "type": "string",
                    "description": "The value used for matching — either an object ID or a name, depending on match_by."
                },
                "kind": {
                    "type": "string",
                    "description": "Optional kind filter; the referenced node must have this kind."
                }
            },
            "if": {
                "allOf": [
                    {
                        "properties": {
                            "match_by": {
                                "type": "string",
                                "const": "property"
                            }
                        }
                    },
                    {
                        "not": {
                            "properties": {
                                "match_by": {
                                    "type": "null"
                                }
                            }
                        }
                    }
                ]
            },
            "then": {
                "required": ["property_matchers"],
                "not": {
                    "required": ["value"]
                }
            },
            "else": {
                "required": ["value"],
                "not": {
                    "required": ["property_matchers"]
                }
            }
        }
    },
    "properties": {
        "start": {
            "$ref": "#/$defs/endpoint"
        },
        "end": {
            "$ref": "#/$defs/endpoint"
        },
        "kind": {
            "type": "string",
            "description": "Edge kind name must contain only alphanumeric characters and underscores.",
            "pattern": "^[A-Za-z0-9_]+$"
        },
        "properties": {
            "$ref": "#/$defs/property_map"
        }
    },
    "required": ["start", "end", "kind"],
    "examples": [
        {
            "start": {
                "match_by": "id",
                "value": "user-1234"
            },
            "end": {
                "match_by": "id",
                "value": "server-5678"
            },
            "kind": "has_session",
            "properties": {
                "timestamp": "2025-04-16T12:00:00Z",
                "duration_minutes": 45
            }
        },
        {
            "start": {
                "match_by": "property",
                "property_matchers": [
                    {
                        "key": "prop_1",
                        "operator": "equals",
                        "value": "value"
                    }
                ]
            },
            "end": {
                "match_by": "id",
                "value": "server-5678"
            },
            "kind": "has_session",
            "properties": {
                "timestamp": "2025-04-16T12:00:00Z",
                "duration_minutes": 45
            }
        },
        {
            "start": {
                "match_by": "name",
                "value": "alice",
                "kind": "User"
            },
            "end": {
                "match_by": "name",
                "value": "file-server-1",
                "kind": "Server"
            },
            "kind": "accessed_resource",
            "properties": {
                "via": "SMB",
                "sensitive": true
            }
        },
        {
            "start": {
                "value": "admin-1"
            },
            "end": {
                "value": "domain-controller-9"
            },
            "kind": "admin_to",
            "properties": {
                "reason": "elevated_permissions",
                "confirmed": false
            }
        },
        {
            "start": {
                "match_by": "name",
                "value": "Printer-007"
            },
            "end": {
                "match_by": "id",
                "value": "network-42"
            },
            "kind": "connected_to",
            "properties": null
        }
    ]
}
