phi_attrs 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b809e5c530692590d9ef986bace3be17d38dfff
4
- data.tar.gz: 47f1af03b09d42744847c22a9052244c3b156cab
3
+ metadata.gz: ba341e9dd1cd04be0df49bb9fde3ed07efe919b0
4
+ data.tar.gz: 347e29ebed345ca44efb5a40526d17c5d259d394
5
5
  SHA512:
6
- metadata.gz: 5e54820917cc4dd8579bc4d1a6707906423d2633d8bf13d50fa9bf7f956715f2c320a307b23ba666a13201d5f80b313b06c9277477c26f8a37619c52caecb70a
7
- data.tar.gz: 4e018c7b2bc85907a70aa8759365d4d7cba4b00d1669da71f49522cbd8a198991b295f2382ef5fe007605775266ff1bf4863320b05049c35430b581d28934530
6
+ metadata.gz: 3c04bcfdf0147373ed81c48110345b1d39eb68aa9912c263d4178faa36fde1bae35d9e8eff7fb5a17d890402b8402706f8ea5a1d218a567ae2975f08f3c03e1d
7
+ data.tar.gz: c8800bf401bd64809f91b481798beb143bb10b78cc7ed85e9cb6d32a9cca48f07133e1e3b36456b1caf80420efd4b1c92406be92acdefd7527fa609ebcb1fc7c
data/.gitignore CHANGED
@@ -15,3 +15,6 @@
15
15
  *.sqlite3
16
16
  *.log
17
17
  .rspec_status
18
+
19
+ # Macs. Ugh.
20
+ .DS_Store
@@ -0,0 +1,90 @@
1
+ Rails:
2
+ Enabled: true
3
+
4
+ AllCops:
5
+ Exclude:
6
+ - 'bin/**/*'
7
+ - 'spec/internal/db/schema.rb'
8
+ TargetRubyVersion: 2.5
9
+
10
+ Documentation:
11
+ Enabled: false
12
+
13
+ Layout/IndentationWidth:
14
+ Enabled: true
15
+
16
+ Lint/UnreachableCode:
17
+ Exclude:
18
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
19
+
20
+ Lint/UnusedMethodArgument:
21
+ Exclude:
22
+ - 'lib/phi_attrs.rb' # TODO: RUBOCOP Cleanup exclusion
23
+
24
+ Metrics/AbcSize:
25
+ Max: 30
26
+ Exclude:
27
+ - 'spec/internal/db/**/*'
28
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
29
+
30
+ Metrics/BlockLength:
31
+ Enabled: false
32
+
33
+ Metrics/ClassLength:
34
+ Max: 1500
35
+
36
+ Metrics/CyclomaticComplexity:
37
+ Exclude:
38
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
39
+
40
+ Metrics/LineLength:
41
+ Exclude:
42
+ - 'spec/**/*'
43
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
44
+ Max: 140
45
+
46
+ Metrics/MethodLength:
47
+ Exclude:
48
+ - 'spec/**/*'
49
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
50
+ Max: 20
51
+
52
+ Metrics/ModuleLength:
53
+ Exclude:
54
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
55
+
56
+ Metrics/PerceivedComplexity:
57
+ Exclude:
58
+ - 'lib/phi_attrs/phi_record.rb' # TODO: RUBOCOP Cleanup exclusion
59
+
60
+ Naming/PredicateName:
61
+ Enabled: false
62
+
63
+ Rails/DynamicFindBy:
64
+ Exclude:
65
+ - 'spec/spec_helper.rb' # TODO: RUBOCOP Cleanup exclusion
66
+
67
+ Style/BracesAroundHashParameters:
68
+ Enabled: false
69
+
70
+ Style/ClassVars:
71
+ Enabled: false
72
+
73
+ Style/CommentedKeyword:
74
+ Exclude:
75
+ - 'spec/**/*'
76
+
77
+ Style/ConditionalAssignment:
78
+ Enabled: false
79
+
80
+ Style/EmptyMethod:
81
+ EnforcedStyle: expanded
82
+
83
+ Style/SymbolArray:
84
+ EnforcedStyle: brackets
85
+
86
+ Style/RedundantReturn:
87
+ Enabled: false
88
+
89
+ Style/WordArray:
90
+ MinSize: 4
@@ -1,5 +1,8 @@
1
1
  sudo: false
2
2
  language: ruby
3
+ cache: bundler
3
4
  rvm:
4
5
  - 2.4.2
5
- before_install: gem install bundler -v 1.16.1
6
+ before_install:
7
+ - gem update --system
8
+ - gem install bundler
data/Appraisals CHANGED
@@ -1,4 +1,6 @@
1
- appraise 'rails-5.0' do
2
- gem 'rails', '5.0.0'
1
+ # frozen_string_literal: true
2
+
3
+ appraise 'rails-5.1' do
4
+ gem 'rails', '5.1.3'
3
5
  gem 'tzinfo-data'
4
6
  end
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+ ### Added
9
+ - Added documentation for CHANGELOG to README
10
+
11
+ ## [v0.1.4] - 2018-07-05
12
+ ## [v0.1.3] - 2018-07-05
13
+ ## [v0.1.2] - 2018-07-05
14
+ ## [v0.1.1] - 2018-07-05
15
+
16
+ ## [v0.1.0] - 2018-07-04
17
+ Initial release
@@ -0,0 +1,15 @@
1
+ DISCLAIMER
2
+ ==========
3
+
4
+ While access logging is part of maintaining a HIPAA compliant application, there are many requirements for building a HIPAA secure application which are not addressed by `phi_attrs`, and as such use of `phi_attrs` on its own does not ensure HIPAA Compliance. As such, this software is provided on an "as-is" basis, and Apsis Labs, LLP makes no warranties or assurances with regards to the HIPAA compliance of any application which makes use of `phi_attrs`.
5
+
6
+ For further reading on how to ensure your application meets the HIPAA security standards, review the HHS Security Series Technical Safeguards and the Summary of the HIPAA Security Rule, in addition to consulting your compliance and legal counsel.
7
+
8
+ Apsis Labs, LLP is not a law firm and does not provide legal advice. The information in this software does not constitute legal advice, nor does usage of this software create an attorney-client relationship.
9
+
10
+ Apsis Labs, LLP is not a HIPAA covered entity, and usage of this software does not create a business associate relationship, nor does it enact a business associate agreement.
11
+
12
+ ---
13
+
14
+ 1. HHS Security Series Technical Safeguards: https://www.hhs.gov/sites/default/files/ocr/privacy/hipaa/administrative/securityrule/techsafeguards.pdf
15
+ 2. Summary of the HIPAA Security Rule: https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:2.5.1-alpine
1
+ FROM ruby:2.5.3-alpine3.8
2
2
  MAINTAINER wyatt@apsis.io
3
3
 
