In this section, you will implement HIPAA audit events using the SDK. Whenever protected health information (PHI) is displayed to users, those events need to be logged. One of the advantages of building a Bridge application is the centralized audit logging provided by an SDK method.

HIPAA Auditing

The audit logging functionality associates a user with clinical data from the Bridge data model. Currently, audit record creation is supported at the patient_mrn, rad_exam, and claim levels.

Best Practice - Some applications may not show the user every records requested from the server, i.e. a data structure with PHI that is updated client-side, but only displays an aggregate metric without the PHI. It is critical to still log that information: anything sent to a client/browser (even if not intended to be rendered) should be logged. While typical users will not see the data, a malicious actor or compromised workstation would have access to that data. In the case of an audit, the request URL and application name help to identify page display state.

To log an audit event, use the SDK method Java::HarbingerSdk::Hipaa.explicitLogger. This method takes seven arguments:

  1. the approved unique application name
  2. the full HTTP request URL
  3. the IP of the the request (typically the IP of the computer running the web browser connected to the application)
  4. the user's SSO username
  5. the user's SSO domain
  6. the table name of the PHI (e.g. rad_exams or patient_mrns)
  7. a list/array of primary keys of the records that will be shown to the user

Build a method in app/controllers/application_controller.rb to use the SDK logger to submit audits:

  # Takes a list of ORM objects (rad_exams, or patient_mrns, but NOT rad_exams and patient_mrns)
  # and does the HIPAA auditing.
  def log_hipaa_view(objects,options={})
    if objects.size > 0
      options.reverse_merge!({
          :app_name => "rails-developer-tutorial",
          :request_info => request.original_fullpath,
          :requesting_ip => request.remote_ip,
          :table_name => objects.first.class.table_name,
          :username => session[:username],
          :domain => session[:domain] || "not set in session",
          :table_ids => objects.collect {|exam| exam.id }
        })
      objects.compact! if objects.class == Array
      Java::HarbingerSdk.Hipaa.explicitLogger(
                               options[:app_name],
                               options[:request_info],
                               options[:requesting_ip],
                               options[:username],
                               options[:domain],
                               options[:table_name],
                               options[:table_ids])
    end
  end

This is a generalized method that accepts an Array of ORM objects, extracts the table name, then builds the explicitLogger call. This method also presents the option to override some of parameters in the audit event (via the options argument) and will safely ignore the call if an empty Array is passed.

Note - The comments in the code above also note that you cannot send ORM objects of more than one type to this method in a single call. You can send an Array of rad_exams or an Array of patient_mrns but not an Array of both patient_mrns and rad_exams in a single call.

This enables HIPAA logging to be added to the views in the WorklistController. Edit app/controllers/worklist_controller.rb in index method:

  def index
    query = Java::HarbingerSdkData::RadExam.createQuery(@entity_manager)
    expression = query.equal(".currentStatus.universalEventType.eventType","complete")
    query.where(query.and([expression,query.isNotNull(".radExamTime.endExam")]))
    query.order(".radExamTime.endExam desc")
    @exams = query.limit(100).list().to_a
    log_hipaa_view(@exams)
  end

This calls the log_hipaa_view method and passes the rad_exam objects set in the @exams variable.