Corrupting the true last character of a JWT's base64url-encoded
HMAC-SHA256 signature is unreliable: that character encodes only 4
real bits plus 2 unused padding bits, and Go's encoding/base64
ignores those padding bits by default -- about 1 in 4 replacement
characters decode to byte-identical signature bytes, so the
"tampered" cookie still verifies and the test spuriously passes.
Corrupting the second-to-last character instead is deterministic,
since HMAC-SHA256's fixed 32-byte digest length means that position
is always fully significant.
Confirmed via 20 repeated runs (previously ~1/3 failure rate).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Carries the raw ID token in the session cookie so logout can hand it back
to Keycloak as id_token_hint, letting it skip its own logout-confirmation
prompt -- otherwise a user could cancel out of it and land back in the app
with a Keycloak SSO session but no geniusrun profile (e.g. right after
deleting their account).
Lets an external reader (sqlite3 CLI, DB Browser, DataGrip) inspect the
database file concurrently without "database is locked" errors while
geniusrund is running. Doesn't change in-process concurrency -- queries
are already fully serialized via SetMaxOpenConns(1).
auth: fix flaky tampered-cookie tests
Both tests corrupted a signed cookie by blindly overwriting its last
character with "x", which is occasionally a no-op if that character (part
of the token's signature, so effectively randomized by the embedded
timestamp) already happened to be "x" -- silently passing without having
tampered with anything. Confirmed via 15 repeated runs (3 spurious passes)
before the fix and 30 clean runs after. flipLastChar now guarantees the
byte actually changes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>