opaque_id 1.2.0 → 1.4.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 +48 -0
- data/CODE_OF_CONDUCT.md +11 -11
- data/README.md +82 -0
- data/docs/.gitignore +5 -0
- data/docs/404.html +25 -0
- data/docs/Gemfile +31 -0
- data/docs/Gemfile.lock +335 -0
- data/docs/_config.yml +151 -0
- data/docs/_data/navigation.yml +132 -0
- data/docs/_includes/footer_custom.html +8 -0
- data/docs/_includes/head_custom.html +67 -0
- data/docs/algorithms.md +412 -0
- data/docs/alphabets.md +524 -0
- data/docs/api-reference.md +597 -0
- data/docs/assets/css/custom.scss +751 -0
- data/docs/assets/images/favicon.svg +17 -0
- data/docs/assets/images/og-image.svg +65 -0
- data/docs/configuration.md +551 -0
- data/docs/development.md +570 -0
- data/docs/getting-started.md +259 -0
- data/docs/index.md +135 -0
- data/docs/installation.md +380 -0
- data/docs/performance.md +491 -0
- data/docs/robots.txt +11 -0
- data/docs/security.md +601 -0
- data/docs/usage.md +417 -0
- data/docs/use-cases.md +572 -0
- data/lib/opaque_id/version.rb +1 -1
- data/tasks/0003-prd-documentation-site.md +191 -0
- data/tasks/tasks-0003-prd-documentation-site.md +84 -0
- metadata +27 -2
- data/sig/opaque_id.rbs +0 -4
data/docs/development.md
ADDED
@@ -0,0 +1,570 @@
|
|
1
|
+
---
|
2
|
+
layout: default
|
3
|
+
title: Development
|
4
|
+
nav_order: 11
|
5
|
+
description: "Development setup, guidelines, and contribution information"
|
6
|
+
permalink: /development/
|
7
|
+
---
|
8
|
+
|
9
|
+
# Development
|
10
|
+
|
11
|
+
This guide covers development setup, guidelines, and contribution information for OpaqueId. Whether you're contributing to the project or developing applications that use OpaqueId, this guide will help you get started.
|
12
|
+
|
13
|
+
- TOC
|
14
|
+
{:toc}
|
15
|
+
|
16
|
+
## Prerequisites
|
17
|
+
|
18
|
+
Before you begin development, ensure you have the following installed:
|
19
|
+
|
20
|
+
### Required Software
|
21
|
+
|
22
|
+
- **Ruby 3.2+** - OpaqueId requires modern Ruby features
|
23
|
+
- **Rails 8.0+** - For testing and development
|
24
|
+
- **Git** - For version control
|
25
|
+
- **Bundler** - For dependency management
|
26
|
+
|
27
|
+
### Development Tools
|
28
|
+
|
29
|
+
- **Text Editor/IDE** - VS Code, RubyMine, or your preferred editor
|
30
|
+
- **Terminal** - For running commands and tests
|
31
|
+
- **Database** - SQLite (for testing), PostgreSQL or MySQL (for production)
|
32
|
+
|
33
|
+
## Setup
|
34
|
+
|
35
|
+
### 1. Clone the Repository
|
36
|
+
|
37
|
+
```bash
|
38
|
+
git clone https://github.com/nyaggah/opaque_id.git
|
39
|
+
cd opaque_id
|
40
|
+
```
|
41
|
+
|
42
|
+
### 2. Install Dependencies
|
43
|
+
|
44
|
+
```bash
|
45
|
+
bundle install
|
46
|
+
```
|
47
|
+
|
48
|
+
### 3. Run Tests
|
49
|
+
|
50
|
+
```bash
|
51
|
+
bundle exec rake test
|
52
|
+
```
|
53
|
+
|
54
|
+
### 4. Run Code Quality Checks
|
55
|
+
|
56
|
+
```bash
|
57
|
+
bundle exec rubocop
|
58
|
+
bundle exec bundle audit --update
|
59
|
+
```
|
60
|
+
|
61
|
+
## Development Commands
|
62
|
+
|
63
|
+
### Testing
|
64
|
+
|
65
|
+
```bash
|
66
|
+
# Run all tests
|
67
|
+
bundle exec rake test
|
68
|
+
|
69
|
+
# Run specific test files
|
70
|
+
bundle exec ruby test/opaque_id_test.rb
|
71
|
+
bundle exec ruby test/opaque_id/model_test.rb
|
72
|
+
bundle exec ruby test/opaque_id/generators/install_generator_test.rb
|
73
|
+
|
74
|
+
# Run tests with verbose output
|
75
|
+
bundle exec rake test VERBOSE=true
|
76
|
+
|
77
|
+
# Run tests with coverage
|
78
|
+
bundle exec rake test COVERAGE=true
|
79
|
+
```
|
80
|
+
|
81
|
+
### Code Quality
|
82
|
+
|
83
|
+
```bash
|
84
|
+
# Run RuboCop
|
85
|
+
bundle exec rubocop
|
86
|
+
|
87
|
+
# Auto-correct RuboCop offenses
|
88
|
+
bundle exec rubocop --autocorrect
|
89
|
+
|
90
|
+
# Run security audit
|
91
|
+
bundle exec bundle audit --update
|
92
|
+
|
93
|
+
# Check for outdated dependencies
|
94
|
+
bundle outdated
|
95
|
+
```
|
96
|
+
|
97
|
+
### Console
|
98
|
+
|
99
|
+
```bash
|
100
|
+
# Start Rails console with OpaqueId loaded
|
101
|
+
bundle exec rails console
|
102
|
+
|
103
|
+
# Test OpaqueId functionality
|
104
|
+
OpaqueId.generate
|
105
|
+
OpaqueId.generate(size: 10)
|
106
|
+
OpaqueId.generate(alphabet: OpaqueId::STANDARD_ALPHABET)
|
107
|
+
```
|
108
|
+
|
109
|
+
### Local Installation
|
110
|
+
|
111
|
+
```bash
|
112
|
+
# Build the gem
|
113
|
+
gem build opaque_id.gemspec
|
114
|
+
|
115
|
+
# Install locally
|
116
|
+
gem install opaque_id-*.gem
|
117
|
+
|
118
|
+
# Or install from local path
|
119
|
+
gem install --local opaque_id-*.gem
|
120
|
+
```
|
121
|
+
|
122
|
+
## Project Structure
|
123
|
+
|
124
|
+
```
|
125
|
+
opaque_id/
|
126
|
+
├── lib/
|
127
|
+
│ ├── opaque_id.rb # Main module
|
128
|
+
│ ├── opaque_id/
|
129
|
+
│ │ ├── model.rb # ActiveRecord concern
|
130
|
+
│ │ └── version.rb # Version information
|
131
|
+
│ └── generators/
|
132
|
+
│ └── opaque_id/
|
133
|
+
│ ├── install_generator.rb
|
134
|
+
│ └── templates/
|
135
|
+
│ └── migration.rb.tt
|
136
|
+
├── test/
|
137
|
+
│ ├── opaque_id_test.rb # Core module tests
|
138
|
+
│ ├── opaque_id/
|
139
|
+
│ │ ├── model_test.rb # Model concern tests
|
140
|
+
│ │ └── generators/
|
141
|
+
│ │ └── install_generator_test.rb
|
142
|
+
│ └── test_helper.rb # Test configuration
|
143
|
+
├── docs/ # Documentation site
|
144
|
+
├── tasks/ # Task lists and PRDs
|
145
|
+
├── .github/
|
146
|
+
│ └── workflows/ # GitHub Actions
|
147
|
+
├── Gemfile # Development dependencies
|
148
|
+
├── opaque_id.gemspec # Gem specification
|
149
|
+
├── Rakefile # Rake tasks
|
150
|
+
└── README.md # Project documentation
|
151
|
+
```
|
152
|
+
|
153
|
+
## Testing Strategy
|
154
|
+
|
155
|
+
### Test Coverage
|
156
|
+
|
157
|
+
OpaqueId maintains comprehensive test coverage across all components:
|
158
|
+
|
159
|
+
- **Core Module Tests** - ID generation, error handling, edge cases
|
160
|
+
- **Model Tests** - ActiveRecord integration, configuration, finder methods
|
161
|
+
- **Generator Tests** - Rails generator functionality, file generation
|
162
|
+
- **Statistical Tests** - Uniformity and randomness verification
|
163
|
+
- **Performance Tests** - Benchmarking and optimization validation
|
164
|
+
|
165
|
+
### Test Categories
|
166
|
+
|
167
|
+
#### Unit Tests
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# test/opaque_id_test.rb
|
171
|
+
class OpaqueIdTest < Minitest::Test
|
172
|
+
def test_generate_default_parameters
|
173
|
+
id = OpaqueId.generate
|
174
|
+
assert_equal 21, id.length
|
175
|
+
assert_match(/\A[A-Za-z0-9]+\z/, id)
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_generate_custom_parameters
|
179
|
+
id = OpaqueId.generate(size: 10, alphabet: OpaqueId::STANDARD_ALPHABET)
|
180
|
+
assert_equal 10, id.length
|
181
|
+
assert_match(/\A[A-Za-z0-9_-]+\z/, id)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
#### Integration Tests
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
# test/opaque_id/model_test.rb
|
190
|
+
class ModelTest < Minitest::Test
|
191
|
+
def test_automatic_id_generation
|
192
|
+
user = User.create!(name: "John Doe")
|
193
|
+
assert_not_nil user.opaque_id
|
194
|
+
assert_equal 21, user.opaque_id.length
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_finder_methods
|
198
|
+
user = User.create!(name: "Jane Smith")
|
199
|
+
found_user = User.find_by_opaque_id(user.opaque_id)
|
200
|
+
assert_equal user, found_user
|
201
|
+
end
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
#### Generator Tests
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
# test/opaque_id/generators/install_generator_test.rb
|
209
|
+
class InstallGeneratorTest < Minitest::Test
|
210
|
+
def test_generator_creates_migration
|
211
|
+
generator = create_generator('User')
|
212
|
+
generator.invoke_all
|
213
|
+
|
214
|
+
assert File.exist?('db/migrate/*_add_opaque_id_to_users.rb')
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_generator_updates_model
|
218
|
+
generator = create_generator('User')
|
219
|
+
generator.invoke_all
|
220
|
+
|
221
|
+
model_content = File.read('app/models/user.rb')
|
222
|
+
assert_includes model_content, 'include OpaqueId::Model'
|
223
|
+
end
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
### Statistical Testing
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
def test_statistical_uniformity
|
231
|
+
# Generate large sample of IDs
|
232
|
+
sample_size = 10000
|
233
|
+
ids = sample_size.times.map { OpaqueId.generate }
|
234
|
+
|
235
|
+
# Analyze character distribution
|
236
|
+
all_chars = ids.join.chars
|
237
|
+
char_counts = all_chars.tally
|
238
|
+
|
239
|
+
# Verify uniform distribution
|
240
|
+
expected_count = all_chars.size / OpaqueId::ALPHANUMERIC_ALPHABET.size
|
241
|
+
char_counts.each_value do |count|
|
242
|
+
assert_in_delta expected_count, count, expected_count * 0.3
|
243
|
+
end
|
244
|
+
end
|
245
|
+
```
|
246
|
+
|
247
|
+
## Release Process
|
248
|
+
|
249
|
+
### Version Management
|
250
|
+
|
251
|
+
OpaqueId uses semantic versioning (SemVer) with automated release management:
|
252
|
+
|
253
|
+
- **Major Version** - Breaking changes
|
254
|
+
- **Minor Version** - New features, backward compatible
|
255
|
+
- **Patch Version** - Bug fixes, backward compatible
|
256
|
+
|
257
|
+
### Release Workflow
|
258
|
+
|
259
|
+
1. **Development** - Work on feature branches
|
260
|
+
2. **Testing** - Comprehensive test suite
|
261
|
+
3. **Code Review** - Pull request review process
|
262
|
+
4. **Release** - Automated via GitHub Actions
|
263
|
+
5. **Publishing** - Automatic gem publishing to RubyGems.org
|
264
|
+
|
265
|
+
### Release Steps
|
266
|
+
|
267
|
+
```bash
|
268
|
+
# 1. Update version in lib/opaque_id/version.rb
|
269
|
+
# 2. Update CHANGELOG.md
|
270
|
+
# 3. Create release commit
|
271
|
+
git add .
|
272
|
+
git commit -m "Release v1.0.0"
|
273
|
+
|
274
|
+
# 4. Create and push tag
|
275
|
+
git tag v1.0.0
|
276
|
+
git push origin v1.0.0
|
277
|
+
|
278
|
+
# 5. GitHub Actions handles the rest:
|
279
|
+
# - Builds the gem
|
280
|
+
# - Publishes to RubyGems.org
|
281
|
+
# - Creates GitHub release
|
282
|
+
```
|
283
|
+
|
284
|
+
## Development Guidelines
|
285
|
+
|
286
|
+
### Code Style
|
287
|
+
|
288
|
+
OpaqueId follows Ruby community standards:
|
289
|
+
|
290
|
+
- **RuboCop** - Automated code style enforcement
|
291
|
+
- **Minitest** - Testing framework
|
292
|
+
- **Conventional Commits** - Commit message format
|
293
|
+
- **Documentation** - Comprehensive inline documentation
|
294
|
+
|
295
|
+
### Commit Messages
|
296
|
+
|
297
|
+
Use conventional commit format:
|
298
|
+
|
299
|
+
```
|
300
|
+
feat: add support for custom alphabets
|
301
|
+
fix: resolve collision handling edge case
|
302
|
+
docs: update installation instructions
|
303
|
+
test: add statistical uniformity tests
|
304
|
+
refactor: optimize fast path algorithm
|
305
|
+
```
|
306
|
+
|
307
|
+
### Pull Request Process
|
308
|
+
|
309
|
+
1. **Fork** the repository
|
310
|
+
2. **Create** a feature branch
|
311
|
+
3. **Implement** your changes
|
312
|
+
4. **Add** tests for new functionality
|
313
|
+
5. **Update** documentation
|
314
|
+
6. **Run** the test suite
|
315
|
+
7. **Submit** a pull request
|
316
|
+
|
317
|
+
### Code Review Checklist
|
318
|
+
|
319
|
+
- [ ] Tests pass
|
320
|
+
- [ ] Code follows style guidelines
|
321
|
+
- [ ] Documentation is updated
|
322
|
+
- [ ] No security vulnerabilities
|
323
|
+
- [ ] Performance impact considered
|
324
|
+
- [ ] Backward compatibility maintained
|
325
|
+
|
326
|
+
## Contributing
|
327
|
+
|
328
|
+
### Issue Reporting
|
329
|
+
|
330
|
+
OpaqueId follows an "open source, closed contribution" model. We welcome:
|
331
|
+
|
332
|
+
- **Bug Reports** - Issues with existing functionality
|
333
|
+
- **Feature Requests** - New functionality suggestions
|
334
|
+
- **Documentation Improvements** - Better documentation
|
335
|
+
|
336
|
+
### Issue Guidelines
|
337
|
+
|
338
|
+
#### Bug Reports
|
339
|
+
|
340
|
+
When reporting bugs, include:
|
341
|
+
|
342
|
+
- **Ruby Version** - `ruby --version`
|
343
|
+
- **Rails Version** - `rails --version`
|
344
|
+
- **OpaqueId Version** - `gem list opaque_id`
|
345
|
+
- **Reproduction Steps** - Clear steps to reproduce
|
346
|
+
- **Expected Behavior** - What should happen
|
347
|
+
- **Actual Behavior** - What actually happens
|
348
|
+
- **Error Messages** - Full error messages and stack traces
|
349
|
+
|
350
|
+
#### Feature Requests
|
351
|
+
|
352
|
+
When requesting features, include:
|
353
|
+
|
354
|
+
- **Use Case** - Why is this feature needed?
|
355
|
+
- **Proposed Solution** - How should it work?
|
356
|
+
- **Alternatives** - Other solutions considered
|
357
|
+
- **Additional Context** - Any other relevant information
|
358
|
+
|
359
|
+
### Code of Conduct
|
360
|
+
|
361
|
+
OpaqueId follows the Contributor Covenant Code of Conduct:
|
362
|
+
|
363
|
+
- **Be Respectful** - Treat everyone with respect
|
364
|
+
- **Be Inclusive** - Welcome people of all backgrounds
|
365
|
+
- **Be Constructive** - Provide helpful feedback
|
366
|
+
- **Be Professional** - Maintain professional communication
|
367
|
+
|
368
|
+
### Community Guidelines
|
369
|
+
|
370
|
+
- **Ask Questions** - Use GitHub Issues for questions
|
371
|
+
- **Share Knowledge** - Help others learn
|
372
|
+
- **Report Issues** - Help improve the project
|
373
|
+
- **Follow Guidelines** - Respect project standards
|
374
|
+
|
375
|
+
## Getting Help
|
376
|
+
|
377
|
+
### Documentation
|
378
|
+
|
379
|
+
- **README.md** - Project overview and quick start
|
380
|
+
- **Documentation Site** - Comprehensive guides
|
381
|
+
- **API Reference** - Complete method documentation
|
382
|
+
- **Examples** - Real-world usage examples
|
383
|
+
|
384
|
+
### Support Channels
|
385
|
+
|
386
|
+
- **GitHub Issues** - Bug reports and feature requests
|
387
|
+
- **GitHub Discussions** - Questions and community discussion
|
388
|
+
- **Documentation** - Comprehensive guides and examples
|
389
|
+
|
390
|
+
### Common Issues
|
391
|
+
|
392
|
+
#### Installation Issues
|
393
|
+
|
394
|
+
```bash
|
395
|
+
# Ensure Ruby version compatibility
|
396
|
+
ruby --version # Should be 3.2+
|
397
|
+
|
398
|
+
# Clear gem cache
|
399
|
+
gem cleanup
|
400
|
+
|
401
|
+
# Reinstall dependencies
|
402
|
+
bundle install --force
|
403
|
+
```
|
404
|
+
|
405
|
+
#### Test Failures
|
406
|
+
|
407
|
+
```bash
|
408
|
+
# Run tests with verbose output
|
409
|
+
bundle exec rake test VERBOSE=true
|
410
|
+
|
411
|
+
# Check test database
|
412
|
+
bundle exec rake db:test:prepare
|
413
|
+
|
414
|
+
# Clear test cache
|
415
|
+
bundle exec rake test:prepare
|
416
|
+
```
|
417
|
+
|
418
|
+
#### Generator Issues
|
419
|
+
|
420
|
+
```bash
|
421
|
+
# Check Rails version
|
422
|
+
rails --version # Should be 8.0+
|
423
|
+
|
424
|
+
# Verify generator is available
|
425
|
+
rails generate opaque_id:install --help
|
426
|
+
|
427
|
+
# Check model file permissions
|
428
|
+
ls -la app/models/
|
429
|
+
```
|
430
|
+
|
431
|
+
## Development Environment
|
432
|
+
|
433
|
+
### Recommended Setup
|
434
|
+
|
435
|
+
#### VS Code
|
436
|
+
|
437
|
+
```json
|
438
|
+
// .vscode/settings.json
|
439
|
+
{
|
440
|
+
"ruby.rubocop.executePath": "bundle exec",
|
441
|
+
"ruby.format": "rubocop",
|
442
|
+
"ruby.lint": {
|
443
|
+
"rubocop": true
|
444
|
+
},
|
445
|
+
"files.associations": {
|
446
|
+
"*.rb": "ruby",
|
447
|
+
"*.gemspec": "ruby"
|
448
|
+
}
|
449
|
+
}
|
450
|
+
```
|
451
|
+
|
452
|
+
#### RubyMine
|
453
|
+
|
454
|
+
- Enable RuboCop integration
|
455
|
+
- Configure test runner for Minitest
|
456
|
+
- Set up code formatting
|
457
|
+
- Enable version control integration
|
458
|
+
|
459
|
+
### Development Dependencies
|
460
|
+
|
461
|
+
```ruby
|
462
|
+
# Gemfile
|
463
|
+
group :development, :test do
|
464
|
+
gem 'rake', '~> 13.3'
|
465
|
+
gem 'sqlite3', '>= 2.1'
|
466
|
+
gem 'rubocop', '~> 1.81'
|
467
|
+
gem 'rails', '>= 8.0'
|
468
|
+
gem 'bundle-audit', '~> 0.1'
|
469
|
+
end
|
470
|
+
```
|
471
|
+
|
472
|
+
### Environment Variables
|
473
|
+
|
474
|
+
```bash
|
475
|
+
# .env (for development)
|
476
|
+
RAILS_ENV=development
|
477
|
+
RUBY_VERSION=3.4.5
|
478
|
+
BUNDLE_GEMFILE=Gemfile
|
479
|
+
```
|
480
|
+
|
481
|
+
## Performance Development
|
482
|
+
|
483
|
+
### Benchmarking
|
484
|
+
|
485
|
+
```ruby
|
486
|
+
# Benchmark ID generation
|
487
|
+
require 'benchmark'
|
488
|
+
|
489
|
+
def benchmark_generation(count = 1000000)
|
490
|
+
puts "Generating #{count} opaque IDs..."
|
491
|
+
|
492
|
+
time = Benchmark.measure do
|
493
|
+
count.times { OpaqueId.generate }
|
494
|
+
end
|
495
|
+
|
496
|
+
puts "Time: #{time.real.round(2)} seconds"
|
497
|
+
puts "Rate: #{(count / time.real).round(0)} IDs/second"
|
498
|
+
end
|
499
|
+
|
500
|
+
# Run benchmark
|
501
|
+
benchmark_generation(1000000)
|
502
|
+
```
|
503
|
+
|
504
|
+
### Memory Profiling
|
505
|
+
|
506
|
+
```ruby
|
507
|
+
# Memory usage analysis
|
508
|
+
require 'memory_profiler'
|
509
|
+
|
510
|
+
def profile_memory(count = 100000)
|
511
|
+
report = MemoryProfiler.report do
|
512
|
+
count.times { OpaqueId.generate }
|
513
|
+
end
|
514
|
+
|
515
|
+
puts "Total allocated: #{report.total_allocated_memsize / 1024 / 1024}MB"
|
516
|
+
puts "Total retained: #{report.total_retained_memsize / 1024 / 1024}MB"
|
517
|
+
end
|
518
|
+
|
519
|
+
# Run memory profile
|
520
|
+
profile_memory(100000)
|
521
|
+
```
|
522
|
+
|
523
|
+
### Load Testing
|
524
|
+
|
525
|
+
```ruby
|
526
|
+
# Concurrent generation testing
|
527
|
+
require 'concurrent'
|
528
|
+
|
529
|
+
def load_test(threads = 10, ids_per_thread = 100000)
|
530
|
+
puts "Testing #{threads} threads, #{ids_per_thread} IDs each..."
|
531
|
+
|
532
|
+
start_time = Time.now
|
533
|
+
|
534
|
+
# Create thread pool
|
535
|
+
pool = Concurrent::FixedThreadPool.new(threads)
|
536
|
+
|
537
|
+
# Submit tasks
|
538
|
+
futures = threads.times.map do
|
539
|
+
pool.post do
|
540
|
+
ids_per_thread.times.map { OpaqueId.generate }
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
# Wait for completion
|
545
|
+
results = futures.map(&:value!)
|
546
|
+
|
547
|
+
end_time = Time.now
|
548
|
+
total_ids = threads * ids_per_thread
|
549
|
+
duration = end_time - start_time
|
550
|
+
|
551
|
+
puts "Total IDs: #{total_ids}"
|
552
|
+
puts "Duration: #{duration.round(2)} seconds"
|
553
|
+
puts "Rate: #{(total_ids / duration).round(0)} IDs/second"
|
554
|
+
|
555
|
+
pool.shutdown
|
556
|
+
pool.wait_for_termination
|
557
|
+
end
|
558
|
+
|
559
|
+
# Run load test
|
560
|
+
load_test(10, 100000)
|
561
|
+
```
|
562
|
+
|
563
|
+
## Next Steps
|
564
|
+
|
565
|
+
Now that you understand development:
|
566
|
+
|
567
|
+
1. **Explore [API Reference](api-reference.md)** for complete method documentation
|
568
|
+
2. **Check out [Use Cases](use-cases.md)** for development examples
|
569
|
+
3. **Review [Configuration](configuration.md)** for development configuration
|
570
|
+
4. **Read [Security](security.md)** for security considerations
|