seedfaker 0.1.0.pre.alpha.14

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4feee9521a45b7a08d1c097de5cc7aceb2c9be089743ff09cc4864c8b7e6a08d
4
+ data.tar.gz: 95f797bdd2d715d5d87cefcfecb59aaab432aa11f2b8c13160e7dadec2f96c9d
5
+ SHA512:
6
+ metadata.gz: 4b347226906654ad572fd40814343dfec5258002fc72c17c57c40cf5ae1e47c805f90bdcec6c2c538ca6d9cdcd92fd20e6eeb5aa76a737ca7eed1e983eb5369a
7
+ data.tar.gz: 523d7910306710bec2e1a93227ea95b83a4a0f28378b6d595ebb65834430ca1c091ed3cbb403e1c9e7f1c3c6f819f41d137d8547e8be50368173e613d2cf26cd
data/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eduard Titov and seedfaker contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ADDITIONAL NOTICE — SYNTHETIC DATA AND LIABILITY
24
+
25
+ This software generates synthetic data that mimics the format and
26
+ appearance of real-world data. The generated output is artificial and
27
+ does not represent real, validated, or authoritative data.
28
+
29
+ The output may resemble sensitive or structured data, including but not
30
+ limited to credentials, identifiers, financial data, government-issued
31
+ identifiers, network values, or cryptographic-looking values. Such
32
+ output is provided solely as synthetic data and does not guarantee
33
+ uniqueness, correctness, validity, compliance with any standard, or
34
+ cryptographic security.
35
+
36
+ The output may be deterministic or predictable (including through the
37
+ use of seeds).
38
+
39
+ Generated data MUST NOT be relied upon as secure, unique,
40
+ standard-compliant, or fit for authentication, authorization, financial,
41
+ cryptographic, or identity-related use.
42
+
43
+ The software does not guarantee that generated data is unique or free
44
+ from similarity to real-world data. Any similarity or correspondence to
45
+ real persons, accounts, credentials, identifiers, or other data is
46
+ purely coincidental.
47
+
48
+ The user is solely responsible for any use of the software and generated
49
+ data, including use in production systems and any resulting data leaks,
50
+ security incidents, financial loss, or regulatory consequences.
51
+
52
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTIES OF ANY KIND.
53
+
54
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
55
+ CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM OR RELATED TO THE USE
56
+ OR MISUSE OF THE SOFTWARE OR GENERATED DATA.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # seedfaker
2
+
3
+ Ruby FFI binding for [seedfaker](https://github.com/opendsr-std/seedfaker).
4
+
5
+ [CLI](https://github.com/opendsr-std/seedfaker) · [Node.js](https://www.npmjs.com/package/@opendsr/seedfaker) · [Python](https://pypi.org/project/seedfaker/) · [Browser/WASM](https://www.npmjs.com/package/@opendsr/seedfaker-wasm) · [Go](https://github.com/opendsr-std/seedfaker-go) · [PHP](https://packagist.org/packages/opendsr/seedfaker) · **Ruby** · [MCP](https://github.com/opendsr-std/seedfaker/blob/main/docs/mcp.md)
6
+
7
+ ## Requirements
8
+
9
+ - Ruby >= 3.1
10
+ - `libseedfaker_ffi` shared library (built from Rust source)
11
+
12
+ > **Pre-1.0:** API may change between minor versions. Pin your version.
13
+
14
+ ## Usage
15
+
16
+ ```ruby
17
+ require "seedfaker"
18
+
19
+ f = Seedfaker::SeedFaker.new(seed: "ci", locale: "en")
20
+
21
+ f.field("name") # "Zoe Kumar"
22
+ f.field("phone", e164: true) # "+14155551234"
23
+
24
+ f.record(["name", "email"], ctx: "strict") # single record
25
+ f.records(["name", "email"], n: 5, ctx: "strict") # batch
26
+ f.validate(["name", "email:e164"]) # check without generating
27
+
28
+ f.records(["name", "email"], n: 100, corrupt: "high") # corrupted data
29
+
30
+ Seedfaker::SeedFaker.fingerprint # "sf0-..."
31
+ Seedfaker::SeedFaker.fields # all field names
32
+ ```
33
+
34
+ ## Documentation
35
+
36
+ - [Quick start](https://github.com/opendsr-std/seedfaker/blob/main/docs/quick-start.md)
37
+ - [Field reference (200+ fields)](https://github.com/opendsr-std/seedfaker/blob/main/docs/field-reference.md)
38
+ - [Library API](https://github.com/opendsr-std/seedfaker/blob/main/docs/library.md)
39
+ - [Full documentation](https://github.com/opendsr-std/seedfaker)
40
+
41
+ ---
42
+
43
+ ## Disclaimer
44
+
45
+ This software generates synthetic data that may resemble real-world identifiers, credentials, or personal information. All output is artificial. See [LICENSE](https://github.com/opendsr-std/seedfaker/blob/main/LICENSE) for the full legal disclaimer.
Binary file
data/lib/seedfaker.rb ADDED
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+ require "fiddle"
5
+ require "fiddle/import"
6
+ require "json"
7
+
8
+ module Seedfaker
9
+ class SeedFaker
10
+ def initialize(seed: nil, locale: nil, tz: nil, since: nil, until_time: nil)
11
+ lib = Seedfaker.find_library
12
+ raise "seedfaker: native FFI library not found" unless lib
13
+
14
+ @ffi = Fiddle.dlopen(lib)
15
+ opts = JSON.generate({
16
+ seed: seed, locale: locale, tz: tz,
17
+ since: since&.to_i, until: until_time&.to_i
18
+ }.compact)
19
+ @sf_create = Fiddle::Function.new(@ffi["sf_create"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
20
+ @sf_destroy = Fiddle::Function.new(@ffi["sf_destroy"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)
21
+ @sf_field = Fiddle::Function.new(@ffi["sf_field"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
22
+ @sf_records = Fiddle::Function.new(@ffi["sf_records"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
23
+ @sf_record = Fiddle::Function.new(@ffi["sf_record"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
24
+ @sf_validate = Fiddle::Function.new(@ffi["sf_validate"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
25
+ @sf_free = Fiddle::Function.new(@ffi["sf_free"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)
26
+ @sf_last_error = Fiddle::Function.new(@ffi["sf_last_error"], [], Fiddle::TYPE_VOIDP)
27
+ @handle = @sf_create.call(opts)
28
+ raise "sf_create failed: #{last_error}" if @handle.null?
29
+
30
+ ObjectSpace.define_finalizer(self, SeedFaker.invoke_release(@sf_destroy, @handle))
31
+ end
32
+
33
+ def self.invoke_release(sf_destroy, handle)
34
+ proc { sf_destroy.call(handle) }
35
+ end
36
+
37
+ def field(name, n: 1, **opts)
38
+ spec = build_spec(name, opts)
39
+ if n == 1
40
+ field_one(spec)
41
+ else
42
+ Array.new(n) { field_one(spec) }
43
+ end
44
+ end
45
+
46
+ def record(fields, ctx: nil, corrupt: nil)
47
+ opts = JSON.generate({ fields: fields, ctx: ctx, corrupt: corrupt }.compact)
48
+ ptr = @sf_record.call(@handle, opts)
49
+ raise "sf_record failed: #{last_error}" if ptr.null?
50
+ json = ptr.to_s
51
+ @sf_free.call(ptr)
52
+ JSON.parse(json)
53
+ end
54
+
55
+ def records(fields, n: 1, ctx: nil, corrupt: nil)
56
+ opts = JSON.generate({ fields: fields, n: n, ctx: ctx, corrupt: corrupt }.compact)
57
+ ptr = @sf_records.call(@handle, opts)
58
+ raise "sf_records failed: #{last_error}" if ptr.null?
59
+ json = ptr.to_s
60
+ @sf_free.call(ptr)
61
+ JSON.parse(json)
62
+ end
63
+
64
+ def validate(fields, ctx: nil, corrupt: nil)
65
+ opts = JSON.generate({ fields: fields, ctx: ctx, corrupt: corrupt }.compact)
66
+ ptr = @sf_validate.call(@handle, opts)
67
+ raise "validate failed: #{last_error}" if ptr.null?
68
+ @sf_free.call(ptr)
69
+ nil
70
+ end
71
+
72
+ def self.fields
73
+ lib = Seedfaker.find_library
74
+ raise "seedfaker: native FFI library not found" unless lib
75
+
76
+ ffi = Fiddle.dlopen(lib)
77
+ sf_fields = Fiddle::Function.new(ffi["sf_fields_json"], [], Fiddle::TYPE_VOIDP)
78
+ sf_free = Fiddle::Function.new(ffi["sf_free"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)
79
+ ptr = sf_fields.call
80
+ json = ptr.to_s
81
+ sf_free.call(ptr)
82
+ JSON.parse(json).map { |f| f["name"] }
83
+ end
84
+
85
+ def self.fingerprint
86
+ lib = Seedfaker.find_library
87
+ raise "seedfaker: native FFI library not found" unless lib
88
+
89
+ ffi = Fiddle.dlopen(lib)
90
+ sf_fp = Fiddle::Function.new(ffi["sf_fingerprint"], [], Fiddle::TYPE_VOIDP)
91
+ sf_free = Fiddle::Function.new(ffi["sf_free"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)
92
+ ptr = sf_fp.call
93
+ val = ptr.to_s
94
+ sf_free.call(ptr)
95
+ val
96
+ end
97
+
98
+ private
99
+
100
+ def field_one(spec)
101
+ ptr = @sf_field.call(@handle, spec)
102
+ raise "sf_field failed for #{spec}: #{last_error}" if ptr.null?
103
+ val = ptr.to_s
104
+ @sf_free.call(ptr)
105
+ val
106
+ end
107
+
108
+ def build_spec(name, opts)
109
+ skip = %i[n]
110
+ parts = [name.to_s]
111
+ opts.each do |k, v|
112
+ next if skip.include?(k)
113
+ # Strip 'r' prefix for digit-starting modifiers (r1x1 → 1x1)
114
+ seg = k.to_s
115
+ seg = seg[1..] if seg.length > 1 && seg[0] == "r" && seg[1].match?(/\d/)
116
+ if k == :range && v.is_a?(Array)
117
+ parts << "#{v[0]}..#{v[1]}"
118
+ elsif v == true
119
+ parts << seg
120
+ elsif v.is_a?(Integer) && k == :omit
121
+ parts << "omit=#{v}"
122
+ elsif v.is_a?(Integer) && k == :length
123
+ parts << v.to_s
124
+ end
125
+ end
126
+ parts.join(":")
127
+ end
128
+
129
+ def last_error
130
+ ptr = @sf_last_error.call
131
+ ptr.null? ? "unknown error" : ptr.to_s
132
+ end
133
+
134
+ end
135
+
136
+ # @checksum-start
137
+ # CI replaces this with real SHA256 before building gem.
138
+ # Empty = dev (running from source). Filled = production (verify mandatory).
139
+ NATIVE_CHECKSUM = ""
140
+ # @checksum-end
141
+
142
+ def self.find_library
143
+ ext = case RbConfig::CONFIG["host_os"]
144
+ when /darwin/ then "dylib"
145
+ when /mswin|mingw/ then "dll"
146
+ else "so"
147
+ end
148
+ name = "libseedfaker_ffi.#{ext}"
149
+
150
+ if NATIVE_CHECKSUM != ""
151
+ # Production: bundled binary only, verify SHA256, no exceptions.
152
+ bundled = File.join(__dir__, "..", "bin", name)
153
+ raise "seedfaker: bundled library not found at #{bundled}" unless File.exist?(bundled)
154
+ actual = Digest::SHA256.hexdigest(File.binread(bundled))
155
+ unless actual == NATIVE_CHECKSUM
156
+ raise "seedfaker: native library integrity check failed. " \
157
+ "Expected #{NATIVE_CHECKSUM[0, 16]}..., got #{actual[0, 16]}... " \
158
+ "Reinstall the package or verify your installation."
159
+ end
160
+ return bundled
161
+ end
162
+
163
+ # Dev: NATIVE_CHECKSUM empty = running from source.
164
+ bundled = File.join(__dir__, "..", "bin", name)
165
+ return bundled if File.exist?(bundled)
166
+
167
+ project = File.join(__dir__, "..", "..", "..", "rust", "target", "release", name)
168
+ return project if File.exist?(project)
169
+
170
+ nil
171
+ end
172
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: seedfaker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.alpha.14
5
+ platform: ruby
6
+ authors:
7
+ - Eduard Titov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 200+ fields, 68 locales. Same seed = same output across CLI, Python,
14
+ Node.js, Go, PHP, Ruby.
15
+ email: editied@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - bin/darwin-arm64/libseedfaker_ffi.dylib
23
+ - bin/darwin-x86_64/libseedfaker_ffi.dylib
24
+ - bin/linux-arm64/libseedfaker_ffi.so
25
+ - bin/linux-x86_64/libseedfaker_ffi.so
26
+ - lib/seedfaker.rb
27
+ homepage: https://github.com/opendsr-std/seedfaker
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.7'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubygems_version: 3.5.22
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Deterministic synthetic data generator
50
+ test_files: []