Skip to content

fix(auth): derive minimum-length messages from the shared constant - #717

Merged
cevheri merged 1 commit into
libredb:mainfrom
2160039878-cyber:fix/jwt-minimum-messages-672
Sep 9, 2026
Merged

fix(auth): derive minimum-length messages from the shared constant#717
cevheri merged 1 commit into
libredb:mainfrom
2160039878-cyber:fix/jwt-minimum-messages-672

Conversation

@2160039878-cyber

@2160039878-cyber 2160039878-cyber commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Description

Five JWT/storage/bootstrap messages hardcode a minimum that can drift from the enforced value. Derive their text from JWT_SECRET_MIN_LENGTH, preserving the single-line templates and the current validation behavior.

Type of Change

  • Bug fix

Related Issue

Closes #672

Changes Made

  • Use the shared constant in all five messages and in the auth module documentation.
  • Export the existing development fallback for its length guard, and hoist the bootstrap message so the guard checks the actual runtime value.
  • Add guards for message text, single-line templates, and the fallback's minimum length.

Testing

bun run test:unit -t 'minimum-length message guard': 0 passed / 3 failed before, 3 passed / 0 failed after. Temporarily setting JWT_SECRET_MIN_LENGTH to 48 produced 2 passed / 1 failed: all messages followed the new minimum, while the existing fallback correctly failed its length guard. Restored the constant before committing. The minimum remains 32, the fallback value is unchanged, and no cryptographic key size changes.

Full Linux validation used the repository's unchanged CI workflow on submitted commit a44413edcb448f151f05e29dcc3c9562ee14cd17: run and logs.

  • bun run test:coverage: 14,716 tests passed, all 392 core test files and 34 component isolation groups passed.
  • bun run coverage:check: 46,321 / 46,321 lines (100%).
  • Format, lint, typecheck, knip, README/chart/channel/security drift guards, application/library builds, package type-resolution checks, Helm lint, and Go launcher checks passed.
  • Browser E2E 65 passed, subpath E2E 1 passed, PostgreSQL functional smoke 1 passed, packaged tarball/npx E2E 3 passed each, Node 24/26 engine smoke passed.
  • Secret Scan, Dependency Scan, and Image Scan passed. The manual secret scan fetched and scanned all fork history and branches, including this commit.

The fork run's overall status is red solely because SonarCloud Analysis lacks the upstream token/project access. All test/build jobs passed. CLAUDE.md explicitly excludes SonarCloud from required checks, and the upstream workflow skips it for fork PRs. Upstream required workflows still need normal maintainer approval.

Full validation ran on GitHub-hosted Linux: this Windows host cannot run the container-based checks because Docker Desktop fails at inference-manager initialization, and its native full component runner encounters SQLite cleanup EBUSY. No complete native-Windows pass is claimed.

Checklist

  • Issue acceptance criteria checked; actual validation results recorded above.
  • Full tests and the 100% line-coverage gate passed on the submitted commit.
  • Diff reviewed; no database-provider changes requiring the provider triad.

Additional Notes

AI-assisted implementation, review, and validation. This branch starts independently from main and contains only this issue's change.

CI follow-up

The fork-run SonarCloud 401 is tracked in #732 and fixed by #733. The inherited condition admitted fork-owned pushes and fork-local PRs to the canonical SonarCloud project. The dedicated CI fix run now succeeds: all nine executable test/build jobs pass, and SonarCloud is scoped to the canonical repository. That run tests CI fix commit 80a318b; this PR's exact-head verification remains the original run linked above, whose nine executable jobs passed. Upstream Actions still await maintainer approval.

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@cevheri

cevheri commented Sep 9, 2026

Copy link
Copy Markdown
Member

Checked against #672. All four "Done when" items hold, and I widened the last one: no literal minimum survives anywhere in src/, not just in the three files the issue named.

Three things I measured that are worth telling you:

  • The guard catches all three drift shapes, not only the one the issue asked for. JWT_SECRET_MIN_LENGTH = 48 turns the fallback guard red, as you reported; reverting one message to a literal 32 turns the source guard red; and making a message stop quoting the constant without writing a digit turns two of the three red.
  • The refactor is behaviour-preserving. I rendered all five constants and diffed them against the old literals: byte-identical at 32, so no operator-visible text changed. That is the right property for a change like this and it is easy to lose by accident.
  • Exporting DEV_FALLBACK_SECRET does not widen the package API, because auth-env is not re-exported from src/exports. knip is clean too, so the two test-only exports do not read as dead code.

One observation, take it or leave it: expect(templates).toHaveLength(5) pins a magnitude, so a sixth correctly written message would turn it red. It does buy completeness in exchange, which the first test alone does not give you, so it is a fair trade rather than a mistake.

For context and not an ask: README.md, .env.example and five files under docs/ still write the minimum as text, so the same drift lives on outside these three files. That is outside this issue and I am tracking it.

Merging shortly.

@cevheri cevheri added the enhancement New feature or request label Sep 9, 2026
@cevheri
cevheri merged commit e79bf06 into libredb:main Sep 9, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Five operator-facing messages spell the JWT_SECRET minimum as "32 characters" beside the constant that defines it

2 participants