datafog-core 0.4.5b4__tar.gz → 0.5.0b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/Cargo.lock +167 -4
  2. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/PKG-INFO +27 -8
  3. {datafog_core-0.4.5b4/crates/core → datafog_core-0.5.0b2}/README.md +26 -7
  4. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/Cargo.toml +2 -2
  5. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/src/lib.rs +1 -1
  6. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/src/models.rs +4 -0
  7. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/capabilities_conformance.py +1 -0
  8. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/test_installed.py +139 -0
  9. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/test_python49_integration.py +2 -2
  10. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/Cargo.toml +3 -1
  11. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2/crates/core}/README.md +26 -7
  12. datafog_core-0.5.0b2/crates/core/src/account_number.rs +53 -0
  13. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/capabilities.rs +23 -0
  14. datafog_core-0.5.0b2/crates/core/src/coverage.rs +59 -0
  15. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/lib.rs +213 -6
  16. datafog_core-0.5.0b2/crates/core/src/model_scan.rs +999 -0
  17. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/models/tests.rs +171 -2
  18. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/models.rs +72 -477
  19. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/offsets.rs +22 -0
  20. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/scan_selection_tests.rs +2 -0
  21. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/selection_tests.rs +181 -12
  22. datafog_core-0.5.0b2/crates/core/src/street_address.rs +70 -0
  23. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/structured.rs +25 -8
  24. datafog_core-0.5.0b2/crates/core/src/workspace/codec.rs +272 -0
  25. datafog_core-0.5.0b2/crates/core/src/workspace/policy.rs +383 -0
  26. datafog_core-0.5.0b2/crates/core/src/workspace/recall.rs +412 -0
  27. datafog_core-0.5.0b2/crates/core/src/workspace/review.rs +441 -0
  28. datafog_core-0.5.0b2/crates/core/src/workspace.rs +1262 -0
  29. datafog_core-0.5.0b2/crates/core/tests/account_number.rs +224 -0
  30. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/capabilities.rs +4 -2
  31. datafog_core-0.5.0b2/crates/core/tests/model_gliner2_entity_count.rs +201 -0
  32. datafog_core-0.5.0b2/crates/core/tests/street_address.rs +120 -0
  33. datafog_core-0.5.0b2/crates/core/tests/workspace.rs +1327 -0
  34. datafog_core-0.5.0b2/crates/core/tests/workspace_policy.rs +699 -0
  35. datafog_core-0.5.0b2/crates/core/tests/workspace_recall.rs +262 -0
  36. datafog_core-0.5.0b2/crates/core/tests/workspace_review.rs +405 -0
  37. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/pyproject.toml +1 -1
  38. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/python/datafog_core/__init__.pyi +9 -0
  39. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/python/datafog_core/_gliner2_worker.py +53 -0
  40. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/Cargo.toml +0 -0
  41. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/api_key_conformance.py +0 -0
  42. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/bearer_token_conformance.py +0 -0
  43. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/credential_overlap_conformance.py +0 -0
  44. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/credential_uri_conformance.py +0 -0
  45. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/email_context_conformance.py +0 -0
  46. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/german_conformance.py +0 -0
  47. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/jwt_conformance.py +0 -0
  48. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/npi_conformance.py +0 -0
  49. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/private_key_conformance.py +0 -0
  50. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/requirements-typing.txt +0 -0
  51. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/synthetic_fixtures.py +0 -0
  52. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/test_typing.py +0 -0
  53. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/us_routing_number_conformance.py +0 -0
  54. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/bindings/python/tests/uuid_conformance.py +0 -0
  55. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/examples/german_benchmark.rs +0 -0
  56. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/examples/scan_benchmark.rs +0 -0
  57. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/api_key.rs +0 -0
  58. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/bearer_token.rs +0 -0
  59. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/credential_uri.rs +0 -0
  60. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/email_context.rs +0 -0
  61. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/german.rs +0 -0
  62. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/jwt.rs +0 -0
  63. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/models/gliner2-lock.json +0 -0
  64. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/models/gliner2.rs +0 -0
  65. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/models/process.rs +0 -0
  66. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/npi.rs +0 -0
  67. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/private_key.rs +0 -0
  68. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/us_routing_number.rs +0 -0
  69. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/src/uuid.rs +0 -0
  70. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/api_key.rs +0 -0
  71. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/bearer_token.rs +0 -0
  72. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/credential_overlaps.rs +0 -0
  73. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/credential_uri.rs +0 -0
  74. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/email_context.rs +0 -0
  75. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/german.rs +0 -0
  76. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/jwt.rs +0 -0
  77. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/model_datafog.rs +0 -0
  78. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/npi.rs +0 -0
  79. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/private_key.rs +0 -0
  80. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/support/synthetic_fixtures.rs +0 -0
  81. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/us_routing_number.rs +0 -0
  82. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/crates/core/tests/uuid.rs +0 -0
  83. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/python/datafog_core/__init__.py +0 -0
  84. {datafog_core-0.4.5b4 → datafog_core-0.5.0b2}/python/datafog_core/py.typed +0 -0
