-
Notifications
You must be signed in to change notification settings - Fork 0
/
datarelatedstuff.Rmd
1063 lines (651 loc) · 57.1 KB
/
datarelatedstuff.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Data Breach Notification Laws"
author: "Dean Gladish"
date: "Last Updated August 15, 2019"
output:
rmdformats::readthedown:
self_contained: true
thumbnails: true
lightbox: true
gallery: false
highlight: tango
css: custom.css
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(ggthemes)
library(shinyWidgets)
library(shinythemes)
library(shinythemes)
library(knitr)
```
```{r Load and wrangle data, message = FALSE, warning = FALSE, echo = FALSE}
library(readr)
statesData <- read_csv("statesSimplified.csv")
# Remove unneeded columns
#statesData <- subset(statesData, select = c(1:14))
statesData <- statesData
# Replace all NA values with the integer 0
library(ggplot2)
statesData$placeHolderColumn <- c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
statesDataSave <- statesData
## This part makes the data easy for graphing.
# Remove textual elements from the notify ag, notify CRA and timeFrame columns
statesData$thresholdNotifyAG <- ifelse(is.na(as.integer(statesData$thresholdNotifyAG)) == TRUE, 0, statesData$thresholdNotifyAG)
statesData$thresholdNotifyAG <- as.integer(statesData$thresholdNotifyAG)
statesData$thresholdNotifyCRA <- ifelse(is.na(as.integer(statesData$thresholdNotifyCRA)) == TRUE, 0, statesData$thresholdNotifyCRA)
statesData$thresholdNotifyCRA <- as.integer(statesData$thresholdNotifyCRA)
statesData$timeFrame <- ifelse(is.na(as.integer(statesData$timeFrame)) == TRUE, 0, statesData$timeFrame)
statesData$timeFrame <- as.integer(statesData$timeFrame)
# Standardize the labels
statesData$serviceProvidersNotifyCustomers <- ifelse(str_detect(statesData$serviceProvidersNotifyCustomers, "Immediately") == TRUE, TRUE, FALSE)
statesData$serviceProvidersNotifyCustomers[is.na(statesData$serviceProvidersNotifyCustomers)] <- FALSE
#statesData[is.na(statesData)] <- 0
```
***
## _State Filter_
***
__*<span style="color:gray">__Filter States by the Following Criteria:__</span>*__
```{r Shiny App for Data Breach Laws, echo = FALSE}
library(shiny)
# CSS Code for making the buttons look better
css <-
"
a#more-apps-by-dean {
display: none;
}
body {
background: #fff;
}
.container {
margin: 0;
padding: 0px;
}
.green {
background: green;
}
#expr-container .selectize-input {
font-size: 12px;
line-height: 12px;
}
#expr-container .selectize-dropdown {
font-size: 12px;
line-height: 12px;
}
#expr-container .selectize-dropdown-content {
max-height: 225px;
padding: 0;
}
#expr-container .selectize-dropdown-content .option {
border-bottom: 0px dotted #ccc;
}
#submitExpr {
font-weight: bold;
font-size: 12px;
padding: 0px 0px;
}
#helpText {
font-size: 12px;
}
#btn {
font-size: 12px;
}
"
axis_vars <- c(
"With DOB as PI" = "hasDOBasPI",
"With Online (not financial) account information as PI" = "hasOnlineAccountsasPI",
"\"access\" instead of acquisition" = "onlyRequiresAccess",
"Harm analysis allowed or not" = "harmAnalysisAllowed",
"No Private Cause of Action" = "governmentInvolvementRequired",
"Reporting threshold: number of individuals to notify Attorney General" = "thresholdNotifyAG",
"Reporting threshold: number of individuals to notify consumer reporting agency" = "thresholdNotifyCRA",
"Time Frame within which to notify" = "timeFrame",
"Requirement for \"service provider\" to report to data owner immediately or not" = "serviceProvidersNotifyCustomers",
"Harm analysis required or not" = "harmAnalysisRequired",
"With Financial (vs. online) account as PI" = "financialAccountInformationisPI",
"Modified its Laws in 2018-2019" = "modifiedLawsin2018or2019"
)
library(stringr)
listServiceProviders = list("as soon as possible" = toString(which(statesData$asSoonAsPossible)),
"as soon as reasonably practicable after discovery" = toString(which(statesData$asSoonAsReasonablyPracticableFollowingDiscovery)),
"within 24 hours" = toString(which(statesData$within24Hours)),
"immediately after discovery if PI is acquired by an unauthorized person" = toString(which(statesData$immediatelyAfterDiscoveryifPIAcquiredbyUnauthorizedPerson)),
"immediately after discovery if misuse of PI is likely to occur" = toString(which(statesData$immediatelyAfterDiscoveryIfPIMisuseisLikelyToOccur)),
"immediately after determination or reasonable belief that information has been breached" = toString(which(statesData$immediatelyAfterDeterminationorReasonableBeliefthatInformationhasBeenBreached)),
"immediately after discovery if PI was included in the breached data" = toString(which(statesData$immediatelyAfterDiscoveryifPIWasIncludedinBreachedData)),
"immediately after discovery, consistent with the legitimate needs of law enforcement" = toString(which(statesData$immediatelyAfterDiscoveryConsistentWithLegitimateNeedsofLawEnforcement)),
"immediately after discovery (possibly conditional)" = toString(which(statesData$immediatelyAfterDiscovery)),
"as soon as reasonably practicable and without unreasonable delay if Pi is likely to be misused" = toString(which(statesData$asSoonAsReasonablyPracticableandWithoutUnreasonableDelayifPIisLikelyToBeMisused)),
"as soon as reasonably practicable and without unreasonable delay if PI is acquired by an unauthorized person" = toString(which(statesData$asSoonAsReasonablyPracticableandWithoutUnreasonableDelayifPIisAcquiredbyUnauthorizedPerson)),
"in the most expedient time possible but no later than 45 calendar days after discovery" = toString(which(statesData$inMostExpedientTimePossibleNoLaterThan45CalendarDays)),
"in an expeditious manner if acquisition by an unauthorized person occurred and is reasonably believed to cause a material risk of identity theft or fraud" = toString(which(statesData$inAnExpeditiousMannerifAcquisitionbyUnauthorizedPersonExistsandisReasonablyBelievedtoCauseaMaterialRiskofIdentityTheftorFraud)),
"as soon as practicable if the service provider has not entered into a contract" = toString(which(statesData$asSoonAsPracticableifServiceProviderhasnotenteredintoaContract)),
"in the most expedient time possible after discovery" = toString(which(statesData$inMostExpedientTimePossibleAfterDiscovery))
)
#sidebarLayout
sidebarLayout(
#sidebarPanel
inputPanel(
#helpText(""),
shinyjs::useShinyjs(),
tags$style(css),
div(id = "btn",
checkboxGroupInput("checkGroup", label = h3("Service Providers shall notify customers"),
choices = listServiceProviders,
selected = 1, inline = FALSE),
hr(),
fluidRow(column(3, verbatimTextOutput("value")))
),
selectInput("var",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var2",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var3",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var4",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var5",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var6",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var7",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var8",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
selectInput("var9",
label = "",
choices = list(" " = toString(which(statesData$placeHolderColumn)),
"Personal Information" = c("Date of Birth alone is PI" = toString(which(statesData$hasDOBasPI)), "Information about Online Accounts is PI" = toString(which(statesData$hasOnlineAccountsasPI))),
"Harm Analysis" = c("Risk-of-harm Analysis is Allowed" = toString(which(statesData$harmAnalysisAllowed)),"Harm Analysis is Required" = toString(which(statesData$harmAnalysisRequired))),
"Service Providers need to notify customers immediately" = toString(which(statesData$serviceProvidersNotifyCustomers)),
"Access only (instead of acquisition as well) is a breach of security" = toString(which(statesData$onlyRequiresAccess)),
"A Private Cause of Action is not Permitted" = toString(which(statesData$governmentInvolvementRequired)),
"Information about Financial Accounts is PI" = toString(which(statesData$financialAccountInformationisPI)),
"Attorney General needs to be notified in some way" = toString(which(statesData$notifyAGRequired)),
"Modified its laws in 2018 or 2019" = toString(which(statesData$modifiedLawsin2018or2019))),
selected = "all states"),
sliderInput("range",
label = "Threshold to Notify the AG",
min = min(statesData$thresholdNotifyAG), max = max(statesData$thresholdNotifyAG), value = c(min(statesData$thresholdNotifyAG), max(statesData$thresholdNotifyAG)), step = NULL)
,
sliderInput("range2",
label = "Threshold to Notify some Consumer Reporting Agencies",
min = min(statesData$thresholdNotifyCRA), max = max(statesData$thresholdNotifyCRA), value = c(min(statesData$thresholdNotifyCRA), max(statesData$thresholdNotifyCRA)), step = NULL)
,
sliderInput("range3",
label = "Time Frame for notifying affected individuals:",
min = min(statesData$timeFrame), max = max(statesData$timeFrame), value = c(min(statesData$timeFrame), max(statesData$timeFrame)), step = NULL)
),
mainPanel(
textOutput("selected_var"),
textOutput("min_max")
)
)
renderUI({
default <- 1:54
if (length(input$checkGroup) != 0) {
for (i in 1:length(input$checkGroup)) {
default <- intersect(default, as.integer(gsub(" ", "", as.integer(unlist(strsplit(input$checkGroup[i], ", "))))))
}
}
HTML(str_replace_all(toString(
paste(toString(statesData[
Reduce(intersect, list(
default,
as.integer(unlist(strsplit(input$var9, split = ", "))),
as.integer(unlist(strsplit(input$var8, split = ", "))),
as.integer(unlist(strsplit(input$var7, split = ", "))),
as.integer(unlist(strsplit(input$var6, split = ", "))),
as.integer(unlist(strsplit(input$var5, split = ", "))),
as.integer(unlist(strsplit(input$var4, split = ", "))),
as.integer(unlist(strsplit(input$var3, split = ", "))),
as.integer(unlist(strsplit(input$var2, split = ", "))),
as.integer(unlist(strsplit(input$var, split = ", "))),
which(statesData$timeFrame >= input$range3[1]),
which(statesData$timeFrame <= input$range3[2]),
which(statesData$thresholdNotifyAG >= input$range[1]),
which(statesData$thresholdNotifyAG <= input$range[2]),
which(statesData$thresholdNotifyCRA >= input$range2[1]),
which(statesData$thresholdNotifyCRA <= input$range2[2])
))
,]$State))
)
, ", ", "<br/>"))
})
#-------------------------------------------------------------------------------------------
```
***
## _Reporting Thresholds and Time-frames for all States_
***
```{r, message = F, warning = F, echo = F}
axis_vars_graph2 <- c(
"Reporting threshold: number of individuals to notify Attorney General" = "thresholdNotifyAG",
"Reporting threshold: number of individuals to notify consumer reporting agencies" = "thresholdNotifyCRA",
"Time Frame within which to notify affected individuals" = "timeFrame"
)
fluidRow(
shinyjs::useShinyjs(),
tags$style(css),
div(id = "expr-container",
selectInput("yvar", label = "X-axis variable", choices = axis_vars_graph2,
selected = "Cost_of_Revenue", width = "600px")
)
)
# This part is not the best way to code this. How else can this be done (for example, by using aes_string instead of aes)?
renderPlot({
if (input$yvar == "thresholdNotifyAG") {
ggplot(statesData) +
geom_bar(mapping = aes(x = reorder(State, thresholdNotifyAG), y = thresholdNotifyAG), stat = "identity") +
xlab("State") +
theme(panel.background = element_blank()) +
theme(axis.ticks = element_blank()) +
labs(title = "States and Threshold", y = "To Notify Attorney General") +
geom_hline(yintercept = seq(0, 1000, by = 250), colour = "gray", size = 1, linetype = 21) +
coord_flip() +
theme(axis.text.y = element_text(size = 7))
}
else if (input$yvar == "thresholdNotifyCRA") {
ggplot(statesData) +
geom_bar(mapping = aes(x = reorder(State, thresholdNotifyCRA), y = thresholdNotifyCRA), stat = "identity") +
xlab("State") +
theme(panel.background = element_blank()) +
theme(axis.ticks = element_blank()) +
labs(title = "States and Threshold", y = "To Notify Consumer Reporting Agencies") +
geom_hline(yintercept = seq(0, 10000, by = 1000), colour = "gray", size = 1, linetype = 21) +
coord_flip() +
theme(axis.text.y = element_text(size = 7))
}
else if (input$yvar == "timeFrame") {
ggplot(statesData) +
geom_bar(mapping = aes(x = reorder(State, timeFrame), y = timeFrame), stat = "identity") +
xlab("State") +
theme(panel.background = element_blank()) +
theme(axis.ticks = element_blank()) +
labs(title = "States and Threshold", y = "How Long to Disclose to Affected Individuals") +
geom_hline(yintercept = seq(0, 100, by = 10), colour = "gray", size = 1, linetype = 21) +
coord_flip() +
theme(axis.text.y = element_text(size = 7))
}
})
```
***
## _Proportions of States which have Enacted Regulations_
***
```{r, message = F, warning = F, echo = F}
axis_vars_graphProportions <- c(
"Date of Birth only is Considered to be Personal Information" = "hasDOBasPI",
"Information about Online Accounts is Personal Information" = "hasOnlineAccountsasPI",
"Definition of Data Breach is access (instead of requiring acquisition)" = "onlyRequiresAccess",
"No Private Cause of Action" = "governmentInvolvementRequired",
"Service Providers shall Notify customers immediately" = "serviceProvidersNotifyCustomers",
"A Risk-of-harm Analysis is Allowed" = "harmAnalysisAllowed",
"Risk-of-harm Analysis is Required" = "harmAnalysisRequired",
"Information related to Financial Accounts is Personal Information" = "financialAccountInformationisPI",
"Attorney General must be Notified" = "notifyAGRequired",
"Modified Laws in 2018 or 2019" = "modifiedLawsin2018or2019"
)
fluidRow(
shinyjs::useShinyjs(),
tags$style(css),
div(id = "expr-container",
selectInput("zvar", label = "Variable", choices = axis_vars_graphProportions,
selected = "Cost_of_Revenue", width = "600px")
)
)
# Again, this part is not the best way to code this. How else can this be done without hardcoding all the graphs?
renderPlot({
if (input$zvar == "modifiedLawsin2018or2019"){
ggplot(data = statesData, mapping = aes(x = modifiedLawsin2018or2019, fill = modifiedLawsin2018or2019)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Did not modify laws 2018-2019", "Modified laws 2018-2019"))
}
else if (input$zvar == "hasDOBasPI") {
ggplot(data = statesData, mapping = aes(x = hasDOBasPI, fill = hasDOBasPI)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Date of Birth alone is not PI", "Date of Birth alone is PI"))
}
else if (input$zvar == "hasOnlineAccountsasPI") {
ggplot(data = statesData, mapping = aes(x = hasOnlineAccountsasPI, fill = hasOnlineAccountsasPI)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Online Accounts are not PI", "Online Accounts are PI"))
}
else if (input$zvar == "onlyRequiresAccess") {
ggplot(data = statesData, mapping = aes(x = onlyRequiresAccess, fill = onlyRequiresAccess)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Acquisition", "Access"))
}
else if (input$zvar == "harmAnalysisAllowed") {
ggplot(data = statesData, mapping = aes(x = harmAnalysisAllowed, fill = harmAnalysisAllowed)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Harm Analysis Not Allowed", "Harm Analysis Allowed"))
}
else if (input$zvar == "governmentInvolvementRequired") {
ggplot(data = statesData, mapping = aes(x = governmentInvolvementRequired, fill = governmentInvolvementRequired)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("A Private Cause of Action is Permitted", "No Private Cause of Action"))
}
else if (input$zvar == "serviceProvidersNotifyCustomers") {
ggplot(data = statesData, mapping = aes(x = serviceProvidersNotifyCustomers, fill = serviceProvidersNotifyCustomers)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Service Providers do not need to immediately notify", "Service Providers need to immediately notify"))
}
else if (input$zvar == "harmAnalysisRequired") {
ggplot(data = statesData, mapping = aes(x = harmAnalysisRequired, fill = harmAnalysisRequired)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Harm Analysis is Not Required", "Harm Analysis is Required"))
}
else if (input$zvar == "financialAccountInformationisPI") {
ggplot(data = statesData, mapping = aes(x = financialAccountInformationisPI, fill = financialAccountInformationisPI)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("Information leading to Financial Accounts is Not PI", "Information leading to Financial Accounts is PI"))
}
else if (input$zvar == "notifyAGRequired") {
ggplot(data = statesData, mapping = aes(x = notifyAGRequired, fill = notifyAGRequired)) +
geom_bar() +
labs(title = "Proportion of States", x = "", y = "Number of States") +
theme(panel.background = element_blank()) +
geom_hline(yintercept = seq(0, 50, by = 10), col = "white", lwd = 1) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank()) +
geom_text(aes(label=..count..), stat="count", position = position_stack(), vjust = 1.5, color = "white") +
theme(legend.position = "none") +
scale_x_discrete(limit = c("FALSE", "TRUE"),
labels = c("AG Notification Not Required", "AG Notification Required"))
}
})
```
***
## _Reference Table_
***
An "X" means that the state has that quality.
```{r, message = F, warning = F, echo = F, eval = T}
#The order of these two statements is important
statesDataPresentable <- statesData
statesDataPresentable[6:8][statesDataPresentable[6:8] == 0] <- ""
colnames(statesDataPresentable) <- c("State", "DOB is PI", "Online Accounts are PI", "Access", "No Private Cause of Action", "Notify AG", "Notify CRA", "Time Frame", "SP Notifies Immediately", "Harm Analysis Allowed", "Harm Analysis Required", "Financial Account Information is PI", "Notify AG Required", "Modified 2018-2019", "as soon as possible", "as soon as reasonably practicable after discovery", "within 24 hours", "immediately after discovery if PI is acquired by an unauthorized person", "immediately after discovery if misuse of PI is likely to occur", "immediately after determination or reasonable belief that information has been breached", "immediately after discovery if PI was included in the breached data", "immediately after discovery, consistent with the legitimate needs of law enforcement", "immediately after discovery (possibly conditional)", "as soon as reasonably practicable and without unreasonable delay if Pi is likely to be misused", "as soon as reasonably practicable and without unreasonable delay if PI is acquired by an unauthorized person", "in the most expedient time possible but no later than 45 calendar days after discovery", "in an expeditious manner if acquisition by an unauthorized person occurred and is reasonably believed to cause a material risk of identity theft or fraud", "as soon as practicable if the service provider has not entered into a contract", "in the most expedient time possible after discovery", "Is a State")
statesDataPresentable <- statesDataPresentable[,-grep("Is a State", colnames(statesDataPresentable))]
statesDataPresentable$`Modified 2018-2019` <- ifelse(statesDataPresentable$`Modified 2018-2019` == "TRUE", "X", "")
statesDataPresentable$`DOB is PI` <- ifelse(statesDataPresentable$`DOB is PI` == "TRUE", "X", "")
statesDataPresentable$`Online Accounts are PI` <- ifelse(statesDataPresentable$`Online Accounts are PI` == "TRUE", "X", "")
statesDataPresentable$`Access` <- ifelse(statesDataPresentable$`Access` == "TRUE", "X", "")
statesDataPresentable$`No Private Cause of Action` <- ifelse(statesDataPresentable$`No Private Cause of Action` == "TRUE", "X", "")
statesDataPresentable$`SP Notifies Immediately` <- ifelse(statesDataPresentable$`SP Notifies Immediately` == "TRUE", "X", "")
statesDataPresentable$`Harm Analysis Allowed` <- ifelse(statesDataPresentable$`Harm Analysis Allowed` == "TRUE", "X", "")
statesDataPresentable$`Harm Analysis Required` <- ifelse(statesDataPresentable$`Harm Analysis Required` == "TRUE", "X", "")
statesDataPresentable$`Financial Account Information is PI` <- ifelse(statesDataPresentable$`Financial Account Information is PI` == "TRUE", "X", "")
statesDataPresentable$`Notify AG Required` <- ifelse(statesDataPresentable$`Notify AG Required` == "TRUE", "X", "")
statesDataPresentable[15:29] <- ifelse(statesDataPresentable[15:29] == "TRUE", "X", "")
library(knitr)
library(kableExtra)
statesDataPresentable[1:14] %>% kable() %>% kable_styling() %>% kable_styling(bootstrap_options = c( "scale_down", "hover", "condensed", "responsive", full_width = F), latex_options = c( "scale_down", "hover", "condensed", "responsive", full_width = F), font_size = 12)
```
```{r, eval = T, echo = F}
secondTable <- cbind(statesDataPresentable[1], statesDataPresentable[15:29])
colnames(secondTable)[1] <- "SP Notifies Customers"
secondTable %>% kable() %>% kable_styling() %>% kable_styling(bootstrap_options = c( "scale_down", "hover", "condensed", "responsive", full_width = F), latex_options = c( "scale_down", "hover", "condensed", "responsive", full_width = F), font_size = 12)
# Write this to a .csv file- it's easier to read that way.
write.csv(statesDataPresentable, file = "statesDataClean.csv")
```
***
## _Discussion_
***
After introducing this table I want to introduce some sources which were the most effective to me. These are Perkins Coie (https://www.perkinscoie.com/en/news-insights/security-breach-notification-chart.html), Baker Law (https://www.bakerlaw.com/files/Uploads/Documents/Data%20Breach%20documents/Data_Breach_Charts.pdf, https://www.bakerlaw.com/BreachNotificationLawMap) and Davis Wright Tremaine (https://www.dwt.com/gcp/state-data-breach-statutes).
<div style="margin-left: 1em;">
Also, to discuss the table above: The Notify AG threshold is describing number of residents; when it's 0 this does not mean that notification is not needed but it just means that a specific number has not been specified. It might indicate that the Attorney General must be notified whenever (and no later than when) notice is provided to the residents of that state. For instance, in Idaho the affected entity, if a public agency, must notify the Attorney General within 24 hours of discovery of a data breach.
If the Notify AG threshold is 1 this indicates that the Attorney General must be notified whenever individuals must be notified, or alternatively whenever there is a breach. The specific laws must be looked at in these cases. For example, in New Jersey the Division of State Police in the Department of Law and Public Safety must be notified regarding a breach prior to notifying customers. In Puerto Rico, the Department of Consumer Affairs must be notified regarding a breach as expeditiously as possible.
</div>
In general, this table is a helpful guide but does not provide specific information. To clarify some of this:
California's time frame (15 business days) only applies to medical-specific data breaches.
While Connecticut's time frame for notifying residents is 90 days, notification must be given to the Connecticut Insurance Department no later than **five calendar days** after the identification of the incident.
Furthermore, when the time frame is 0 this typically means that notification must still be made as expediently as possible. And as a side note, residents generally must be notified within the same time as the Attorney General must be notified.
There are other exceptions, and this list does not include everything:
In Maryland, if notification had been delayed based on determination of law enforcement that such notification would impede a criminal investigation or jeopardize homeland or national security, then the time frame becomes 30 days starting from this re-evaluated decision instead of 45 days starting from discovery of a data breach. Similarly, in the same kind of situation South Dakota's time frame is 30 (not 60) days.
<div style="margin-left: 1em;">
The "Government Involvement Required" variable means that the state does not permit a private cause of action in any circumstance, so this definition seems very strong.
</div>
Since financial information itself should always be Personal Information, the financial account variable refers not to the information itself but to information which could be used to access financial accounts. In New Hampshire for instance, Financial Services account number is considered to be personal information.
<div style="margin-left: 1em;">
About what makes a breach of security, the table has California considering access to be sufficient. While its general breach notification statute refers to acquisition, the state of California regards access as sufficient when it involves medical information.
</div>
Furthermore: the definition regarding service providers (and other third parties which house information for customers) is very strict. That is, phrases like "as soon as practicable", "as soon as possible", "in the most expedient time possible" and "within 24 hours following discovery" are not the same as "immediately."
***
## _Some history (out of date)_
***
During the last decade, the topic of data privacy and security has been increasing in importance as more companies (which are disproportionately hospitals and universities) are breached. Even by January of 2010 over 354 million pieces of personally identifying information (PII) had been compromised and 46 states had enacted legislation requiring companies to protect consumers by notifying them about personal information (PI) breaches.
\ \ \ \ \ \ \ In February of 2005, consumer data broker ChoicePoint (the Company) ended up paying a $10 million fine in restitution to identity theft victims. What happened was that over 145,000 consumers' information (including names, addresses, social security numbers, driver's license numbers, credit reports and other financial information) was sold by ChoicePoint to scammers posing as legitimate businesses who then gained access to this information. And because of disparate laws among states in which only some state laws required notification, the Company chose to initially disclose the breach only to California residents.
\ \ \ \ \ \ \ Recently, more states have enacted legislation requiring notification to consumers, consumer reporting agencies (CRAs) and/or state regulators. Some of these laws allow for a private cause of action (which may require proving actual damages caused by a data breach or notification failure), and some have created additional laws; in particular, Minnesota enacted the "Plastic Card Security Act," which transfers the cost of card-related breaches from financial institutions to retail institutions. Additionally, since there have been more state and federal laws proposed, it's important to have a general understanding.
\ \ \ \ \ \ \ This document is just an overview of requirements, for different states, that some entities (like service providers) need to fulfill to comply with state laws after a data incident or data breach. I wanted to create a document which also gives helpful graphs and which can be updated. This is important because although current state laws generally do not conflict with each other they have vast differences which can make obligations to consumers unclear and ambiguous. With this in mind we are obligated to provide effective support to affected individuals within the current situation.
\ \ \ \ \ \ \ That's the purpose of this document.
***
## _References_
***
This section is just a references section. I used a variety of sources (various law firms, etc.) and the main gist of this sheet is to demonstrate facts about the laws themselves which can be verified independently as well. The following is a list of the actual acts which I have looked at:
* https://privacy.huntonwilliamsblogs.com/wp-content/uploads/sites/18/2018/04/Alabama-Data-Breach-Notification-Act-of-2018.pdf (Act for Alabama)
* https://www.azleg.gov/legtext/53leg/2r/bills/hb2154p.pdf (Arizona)
* https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=201720180SB1121 (California)
* http://www.ilga.gov/legislation/fulltext.asp?DocName=10100SB1624lv&SessionID=108&GA=101&DocTypeID=SB&DocNum=1624&print=true (Illinois)
* http://www.mainelegislature.org/legis/bills/bills_129th/billtexts/SP027501.asp (Maine)
* http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=HB1154&stab=01&pid=billpage&tab=subject3&ys=2019RS (Maryland)
* https://malegislature.gov/Bills/190/H4806 (Massachusetts)
* https://www.njleg.state.nj.us/2018/Bills/S0500/52_R1.PDF (New Jersey)
* https://legislation.nysenate.gov/pdf/bills/2019/S5575B (New York)
* https://olis.leg.state.or.us/liz/2019R1/Downloads/MeasureDocument/SB684 (Oregon)
* https://capitol.texas.gov/tlodocs/86R/billtext/html/HB04390H.htm (Texas)
* http://lawfilesext.leg.wa.gov/biennium/2019-20/Pdf/Amendments/Senate/1071-S%20AMS%20WM%20S3925.1.pdf (Washington)
__Some more information on states which modified their laws in 2019 and 2018__
* https://www.jdsupra.com/legalnews/year-to-date-changes-to-state-data-21648/
* https://blogs.claconnect.com/residentialmortgage/arkansas-amends-its-personal-information-protection-act/
* https://www.csoonline.com/article/3339565/what-is-biometrics-and-why-collecting-biometric-data-is-risky.html
+ During the calendar year 2019, Arkansas passed House Bill 1943 which amends and revises the Personal Information Protection Act (part of Arkansas state law). HB 1943 revises Arkansas Code section 4-110-103(7) to include biometric data in the definition of personal information (Biometric data is data generated by automatic measurements on an individual’s biological characteristics such as fingerprints, retinal or iris scans, facial recognition, DNA and other identifiers including behavioral identifiers).
+ So biometric data is considered to be personal information. Additionally, the bill (HB 1943) amends Arkansas Code section 4-110-105(b) which requires that in the event of a data breach involving more than 1,000 individuals a notification breach must also be made to the attorney general. Breached entities are now required to (after a data breach has been detected) retain a copy of the written determination of the data breach and of supporting documentation for five years. Furthermore the entity must provide documentation within 30 days of an attorney general’s written request.
+ House Bill 1943 became law on April 15, 2019 and became effective on July 23, 2019.
* https://www.huntonprivacyblog.com/2019/06/04/illinois-general-assembly-approves-breach-notification-amendment-to-personal-information-protection-act/
+ On May 27, 2019 the Illinois General Assembly passed amendments to the Illinois Personal Information Protection Act’s section on data notifications. In addition to obligations to notify the affected individuals, data collectors are also required to notify the Illinois attorney general if the data breach involves personal information from over 500 Illinois residents. Data collectors must notify the Office of the Attorney General (as in Arkansas) in the most expedient time possible and without unreasonable delay, but no later than when notice is given to the affected individuals.
+ The amendment also grants the Attorney General the authority to publish the name of the data collector, the types of personal information compromised and other relevant information. The aim of the amendment is to ensure timely notification of the breach to the residents of Illinois.
* https://www.jdsupra.com/legalnews/maryland-privacy-act-amendments-impact-16436/
+ On April 30, 2019 Maryland passed amendments to the security breach notification requirements of Maryland’s Personal Information Protection Act, which became effective on October 1, 2019.
+ Specifically, this one is for businesses which maintain computerized personal data but do not own it. These businesses (any business which maintains computerized data) will now be required to perform a prompt and reasonable investigation to identify the risk of harm to the compromised individuals. And they are required to notify the owner of the personal data no later than 45 days after the discovery of the breach. Businesses maintaining the data cannot charge its owner a fee for providing the necessary information (necessary to make the required notifications).
* https://www.huntonprivacyblog.com/2019/05/17/new-jersey-amends-data-breach-law-to-include-online-account-information/
* https://www.njleg.state.nj.us/2018/Bills/S0500/52_S1.PDF
+ On May 10, 2019, New Jersey Governor Phil Murphy signed into law a bill that amends New Jersey’s data breach notification law.
+ Businesses subject to the law must notify New Jersey residents of a breach of security affecting a resident’s user name, email password or any other account holder identifying information, in combination with any password or security question and answer that would permit access to an online account. Basically, the bill adds account holder identifying information (including first and last name) in combination with any password or security question and answer that would permit access to an online account to the list of breaches which require disclosure.
+ Essentially it expands the notion of personal information to include online account information to the preexisting list (Social Security number, driver’s license number, credit or debit card number in combination with any required security code, access code or password permitting access to the related individual’s financial account). The bill itself requires all entities compiling or maintaining computerized records that include information requiring access to an online account to disclose breaches of security.
\ \ \ \ \ \ \ On May 24, 2019, Governor Kate Brown signed into law amendments to the Oregon Consumer Identity Theft Protection Act which distinguish between a “covered entity” and a “vendor”; similarly to the “controller” and “processor” distinction in the GDPR.
__Additional Resources__
Additional resources about data breach laws:
* https://openscholarship.wustl.edu/cgi/viewcontent.cgi?article=1087&context=law_journal_law_policy
+ Jill Joerling argues for a comprehensive federal law to protect consumer data
* http://www.nbcnews.com/id/11030692/ns/technology_and_science-security/t/choicepoint-pay-million-over-data-breach/#.XUMtBOhKhPY
+ Some more information about the ChoicePoint data breach of 2005
* https://www.dataprotectionreport.com/2019/06/nine-states-pass-new-and-expanded-data-breach-notification-laws/
+ (same findings as the previous link which is https://www.jdsupra.com/legalnews/year-to-date-changes-to-state-data-21648/).
+ http://www.ncsl.org/research/telecommunications-and-information-technology/2018-security-breach-legislation.aspx (relevant).
* https://legislation.nysenate.gov/pdf/bills/2019/S5575B
+ Demonstrates that New York has an amendment which is headed to the governor’s desk (https://www.jdsupra.com/legalnews/updates-to-new-york-state-s-breach-28999/).
* https://info.digitalguardian.com/rs/768-OQW-145/images/the-definitive-guide-to-us-state-data-breach-laws.pdf “The Definitive Guide to U.S. State Data Breach Laws”
* https://www.huntonprivacyblog.com/2018/04/03/alabama-becomes-final-state-enact-data-breach-notification-law/
* https://www.consumerfinancemonitor.com/2018/04/19/arizona-strengthens-and-expands-data-breach-notification-law/
* https://www.azleg.gov/legtext/53leg/2r/bills/hb2154p.pdf
* https://privacylaw.proskauer.com/2018/09/articles/california/california-legislature-passes-amendments-to-the-california-consumer-privacy-act/
* https://www.huntonprivacyblog.com/2018/06/14/colorado-amends-data-breach-notification-law-enacts-data-security-requirements/