{"id":15917606,"url":"https://github.com/dsfields/hailstone","last_synced_at":"2026-02-07T14:31:18.047Z","repository":{"id":30061028,"uuid":"33610444","full_name":"dsfields/hailstone","owner":"dsfields","description":"A simple, lightweight utility for generating quasi-unique, variable length identifiers with embedded type information.","archived":false,"fork":false,"pushed_at":"2015-04-15T21:26:46.000Z","size":192,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T07:36:49.221Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dsfields.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-08T14:04:07.000Z","updated_at":"2022-04-18T14:08:46.000Z","dependencies_parsed_at":"2022-08-25T04:50:42.023Z","dependency_job_id":null,"html_url":"https://github.com/dsfields/hailstone","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dsfields/hailstone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsfields%2Fhailstone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsfields%2Fhailstone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsfields%2Fhailstone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsfields%2Fhailstone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsfields","download_url":"https://codeload.github.com/dsfields/hailstone/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsfields%2Fhailstone/sbom","scorecard":{"id":357640,"data":{"date":"2025-08-11","repo":{"name":"github.com/dsfields/hailstone","commit":"60d262bd45f46043f1c6571228c5379934f48d33"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T10:01:41.345Z","repository_id":30061028,"created_at":"2025-08-18T10:01:41.345Z","updated_at":"2025-08-18T10:01:41.345Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29197022,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T12:38:28.597Z","status":"ssl_error","status_checked_at":"2026-02-07T12:38:23.888Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-06T18:11:50.612Z","updated_at":"2026-02-07T14:31:18.031Z","avatar_url":"https://github.com/dsfields.png","language":"CoffeeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hailstone\n\n[![Build Status](https://secure.travis-ci.org/dsfields/hailstone.svg)](https://travis-ci.org/dsfields/hailstone)\n\nA simple, lightweight, stateless utility for generating quasi-unique, variable length identifiers with embedded type information.  Hailstone is intended as a method of providing unique identifiers within a system\n\nA hailstone identifier is a 64 or 128 bit value encoded using RFC 1924 base85 encoding with a slightly modified, more URL-friendly alphabet.  This results in either a fairly compact 10 or 20 character value respectively.\n\n## Structure\nA hailstone identifier consists of:\n\n* (8-bit) header value which contains version and size information.\n* (8-bit) domain identifier.\n* (8-bit) type identifier.\n* (40-bit) or (104-bit) instance idenfier.\n\nThe internal structure looks like this:\n\n```\n header | domain | type   | instance\n-------------------------------------------------------------\n 8F     | FF     | FF     | 1FFFFFFFFFF ...or...\n        |        |        | FFFFFFFFFFFFFFFFFFFFFFFFFF000000\n```\n\n### Header\nThe header value consists of two piece of information:\n\n* Version: the algorithm version for the hailstone identifier.  This value takes up the first 4 bits of the header byte, which provides a maximum of 16 algorithm version (though there is currently only one.)\n* Size: can be either 64 or 128, which means size only needs to utilize the 7 or 8 bit position on the header byte.\n\nThese two values are bitwise `OR`ed together for encoding, and bitwise `AND`ed when decoded.\n\n### Domain \u0026 Type Identifiers\nThe domain and type identifier portions are intended to provide some additional system-specific information about entity instances the hailstone value is identifying.  Each domain identifier is specific to a system implementing hailstone, and each type identifier is specific to that domain.  All identifiers must be an unsigned integer from 0 to 255.\n\n### Instance Identifier\nA randomly selected value, which can be either 40 or 104 bits.  Hailstone uses the Node.js 'crypto.randomBytes' methods for generating random numbers.  This method is cryptographically secured, and, so, has a very low probability of collision.\n\n## Usage\nHailstone identifiers are simple to generate...\n\n```js\nvar Identifier = require('hailstone');\n\nvar domain = 42;\nvar type = 84;\n\nvar id = Identifier.create(domain, type);\n\nconsole.log(id);\n```\n\nEach identifier can then be parsed to extract domain and type information...\n\n```js\nvar Identifier = require('hailstone');\n\nvar id = new Identifier(identifierString);\n\nconsole.log(id.domain);\nconsole.log(id.type);\n```\n\n### API Documentation\n* `new Hailstone(value)`: parses a hailstone value so that the version, size, domain, and type information can be extracted.\n  * Parameters:\n    * `value`: a hailstone-base85 string or a Node.js `Buffer` containing a hailstone identifer.\n\n* `Hailstone.create(domain, type, [options, callback])`: creates a new hailstone identifier for the specified domain and type.\n  * Parameters:\n    * `domain`: an unsigned intenger value 0-255.  Each domain identifier should be unique to given a domain, microservice, namespace, etc within a single system.\n    * `type`: an unsigned intenger value 0-255.  Each type identifier should be unique to a given entity type within the domain.\n    * `options`: optional values for controlling behavior.\n      * `length`: the total number of bits of the hailstone identifier.  Can be 64 or 128.  The default is 128.\n    * `callback`: A standard EventLoop callback function pointer.  Node.js's crypto RNG method relies on an pool of entropy values to ensure randomness and distribution. It is indeed possible for the entropy pool to become exhausted.  Node.js crypto will throw an error if this happens. To prevent errors, a callback function parameter is provided, thus allowing calling threads a method to wait in a non-blocking manner for the Node.js crypto to gather sufficient entropy to generate a PRN.\n\n* `Hailstone.createAsync(domain, type, [options])`: The same as the aforementioned `create()` method, but returns a then-able promise.\n\n* `id.toBuffer()`: converts an instance of `Hailstone` to a Node.js `Buffer`.\n\n* `id.toString()`: converts an instance of `Hailstone` to a hailstone-base85 encoded string.\n\n* `id.domain`: the domain identifier of the `Hailstone` instance.\n\n* `id.type`: the entity type identifier of the `Hailstone` instance.\n\n## Chances of Collision\nThe probability of id collisions within a single system are negligable.  The pseudo-random number portion of each Hailstone identifier is generated using the Node.js cryptographic PRNG, which has more than adequate distribution to avoid collisions.  The 64-bit version utilizes 40 bits for the PRN, which translates into a 1 in 2,199,023,255,551 chance of collision per domain and entity pairing.  The 128 bit version utilies 104 bits for the PRN, which translates into a 1 in 340,282,366,920,938,463,463,374,607,431,751,434,240 chance of collision per domain and type pairing.\n\n## Encoding\nHailstone identifiers are encoded using RFC 1924 base85 with a slightly modified alphabet, with the intention of making encoded values more URL-friendly.  The code used in this library is based on [Alexander Olsson's](https://github.com/noseglid) [base85](https://github.com/noseglid/base85) module.  Some key differences are:\n\n* The code has been optimized for the hailstone use case.\n* Uses a modified, non-canon alphabet.\n\n### Alphabet\n```\n!$%()*,-.0123456789;\u003c=\u003e@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsfields%2Fhailstone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsfields%2Fhailstone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsfields%2Fhailstone/lists"}