def on_fire(ctx):
    """Fire outbound webhook with optional connection credentials."""
    data = ctx["stage_data"]
    url = data.get("webhook_url", "")

    # Fallback to configured connection
    if not url:
        conn = connections.get("webhook")
        if conn:
            url = conn.get("url", "")

    if not url:
        return {"error": "No webhook URL configured"}

    payload = json.encode({
        "event": data.get("event_name", "workflow.notify"),
        "instance_id": ctx["instance_id"],
        "workflow_id": ctx["workflow_id"],
        "data": data,
    })

    resp = http.post(url, body=payload, headers={
        "Content-Type": "application/json",
        "X-Armature-Event": data.get("event_name", "workflow.notify"),
    })

    # Log the delivery
    db.insert("webhook_log", {
        "url": url,
        "status_code": str(resp["status"]),
        "event": data.get("event_name", ""),
        "instance_id": ctx["instance_id"],
    })

    status = "delivered" if int(resp["status"]) < 400 else "failed"

    return {"advance": True, "data": {
        "delivery_status": status,
        "status_code": str(resp["status"]),
        "response_body": resp["body"][:500],
    }}
