def encode_for_jwt(hash)
      hash = hash.dup

      out = {
        id: hash.delete(:id),
        iss: hash.delete(:issuer),
        sub: hash.delete(:subject),
        scope: hash.delete(:scope)
      }.delete_if { |_, v| v.nil? }

      # Unfortunately, nil.to_i returns 0, which means we can't
      # easily clean out exp if we include it although it wasn't passed
      # in like we do for other keys. So, we only include it if it's
      # actually passed in and non-nil. Either way, we delete the keys.
      hash.delete(:expires_at).tap { |e| out[:exp] = e.to_i if e }
      hash.delete(:actor).tap { |a| out[:act] = encode_for_jwt(a) if a }

      # Extra attributes passed through as-is
      out.merge!(hash)

      out
    end
def encode_for_jwt(hash)
      hash = hash.dup

      out = {
        id: hash.delete(:id),
        iss: hash.delete(:issuer),
        sub: hash.delete(:subject),
        scope: hash.delete(:scope)
      }.delete_if { |_, v| v.nil? }

      # Unfortunately, nil.to_i returns 0, which means we can't
      # easily clean out exp if we include it although it wasn't passed
      # in like we do for other keys. So, we only include it if it's
      # actually passed in and non-nil. Either way, we delete the keys.
      hash.delete(:expires_at).tap { |e| out[:exp] = e.to_i if e }
      hash.delete(:actor).tap { |a| out[:act] = encode_for_jwt(a) if a }

      # Extra attributes passed through as-is
      out.merge!(hash)

      out
    end
Internally, we use "subject" to refer to "sub", and so on. We also
 represent some objects (expiry) differently. These functions do the
 mapping from Fridge to JWT and vice-versa.