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 +7 -0
- data/LICENSE +56 -0
- data/README.md +45 -0
- data/bin/darwin-arm64/libseedfaker_ffi.dylib +0 -0
- data/bin/darwin-x86_64/libseedfaker_ffi.dylib +0 -0
- data/bin/linux-arm64/libseedfaker_ffi.so +0 -0
- data/bin/linux-x86_64/libseedfaker_ffi.so +0 -0
- data/lib/seedfaker.rb +172 -0
- metadata +50 -0
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
|
|
Binary file
|
|
Binary file
|
|
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: []
|