4
4
  RUN apk add --no-cache --update \
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 Wyatt Kirby
3
+ Copyright (c) 2018 Apsis Labs, LLP
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,6 +1,24 @@
1
- # PhiAttrs
1
+ # phi_attrs [![Gem Version](https://badge.fury.io/rb/phi_attrs.svg)](https://badge.fury.io/rb/phi_attrs) [![Build Status](https://travis-ci.org/apsislabs/phi_attrs.svg?branch=master)](https://travis-ci.org/apsislabs/phi_attrs)
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/phi_attrs.svg)](https://badge.fury.io/rb/phi_attrs) [![Build Status](https://travis-ci.org/apsislabs/phi_attrs.svg?branch=master)](https://travis-ci.org/apsislabs/phi_attrs)
3
+ HIPAA compliant PHI access logging for Ruby on Rails.
4
+
5
+ According to [HIPAA Security Rule](https://www.hhs.gov/hipaa/for-professionals/security/index.html) `§ 164.312(b)`, HIPAA covered entities are required to:
6
+
7
+ > Implement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use electronic protected health information.
8
+
9
+ The `phi_attrs` gem is intended to assist with implementing logging to comply with the access log requirements of `§ 164.308(a)(1)(ii)(D)`:
10
+
11
+ > Information system activity review (Required). Implement procedures to regularly review records of information system activity, such as audit logs, access reports, and security incident tracking reports.
12
+
13
+ To do so, `phi_attrs` extends `ActiveRecord` models by adding automated logging and explicit access control methods. The access control mechanism creates a separate `phi_access_log`.
14
+
15
+ **Please Note:** while `phi_attrs` helps facilitate access logging, it still requires due diligence by developers, both in ensuring that models and attributes which store PHI are flagged with `phi_model` and that calls to `allow_phi!` properly attribute both a _unique_ identifier and an explicit reason for PHI access.
16
+
17
+ **Please Note:** there are other aspects of building a HIPAA secure application which are not addressed by `phi_attrs`, and as such _use of `phi_attrs` on its own does not ensure HIPAA Compliance_. For further reading on how to ensure your application meets the HIPAA security standards, review the [HHS Security Series Technical Safeguards](https://www.hhs.gov/sites/default/files/ocr/privacy/hipaa/administrative/securityrule/techsafeguards.pdf) and [Summary of the HIPAA Security Rule](https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html), in addition to consulting your compliance and legal counsel.
18
+
19
+ ## Stability
20
+
21
+ All versions of this project below `1.0.0` should be considered unstable beta software. Even minor-version updates may introduce breaking changes to the public API at this stage. We strongly suggest that you lock the installed version in your Gemfile to avoid unintended breaking updates.
4
22
 
5
23
  ## Installation
6
24
 
@@ -18,6 +36,20 @@ Or install it yourself as:
18
36
 
19
37
  $ gem install phi_attrs
20
38
 
39
+ ## Initialize
40
+
41
+ Create an initializer to configure the PHI log file location.
42
+
43
+ Example:
44
+
45
+ `config/initializers/phi_attrs.rb`
46
+
47
+ ```ruby
48
+ PhiAttrs.configure do |conf|
49
+ conf.log_path = Rails.root.join("log", "phi_access_#{Rails.env}.log")
50
+ end
51
+ ```
52
+
21
53
  ## Usage
22
54
 
23
55
  ```ruby
@@ -33,19 +65,118 @@ class PatientInfo < ActiveRecord::Base
33
65
  end
34
66
  ```
35
67
 
36
- Access is granted on a model level:
68
+ Access is granted on a instance level:
37
69
 
38
70
  ```ruby
39
- info = new PatientInfo
71
+ info = PatientInfo.new
40
72
  info.allow_phi!("allowed_user@example.com", "Customer Service")
41
73
  ```
42
74
 
75
+ *When using on an instance if you find it in a second place you will need to call allow_phi! again.*
76
+
43
77
  or a class:
44
78
 
45
79
  ```ruby
46
80
  PatientInfo.allow_phi!("allowed_user@example.com", "Customer Service")
47
81
  ```
48
82
 
83
+ As of version `0.1.5`, a block syntax is available. As above, this is available on both class and instance levels.
84
+
85
+ Note the lack of a `!` at the end. These methods should not be used alongside the mutating (bang) methods! We recommend using the block syntax for tighter control.
86
+
87
+ ```ruby
88
+ patient = PatientInfo.find(params[:id])
89
+ patient.allow_phi('allowed_user@example.com', 'Display Customer Data') do
90
+ @data = patient.to_json
91
+ end # Access no longer allowed beyond this point
92
+ ```
93
+
94
+ or a block on a class:
95
+
96
+ ```ruby
97
+ PatientInfo.allow_phi('allowed_user@example.com', 'Display Customer Data') do
98
+ @data = PatientInfo.find(params[:id]).to_json
99
+ end # Access no longer allowed beyond this point
100
+ ```
101
+
102
+ ### Controlling What Is PHI
103
+
104
+ When you include `phi_model` on your active record all fields except the id will be considered PHI.
105
+
106
+ To remove fields from PHI tracking use `exclude_from_phi`:
107
+
108
+ ```ruby
109
+ # created_at and updated_at will be accessible as normal
110
+ class PatientInfo < ActiveRecord::Base
111
+ phi_model
112
+
113
+ exclude_from_phi :created_at, :updated_at
114
+ end
115
+ ```
116
+
117
+ To add a method as PHI use `include_in_phi`. Include takes precedence over exclude so a method that appears in both will be considered PHI.
118
+
119
+ ```ruby
120
+ # birthday and node will throw PHIExceptions if accessed without permission
121
+ class PatientInfo < ActiveRecord::Base
122
+ phi_model
123
+
124
+ include_in_phi :birthday, :note
125
+
126
+ def birthday
127
+ Time.current
128
+ end
129
+
130
+ attr_accessor :note
131
+ end
132
+ ```
133
+
134
+ #### Example Usage
135
+
136
+ Example of `exclude_from_phi` and `include_in_phi` with inheritance.
137
+
138
+ ```ruby
139
+ class PatientInfo < ActiveRecord::Base
140
+ phi_model
141
+ end
142
+
143
+ pi = PatientInfo.new(first_name: "Ash", last_name: "Ketchum")
144
+ pi.created_at
145
+ # PHIAccessException!
146
+ pi.last_name
147
+ # PHIAccessException!
148
+ pi.allow_phi "Ash", "Testing PHI Attrs" { pi.last_name }
149
+ # "Ketchum"
150
+ ```
151
+
152
+ ```ruby
153
+ class PatientInfoTwo < PatientInfo
154
+ exclude_from_phi :created_at
155
+ end
156
+
157
+ pi = PatientInfoTwo.new(first_name: "Ash", last_name: "Ketchum")
158
+ pi.created_at
159
+ # current time
160
+ pi.last_name
161
+ # PHIAccessException!
162
+ pi.allow_phi "Ash", "Testing PHI Attrs" { pi.last_name }
163
+ # "Ketchum"
164
+ ```
165
+
166
+ ```ruby
167
+ class PatientInfoThree < PatientInfoTwo
168
+ include_in_phi :created_at # Changed our mind
169
+ end
170
+
171
+ pi = PatientInfoThree.new(first_name: "Ash", last_name: "Ketchum")
172
+ pi.created_at
173
+ # PHIAccessException!
174
+ pi.last_name
175
+ # PHIAccessException!
176
+ pi.allow_phi "Ash", "Testing PHI Attrs" { pi.last_name }
177
+ # "Ketchum"
178
+ ```
179
+
49
180
  ### Extending PHI Access
50
181
 
51
182
  Sometimes you'll have a single mental model that is composed of several `ActiveRecord` models joined by association. In this case, instead of calling `allow_phi!` on all joined models, we expose a shorthand of extending PHI access to related models.
@@ -68,27 +199,260 @@ patient.allow_phi!('user@example.com', 'reason')
68
199
  patient.patient_info.first_name
69
200
  ```
70
201
 
71
- **NOTE:** This is not intended to be used on all relationships! Only those where you intend to grant implicit access based on access to another model. In this use case, we assume that allowed access to `Patient` implies allowed access to `PatientInfo`, and therefore does not require an additional `allow_phi!` check.
202
+ **NOTE:** This is not intended to be used on all relationships! Only those where you intend to grant implicit access based on access to another model. In this use case, we assume that allowed access to `Patient` implies allowed access to `PatientInfo`, and therefore does not require an additional `allow_phi!` check. There are no guaranteed safeguards against circular `extend_phi_access` calls!
203
+
204
+ ### Check If PHI Access Is Allowed
205
+
206
+ To check if PHI is allowed for a particular instance of a class call `phi_allowed?`.
207
+
208
+ ```ruby
209
+ patient = Patient.new
210
+ patient.phi_allowed? # => false
211
+
212
+ patient.allow_phi('user@example.com', 'reason') do
213
+ patient.phi_allowed? # => true
214
+ end
215
+
216
+ patient.phi_allowed? # => false
217
+
218
+ patient.allow_phi!('user@example.com', 'reason')
219
+ patient.phi_allowed? # => true
220
+ ```
221
+
222
+ This also works if access was granted at the class level:
223
+
224
+ ```ruby
225
+ patient = Patient.new
226
+ patient.phi_allowed? # => false
227
+ Patient.allow_phi!('user@example.com', 'reason')
228
+ patient.phi_allowed? # => true
229
+ ```
230
+
231
+ There is also a `phi_allowed?` check available to see at the class level.
232
+
233
+ ```ruby
234
+ Patient.phi_allowed? # => false
235
+ Patient.allow_phi!('user@example.com', 'reason')
236
+ Patient.phi_allowed? # => true
237
+ ```
238
+
239
+ **Note that any instance level access grants will not change class level access:**
240
+
241
+ ```ruby
242
+ patient = Patient.new
243
+
244
+ patient.phi_allowed? # => false
245
+ Patient.phi_allowed? # => false
246
+
247
+ patient.allow_phi!('user@example.com', 'reason')
248
+
249
+ patient.phi_allowed? # => true
250
+ Patient.phi_allowed? # => false
251
+ ```
252
+
253
+
254
+ ### Revoking PHI Access
255
+
256
+ You can remove access to PHI with `disallow_phi!`. Each `disallow_phi!` call removes all access granted by `allow_phi!` at that level (class or instance).
257
+
258
+ At a class level:
259
+
260
+ ```ruby
261
+ Patient.disallow_phi!
262
+ ```
263
+
264
+ Or at a instance level:
265
+
266
+ ```ruby
267
+ patient.disallow_phi!
268
+ ```
269
+
270
+ * *If access is granted at both class and instance level you will need to call `disallow_phi!` twice, once for the instance and once for the class.*
271
+
272
+ There is also a block syntax of `disallow_phi` for temporary suppression phi access to the class or instance level
273
+
274
+ ```ruby
275
+ patient = PatientInfo.find(params[:id])
276
+ patient.allow_phi!('allowed_user@example.com', 'Display Patient Data')
277
+ patient.diallow_phi do
278
+ @data = patient.to_json # PHIAccessException
279
+ end # Access is allowed again beyond this point
280
+ ```
281
+
282
+ or a block level on a class:
283
+
284
+ ```ruby
285
+ PatientInfo.allow_phi!('allowed_user@example.com', 'Display Patient Data')
286
+ PatientInfo.diallow_phi do
287
+ @data = PatientInfo.find(params[:id]).to_json # PHIAccessException
288
+ end # Access is allowed again beyond this point
289
+ ```
290
+
291
+ * *Reminder instance level `phi_allow` will take precedent over a class level `disallow_phi`*
292
+
293
+ ### Manual PHI Access Logging
294
+
295
+ If you aren't using `phi_record` you can still use `phi_attrs` to manually log phi access in your application. Where ever you are granting PHI access call:
296
+
297
+ ```ruby
298
+ user = 'user@example.com'
299
+ message = 'accessed list of all patients'
300
+ PhiAttrs.log_phi_access(user, message)
301
+ ```
302
+
303
+ ### Reason Translations
304
+
305
+ It can get cumbersome to pass around PHI Access reasons. PHI Attrs allows you to
306
+ use your translations file to keep your code dry. If your translation file
307
+ contains a reason for the combination of controller, action, and model you can
308
+ skip passing `reason`:
309
+
310
+ ```ruby
311
+ module Admin
312
+ class PatientDashboardController < ApplicationController
313
+ def expelliarmus
314
+ patient_info.allow_phi(current_user) do
315
+ # reason tries to use `phi.admin.patient_dashbaord.expelliarmus.patient_info`
316
+ end
317
+ end
318
+
319
+ def leviosa
320
+ patient_info.allow_phi(current_user) do
321
+ # reason tries to use `phi.admin.patient_dashbaord.expelliarmus.patient_info`
322
+ end
323
+ end
324
+ end
325
+ end
326
+ ```
327
+
328
+ The following `en.yml` file would work:
329
+
330
+ ```yml
331
+ en:
332
+ phi:
333
+ admin:
334
+ patient_dashboard:
335
+ expelliarmus:
336
+ patient_info: "Patient Disarmed"
337
+ leviosa:
338
+ patient_info: "Patient Levitated"
339
+ ```
340
+
341
+ If you have a typo in your en.yml file or you choose not to provide a translation
342
+ for your phi reasons your code will fail with an ArgumentError. To assist you in
343
+ debugging PHI Attrs will print a `:warn` message with the expected location for
344
+ the missing translation.
345
+
346
+ If you would like to change from `phi` to a custom location you can set the path in your initializer.
347
+
348
+ ```ruby
349
+ PhiAttrs.configure do |conf|
350
+ conf.translation_prefix = 'custom_prefix'
351
+ end
352
+ ```
353
+
354
+ ### Default User
355
+
356
+ Passing around the current user can clutter your code. PHI Attrs allows you to
357
+ configure a controller method that will be called to get the currently logged in
358
+ user:
359
+
360
+ #### `config/initializers/phi_attrs.rb`
361
+
362
+ ```ruby
363
+ PhiAttrs.configure do |conf|
364
+ conf.current_user_method = :user_email
365
+ end
366
+ ```
367
+
368
+ #### `app/controllers/home_controller.rb`
369
+
370
+ ```ruby
371
+ class ApplicationController < ActionController::Base
372
+ private
373
+
374
+ def user_email
375
+ current_user&.email
376
+ end
377
+ end
378
+ ```
379
+
380
+ With the above code, any call to `allow_phi` (that starts in a controller
381
+ derived from ApplicationController) will use the result of `user_email` as the
382
+ user argument of `allow_phi`.
383
+
384
+ Note that if you have a default user, but choose not to use translations for
385
+ reasons you'll have to pass `nil` as the user:
386
+
387
+ ```ruby
388
+ person_phi.allow_phi(nil, "Because I felt like looking at PHI") do
389
+ # Allows PHI
390
+ end
391
+ ```
392
+
393
+ ## Best Practices
394
+
395
+ * Mix and matching `instance`, `class` and `block` syntaxes for allowing/denying PHI is not recommended.
396
+ * Sticking with one style in your application will make it easier to understand what access is granted and where.
72
397
 
73
398
  ## Development
74
399
 
75
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
400
+ It is recommended to use the provided `docker-compose` environment for development to help ensure dependency consistency and code isolation from other projects you may be working on.
401
+
402
+ ### Begin
403
+
404
+ $ docker-compose up
405
+ $ bin/ssh_to_container
406
+
407
+ ### Tests
408
+
409
+ Tests are written using [RSpec](http://rspec.info/) and are setup to use [Appraisal](https://github.com/thoughtbot/appraisal) to run tests over multiple rails versions.
410
+
411
+ $ bin/run_tests
412
+ or for individual tests:
413
+ $ bin/ssh_to_container
414
+ $ bundle exec appraisal rspec spec/path/to/spec.rb
415
+
416
+ ### Console
417
+
418
+ An interactive prompt that will allow you to experiment with the gem.
76
419
 
77
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
420
+ $ bin/ssh_to_container
421
+ $ bin/console
78
422
 
79
- ### Docker
423
+ ### Local Install
80
424
 
81
- - `docker-compose up`
82
- - `bin/ssh_to_container`
425
+ Run `bin/setup` to install dependencies. Then, run `bundle exec appraisal rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
83
426
 
84
- ## Testing
427
+ To install this gem onto your local machine, run `bundle exec rake install`.
428
+
429
+ ### Versioning
430
+
431
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
85
432
 
86
- $ bundle exec appraisal rspec spec/phi_attrs_spec.rb
87
433
 
88
434
  ## Contributing
89
435
 
90
- Bug reports and pull requests are welcome on GitHub at https://github.com/wkirby/phi_attrs.
436
+ Bug reports and pull requests are welcome on GitHub at https://github.com/apsislabs/phi_attrs.
437
+
438
+ Any PRs should be accompanied with documentation in `README.md`, and changes documented in [`CHANGELOG.md`](https://keepachangelog.com/).
91
439
 
92
440
  ## License
93
441
 
94
442
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
443
+
444
+ ## Legal Disclaimer
445
+
446
+ Apsis Labs, LLP is not a law firm and does not provide legal advice. The information in this repo and software does not constitute legal advice, nor does usage of this software create an attorney-client relationship.
447
+
448
+ Apsis Labs, LLP is not a HIPAA covered entity, and usage of this software does not create a business associate relationship, nor does it enact a business associate agreement.
449
+
450
+ [Full Disclaimer](./DISCLAIMER.txt)
451
+
452
+ ---
453
+
454
+ # Built by Apsis
455
+
456
+ [![apsis](https://s3-us-west-2.amazonaws.com/apsiscdn/apsis.png)](https://www.apsis.io)
457
+
458
+ `phi_attrs` was built by Apsis Labs. We love sharing what we build! Check out our [other libraries on Github](https://github.com/apsislabs), and if you like our work you can [hire us](https://www.apsis.io/work-with-us/) to build your vision.