Skip to content

test: add regression tests for local-coding API key auth mismatch (#1748)#1768

Merged
Priyanshu-byte-coder merged 1 commit into
Priyanshu-byte-coder:mainfrom
Ridanshi:fix/local-coding-api-key-auth
May 31, 2026
Merged

test: add regression tests for local-coding API key auth mismatch (#1748)#1768
Priyanshu-byte-coder merged 1 commit into
Priyanshu-byte-coder:mainfrom
Ridanshi:fix/local-coding-api-key-auth

Conversation

@Ridanshi
Copy link
Copy Markdown
Contributor

Closes #1748

Root cause (confirmed)

The initial migration (20260521000000_add_local_coding_tables.sql) created local_coding_api_keys with a single column api_key to store SHA-256 key hashes. A later migration (20260522000000_add_api_key_hash_column.sql) added api_key_hash as a nullable column.

While the schema had two columns, the application code was split:

Path Operation Column
POST /api/local-coding/keys store hash api_key only
POST /api/local-coding/sync authenticate api_key_hash only

Every key generated through the UI therefore failed authentication immediately — the hash was in api_key but the lookup was in api_key_hash.

Applied fix (already on main)

Key creation now writes the same SHA-256 hash to both columns:

insert({
  api_key: apiKeyHash,       // backward compat
  api_key_hash: apiKeyHash,  // new canonical column
  name,
})

Authentication uses an OR filter across both columns, which handles both pre-migration rows (only api_key populated) and newly created rows (both populated):

const filter = `api_key_hash.eq.${keyHash},api_key.eq.${keyHash}`;
.or(filter).single()   // lookup
.or(filter)            // last_used_at update

What this PR adds — test/local-coding-auth-regression.test.ts (9 new tests)

The fix was in place but lacked explicit regression coverage. This PR adds a dedicated test file:

Test Purpose
Key creation writes to api_key AND api_key_hash Verifies dual-write from POST /keys
Sync POST uses OR filter — regression for #1748 Confirms the OR filter covers both columns
Legacy row (only api_key set) still authenticates Backward-compat for pre-migration deployments
Invalid key is rejected Confirms bad keys return 401
GET /sync returns 401 without auth header GET handler was previously untested
GET /sync returns 401 for invalid key
GET /sync returns session data for valid key Happy path for GET
GET /sync uses same OR filter as POST Confirms both verbs use the same auth code path
Hash function consistency Verifies creation hash satisfies the auth filter

Test results

All 9 new tests pass. All 13 pre-existing tests in test/local-coding-keys.test.ts and test/local-coding-sync.test.ts pass unchanged. The single failing test (test/dateUtils.test.ts timezone boundary) is a pre-existing, unrelated issue.

…iyanshu-byte-coder#1748)

Root cause (confirmed)
----------------------
The initial migration created local_coding_api_keys with a single column
api_key to store SHA-256 hashes. A later migration added api_key_hash as
a nullable column. At the time issue Priyanshu-byte-coder#1748 was filed, the code was split:

  Creation  → insert({ api_key: hash })         # only api_key written
  Auth      → .eq("api_key_hash", hash)          # only api_key_hash read

Every key generated through the UI was therefore permanently invalid;
authentication always returned "Invalid API key".

Applied fix (in place on main branch)
--------------------------------------
Key creation now writes the same SHA-256 hash to BOTH columns:

  insert({ api_key: hash, api_key_hash: hash })

Authentication queries BOTH columns with an OR filter so that pre-existing
rows (with only api_key populated) and newly created rows (with both
populated) authenticate identically:

  .or("api_key_hash.eq.<hash>,api_key.eq.<hash>")

This preserves backward compatibility with any deployment that had keys
created before the api_key_hash column existed.

Regression test suite — test/local-coding-auth-regression.test.ts (9 tests)
-----------------------------------------------------------------------------
Tests added in this commit provide explicit coverage that was absent:

  * Key creation writes hash to api_key AND api_key_hash.
  * POST /local-coding/sync uses OR filter across both columns.
  * Legacy row (api_key only, api_key_hash NULL) still authenticates.
  * Invalid key is rejected by both POST and GET sync handlers.
  * GET /local-coding/sync was previously untested; 4 tests now cover:
      - missing Authorization header → 401
      - invalid key → 401
      - valid key → 200 with session data
      - same OR filter used as POST
  * Hash function consistency: verifies the hash written during creation
    would satisfy the filter used during authentication.

The pre-existing tests in test/local-coding-keys.test.ts and
test/local-coding-sync.test.ts continue to pass unchanged.

Closes Priyanshu-byte-coder#1748
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

@Ridanshi is attempting to deploy a commit to the PRIYANSHU DOSHI's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added gssoc26 GSSoC 2026 contribution type:feature GSSoC type bonus: new feature type:security GSSoC type bonus: security (+20 pts) type:testing GSSoC type bonus: tests (+10 pts) labels May 31, 2026
@github-actions
Copy link
Copy Markdown

GSSoC Label Checklist 🏷️

@Priyanshu-byte-coder — please apply the appropriate labels before merging:

Difficulty (pick one):

  • level:beginner — 20 pts
  • level:intermediate — 35 pts
  • level:advanced — 55 pts
  • level:critical — 80 pts

Quality (optional):

  • quality:clean — ×1.2 multiplier
  • quality:exceptional — ×1.5 multiplier

Validation (required to score):

  • gssoc:approved — counts for points
  • gssoc:invalid / gssoc:spam / gssoc:ai-slop — does not score

Type labels (type:*) are auto-detected from files and title. Review and adjust if needed.
Points formula: (difficulty × quality_multiplier) + type_bonus

@Priyanshu-byte-coder Priyanshu-byte-coder added level2 GSSoC Level 2 - Medium complexity (25 points) gssoc:approved GSSoC: PR approved for scoring labels May 31, 2026
@Priyanshu-byte-coder Priyanshu-byte-coder merged commit dd5fead into Priyanshu-byte-coder:main May 31, 2026
4 of 5 checks passed
@github-actions
Copy link
Copy Markdown

🎉 Merged! Thanks for contributing to DevTrack.

If the project has been useful to you, a ⭐ star on the repo is the easiest way to support it — it helps DevTrack get discovered by more developers.

Keep an eye on open issues for your next contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved GSSoC: PR approved for scoring gssoc26 GSSoC 2026 contribution level2 GSSoC Level 2 - Medium complexity (25 points) type:feature GSSoC type bonus: new feature type:security GSSoC type bonus: security (+20 pts) type:testing GSSoC type bonus: tests (+10 pts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Local coding API keys generated through the UI can never authenticate due to database column mismatch

2 participants