opaque_id 1.3.0 → 1.6.0
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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +136 -0
- data/README.md +62 -70
- data/docs/_config.yml +8 -17
- data/docs/algorithms.md +7 -4
- data/docs/alphabets.md +3 -0
- data/docs/api-reference.md +3 -0
- data/docs/assets/css/custom.scss +6 -53
- data/docs/configuration.md +3 -0
- data/docs/development.md +3 -0
- data/docs/getting-started.md +3 -0
- data/docs/index.md +6 -3
- data/docs/installation.md +3 -0
- data/docs/performance.md +6 -3
- data/docs/security.md +3 -0
- data/docs/usage.md +18 -15
- data/docs/use-cases.md +3 -0
- data/lib/opaque_id/version.rb +1 -1
- data/lib/opaque_id.rb +4 -1
- data/release-please-config.json +2 -1
- metadata +1 -9
- data/tasks/0001-prd-opaque-id-gem.md +0 -202
- data/tasks/0002-prd-publishing-release-automation.md +0 -206
- data/tasks/0003-prd-documentation-site.md +0 -191
- data/tasks/references/opaque_gem_requirements.md +0 -482
- data/tasks/references/original_identifiable_concern_and_nanoid.md +0 -110
- data/tasks/tasks-0001-prd-opaque-id-gem.md +0 -109
- data/tasks/tasks-0002-prd-publishing-release-automation.md +0 -177
- data/tasks/tasks-0003-prd-documentation-site.md +0 -84
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 016b3d2bbd7ae3af1ba38973c0b590164d7be1a4bd60a8c0e0379cfca1c9dc0f
|
4
|
+
data.tar.gz: 2924779f8769585995732ce79da51b8a1171c0b22fd33636c6476f77815adb44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82206f53378e08c302fbb9bd56caf94238e3b0780b6a271732d00d04f0e7e37136c1c6c941ef58fe6c6fffd154c7ce1b82c0b12b76240d23399007d34d81a0bd
|
7
|
+
data.tar.gz: b5d588f50a7a2337b42fc4e021b9aef658cf3e9f92c64fe5c21c7bf901560d5575b48c05fe72edefa77112175357562b0497c4c3d2ba73dd23be2165b6eadd87
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,142 @@ All notable changes to the OpaqueId gem will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [1.6.0](https://github.com/nyaggah/opaque_id/compare/opaque_id-v1.5.0...opaque_id/v1.6.0) (2025-10-03)
|
9
|
+
|
10
|
+
|
11
|
+
### Features
|
12
|
+
|
13
|
+
* add external links to sidebar using JavaScript ([cd77079](https://github.com/nyaggah/opaque_id/commit/cd770795936ca76633a18f80cba8482ec09db8e2))
|
14
|
+
* add SLUG_LIKE_ALPHABET as default for URL-safe IDs ([1e52b17](https://github.com/nyaggah/opaque_id/commit/1e52b174d70ca72b74badf399401605b307e3604))
|
15
|
+
* add Table of Contents to all documentation pages ([9472175](https://github.com/nyaggah/opaque_id/commit/94721752270211d5b7db460da61d79a8a81218b2))
|
16
|
+
* complete Table of Contents implementation ([5b037e4](https://github.com/nyaggah/opaque_id/commit/5b037e42692803204bc4d8991b6d2e0c9639a05c))
|
17
|
+
* implement dynamic copyright year ([b86cea6](https://github.com/nyaggah/opaque_id/commit/b86cea66e60939377c6b0a67c1d385c9bf4bece3))
|
18
|
+
* improve documentation site theme and navigation ([304f845](https://github.com/nyaggah/opaque_id/commit/304f845a47397ea2a15f12d2c635144b39be431b))
|
19
|
+
* improve generator API and add custom column configuration ([5c1a570](https://github.com/nyaggah/opaque_id/commit/5c1a5703dee269f6985d26096942c086787296f3))
|
20
|
+
* initial release of OpaqueId gem v0.1.0 ([3a90274](https://github.com/nyaggah/opaque_id/commit/3a9027403552f8160e3aaf413d1e99ce8c63bbe4))
|
21
|
+
|
22
|
+
|
23
|
+
### Bug Fixes
|
24
|
+
|
25
|
+
* add frozen string literal comment to docs/Gemfile ([2d653a7](https://github.com/nyaggah/opaque_id/commit/2d653a7bbc071e67e94e63ebc1602768b8d04456))
|
26
|
+
* add Release Please manifest and update workflow configuration ([f33ce6c](https://github.com/nyaggah/opaque_id/commit/f33ce6c96805b6c670cd1eedf5ebed2a46e8ffa6))
|
27
|
+
* add required permissions for Release Please job ([cdf8d2b](https://github.com/nyaggah/opaque_id/commit/cdf8d2bfc5dbea9a9ec40411a988191ba91913fa))
|
28
|
+
* configure just-the-docs theme for GitHub Pages compatibility ([c2fb96c](https://github.com/nyaggah/opaque_id/commit/c2fb96c46e99fd5287520e01c3bc2dd7bd5d4817))
|
29
|
+
* correct aux_links configuration format ([61b3fb9](https://github.com/nyaggah/opaque_id/commit/61b3fb9441ce3cfc3cf30637c277d19135f89dab))
|
30
|
+
* correct release-please tag format ([b4c31e5](https://github.com/nyaggah/opaque_id/commit/b4c31e5d0f4878878dd728e82fe9f5eb09ce5b82))
|
31
|
+
* improve publish workflow trigger reliability ([9c6e240](https://github.com/nyaggah/opaque_id/commit/9c6e2402474d8ecf8a3f754a9f2ca149a63bf1d1))
|
32
|
+
* improve statistical test reliability for CI ([c9b0d52](https://github.com/nyaggah/opaque_id/commit/c9b0d52fb4e9559aad489fcf58bdff1917d613a6))
|
33
|
+
* remove unsupported Release Please configuration parameters ([e3b0d2a](https://github.com/nyaggah/opaque_id/commit/e3b0d2ac96b905316a78992004fae83423991632))
|
34
|
+
* resolve CSS linting warnings ([d01e8c0](https://github.com/nyaggah/opaque_id/commit/d01e8c05628b7f2bd8b39a13325112168cf4e689))
|
35
|
+
* resolve dependency version conflicts and improve test robustness ([af43e13](https://github.com/nyaggah/opaque_id/commit/af43e13393a452f11ce32bafb26a267d1460736c))
|
36
|
+
* resolve TOC rendering and improve workflow configuration ([244d532](https://github.com/nyaggah/opaque_id/commit/244d5321e5b18091d8599bd772a28f5a30239c80))
|
37
|
+
* update deprecated platform specifications in docs/Gemfile ([cf96134](https://github.com/nyaggah/opaque_id/commit/cf9613499150dd7152bff38aa8f8fe7ab9923eb5))
|
38
|
+
* use correct aux_links format ([d4a4bc0](https://github.com/nyaggah/opaque_id/commit/d4a4bc0c11bc66b661034915b471ed762611d821))
|
39
|
+
|
40
|
+
|
41
|
+
### Documentation
|
42
|
+
|
43
|
+
* final cleanup of over-inflated claims ([795b5b0](https://github.com/nyaggah/opaque_id/commit/795b5b0071a098f718a40e84e81ceba4525b8d3b))
|
44
|
+
* implement comprehensive documentation site with dark theme ([19cc9e3](https://github.com/nyaggah/opaque_id/commit/19cc9e30c584658559c5404a4518e871039cc223))
|
45
|
+
* implement comprehensive documentation site with dark theme ([a249c6a](https://github.com/nyaggah/opaque_id/commit/a249c6ad2253439f0d070620a914ff87597cf7cb))
|
46
|
+
* tone down over-inflated claims and remove unsubstantiated benchmarks ([6536b87](https://github.com/nyaggah/opaque_id/commit/6536b87f9a9c2049497328319641ff21368c6032))
|
47
|
+
* tone down pretentious language in algorithms intro ([58c0caf](https://github.com/nyaggah/opaque_id/commit/58c0caf116228401b6218ec589a35b350d068b49))
|
48
|
+
|
49
|
+
|
50
|
+
### Styles
|
51
|
+
|
52
|
+
* improve code formatting in generator ([ce52021](https://github.com/nyaggah/opaque_id/commit/ce52021cd60e3594dc1ee34e5b96d48568008b5a))
|
53
|
+
|
54
|
+
|
55
|
+
### Miscellaneous Chores
|
56
|
+
|
57
|
+
* configure just-the-docs theme ([3dfcac8](https://github.com/nyaggah/opaque_id/commit/3dfcac88099e65e61931e558e9242050bdbf0bc9))
|
58
|
+
* **main:** release 1.0.0 ([43282c5](https://github.com/nyaggah/opaque_id/commit/43282c5865aae3f136c9eaa49f013066a2359826))
|
59
|
+
* **main:** release 1.0.0 ([b8271ad](https://github.com/nyaggah/opaque_id/commit/b8271ad43cf6fab4687276258f0105c06a87bff7))
|
60
|
+
* **main:** release 1.0.1 ([4ee2e2c](https://github.com/nyaggah/opaque_id/commit/4ee2e2c69905e71d6c5048617af09b65cbb9e12a))
|
61
|
+
* **main:** release 1.0.1 ([e6cd2f8](https://github.com/nyaggah/opaque_id/commit/e6cd2f8f8ff545ad3010598488f71956e36a88c5))
|
62
|
+
* **main:** release 1.0.2 ([d5c7423](https://github.com/nyaggah/opaque_id/commit/d5c7423cf06ae7638d95cdd29b2631049efed727))
|
63
|
+
* **main:** release 1.0.2 ([365dff8](https://github.com/nyaggah/opaque_id/commit/365dff87a044aa967906866d6ace8d1ccad08c78))
|
64
|
+
* **main:** release opaque_id 1.1.0 ([df65c79](https://github.com/nyaggah/opaque_id/commit/df65c79d0efaee1dcd89b8af2f1b1c712c3cc2cd))
|
65
|
+
* **main:** release opaque_id 1.1.0 ([e2a4ee0](https://github.com/nyaggah/opaque_id/commit/e2a4ee0fd2d31132bc5bc0de6b6115f3ceae8afb))
|
66
|
+
* **main:** release opaque_id 1.2.0 ([1987b07](https://github.com/nyaggah/opaque_id/commit/1987b07b3db92216f3fbbe807c3ad66ca105866e))
|
67
|
+
* **main:** release opaque_id 1.2.0 ([aacd20a](https://github.com/nyaggah/opaque_id/commit/aacd20aa5eaa1fe2fa76d89cc6bdab26214b744d))
|
68
|
+
* **main:** release opaque_id 1.3.0 ([964b1b4](https://github.com/nyaggah/opaque_id/commit/964b1b421b1fac3fe43b15549e0e6b216b600357))
|
69
|
+
* **main:** release opaque_id 1.3.0 ([76453ad](https://github.com/nyaggah/opaque_id/commit/76453ad18b2d2b81548e49dafb5dde6fb52abcca))
|
70
|
+
* **main:** release opaque_id 1.4.0 ([6c3ccd1](https://github.com/nyaggah/opaque_id/commit/6c3ccd108b3eea0bbf0ac71fda4ccc0e47e97b95))
|
71
|
+
* **main:** release opaque_id 1.4.0 ([3d9d818](https://github.com/nyaggah/opaque_id/commit/3d9d818b34771ad1ca729f3f9b443784a6965568))
|
72
|
+
* **main:** release opaque_id 1.5.0 ([113af74](https://github.com/nyaggah/opaque_id/commit/113af74dda07330bf7108977147362385dc806ae))
|
73
|
+
* **main:** release opaque_id 1.5.0 ([ff14fe9](https://github.com/nyaggah/opaque_id/commit/ff14fe92d94cf4ecbe5aaeb31ad6cd044bfa89d0))
|
74
|
+
* remove tasks/ directory from source control ([e007ead](https://github.com/nyaggah/opaque_id/commit/e007ead90fa3fbb62ab17e334563e69899afb259))
|
75
|
+
* sync version to 1.0.2 ([2f870c8](https://github.com/nyaggah/opaque_id/commit/2f870c89d486f0a5cda8ef37e5544c29c8fa2919))
|
76
|
+
* update author name and GitHub URLs ([e911548](https://github.com/nyaggah/opaque_id/commit/e911548e89e1e60ac3281157059f7c7b812750bd))
|
77
|
+
* update bundle and add Linux platform support ([661842f](https://github.com/nyaggah/opaque_id/commit/661842f0ba66ce36962bb11f75a1b0e35eb5a3e7))
|
78
|
+
* update Gemfile.lock after dependency check ([058281f](https://github.com/nyaggah/opaque_id/commit/058281f6e07f3c9a1057c6fbeb0200bccf221558))
|
79
|
+
|
80
|
+
|
81
|
+
### Code Refactoring
|
82
|
+
|
83
|
+
* improve generator code quality and resolve RuboCop issues ([b658bbc](https://github.com/nyaggah/opaque_id/commit/b658bbcb29f6c0134f2bf256b24c5b3c2bccb265))
|
84
|
+
* integrate Release Please into main CI workflow ([8a0b189](https://github.com/nyaggah/opaque_id/commit/8a0b189a8bfbfcc07275c9bdda3397ff367b2054))
|
85
|
+
* simplify external links implementation ([5cb84c1](https://github.com/nyaggah/opaque_id/commit/5cb84c1e8952a0fd1aa4b9089b9ff11829dc397c))
|
86
|
+
|
87
|
+
|
88
|
+
### Tests
|
89
|
+
|
90
|
+
* add test for lowercase model names ([8ef4675](https://github.com/nyaggah/opaque_id/commit/8ef4675a0698d2cda054084360c9e80d956ddb14))
|
91
|
+
* update tests for SLUG_LIKE_ALPHABET defaults ([d7296c7](https://github.com/nyaggah/opaque_id/commit/d7296c77b1b7a995e7a42b3ba546fdeb8e41c297))
|
92
|
+
* update tests for SLUG_LIKE_ALPHABET defaults ([d1f8f26](https://github.com/nyaggah/opaque_id/commit/d1f8f26e7be80f6cbefc98563c0ffa45033372dc))
|
93
|
+
|
94
|
+
## [1.5.0](https://github.com/nyaggah/opaque_id/compare/opaque_id/v1.4.0...opaque_id/v1.5.0) (2025-10-03)
|
95
|
+
|
96
|
+
|
97
|
+
### Features
|
98
|
+
|
99
|
+
* add SLUG_LIKE_ALPHABET as default for URL-safe IDs ([1e52b17](https://github.com/nyaggah/opaque_id/commit/1e52b174d70ca72b74badf399401605b307e3604))
|
100
|
+
|
101
|
+
|
102
|
+
### Bug Fixes
|
103
|
+
|
104
|
+
* resolve TOC rendering and improve workflow configuration ([244d532](https://github.com/nyaggah/opaque_id/commit/244d5321e5b18091d8599bd772a28f5a30239c80))
|
105
|
+
|
106
|
+
|
107
|
+
### Documentation
|
108
|
+
|
109
|
+
* final cleanup of over-inflated claims ([795b5b0](https://github.com/nyaggah/opaque_id/commit/795b5b0071a098f718a40e84e81ceba4525b8d3b))
|
110
|
+
* tone down over-inflated claims and remove unsubstantiated benchmarks ([6536b87](https://github.com/nyaggah/opaque_id/commit/6536b87f9a9c2049497328319641ff21368c6032))
|
111
|
+
* tone down pretentious language in algorithms intro ([58c0caf](https://github.com/nyaggah/opaque_id/commit/58c0caf116228401b6218ec589a35b350d068b49))
|
112
|
+
|
113
|
+
|
114
|
+
### Miscellaneous Chores
|
115
|
+
|
116
|
+
* remove tasks/ directory from source control ([e007ead](https://github.com/nyaggah/opaque_id/commit/e007ead90fa3fbb62ab17e334563e69899afb259))
|
117
|
+
|
118
|
+
|
119
|
+
### Tests
|
120
|
+
|
121
|
+
* update tests for SLUG_LIKE_ALPHABET defaults ([d7296c7](https://github.com/nyaggah/opaque_id/commit/d7296c77b1b7a995e7a42b3ba546fdeb8e41c297))
|
122
|
+
* update tests for SLUG_LIKE_ALPHABET defaults ([d1f8f26](https://github.com/nyaggah/opaque_id/commit/d1f8f26e7be80f6cbefc98563c0ffa45033372dc))
|
123
|
+
|
124
|
+
## [1.4.0](https://github.com/nyaggah/opaque_id/compare/opaque_id/v1.3.0...opaque_id/v1.4.0) (2025-10-02)
|
125
|
+
|
126
|
+
|
127
|
+
### Features
|
128
|
+
|
129
|
+
* add external links to sidebar using JavaScript ([cd77079](https://github.com/nyaggah/opaque_id/commit/cd770795936ca76633a18f80cba8482ec09db8e2))
|
130
|
+
* add Table of Contents to all documentation pages ([9472175](https://github.com/nyaggah/opaque_id/commit/94721752270211d5b7db460da61d79a8a81218b2))
|
131
|
+
* complete Table of Contents implementation ([5b037e4](https://github.com/nyaggah/opaque_id/commit/5b037e42692803204bc4d8991b6d2e0c9639a05c))
|
132
|
+
|
133
|
+
|
134
|
+
### Bug Fixes
|
135
|
+
|
136
|
+
* correct aux_links configuration format ([61b3fb9](https://github.com/nyaggah/opaque_id/commit/61b3fb9441ce3cfc3cf30637c277d19135f89dab))
|
137
|
+
* use correct aux_links format ([d4a4bc0](https://github.com/nyaggah/opaque_id/commit/d4a4bc0c11bc66b661034915b471ed762611d821))
|
138
|
+
|
139
|
+
|
140
|
+
### Code Refactoring
|
141
|
+
|
142
|
+
* simplify external links implementation ([5cb84c1](https://github.com/nyaggah/opaque_id/commit/5cb84c1e8952a0fd1aa4b9089b9ff11829dc397c))
|
143
|
+
|
8
144
|
## [1.3.0](https://github.com/nyaggah/opaque_id/compare/opaque_id/v1.2.0...opaque_id/v1.3.0) (2025-10-02)
|
9
145
|
|
10
146
|
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](https://github.com/rubocop/rubocop)
|
5
5
|
[](https://rubygems.org/gems/opaque_id)
|
6
6
|
|
7
|
-
A Ruby gem for generating
|
7
|
+
A simple Ruby gem for generating secure, opaque IDs for ActiveRecord models. OpaqueId provides a drop-in replacement for `nanoid.rb` using Ruby's built-in `SecureRandom` methods, with slug-like IDs as the default for optimal URL safety and user experience.
|
8
8
|
|
9
9
|
## Table of Contents
|
10
10
|
|
@@ -87,12 +87,12 @@ A Ruby gem for generating cryptographically secure, collision-free opaque IDs fo
|
|
87
87
|
## Features
|
88
88
|
|
89
89
|
- **🔐 Cryptographically Secure**: Uses Ruby's `SecureRandom` for secure ID generation
|
90
|
-
- **⚡
|
91
|
-
- **🎯 Collision
|
90
|
+
- **⚡ Performance Optimized**: Efficient algorithms with fast paths for 64-character alphabets
|
91
|
+
- **🎯 Collision Resistant**: Built-in collision detection with configurable retry attempts
|
92
92
|
- **🔧 Highly Configurable**: Customizable alphabet, length, column name, and validation rules
|
93
|
-
- **🚀 Rails Integration**:
|
93
|
+
- **🚀 Rails Integration**: ActiveRecord integration with automatic ID generation
|
94
94
|
- **📦 Rails Generator**: One-command setup with `rails generate opaque_id:install`
|
95
|
-
- **🧪
|
95
|
+
- **🧪 Tested**: Includes test suite with statistical uniformity tests
|
96
96
|
- **📚 Rails 8.0+ Compatible**: Built for modern Rails applications
|
97
97
|
|
98
98
|
## Installation
|
@@ -176,15 +176,34 @@ end
|
|
176
176
|
|
177
177
|
# IDs are automatically generated on creation
|
178
178
|
user = User.create!(name: "John Doe")
|
179
|
-
puts user.opaque_id # => "
|
179
|
+
puts user.opaque_id # => "izkpm55j334u8x9y2"
|
180
180
|
|
181
181
|
# Find by opaque ID
|
182
|
-
user = User.find_by_opaque_id("
|
183
|
-
user = User.find_by_opaque_id!("
|
182
|
+
user = User.find_by_opaque_id("izkpm55j334u8x9y2")
|
183
|
+
user = User.find_by_opaque_id!("izkpm55j334u8x9y2") # raises if not found
|
184
184
|
```
|
185
185
|
|
186
186
|
## Usage
|
187
187
|
|
188
|
+
### URL-Safe, Double-Click Selectable IDs
|
189
|
+
|
190
|
+
OpaqueId defaults to generating **slug-like IDs** that are perfect for URLs and user-facing identifiers:
|
191
|
+
|
192
|
+
- **URL-safe**: No special characters that need encoding
|
193
|
+
- **Double-click selectable**: Users can easily select the entire ID
|
194
|
+
- **Shorter than UUIDs**: 18 characters vs 36 for UUIDs
|
195
|
+
- **Collision resistant**: Built on Ruby's `SecureRandom` for security
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
# Default generation creates slug-like IDs
|
199
|
+
id = OpaqueId.generate
|
200
|
+
# => "izkpm55j334u8x9y2" # Perfect for URLs and user selection
|
201
|
+
|
202
|
+
# Compare to UUIDs
|
203
|
+
uuid = SecureRandom.uuid
|
204
|
+
# => "7cb776c5-8c12-4b1a-84aa-9941b815d873" # Harder to select, longer
|
205
|
+
```
|
206
|
+
|
188
207
|
### Standalone ID Generation
|
189
208
|
|
190
209
|
OpaqueId can be used independently of ActiveRecord for generating secure IDs in any Ruby application:
|
@@ -192,13 +211,13 @@ OpaqueId can be used independently of ActiveRecord for generating secure IDs in
|
|
192
211
|
#### Basic Usage
|
193
212
|
|
194
213
|
```ruby
|
195
|
-
# Generate with default settings (
|
214
|
+
# Generate with default settings (18 characters, slug-like)
|
196
215
|
id = OpaqueId.generate
|
197
|
-
# => "
|
216
|
+
# => "izkpm55j334u8x9y2"
|
198
217
|
|
199
218
|
# Custom length
|
200
219
|
id = OpaqueId.generate(size: 10)
|
201
|
-
# => "
|
220
|
+
# => "izkpm55j334u"
|
202
221
|
|
203
222
|
# Custom alphabet
|
204
223
|
id = OpaqueId.generate(alphabet: OpaqueId::STANDARD_ALPHABET)
|
@@ -210,7 +229,7 @@ id = OpaqueId.generate(size: 8, alphabet: "ABCDEFGH")
|
|
210
229
|
|
211
230
|
# Generate multiple IDs
|
212
231
|
ids = 5.times.map { OpaqueId.generate(size: 8) }
|
213
|
-
# => ["
|
232
|
+
# => ["izkpm55j", "334u8x9y", "2abc1234", "def5678g", "hij9klmn"]
|
214
233
|
```
|
215
234
|
|
216
235
|
#### Standalone Use Cases
|
@@ -229,7 +248,7 @@ class BackgroundJob
|
|
229
248
|
end
|
230
249
|
|
231
250
|
job_id = BackgroundJob.enqueue(ProcessDataJob, user_id: 123)
|
232
|
-
# => "
|
251
|
+
# => "izkpm55j334u8x9y2"
|
233
252
|
```
|
234
253
|
|
235
254
|
##### Temporary File Names
|
@@ -243,7 +262,7 @@ def create_temp_file(content)
|
|
243
262
|
end
|
244
263
|
|
245
264
|
filename = create_temp_file("Hello World")
|
246
|
-
# => "
|
265
|
+
# => "temp_izkpm55j334u8x9y2.txt"
|
247
266
|
```
|
248
267
|
|
249
268
|
##### Cache Keys
|
@@ -264,7 +283,7 @@ user_key = CacheManager.user_cache_key(123)
|
|
264
283
|
# => "user:V1StGX:123"
|
265
284
|
|
266
285
|
session_key = CacheManager.session_cache_key
|
267
|
-
# => "session:
|
286
|
+
# => "session:izkpm55j334u8x9y2"
|
268
287
|
```
|
269
288
|
|
270
289
|
##### Webhook Signatures
|
@@ -281,7 +300,7 @@ class WebhookService
|
|
281
300
|
end
|
282
301
|
|
283
302
|
signature = WebhookService.generate_signature({ user_id: 123 })
|
284
|
-
# => "1703123456:
|
303
|
+
# => "1703123456:izkpm55j334u8x9y2:1234567890"
|
285
304
|
```
|
286
305
|
|
287
306
|
##### Database Migration IDs
|
@@ -309,7 +328,7 @@ class EmailService
|
|
309
328
|
end
|
310
329
|
|
311
330
|
tracking_id = EmailService.tracking_pixel_id
|
312
|
-
# => "
|
331
|
+
# => "izkpm55j334u8x9y2abc"
|
313
332
|
|
314
333
|
# Use in email template
|
315
334
|
# <img src="https://example.com/track/#{tracking_id}" width="1" height="1" />
|
@@ -328,7 +347,7 @@ class ApiLogger
|
|
328
347
|
end
|
329
348
|
|
330
349
|
request_id = ApiLogger.log_request("/api/users", { page: 1 })
|
331
|
-
# => "
|
350
|
+
# => "izkpm55j334u8x9y2"
|
332
351
|
```
|
333
352
|
|
334
353
|
##### Batch Processing IDs
|
@@ -350,9 +369,9 @@ class BatchProcessor
|
|
350
369
|
end
|
351
370
|
|
352
371
|
batch_id = BatchProcessor.process_batch([1, 2, 3, 4, 5])
|
353
|
-
# => "
|
354
|
-
# => Processing item
|
355
|
-
# => Processing item
|
372
|
+
# => "izkpm55j334u8x9y2"
|
373
|
+
# => Processing item izkpm55j334u8x9y2_000: 1
|
374
|
+
# => Processing item izkpm55j334u8x9y2_001: 2
|
356
375
|
# => ...
|
357
376
|
```
|
358
377
|
|
@@ -417,7 +436,7 @@ end
|
|
417
436
|
|
418
437
|
# Create a new post - opaque_id is automatically generated
|
419
438
|
post = Post.create!(title: "Hello World", content: "This is my first post")
|
420
|
-
puts post.opaque_id # => "
|
439
|
+
puts post.opaque_id # => "izkpm55j334u8x9y2"
|
421
440
|
|
422
441
|
# Create multiple posts
|
423
442
|
posts = Post.create!([
|
@@ -427,9 +446,9 @@ posts = Post.create!([
|
|
427
446
|
])
|
428
447
|
|
429
448
|
posts.each { |p| puts "#{p.title}: #{p.opaque_id}" }
|
430
|
-
# => Post 1:
|
431
|
-
# => Post 2:
|
432
|
-
# => Post 3:
|
449
|
+
# => Post 1: izkpm55j334u8x9y2
|
450
|
+
# => Post 2: 334u8x9y2abc1234
|
451
|
+
# => Post 3: abc1234def5678gh
|
433
452
|
```
|
434
453
|
|
435
454
|
#### Custom Configuration
|
@@ -482,7 +501,7 @@ class ApiKey < ApplicationRecord
|
|
482
501
|
self.opaque_id_max_retry = 10
|
483
502
|
end
|
484
503
|
|
485
|
-
# Generated API keys will look like: "
|
504
|
+
# Generated API keys will look like: "izkpm55j334u8x9y2abc1234def5678gh"
|
486
505
|
```
|
487
506
|
|
488
507
|
##### Short URL Configuration
|
@@ -529,7 +548,7 @@ class Upload < ApplicationRecord
|
|
529
548
|
self.opaque_id_purge_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|']
|
530
549
|
end
|
531
550
|
|
532
|
-
# Generated filenames will look like: "
|
551
|
+
# Generated filenames will look like: "izkpm55j334u8x9y2"
|
533
552
|
```
|
534
553
|
|
535
554
|
##### Session Token Configuration
|
@@ -554,7 +573,7 @@ class Session < ApplicationRecord
|
|
554
573
|
self.opaque_id_max_retry = 8
|
555
574
|
end
|
556
575
|
|
557
|
-
# Generated session tokens will look like: "
|
576
|
+
# Generated session tokens will look like: "izkpm55j334u8x9y2abc123"
|
558
577
|
```
|
559
578
|
|
560
579
|
##### Custom Alphabet Examples
|
@@ -592,7 +611,7 @@ end
|
|
592
611
|
|
593
612
|
```ruby
|
594
613
|
# Find by opaque ID (returns nil if not found)
|
595
|
-
user = User.find_by_opaque_id("
|
614
|
+
user = User.find_by_opaque_id("izkpm55j334u8x9y2")
|
596
615
|
if user
|
597
616
|
puts "Found user: #{user.name}"
|
598
617
|
else
|
@@ -600,14 +619,14 @@ else
|
|
600
619
|
end
|
601
620
|
|
602
621
|
# Find by opaque ID (raises ActiveRecord::RecordNotFound if not found)
|
603
|
-
user = User.find_by_opaque_id!("
|
622
|
+
user = User.find_by_opaque_id!("izkpm55j334u8x9y2")
|
604
623
|
puts "Found user: #{user.name}"
|
605
624
|
|
606
625
|
# Use in controllers for public-facing URLs
|
607
626
|
class PostsController < ApplicationController
|
608
627
|
def show
|
609
628
|
@post = Post.find_by_opaque_id!(params[:id])
|
610
|
-
# This allows URLs like /posts/
|
629
|
+
# This allows URLs like /posts/izkpm55j334u8x9y2
|
611
630
|
end
|
612
631
|
end
|
613
632
|
|
@@ -672,8 +691,8 @@ OpaqueId provides comprehensive configuration options to customize ID generation
|
|
672
691
|
- **Performance**: Longer IDs are more secure but use more storage
|
673
692
|
- **Examples**:
|
674
693
|
- `6` → Short URLs: `"V1StGX"`
|
675
|
-
- `
|
676
|
-
- `32` → API Keys: `"
|
694
|
+
- `18` → Default: `"izkpm55j334u8x9y2"`
|
695
|
+
- `32` → API Keys: `"izkpm55j334u8x9y2abc1234def5678gh"`
|
677
696
|
|
678
697
|
#### `opaque_id_alphabet`
|
679
698
|
|
@@ -691,7 +710,7 @@ OpaqueId provides comprehensive configuration options to customize ID generation
|
|
691
710
|
- **Purpose**: Ensures IDs start with a letter for better readability
|
692
711
|
- **Use Cases**: When IDs are user-facing or need to be easily readable
|
693
712
|
- **Performance**: Slight overhead due to rejection sampling
|
694
|
-
- **Example**: `true` → `"
|
713
|
+
- **Example**: `true` → `"izkpm55j334u8x9y2"`, `false` → `"zkpm55j334u8x9y2"`
|
695
714
|
|
696
715
|
#### `opaque_id_purge_chars`
|
697
716
|
|
@@ -744,7 +763,7 @@ OpaqueId::ALPHANUMERIC_ALPHABET
|
|
744
763
|
|
745
764
|
```ruby
|
746
765
|
OpaqueId.generate(size: 8, alphabet: OpaqueId::ALPHANUMERIC_ALPHABET)
|
747
|
-
# => "
|
766
|
+
# => "izkpm55j"
|
748
767
|
```
|
749
768
|
|
750
769
|
### `STANDARD_ALPHABET`
|
@@ -932,41 +951,14 @@ def generate(size:, alphabet:)
|
|
932
951
|
end
|
933
952
|
```
|
934
953
|
|
935
|
-
## Performance
|
936
|
-
|
937
|
-
### Generation Speed (IDs per second)
|
938
|
-
|
939
|
-
| Alphabet Size | Algorithm | Performance | Relative Speed |
|
940
|
-
| ------------- | --------- | ------------------ | --------------- |
|
941
|
-
| 64 characters | Fast Path | ~2,500,000 IDs/sec | 100% (baseline) |
|
942
|
-
| 62 characters | Unbiased | ~1,200,000 IDs/sec | 48% |
|
943
|
-
| 36 characters | Unbiased | ~1,100,000 IDs/sec | 44% |
|
944
|
-
| 26 characters | Unbiased | ~1,000,000 IDs/sec | 40% |
|
945
|
-
| 10 characters | Unbiased | ~900,000 IDs/sec | 36% |
|
946
|
-
|
947
|
-
_Benchmarks run on Ruby 3.2.0, generating 21-character IDs_
|
948
|
-
|
949
|
-
### Memory Usage
|
950
|
-
|
951
|
-
| Algorithm | Memory per ID | Memory per 1M IDs |
|
952
|
-
| --------- | ------------- | ----------------- |
|
953
|
-
| Fast Path | ~21 bytes | ~21 MB |
|
954
|
-
| Unbiased | ~21 bytes | ~21 MB |
|
955
|
-
|
956
|
-
_Memory usage is consistent regardless of algorithm choice_
|
957
|
-
|
958
|
-
### Collision Probability
|
959
|
-
|
960
|
-
For 21-character IDs with different alphabets:
|
954
|
+
## Performance Characteristics
|
961
955
|
|
962
|
-
|
963
|
-
| --------------------- | ---------- | ---------------------------- |
|
964
|
-
| STANDARD_ALPHABET | 64 | 2.9 × 10^37 |
|
965
|
-
| ALPHANUMERIC_ALPHABET | 62 | 1.4 × 10^37 |
|
966
|
-
| Numeric (0-9) | 10 | 1.0 × 10^21 |
|
967
|
-
| Binary (0-1) | 2 | 2.1 × 10^6 |
|
956
|
+
OpaqueId is designed for efficient ID generation with different performance characteristics based on alphabet size:
|
968
957
|
|
969
|
-
|
958
|
+
- **64-character alphabets**: Use optimized bitwise operations for faster generation
|
959
|
+
- **Other alphabets**: Use rejection sampling for unbiased distribution with slight overhead
|
960
|
+
- **Memory usage**: Scales linearly with ID length
|
961
|
+
- **Collision resistance**: Extremely low probability for typical use cases
|
970
962
|
|
971
963
|
### Performance Characteristics
|
972
964
|
|
@@ -975,7 +967,7 @@ _Collision probability calculated using birthday paradox formula_
|
|
975
967
|
- **Time Complexity**: O(n) where n = ID length
|
976
968
|
- **Space Complexity**: O(n)
|
977
969
|
- **Rejection Rate**: 0% (no rejections)
|
978
|
-
- **Distribution**:
|
970
|
+
- **Distribution**: Uniform distribution
|
979
971
|
- **Best For**: High-performance applications, short URLs
|
980
972
|
|
981
973
|
#### Unbiased Path (other alphabets)
|
@@ -983,7 +975,7 @@ _Collision probability calculated using birthday paradox formula_
|
|
983
975
|
- **Time Complexity**: O(n × (1 + rejection_rate)) where rejection_rate ≈ 0.01
|
984
976
|
- **Space Complexity**: O(n)
|
985
977
|
- **Rejection Rate**: <1% for most alphabet sizes
|
986
|
-
- **Distribution**:
|
978
|
+
- **Distribution**: Uniform distribution using rejection sampling
|
987
979
|
- **Best For**: General-purpose applications, custom alphabets
|
988
980
|
|
989
981
|
### Real-World Performance
|
data/docs/_config.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Site settings
|
2
|
-
title: OpaqueId
|
2
|
+
title: OpaqueId
|
3
3
|
description: Generate cryptographically secure, collision-free opaque IDs for ActiveRecord models
|
4
4
|
url: "https://nyaggah.github.io"
|
5
5
|
baseurl: "/opaque_id"
|
@@ -88,6 +88,8 @@ kramdown:
|
|
88
88
|
block:
|
89
89
|
line_numbers: false
|
90
90
|
start_line: 1
|
91
|
+
auto_id: true
|
92
|
+
table_of_contents: true
|
91
93
|
|
92
94
|
# Custom head includes
|
93
95
|
head_scripts:
|
@@ -104,23 +106,12 @@ nav_external_links_new_tab: true
|
|
104
106
|
nav_footer: true
|
105
107
|
nav_order: 1
|
106
108
|
|
107
|
-
#
|
108
|
-
header_links:
|
109
|
-
- title: "GitHub"
|
110
|
-
url: "https://github.com/nyaggah/opaque_id"
|
111
|
-
- title: "RubyGems"
|
112
|
-
url: "https://rubygems.org/gems/opaque_id"
|
113
|
-
|
114
|
-
# Auxiliary links (moved to sidebar top)
|
109
|
+
# Auxiliary links (appear at top right)
|
115
110
|
aux_links:
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
- title: "Issues"
|
121
|
-
url: "https://github.com/nyaggah/opaque_id/issues"
|
122
|
-
- title: "Releases"
|
123
|
-
url: "https://github.com/nyaggah/opaque_id/releases"
|
111
|
+
GitHub: https://github.com/nyaggah/opaque_id
|
112
|
+
RubyGems: https://rubygems.org/gems/opaque_id
|
113
|
+
Issues: https://github.com/nyaggah/opaque_id/issues
|
114
|
+
Releases: https://github.com/nyaggah/opaque_id/releases
|
124
115
|
|
125
116
|
# Color scheme - use system theme with light fallback
|
126
117
|
color_scheme: light
|
data/docs/algorithms.md
CHANGED
@@ -8,7 +8,10 @@ permalink: /algorithms/
|
|
8
8
|
|
9
9
|
# Algorithms
|
10
10
|
|
11
|
-
OpaqueId
|
11
|
+
OpaqueId builds on Ruby's built-in `SecureRandom` methods to generate cryptographically secure, collision-free opaque IDs. This guide explains the technical details behind the generation process, optimization strategies, and mathematical foundations.
|
12
|
+
|
13
|
+
- TOC
|
14
|
+
{:toc}
|
12
15
|
|
13
16
|
## Overview
|
14
17
|
|
@@ -42,10 +45,10 @@ end
|
|
42
45
|
|
43
46
|
### Key Features
|
44
47
|
|
45
|
-
- **Bitwise Operations**: Uses `byte & 63` instead of `byte % 64` for
|
48
|
+
- **Bitwise Operations**: Uses `byte & 63` instead of `byte % 64` for efficient computation
|
46
49
|
- **No Modulo Bias**: 64 is a power of 2, so bitwise AND provides uniform distribution
|
47
50
|
- **Single Random Call**: One `SecureRandom.random_bytes(1)` call per character
|
48
|
-
- **
|
51
|
+
- **Performance Optimized**: Designed for speed with 64-character alphabets
|
49
52
|
|
50
53
|
### Mathematical Foundation
|
51
54
|
|
@@ -57,7 +60,7 @@ For a 64-character alphabet:
|
|
57
60
|
|
58
61
|
### Performance Characteristics
|
59
62
|
|
60
|
-
- **Optimized for speed**: Uses bitwise operations for
|
63
|
+
- **Optimized for speed**: Uses bitwise operations for efficient performance
|
61
64
|
- **No rejection sampling**: All generated bytes are used efficiently
|
62
65
|
- **Linear time complexity**: O(n) where n is the ID length
|
63
66
|
|
data/docs/alphabets.md
CHANGED
@@ -10,6 +10,9 @@ permalink: /alphabets/
|
|
10
10
|
|
11
11
|
OpaqueId provides flexible alphabet configuration for generating IDs with different character sets. This guide covers built-in alphabets, custom alphabet creation, and best practices for alphabet selection.
|
12
12
|
|
13
|
+
- TOC
|
14
|
+
{:toc}
|
15
|
+
|
13
16
|
## Built-in Alphabets
|
14
17
|
|
15
18
|
OpaqueId comes with two pre-configured alphabets optimized for different use cases.
|
data/docs/api-reference.md
CHANGED
data/docs/assets/css/custom.scss
CHANGED
@@ -292,59 +292,12 @@ table {
|
|
292
292
|
color: var(--nav-child-link-color);
|
293
293
|
}
|
294
294
|
|
295
|
-
//
|
296
|
-
.
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
.aux-nav-list {
|
302
|
-
list-style: none;
|
303
|
-
margin: 0;
|
304
|
-
padding: 0;
|
305
|
-
display: flex;
|
306
|
-
flex-wrap: wrap;
|
307
|
-
gap: 0.5rem;
|
308
|
-
|
309
|
-
.aux-nav-list-item {
|
310
|
-
margin: 0;
|
311
|
-
|
312
|
-
.aux-nav-list-link {
|
313
|
-
display: inline-flex;
|
314
|
-
align-items: center;
|
315
|
-
padding: 0.375rem 0.75rem;
|
316
|
-
font-size: 0.875rem;
|
317
|
-
font-weight: 500;
|
318
|
-
color: var(--aux-link-color);
|
319
|
-
text-decoration: none;
|
320
|
-
border: 1px solid var(--border-color);
|
321
|
-
border-radius: 6px;
|
322
|
-
background-color: transparent;
|
323
|
-
transition: all 0.2s ease;
|
324
|
-
|
325
|
-
&:hover {
|
326
|
-
color: var(--aux-link-hover-color);
|
327
|
-
border-color: var(--aux-link-hover-color);
|
328
|
-
background-color: rgba(168, 85, 247, 0.05);
|
329
|
-
text-decoration: none;
|
330
|
-
}
|
331
|
-
|
332
|
-
&:focus {
|
333
|
-
outline: 2px solid var(--aux-link-hover-color);
|
334
|
-
outline-offset: 2px;
|
335
|
-
}
|
336
|
-
|
337
|
-
// External link icon
|
338
|
-
&[href^="http"]:not([href*="nyaggah.github.io"]) {
|
339
|
-
&::after {
|
340
|
-
content: "↗";
|
341
|
-
margin-left: 0.25rem;
|
342
|
-
font-size: 0.75rem;
|
343
|
-
opacity: 0.7;
|
344
|
-
}
|
345
|
-
}
|
346
|
-
}
|
347
|
-
}
|
295
|
+
// Simple external links styling
|
296
|
+
.nav-list .nav-list-item .nav-list-link[href^="http"] {
|
297
|
+
color: var(--link-color);
|
298
|
+
|
299
|
+
&:hover {
|
300
|
+
color: var(--link-color-hover);
|
348
301
|
}
|
349
302
|
}
|
350
303
|
|
data/docs/configuration.md
CHANGED
@@ -10,6 +10,9 @@ permalink: /configuration/
|
|
10
10
|
|
11
11
|
OpaqueId provides extensive configuration options to customize ID generation for your specific needs. This guide covers all available configuration options with practical examples.
|
12
12
|
|
13
|
+
- TOC
|
14
|
+
{:toc}
|
15
|
+
|
13
16
|
## Model-Level Configuration
|
14
17
|
|
15
18
|
Configure OpaqueId on a per-model basis using class-level settings.
|