@@ -11,6 +11,21 @@ dependencies = [
11
11
  "memchr",
12
12
  ]
13
13
 
14
+ [[package]]
15
+ name = "android_system_properties"
16
+ version = "0.1.6"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
19
+ dependencies = [
20
+ "libc",
21
+ ]
22
+
23
+ [[package]]
24
+ name = "autocfg"
25
+ version = "1.5.1"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
28
+
14
29
  [[package]]
15
30
  name = "base64"
16
31
  version = "0.22.1"
@@ -38,12 +53,33 @@ version = "3.20.3"
38
53
  source = "registry+https://github.com/rust-lang/crates.io-index"
39
54
  checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
40
55
 
56
+ [[package]]
57
+ name = "cc"
58
+ version = "1.10.0"
59
+ source = "registry+https://github.com/rust-lang/crates.io-index"
60
+ checksum = "86e055fa6e3e40ad6187ba25b6855eeb635d5271f8e0f0e1e9a5826b8d75bea0"
61
+ dependencies = [
62
+ "find-msvc-tools",
63
+ "shlex",
64
+ ]
65
+
41
66
  [[package]]
42
67
  name = "cfg-if"
43
68
  version = "1.0.4"
44
69
  source = "registry+https://github.com/rust-lang/crates.io-index"
45
70
  checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
46
71
 
72
+ [[package]]
73
+ name = "chrono"
74
+ version = "0.4.45"
75
+ source = "registry+https://github.com/rust-lang/crates.io-index"
76
+ checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
77
+ dependencies = [
78
+ "iana-time-zone",
79
+ "num-traits",
80
+ "windows-link",
81
+ ]
82
+
47
83
  [[package]]
48
84
  name = "convert_case"
49
85
  version = "0.11.0"
@@ -53,6 +89,12 @@ dependencies = [
53
89
  "unicode-segmentation",
54
90
  ]
55
91
 
92
+ [[package]]
93
+ name = "core-foundation-sys"
94
+ version = "0.8.7"
95
+ source = "registry+https://github.com/rust-lang/crates.io-index"
96
+ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
97
+
56
98
  [[package]]
57
99
  name = "cpufeatures"
58
100
  version = "0.2.17"
@@ -80,11 +122,12 @@ checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d"
80
122
 
81
123
  [[package]]
82
124
  name = "datafog-core"
