Skip to content

Add ID generator, and automate releases from the changelog - #1

Merged
fadeltd merged 2 commits into
mainfrom
feat/id-generator
Sep 24, 2026
Merged

fadeltd merged 2 commits into
mainfrom
feat/id-generator

Conversation

@fadeltd

@fadeltd fadeltd commented Sep 24, 2026

Copy link
Copy Markdown
Owner

What

Two things that belong together, because the second is what ships the first.

1. ID generator

Prefixed identifiers in the Stripe shape — a readable prefix, a separator, then a run of random characters. Configurable prefix, separator, random length, alphabet and batch size, with presets for Stripe secret/test keys, object ids, API tokens, hex session ids, passwords and human-readable codes.

It doubles as a password generator: a symbol alphabet plus an option to drop confusable glyphs (0/O, 1/l/I). That closes the separate password-generator item too — it is the same machine underneath, and shipping two would have implied one was the non-secure option.

Decisions worth reviewing:

  • Entropy counts the random portion only. The prefix is public by design, so counting it would overstate strength.
  • No "time to crack" figure. It depends entirely on assumed hardware and on whether the value is hashed. Quoting one would be false precision dressed as a guarantee, so the tool reports bits plus a qualitative band.
  • Rejection sampling, not % n. Modulo biases toward the start of the alphabet whenever the size does not divide 2^32. There is a distribution test that fails if that regresses.
  • Settings persist; generated values never do. The output is a secret, so it lives in component state and cannot reach disk on any code path.

2. Release automation

Merging this does not deploy. Instead:

  1. Release reads ## [Unreleased] in CHANGELOG.md and derives the bump — ### Breaking → major, ### Added → minor, anything else → patch.
  2. It rewrites the changelog into a dated section, bumps package.json, commits back to main, and pushes vx.y.z.
  3. The tag triggers the Cloudflare deploy.

An empty [Unreleased] releases nothing, so merging and releasing stay separate decisions.

The bump logic is a tested pure module (scripts/changelog.ts, 22 tests) rather than inline shell, because a mistake there silently ships the wrong version and a green workflow run would not reveal it. Preview any merge with:

pnpm exec vite-node scripts/release.ts --dry-run

Merging this will release v0.2.0

The dry run confirms it: [Unreleased] contains ### Added → minor → 0.1.0 → 0.2.0.

Needed before the deploy can succeed

  1. CLOUDFLARE_API_TOKEN is not set yet. Create it at Cloudflare → My Profile → API Tokens → Custom with Account → Workers Scripts: Edit and Zone → Workers Routes: Edit on fadeltd.dev only, then run gh secret set CLOUDFLARE_API_TOKEN --repo fadeltd/devtools and paste at the prompt. Without it the deploy step fails; everything before it still passes.

  2. RELEASE_TOKEN (optional). A tag pushed with the default GITHUB_TOKEN deliberately does not trigger other workflows. Without a PAT the Release workflow starts Deploy explicitly, which works. If you want the tag itself to trigger it, add a fine-grained PAT with Contents: Read and write as RELEASE_TOKEN.

Note

GitHub push protection blocked the first push of this branch: I had used Stripe's documentation example key as a doc comment, and it matches their live-key pattern. I replaced the example with prose rather than allowlisting it — a scanner cannot tell a doc example from a real leak, and should not have to.

Verification

  • 330 tests pass (27 new for the generator, 22 for the release logic), including property tests for id shape, alphabet containment and distribution bias.
  • Typecheck, lint and build clean; entry bundle unchanged at ~82.6 kB gzip against a 90 kB budget. The new tool is a 3.4 kB lazy chunk.
  • Adding the tool needed one folder and one registry entry — router, sidebar, palette, prerender and sitemap picked it up unaided.

ID generator
- Prefixed identifiers in the Stripe shape (sk_live_4eC39HqL...): prefix,
  separator, random length, alphabet and batch size are all configurable.
- Doubles as a password generator via a symbol alphabet plus an option to drop
  confusable glyphs (0/O, 1/l/I), which matters for anything a human retypes
  and is pointless for a machine token -- hence optional rather than default.
- Live entropy readout with a qualitative verdict. Deliberately no "time to
  crack" figure: it depends entirely on assumed hardware and on whether the
  value is hashed, so quoting one would be false precision presented as a
  guarantee.
- Entropy counts the random portion only. The prefix is public by design and
  contributes none.
- Rejection sampling, never `value % n`, which biases toward the start of the
  alphabet whenever the size does not divide 2^32. A distribution test would
  fail if that regressed.
- Settings persist; generated values live in component state and are never
  written to disk under any code path.
- The unbiased randomness primitives move to src/lib/random.ts now that the
  list shuffler and this tool both need them.

Release automation
- CI gates every pull request on typecheck, lint, tests, build, and an entry
  bundle budget, so a heavy dependency escaping a lazy chunk fails the build
  rather than reaching production.
- Merging to main does not deploy. It derives the next version from the
  [Unreleased] section of CHANGELOG.md, rewrites the changelog, commits that
  back to main and pushes a tag. The tag is what deploys, so merging and
  releasing stay separate decisions and an empty [Unreleased] ships nothing.
- The bump logic is a tested pure module rather than inline shell, because a
  mistake there silently ships the wrong version and a green run would not
  reveal it. `### Removed` maps to patch, not major, so a tidy-up cannot
  silently become a 1.0; major requires an explicit `### Breaking`.
- A tag pushed with the default GITHUB_TOKEN does not trigger other workflows,
  by design. With a PAT in RELEASE_TOKEN the tag triggers Deploy natively;
  without one the workflow starts Deploy explicitly, so this works either way.
GitHub is forcing actions that target Node 20 onto Node 24 and warning about
it, so move to the current majors rather than wait for them to break.

Also clears the two warnings the run surfaced in the new release scripts: a
Set lookup instead of repeated array scans, and a test helper hoisted out of
its describe block.
@fadeltd fadeltd self-assigned this Sep 24, 2026
@fadeltd
fadeltd merged commit 3a0a71e into main Sep 24, 2026
1 check passed
@fadeltd
fadeltd deleted the feat/id-generator branch September 24, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant