Module: PostHog::MCP::Identity Private

Defined in:
lib/posthog/mcp/identity.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Identity resolution: runs the identify option, dedupes against the per-server cache, and decides when a standalone $identify event fires.

Class Method Summary collapse

Class Method Details

.captured_extra(extra) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Only JSON scalars from extra are captured; never opaque transport objects.



154
155
156
157
158
159
160
# File 'lib/posthog/mcp/identity.rb', line 154

def captured_extra(extra)
  return nil unless extra.is_a?(Hash)

  extra.select do |_, value|
    value.nil? || value.is_a?(String) || value.is_a?(Numeric) || value == true || value == false
  end
end

.handle_identify(data, session_id, request, extra) ⇒ Hash?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the $identify event alone; see identify_for_request.

Returns:



139
140
141
# File 'lib/posthog/mcp/identity.rb', line 139

def handle_identify(data, session_id, request, extra)
  identify_for_request(data, session_id, request, extra).first
end

.identify_for_request(data, session_id, request, extra) ⇒ Array(Hash, UserIdentity), ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolve the optional identify callback for one request: the identity the request's events belong to, plus an $identify event to emit only when that identity has materially changed.

The actor is handed back rather than left for the caller to read out of PostHog::MCP::IdentityCache later. The cache is keyed by session, and a request's events are built after its handler returns, so a concurrent request on the same session would otherwise decide who this one is attributed to. When resolution yields nothing the cache is read once, here, so whatever a request is attributed to it is attributed to consistently.

Returns:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/posthog/mcp/identity.rb', line 106

def identify_for_request(data, session_id, request, extra)
  identify = data.options.identify
  return [nil, nil] unless identify

  result = if identify.is_a?(UserIdentity) || identify.is_a?(Hash)
             identify
           else
             Callbacks.call(identify, request,
                            extra)
           end
  identity = UserIdentity.coerce(result)
  unless identity
    Log.debug(data.options, "Warning: Supplied identify function returned null for session #{session_id}")
    return [nil, data.identified_sessions.get(session_id)]
  end

  merged, changed = data.identified_sessions.merge!(session_id, identity)
  return [nil, merged] unless changed

  Log.debug(data.options, "Identified session #{session_id}")
  [{
    'session_id' => session_id,
    'resource_name' => request_resource_name(request),
    'event_type' => EventType::IDENTIFY,
    'parameters' => { 'request' => request, 'extra' => captured_extra(extra) },
    'timestamp' => Time.now.utc
  }, merged]
rescue StandardError => e
  Log.debug(data.options, "Error: identify function threw while identifying session #{session_id} - #{e.message}")
  [nil, data.identified_sessions.get(session_id)]
end

.identities_equal?(first, second) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/posthog/mcp/identity.rb', line 66

def identities_equal?(first, second)
  return false if first.distinct_id != second.distinct_id
  return false if sorted_json(first.groups || {}) != sorted_json(second.groups || {})

  a_props = first.properties || {}
  b_props = second.properties || {}
  return false if a_props.keys.map(&:to_s).sort != b_props.keys.map(&:to_s).sort

  a_props.all? do |key, value|
    other = if b_props.key?(key)
              b_props[key]
            else
              b_props[key.is_a?(Symbol) ? key.to_s : key.to_s.to_sym]
            end
    sorted_json(value) == sorted_json(other)
  end
end

.merge_identities(previous, nxt) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



84
85
86
87
88
89
90
91
92
# File 'lib/posthog/mcp/identity.rb', line 84

def merge_identities(previous, nxt)
  return nxt if previous.nil?

  UserIdentity.new(
    distinct_id: nxt.distinct_id,
    properties: (previous.properties || {}).merge(nxt.properties || {}),
    groups: nxt.groups.nil? ? previous.groups : nxt.groups
  )
end

.request_resource_name(request) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



143
144
145
146
147
148
149
150
151
# File 'lib/posthog/mcp/identity.rb', line 143

def request_resource_name(request)
  return 'Unknown' unless request.is_a?(Hash)

  params = request[:params] || request['params']
  return 'Unknown' unless params.is_a?(Hash)

  name = params[:name] || params['name']
  name.is_a?(String) ? name : 'Unknown'
end

.sort_deep(value) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



168
169
170
171
172
173
174
175
# File 'lib/posthog/mcp/identity.rb', line 168

def sort_deep(value)
  case value
  when Hash then value.map { |k, v| [k.to_s, sort_deep(v)] }.sort_by(&:first).to_h
  when Array then value.map { |v| sort_deep(v) }
  when String, Numeric, true, false, nil then value
  else value.to_s
  end
end

.sorted_json(value) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



162
163
164
165
166
# File 'lib/posthog/mcp/identity.rb', line 162

def sorted_json(value)
  JSON.generate(sort_deep(value))
rescue StandardError
  value.to_s
end