83
- version = "0.4.5-beta.4"
125
+ version = "0.5.0-beta.2"
84
126
  dependencies = [
85
127
  "base64",
86
128
  "futures",
87
129
  "hmac",
130
+ "minicbor",
88
131
  "regex",
89
132
  "serde",
90
133
  "serde_json",
@@ -94,7 +137,7 @@ dependencies = [
94
137
 
95
138
  [[package]]
96
139
  name = "datafog-core-python"
97
- version = "0.4.5-beta.4"
140
+ version = "0.5.0-beta.2"
98
141
  dependencies = [
99
142
  "datafog-core",
100
143
  "pyo3",
@@ -105,7 +148,7 @@ dependencies = [
105
148
 
106
149
  [[package]]
107
150
  name = "datafog-node"
108
- version = "0.4.5-beta.4"
151
+ version = "0.5.0-beta.2"
109
152
  dependencies = [
110
153
  "datafog-core",
111
154
  "napi",
@@ -116,7 +159,7 @@ dependencies = [
116
159
 
117
160
  [[package]]
118
161
  name = "datafog-wasm"
119
- version = "0.4.5-beta.4"
162
+ version = "0.5.0-beta.2"
120
163
  dependencies = [
121
164
  "datafog-core",
122
165
  "serde",
@@ -136,6 +179,12 @@ dependencies = [
136
179
  "subtle",
137
180
  ]
138
181
 
182
+ [[package]]
183
+ name = "find-msvc-tools"
184
+ version = "0.1.15"
185
+ source = "registry+https://github.com/rust-lang/crates.io-index"
186
+ checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48"
187
+
139
188
  [[package]]
140
189
  name = "futures"
141
190
  version = "0.3.34"
@@ -249,6 +298,30 @@ dependencies = [
249
298
  "digest",
250
299
  ]
251
300
 
301
+ [[package]]
302
+ name = "iana-time-zone"
303
+ version = "0.1.65"
304
+ source = "registry+https://github.com/rust-lang/crates.io-index"
305
+ checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
306
+ dependencies = [
307
+ "android_system_properties",
308
+ "core-foundation-sys",
309
+ "iana-time-zone-haiku",
310
+ "js-sys",
311
+ "log",
312
+ "wasm-bindgen",
313
+ "windows-core",
314
+ ]
315
+
316
+ [[package]]
317
+ name = "iana-time-zone-haiku"
318
+ version = "0.1.2"
319
+ source = "registry+https://github.com/rust-lang/crates.io-index"
320
+ checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
321
+ dependencies = [
322
+ "cc",
323
+ ]
324
+
252
325
  [[package]]
253
326
  name = "itoa"
254
327
  version = "1.0.18"
@@ -282,12 +355,24 @@ dependencies = [
282
355
  "windows-link",
283
356
  ]
284
357
 
358
+ [[package]]
359
+ name = "log"
360
+ version = "0.4.34"
361
+ source = "registry+https://github.com/rust-lang/crates.io-index"
362
+ checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
363
+
285
364
  [[package]]
286
365
  name = "memchr"
287
366
  version = "2.8.3"
288
367
  source = "registry+https://github.com/rust-lang/crates.io-index"
289
368
  checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
290
369
 
370
+ [[package]]
371
+ name = "minicbor"
372
+ version = "2.3.0"
373
+ source = "registry+https://github.com/rust-lang/crates.io-index"
374
+ checksum = "c12b4033ffaa92fbf9df03df38d19324f52bad130dd223f811734a8006dd2d69"
375
+
291
376
  [[package]]
292
377
  name = "napi"
293
378
  version = "3.12.2"
@@ -354,6 +439,15 @@ version = "0.2.0"
354
439
  source = "registry+https://github.com/rust-lang/crates.io-index"
355
440
  checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
356
441
 
442
+ [[package]]
443
+ name = "num-traits"
444
+ version = "0.2.19"
445
+ source = "registry+https://github.com/rust-lang/crates.io-index"
446
+ checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
447
+ dependencies = [
448
+ "autocfg",
449
+ ]
450
+
357
451
  [[package]]
358
452
  name = "once_cell"
359
453
  version = "1.21.4"
@@ -573,6 +667,12 @@ dependencies = [
573
667
  "digest",
574
668
  ]
575
669
 
670
+ [[package]]
671
+ name = "shlex"
672
+ version = "2.0.1"
673
+ source = "registry+https://github.com/rust-lang/crates.io-index"
674
+ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
675
+
576
676
  [[package]]
577
677
  name = "slab"
578
678
  version = "0.4.12"
@@ -691,12 +791,75 @@ dependencies = [
691
791
  "unicode-ident",
692
792
  ]
693
793
 
794
+ [[package]]
795
+ name = "windows-core"
796
+ version = "0.62.2"
797
+ source = "registry+https://github.com/rust-lang/crates.io-index"
798
+ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
799
+ dependencies = [
800
+ "windows-implement",
801
+ "windows-interface",
802
+ "windows-link",
803
+ "windows-result",
804
+ "windows-strings",
805
+ ]
806
+
807
+ [[package]]
808
+ name = "windows-implement"
809
+ version = "0.60.2"
810
+ source = "registry+https://github.com/rust-lang/crates.io-index"
811
+ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
812
+ dependencies = [
813
+ "proc-macro2",
814
+ "quote",
815
+ "syn 2.0.119",
816
+ ]
817
+
818
+ [[package]]
819
+ name = "windows-interface"
820
+ version = "0.59.3"
821
+ source = "registry+https://github.com/rust-lang/crates.io-index"
822
+ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
823
+ dependencies = [
824
+ "proc-macro2",
825
+ "quote",
826
+ "syn 2.0.119",
827
+ ]
828
+
694
829
  [[package]]
695
830
  name = "windows-link"
696
831
  version = "0.2.1"
697
832
  source = "registry+https://github.com/rust-lang/crates.io-index"
698
833
  checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
699
834
 
835
+ [[package]]
836
+ name = "windows-result"
837
+ version = "0.4.1"
838
+ source = "registry+https://github.com/rust-lang/crates.io-index"
839
+ checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
840
+ dependencies = [
841
+ "windows-link",
842
+ ]
843
+
844
+ [[package]]
845
+ name = "windows-strings"
846
+ version = "0.5.1"
847
+ source = "registry+https://github.com/rust-lang/crates.io-index"
848
+ checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
849
+ dependencies = [
850
+ "windows-link",
851
+ ]
852
+
853
+ [[package]]
854
+ name = "xtask"
855
+ version = "0.1.0"
856
+ dependencies = [
857
+ "chrono",
858
+ "serde",
859
+ "serde_json",
860
+ "sha2",
861
+ ]
862
+
700
863
  [[package]]
701
864
  name = "zeroize"
702
865
  version = "1.9.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datafog-core
3
- Version: 0.4.5b4
3
+ Version: 0.5.0b2
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: MIT License
6
6
  Classifier: Programming Language :: Python :: 3
@@ -59,7 +59,7 @@ DataFog Core is a Rust library with Python, Node.js, and browser WebAssembly bin
59
59
 
60
60
  Rule-based scanning runs locally without model weights or downloads. Optional local model sessions add DataFog and GLiNER2 support in Rust, Python, and Node.js.
61
61
 
62
- **Stable:** [0.4.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.4) · **Model beta:** [0.4.5-beta.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.5-beta.4)
62
+ **Stable:** [0.4.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.4) · **Prerelease:** [0.5.0-beta.1](https://github.com/DataFog/datafog-core/releases/tag/v0.5.0-beta.1)
63
63
 
64
64
  ## Quickstart
65
65
 
@@ -158,12 +158,14 @@ Python and Node.js packages include prebuilt native binaries for Linux x64 and A
158
158
  | --- | --- | --- |
159
159
  | Personal and financial data | `EMAIL`, `PHONE`, `SSN`, `CREDIT_CARD`, `IP_ADDRESS`, `DATE`, `ZIP_CODE` | On by default |
160
160
  | Credentials | [`API_KEY`](docs/reference/api-keys.mdx), [`BEARER_TOKEN`](docs/reference/bearer-token.mdx), [`JWT`](docs/reference/jwt.mdx), [`PRIVATE_KEY`](docs/reference/private-keys.mdx), [`CREDENTIAL_URI`](docs/reference/credential-uri.mdx) | On by default |
161
+ | Labeled street addresses | [`STREET_ADDRESS`](docs/reference/street-address.mdx) | On by default; bounded English street-line rule |
162
+ | Labeled accounts | [`ACCOUNT_NUMBER`](docs/reference/account-number.mdx) | On by default; bounded lexical rule |
161
163
  | Labeled US identifiers | [`US_ROUTING_NUMBER`](docs/reference/us-routing-number.mdx), [`NPI`](docs/reference/npi.mdx) | On by default; requires a supported text label |
162
164
  | German identifiers | IBAN, VAT ID, tax ID, social security number, postal code, passport number, residence permit number | Explicit [German locale](docs/reference/german-entities.mdx) |
163
165
  | UUIDs | [`UUID`](docs/reference/uuid.mdx) | Explicit `detect_uuid` setting |
164
166
  | Names in JSON fields | `PERSON` | [Structured scans](docs/guides/person-discovery.mdx), using name-field aliases or explicit JSON Pointer mappings |
165
167
 
166
- Use [structured scans](docs/guides/person-discovery.mdx) to find names by JSON field, or [local models](#local-models-beta) to detect names and street addresses in prose.
168
+ Use [structured scans](docs/guides/person-discovery.mdx) to find names by JSON field, or [local models](#local-models-beta) to detect names and unlabelled street addresses in prose.
167
169
 
168
170
  Each finding includes its entity type, matched text, byte and code-point ranges, optional confidence, and detector name/version. Ranges are zero-based and end-exclusive. Node.js and WASM also provide UTF-16 ranges for JavaScript `slice`. Rule-based findings have no confidence score. [Findings and ranges →](docs/concepts/findings-and-ranges.mdx)
169
171
 
@@ -196,22 +198,37 @@ Use `transform` with existing findings, or `scan_and_transform` / `scanAndTransf
196
198
 
197
199
  Keep scan settings under `scan` and transformation policy under `transform`. A default strategy is required; entity selection, per-type overrides, and allowlists are optional. [Configuration guide →](docs/guides/configuration.mdx) · [Strategy details →](docs/concepts/privacy-transformations.mdx)
198
200
 
201
+ ## Chrome extension integration in 0.5.0-beta.1
202
+
203
+ The developer prerelease adds persistent `Workspace` pseudonyms, approved
204
+ save-before-handoff, strict restoration, follow-ups and host-owned encrypted
205
+ backup/recovery, plus optional English GLiNER2.5 Small browser sessions. Use
206
+ synthetic data while the snapshot format and vault integration remain provisional.
207
+
208
+ ```bash
209
+ npm install --save-exact @datafog/wasm@0.5.0-beta.1
210
+ ```
211
+
212
+ [Integration lifecycle, all browser calls and errors →](docs/extension-integration-0.5.0-beta.1.md)
213
+ · [Model assets and runtime setup →](docs/browser-model.md)
214
+ · [Release scope and verification →](https://github.com/DataFog/datafog-core/issues/132)
215
+
199
216
  ## Local models (beta)
200
217
 
201
218
  [0.4.5-beta.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.5-beta.4) adds local sessions for the DataFog PII model and GLiNER2 in Rust, Python, and Node.js on all five native platforms.
202
219
 
203
- Install the beta for your runtime:
220
+ Install `0.5.0-beta.1` (Python `0.5.0b1`) for the current native prerelease:
204
221
 
205
222
  ```bash
206
- python -m pip install 'datafog-core==0.4.5b4'
207
- npm install @datafog/node@beta
208
- cargo add datafog-core@0.4.5-beta.4 --features models
223
+ python -m pip install 'datafog-core==0.5.0b1'
224
+ npm install --save-exact @datafog/node@0.5.0-beta.1
225
+ cargo add datafog-core@0.5.0-beta.1 --features models
209
226
  ```
210
227
 
211
228
  For GLiNER2, install its optional dependencies in the Python environment used by the runner:
212
229
 
213
230
  ```bash
214
- python -m pip install 'datafog-core[gliner2]==0.4.5b4'
231
+ python -m pip install 'datafog-core[gliner2]==0.5.0b1'
215
232
  ```
216
233
 
217
234
  GLiNER2 supports the PII checkpoint and compatible general-purpose span models with caller-defined labels. The GLiNER2 runner ships in the Python package and also serves Node.js and Rust callers. Download and verify model files separately, then use `ModelSession.open`, text `scan`, and `close`. Reuse sessions across calls. Both backends return consistent results and errors, with cancellation and cleanup support.
@@ -220,6 +237,8 @@ GLiNER2 supports the PII checkpoint and compatible general-purpose span models w
220
237
 
221
238
  ## Documentation and development
222
239
 
240
+ - [Roadmap](ROADMAP.md)
241
+ - [Dev environment setup](CONTRIBUTING.md#dev-environment-setup) — devcontainer or local install, `cargo dfv doctor`
223
242
  - [Installation and runtime requirements](docs/get-started/installation.mdx)
224
243
  - [Python](docs/reference/python.mdx) · [Node.js](docs/reference/node.mdx) · [Rust](docs/reference/rust.mdx) · [Browser / WASM](docs/reference/browser-wasm.mdx) API references
225
244
  - [Structured JSON scans and name-field discovery](docs/guides/person-discovery.mdx)
@@ -26,7 +26,7 @@ DataFog Core is a Rust library with Python, Node.js, and browser WebAssembly bin
26
26
 
27
27
  Rule-based scanning runs locally without model weights or downloads. Optional local model sessions add DataFog and GLiNER2 support in Rust, Python, and Node.js.
28
28
 
29
- **Stable:** [0.4.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.4) · **Model beta:** [0.4.5-beta.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.5-beta.4)
29
+ **Stable:** [0.4.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.4) · **Prerelease:** [0.5.0-beta.1](https://github.com/DataFog/datafog-core/releases/tag/v0.5.0-beta.1)
30
30
 
31
31
  ## Quickstart
32
32
 
@@ -125,12 +125,14 @@ Python and Node.js packages include prebuilt native binaries for Linux x64 and A
125
125
  | --- | --- | --- |
126
126
  | Personal and financial data | `EMAIL`, `PHONE`, `SSN`, `CREDIT_CARD`, `IP_ADDRESS`, `DATE`, `ZIP_CODE` | On by default |
127
127
  | Credentials | [`API_KEY`](docs/reference/api-keys.mdx), [`BEARER_TOKEN`](docs/reference/bearer-token.mdx), [`JWT`](docs/reference/jwt.mdx), [`PRIVATE_KEY`](docs/reference/private-keys.mdx), [`CREDENTIAL_URI`](docs/reference/credential-uri.mdx) | On by default |
128
+ | Labeled street addresses | [`STREET_ADDRESS`](docs/reference/street-address.mdx) | On by default; bounded English street-line rule |
129
+ | Labeled accounts | [`ACCOUNT_NUMBER`](docs/reference/account-number.mdx) | On by default; bounded lexical rule |
128
130
  | Labeled US identifiers | [`US_ROUTING_NUMBER`](docs/reference/us-routing-number.mdx), [`NPI`](docs/reference/npi.mdx) | On by default; requires a supported text label |
129
131
  | German identifiers | IBAN, VAT ID, tax ID, social security number, postal code, passport number, residence permit number | Explicit [German locale](docs/reference/german-entities.mdx) |
130
132
  | UUIDs | [`UUID`](docs/reference/uuid.mdx) | Explicit `detect_uuid` setting |
131
133
  | Names in JSON fields | `PERSON` | [Structured scans](docs/guides/person-discovery.mdx), using name-field aliases or explicit JSON Pointer mappings |
132
134
 
133
- Use [structured scans](docs/guides/person-discovery.mdx) to find names by JSON field, or [local models](#local-models-beta) to detect names and street addresses in prose.
135
+ Use [structured scans](docs/guides/person-discovery.mdx) to find names by JSON field, or [local models](#local-models-beta) to detect names and unlabelled street addresses in prose.
134
136
 
135
137
  Each finding includes its entity type, matched text, byte and code-point ranges, optional confidence, and detector name/version. Ranges are zero-based and end-exclusive. Node.js and WASM also provide UTF-16 ranges for JavaScript `slice`. Rule-based findings have no confidence score. [Findings and ranges →](docs/concepts/findings-and-ranges.mdx)
136
138
 
@@ -163,22 +165,37 @@ Use `transform` with existing findings, or `scan_and_transform` / `scanAndTransf
163
165
 
164
166
  Keep scan settings under `scan` and transformation policy under `transform`. A default strategy is required; entity selection, per-type overrides, and allowlists are optional. [Configuration guide →](docs/guides/configuration.mdx) · [Strategy details →](docs/concepts/privacy-transformations.mdx)
165
167
 
168
+ ## Chrome extension integration in 0.5.0-beta.1
169
+
170
+ The developer prerelease adds persistent `Workspace` pseudonyms, approved
171
+ save-before-handoff, strict restoration, follow-ups and host-owned encrypted
172
+ backup/recovery, plus optional English GLiNER2.5 Small browser sessions. Use
173
+ synthetic data while the snapshot format and vault integration remain provisional.
174
+
175
+ ```bash
176
+ npm install --save-exact @datafog/wasm@0.5.0-beta.1
177
+ ```
178
+
179
+ [Integration lifecycle, all browser calls and errors →](docs/extension-integration-0.5.0-beta.1.md)
180
+ · [Model assets and runtime setup →](docs/browser-model.md)
181
+ · [Release scope and verification →](https://github.com/DataFog/datafog-core/issues/132)
182
+
166
183
  ## Local models (beta)
167
184
 
168
185
  [0.4.5-beta.4](https://github.com/DataFog/datafog-core/releases/tag/v0.4.5-beta.4) adds local sessions for the DataFog PII model and GLiNER2 in Rust, Python, and Node.js on all five native platforms.
169
186
 
170
- Install the beta for your runtime:
187
+ Install `0.5.0-beta.1` (Python `0.5.0b1`) for the current native prerelease:
171
188
 
172
189
  ```bash
173
- python -m pip install 'datafog-core==0.4.5b4'
174
- npm install @datafog/node@beta
175
- cargo add datafog-core@0.4.5-beta.4 --features models
190
+ python -m pip install 'datafog-core==0.5.0b1'
191
+ npm install --save-exact @datafog/node@0.5.0-beta.1
192
+ cargo add datafog-core@0.5.0-beta.1 --features models
176
193
  ```
177
194
 
178
195
  For GLiNER2, install its optional dependencies in the Python environment used by the runner:
179
196
 
180
197
  ```bash
181
- python -m pip install 'datafog-core[gliner2]==0.4.5b4'
198
+ python -m pip install 'datafog-core[gliner2]==0.5.0b1'
182
199
  ```
183
200
 
184
201
  GLiNER2 supports the PII checkpoint and compatible general-purpose span models with caller-defined labels. The GLiNER2 runner ships in the Python package and also serves Node.js and Rust callers. Download and verify model files separately, then use `ModelSession.open`, text `scan`, and `close`. Reuse sessions across calls. Both backends return consistent results and errors, with cancellation and cleanup support.
@@ -187,6 +204,8 @@ GLiNER2 supports the PII checkpoint and compatible general-purpose span models w
187
204
 
188
205
  ## Documentation and development
189
206
 
207
+ - [Roadmap](ROADMAP.md)
208
+ - [Dev environment setup](CONTRIBUTING.md#dev-environment-setup) — devcontainer or local install, `cargo dfv doctor`
190
209
  - [Installation and runtime requirements](docs/get-started/installation.mdx)
191
210
  - [Python](docs/reference/python.mdx) · [Node.js](docs/reference/node.mdx) · [Rust](docs/reference/rust.mdx) · [Browser / WASM](docs/reference/browser-wasm.mdx) API references
192
211
  - [Structured JSON scans and name-field discovery](docs/guides/person-discovery.mdx)
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "datafog-core-python"
3
- version = "0.4.5-beta.4"
3
+ version = "0.5.0-beta.2"
4
4
  edition = "2024"
5
5
  rust-version = "1.88"
6
6
  description = "Python bindings for datafog-core"
@@ -12,7 +12,7 @@ name = "datafog_core"
12
12
  crate-type = ["cdylib"]
13
13
 
14
14
  [dependencies]
15
- datafog-core = { version = "0.4.5-beta.4", path = "../../crates/core", features = ["models"] }
15
+ datafog-core = { version = "0.5.0-beta.2", path = "../../crates/core", features = ["models"] }
16
16
  pyo3 = { version = "0.29", features = ["abi3-py310"] }
17
17
  pyo3-async-runtimes = { version = "0.29", features = ["tokio-runtime"] }
18
18
  serde_json = "1"
@@ -921,7 +921,7 @@ fn privacy_error(py: Python<'_>, error: core::PrivacyError) -> PyErr {
921
921
  core::PrivacyErrorCode::InvalidConfiguration => {
922
922
  PyErr::new::<DataFogConfigurationError, _>(error.to_string())
923
923
  }
924
- core::PrivacyErrorCode::InvalidFinding => {
924
+ core::PrivacyErrorCode::InvalidFinding | core::PrivacyErrorCode::ReviewConflict => {
925
925
  PyErr::new::<DataFogFindingError, _>(error.to_string())
926
926
  }
927
927
  core::PrivacyErrorCode::KeyProviderRequired
@@ -82,6 +82,10 @@ pub(super) struct ModelSession {
82
82
  }
83
83
  #[pymethods]
84
84
  impl ModelSession {
85
+ fn describe(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
86
+ json_object(py, &self.session.describe())
87
+ }
88
+
85
89
  #[staticmethod]
86
90
  fn open(py: Python<'_>, config: &Bound<'_, PyAny>) -> PyResult<Self> {
87
91
  let started = std::time::Instant::now();
@@ -5,6 +5,7 @@ from pathlib import Path
5
5
  import datafog_core as api
6
6
 
7
7
  SUPPORTED = sorted([
8
+ "ACCOUNT_NUMBER", "STREET_ADDRESS",
8
9
  "BEARER_TOKEN", "CREDIT_CARD", "DATE", "DE_IBAN", "DE_PASSPORT_NUMBER", "DE_POSTAL_CODE", "API_KEY", "CREDENTIAL_URI",
9
10
  "DE_RESIDENCE_PERMIT_NUMBER", "DE_SOCIAL_SECURITY_NUMBER", "DE_TAX_ID",
10
11
  "DE_VAT_ID", "EMAIL", "IP_ADDRESS", "JWT", "NPI", "PERSON", "PHONE",
@@ -23,6 +23,8 @@ from datafog_core import (
23
23
  DataFogFindingError,
24
24
  DataFogKeyProviderError,
25
25
  Finding,
26
+ StructuredFinding,
27
+ ModelSession,
26
28
  PrivacyManager,
27
29
  TextRange,
28
30
  scan,
@@ -38,6 +40,120 @@ from datafog_core import (
38
40
  ROOT = Path(__file__).resolve().parents[3]
39
41
 
40
42
 
43
+ def verify_account_number() -> None:
44
+ for line in ((ROOT / "fixtures" / "account-number.jsonl").read_text().splitlines()
45
+ + (ROOT / "fixtures" / "masked-account-number.jsonl").read_text().splitlines()):
46
+ row = json.loads(line)
47
+ text = row["text"]
48
+ def project(findings):
49
+ result = []
50
+ for finding in findings:
51
+ if finding.entity_type != "ACCOUNT_NUMBER":
52
+ continue
53
+ assert text.encode()[finding.byte_range.start:finding.byte_range.end].decode() == finding.matched_text
54
+ assert text[finding.codepoint_range.start:finding.codepoint_range.end] == finding.matched_text
55
+ assert finding.detector_name == "datafog-core/account-number"
56
+ assert finding.confidence is None
57
+ result.append(dict(label=finding.entity_type, text=finding.matched_text, start=finding.codepoint_range.start, end=finding.codepoint_range.end))
58
+ return result
59
+ assert project(scan(text)) == row["entities"], row["id"]
60
+ assert project(scan(text, {"entities":["ACCOUNT_NUMBER"]})) == row["entities"], row["id"]
61
+ assert project([f.finding for f in scan_structured({"note":text}).findings]) == row["entities"]
62
+ cases = row.get("transforms", [dict(config={"default":{"strategy":"redact"},"entities":["ACCOUNT_NUMBER"]},text=text)])
63
+ for case in cases:
64
+ config = {"transform":case["config"]}
65
+ assert scan_and_transform(text, config).text == case["text"], row["id"]
66
+ assert scan_and_transform_structured({"note":text}, config).data == {"note":case["text"]}
67
+ assert not any(f.finding.entity_type == "ACCOUNT_NUMBER" for f in scan_structured({"account number":"12345678"}).findings)
68
+
69
+
70
+ def verify_street_address() -> None:
71
+ for line in (ROOT / "fixtures" / "street-address.jsonl").read_text().splitlines():
72
+ row = json.loads(line)
73
+ text = row["text"]
74
+ def project(findings):
75
+ result = []
76
+ for finding in findings:
77
+ if finding.entity_type != "STREET_ADDRESS":
78
+ continue
79
+ assert text.encode()[finding.byte_range.start:finding.byte_range.end].decode() == finding.matched_text
80
+ assert text[finding.codepoint_range.start:finding.codepoint_range.end] == finding.matched_text
81
+ assert finding.detector_name == "datafog-core/street-address"
82
+ assert finding.confidence is None
83
+ result.append(dict(label=finding.entity_type, text=finding.matched_text, start=finding.codepoint_range.start, end=finding.codepoint_range.end))
84
+ return result
85
+ assert project(scan(text)) == row["entities"], row["id"]
86
+ assert project(scan(text, {"entities":["STREET_ADDRESS"]})) == row["entities"], row["id"]
87
+ assert project([f.finding for f in scan_structured({"note":text}).findings]) == row["entities"]
88
+ cases = row.get("transforms") or [dict(config={"default":{"strategy":"redact"},"entities":["STREET_ADDRESS"]},text=text)]
89
+ for case in cases:
90
+ config = {"transform":case["config"]}
91
+ assert scan_and_transform(text, config).text == case["text"], row["id"]
92
+ assert scan_and_transform_structured({"note":text}, config).data == {"note":case["text"]}
93
+ assert not any(f.finding.entity_type == "STREET_ADDRESS" for f in scan_structured({"street address":"12 Willow Road"}).findings)
94
+
95
+
96
+ def verify_coverage_conflicts() -> None:
97
+ text = "👋 abcdef"
98
+ first = Finding("PERSON", "abcd", TextRange(5, 9), TextRange(2, 6), "synthetic")
99
+ second = Finding("CUSTOM", "cdef", TextRange(7, 11), TextRange(4, 8), "synthetic")
100
+ config = {"default": {"strategy": "redact"}}
101
+ for inputs, index in [([first, second], 1), ([second, first], 0)]:
102
+ for operation in [
103
+ lambda: transform(text, inputs, config),
104
+ lambda: transform_structured({"z": text}, [StructuredFinding("/z", f) for f in inputs], config),
105
+ ]:
106
+ try:
107
+ operation()
108
+ except DataFogFindingError as error:
109
+ assert error.code == "review_conflict" and error.finding_index == index
110
+ assert "abcdef" not in str(error)
111
+ else:
112
+ raise AssertionError("crossing findings returned partial output")
113
+ assert transform(text, [first, second], {**config, "entities": ["PERSON"]}).text == "👋 [PERSON]ef"
114
+ assert transform(text, [first, second], {**config, "allow": {"exact": {"PERSON": ["abcd"]}}}).text == "👋 ab[CUSTOM]"
115
+ class UnusedProvider:
116
+ def __init__(self): self.calls = 0
117
+ async def resolve_key(self, *args): self.calls += 1; raise AssertionError("provider must not run")
118
+ async def tokenize_batch(self, *args): self.calls += 1; raise AssertionError("provider must not run")
119
+ async def restore_batch(self, *args): self.calls += 1; raise AssertionError("provider must not run")
120
+ provider = UnusedProvider()
121
+ async def verify_providers():
122
+ manager = PrivacyManager(provider, provider)
123
+ for strategy in [{"strategy":"pseudonymize", "key_ref":"unused"}, {"strategy":"tokenize", "token_ref":"unused"}]:
124
+ for operation in [
125
+ lambda: manager.transform(text, [first, second], {"default":strategy}, {"scope":"synthetic"}),
126
+ lambda: manager.transform_structured({"z":text}, [StructuredFinding("/z", f) for f in [first, second]], {"default":strategy}, {"scope":"synthetic"}),
127
+ ]:
128
+ try: await operation()
129
+ except DataFogFindingError as error: assert error.code == "review_conflict"
130
+ else: raise AssertionError("provider-backed conflict returned output")
131
+ asyncio.run(verify_providers())
132
+ assert provider.calls == 0
133
+
134
+
135
+ def verify_model_engine_selection() -> None:
136
+ config = {
137
+ "bundle": str(ROOT / "target" / "missing-engine-bundle"),
138
+ "manifest_sha256": "a" * 64,
139
+ "limits": dict(max_input_bytes=1000, max_response_bytes=10000,
140
+ max_findings=10, timeout_ms=1000, cleanup_timeout_ms=1000),
141
+ }
142
+ for engine, path, reason in [
143
+ ("private-engine", "/engine", "invalid_value"),
144
+ (True, "/engine", "invalid_type"),
145
+ (None, "/engine", "invalid_type"),
146
+ ("gliner2", "/gliner2", "missing_field"),
147
+ ]:
148
+ try:
149
+ ModelSession.open(dict(config, engine=engine))
150
+ except DataFogConfigurationError as error:
151
+ assert (error.path, error.reason) == (path, reason)
152
+ assert "private-engine" not in str(error)
153
+ else:
154
+ raise AssertionError("invalid engine selection accepted")
155
+
156
+
41
157
  def expected_entities(record: dict[str, object]) -> list[dict[str, object]]:
42
158
  return record["entities"] # type: ignore[return-value]
43
159
 
@@ -163,7 +279,10 @@ def verify_text_selection() -> None:
163
279
 
164
280
 
165
281
  def main() -> None:
282
+ verify_coverage_conflicts()
166
283
  verify_text_selection()
284
+ verify_account_number()
285
+ verify_street_address()
167
286
  capabilities_conformance.verify()
168
287
  german_conformance.verify()
169
288
  credential_overlap_conformance.verify()
@@ -505,5 +624,25 @@ def main() -> None:
505
624
  print("Installed datafog_core wheel matches fixtures and transform contracts.")
506
625
 
507
626
 
627
+ def verify_ssn_person_priority() -> None:
628
+ text = "👋 José: 123-45-6789"
629
+ ssn = next(finding for finding in scan(text) if finding.entity_type == "SSN")
630
+ person = Finding(
631
+ "PERSON", ssn.matched_text, ssn.byte_range, ssn.codepoint_range,
632
+ "semantic-person", 1.0,
633
+ )
634
+ for findings in ([ssn, person], [person, ssn]):
635
+ protected = transform(text, findings, {"default": {"strategy": "redact"}})
636
+ assert protected.text == "👋 José: [SSN]"
637
+ assert protected.transformations[0].entity_type == "SSN"
638
+ allowed = transform(text, findings, {
639
+ "default": {"strategy": "redact"},
640
+ "allow": {"exact": {"SSN": [ssn.matched_text]}},
641
+ })
642
+ assert allowed.text == "👋 José: [PERSON]"
643
+
644
+
508
645
  if __name__ == "__main__":
646
+ verify_model_engine_selection()
647
+ verify_ssn_person_priority()
509
648
  main()
@@ -21,8 +21,8 @@ def verify_integration():
21
21
  rows = [expand_fixture(json.loads(line)) for line in FIXTURES.read_text().splitlines()]
22
22
  capabilities = datafog_core.capabilities()
23
23
  assert capabilities["contract_version"] == 1
24
- assert len(capabilities["supported_entities"]) == 23
25
- assert len(capabilities["default_entities"]) == 14
24
+ assert len(capabilities["supported_entities"]) == 25
25
+ assert len(capabilities["default_entities"]) == 16
26
26
  assert {"API_KEY", "BEARER_TOKEN", "CREDENTIAL_URI"} <= set(
27
27
  capabilities["default_entities"]
28
28
  )