Skip to content

chore: sync upstream @ v2.17.0 — fixes frozen session-cookie expiry (all logins broken since 4 Jul) - #5

Merged
Mudit-Lal merged 1 commit into
mainfrom
chore/upstream-merge-aug26
Aug 19, 2026
Merged

Mudit-Lal merged 1 commit into
mainfrom
chore/upstream-merge-aug26

Conversation

@Mudit-Lal

Copy link
Copy Markdown
Contributor

Why

Every login on sign.devalok.in has silently failed since 2026-07-04 18:54 UTC — Google OAuth and email/password alike. The symptom was "Google sign-in does nothing"; server logs were clean because nothing errored.

Deployed commit bfade19a predates upstream 583e35c7 ("fix: ensures new expire on setSessionCookie", #2708, 9 Jun — five days after our last sync). Before that fix:

export const sessionCookieOptions = {
  ...
  expires: new Date(Date.now() + AUTH_SESSION_LIFETIME),  // evaluated once at module import
} as const;

setSessionCookie passed those options straight through with no maxAge, so every session cookie the process issued carried the same Expires — process start + 30 days. The container started 2026-06-04 18:54:19 UTC, so from 4 Jul onward every cookie arrived at the browser already expired and was discarded on the spot.

Observable on the live instance before this change:

Set-Cookie: google_oauth_state=...; Max-Age=600; Domain=sign.devalok.in; Expires=Sat, 04 Jul 2026 18:54:19 GMT

Identical Expires across requests 12 seconds apart — frozen, not clock skew. The OAuth state cookies survived because they also set Max-Age (which wins per RFC 6265); the session cookie sets only expires, so it had nothing to fall back on.

Not an email or Google problem: Zeptomail SMTP authenticates and accepts sender + recipient, reset emails deliver to INBOX, and the Google OAuth client resolves to the account picker with the correct redirect_uri.

What

Squash-import of upstream/main @ 7533016 (v2.17.0) — 120 commits, v2.11 → v2.17.0.

Also imports upstream's deletions, which the 2026-06-04 sync silently kept: packages/eslint-config/, packages/prettier-config/, prettier.config.cjs, .prettierignore, .eslintrc.cjs, .eslintignore, tsconfig.eslint.json, packages/lib/server-only/document/send-completed-email.ts, and stale embedding/authoring docs. DEVALOK_FORK_NOTES.md now documents the git read-tree -u --reset upstream/main method, since a diff-based import does not propagate deletions.

Migrations

4 pending, all additive — no DROP TABLE / DROP COLUMN / TRUNCATE:

Migration Ops
20260525103410_add_signature_level_and_csc_tables Envelope.signatureLevel (default 'SES'), CscCredential, CscSession
20260604143030_add_email_transports EmailTransportType enum, EmailTransport table, emailTransportId FKs
20260616120000_add_cancelled_document_status ALTER TYPE "DocumentStatus" ADD VALUE 'CANCELLED'
20260622120000_add_recipient_reminder_count Recipient.reminderCount (default 0)

Volume backup pre-v2.17-upstream-merge taken before merge (1180 MB referenced) — this volume had no prior backups.

Fork CI guards

Re-applied to 13 workflows. Upstream deleted issue-assignee-check.yml and pr-review-reminder.yml, so those rows are dropped from the guarded table. A per-job audit confirms the only intentionally open jobs remain ci.yml/build_docker and codeql-analysis.yml/analyze.

Follow-up (not in this PR)

  • NEXTAUTH_SECRET is the literal Documenso default secret. Session cookies are HMAC-signed with it, so the signing key is public knowledge — anyone can forge a valid session for any user. Rotating next, in the same restart.
  • Postgres is postgres:password. Private-network-only today (no TCP proxy), but one accidental proxy from being open.
  • EmailTransport arrives in this range; verify env-var SMTP still drives mail after deploy.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DYNE3dT1E7bGHk8Y8joXMm

Squash-import of upstream/main (120 commits, v2.11 -> v2.17.0).

Primary motivation: the previously deployed commit predates upstream
583e35c7 ("fix: ensures new expire on setSessionCookie", #2708). Before
that fix, `sessionCookieOptions` carried

    expires: new Date(Date.now() + AUTH_SESSION_LIFETIME)

evaluated once at module import, and `setSessionCookie` passed those
options through unchanged with no `maxAge`. Every session cookie the
process ever issued therefore expired at (process start + 30 days) --
frozen at 2026-07-04T18:54:19Z for the deployment running since
2026-06-04. Browsers discarded the cookie on arrival, so all logins
(Google OAuth and email/password alike) silently failed from that date.

Also imported upstream's deletions, which the 2026-06-04 sync missed:
packages/eslint-config/, packages/prettier-config/, prettier.config.cjs,
.prettierignore, .eslintrc.cjs, .eslintignore, tsconfig.eslint.json,
packages/lib/server-only/document/send-completed-email.ts and the stale
embedding/authoring docs. DEVALOK_FORK_NOTES.md now documents the
read-tree import method so future syncs propagate deletions.

Fork CI guards re-applied to 13 workflows. Upstream deleted
issue-assignee-check.yml and pr-review-reminder.yml, so those rows are
dropped from the guarded list. Per-job audit confirms the only
intentionally open jobs remain ci.yml/build_docker and
codeql-analysis.yml/analyze.

Pending Prisma migrations (all additive, no drops):
  20260525103410_add_signature_level_and_csc_tables
  20260604143030_add_email_transports
  20260616120000_add_cancelled_document_status
  20260622120000_add_recipient_reminder_count

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DYNE3dT1E7bGHk8Y8joXMm
@Mudit-Lal
Mudit-Lal merged commit b0dad22 into main Aug 19, 2026
6 of 7 checks passed
@Mudit-Lal
Mudit-Lal deleted the chore/upstream-merge-aug26 branch August 19, 2026 16:08
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