Skip to content

resync#423

Merged
theg1239 merged 34 commits into
devfrom
main
May 23, 2026
Merged

resync#423
theg1239 merged 34 commits into
devfrom
main

Conversation

@theg1239
Copy link
Copy Markdown
Member

No description provided.

theg1239 and others added 30 commits May 5, 2026 03:57
refactor: optimize path change handling with useCallback for better p…
feat: add Android install banner component
feat: enhance video handling in HeroBackdropVideo component
* gpt-realtime-2

* chore : bump next version

* fix: adjust padding for navbar action items

* fix: native tab bar (mobile)

* exclude logging

* chore: reorg

* chore: make things more modular wrt voice agents

* feat: make voice agent more reliable

* feat: enhance loading state and animations for markdown components

* fixes to voice agent

* fix: remove set state from useeffects & use react activity

* feat: add prefetching to delete link and navigation links in NavBar

* fix: styling of voice input

* experiment
* gpt-realtime-2

* chore : bump next version

* fix: adjust padding for navbar action items

* fix: native tab bar (mobile)

* exclude logging

* chore: reorg

* chore: make things more modular wrt voice agents

* feat: make voice agent more reliable

* feat: enhance loading state and animations for markdown components

* fixes to voice agent

* fix: remove set state from useeffects & use react activity

* feat: add prefetching to delete link and navigation links in NavBar

* fix: styling of voice input

* experiment
chore: disable youtube hero backdrop variant
[codex] add claude hero background
Co-authored-by: theg1239 <theg1239@users.noreply.github.com>
cursoragent and others added 4 commits May 19, 2026 11:16
Co-authored-by: theg1239 <theg1239@users.noreply.github.com>
Co-authored-by: theg1239 <theg1239@users.noreply.github.com>
…-bfb3

fix: protect unpublished papers and incomplete markdown caches
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
examcooker-dev Building Building Preview, Comment May 23, 2026 1:59am

@theg1239 theg1239 merged commit 2a5fa06 into dev May 23, 2026
2 of 4 checks passed
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR bundles several independent improvements: an AI model rename (gpt-realtime-minigpt-realtime-2) across voice/realtime files, XSS hardening in the MCP widget's linkify/renderBtn helpers, truncated-PDF detection in the markdown route, and two data-integrity fixes for past-paper lookups (wrapping metadata updates in a transaction and filtering published-only papers in the detail/sibling queries).

  • Transaction + new validations in update-paper-metadata.ts: the update is now atomic, tracks the previous questionPaperId so the old question paper's cache is also revalidated, and adds a linkedAnswerKey guard that prevents a paper from becoming an answer key when it is already acting as a question paper for another paper.
  • isClear filter in past-paper-detail.ts: both loadPastPaperDetail and the getSiblingPastPaper question-paper branch now require isClear = true, and the Redis cache key prefix was renamed to match the new semantics, avoiding stale entries from the old unchecked cache.
  • XSS fix in examcooker-widget.ts: a new safeHref validator enforces http:/https: protocol and passes URLs through esc() before injecting into HTML, patching a reflected-URL injection in linkify, renderRow, and renderBtn.

Confidence Score: 4/5

Safe to merge; all changes are additive hardening with no breaking interface changes.

The transaction wrapper and new answer-key guard in the metadata action are logically correct and improve data integrity. The isClear filter and cache-key rename in past-paper-detail are a clean, consistent pair. The XSS fix in the widget is straightforward and well-applied. The only minor concerns are a redundant ne clause and the expected slow expiry of old Redis cache entries under the previous key prefix.

app/actions/update-paper-metadata.ts and lib/data/past-paper-detail.ts carry the most logic change and are worth a quick second read.

Important Files Changed

Filename Overview
app/actions/update-paper-metadata.ts Logic wrapped in a DB transaction with new validation guards; previous question-paper ID now tracked for cache invalidation; ne(pastPaper.id, parsed.id) in the linkedAnswerKey check is redundant but harmless.
lib/data/past-paper-detail.ts Adds isClear = true filter to loadPastPaperDetail and getSiblingPastPaper; Redis cache key prefix renamed to avoid serving old unchecked-paper results.
app/api/pdf/markdown/route.ts Adds truncated-output detection via finishReason === 'length' and normalises the previously unresolved result.finishReason Promise before passing it to capture-event logging.
lib/mcp/examcooker-widget.ts Introduces safeHref URL validator (protocol whitelist + URL parse) and consistently applies esc() to all injected href values, closing a reflected-URL XSS vector in the widget HTML.
app/api/realtime/session/route.ts Model name constant updated from gpt-realtime-mini to gpt-realtime-2; no other logic changes.
app/components/voice/voice-agent-provider.tsx Two model-name literals updated from gpt-realtime-mini to gpt-realtime-2; no logic changes.
app/components/voice/voice-runtime.tsx Default model constant renamed to gpt-realtime-2; no other changes.

Sequence Diagram

sequenceDiagram
    participant Mod as Moderator
    participant Action as updatePaperMetadata
    participant DB as Database (tx)
    participant Cache as Next.js/Redis Cache

    Mod->>Action: submit metadata update
    Action->>Action: auth check (MODERATOR only)
    Action->>Action: zod schema parse
    Action->>DB: BEGIN TRANSACTION
    DB->>DB: fetch existingPaper (get previousQuestionPaperId)
    alt "hasAnswerKey = true"
        DB->>DB: fetch questionPaper
        DB->>DB: check conflictingLink (another answer key for same QP?)
        DB->>DB: check linkedAnswerKey (current paper already a question paper?)
    end
    DB->>DB: UPDATE pastPaper SET ...
    DB->>Action: "COMMIT → {questionPaperId, previousQuestionPaperId}"
    Action->>Cache: revalidateTag(past_paper:id)
    Action->>Cache: revalidateTag(past_paper:previousQuestionPaperId)
    Action->>Cache: revalidateTag(past_paper:questionPaperId)
    Action->>Cache: invalidatePastPapersSurfaceCache()
    Action-->>Mod: "{success: true}"
Loading

Comments Outside Diff (1)

  1. lib/data/past-paper-detail.ts, line 157-169 (link)

    P2 Stale Redis cache entries after isClear filter change

    getPastPaperDetail now queries only papers with isClear = true and uses the new published-past-paper-detail Redis key prefix, but any entry previously written under the old past-paper-detail prefix (for a paper that was already clear) is never explicitly evicted. Those entries will linger in Redis until their TTL expires (up to one hour per cacheLife). In practice this is cosmetically stale data rather than a correctness issue, but it is worth ensuring the Redis cache has an appropriate TTL so old-prefix entries do not persist indefinitely.

Reviews (1): Last reviewed commit: "Merge pull request #417 from ACM-VIT/cur..." | Re-trigger Greptile

Comment on lines +148 to +160
const [linkedAnswerKey] = await tx
.select({
id: pastPaper.id,
title: pastPaper.title,
})
.from(pastPaper)
.where(
and(
eq(pastPaper.questionPaperId, parsed.id),
ne(pastPaper.id, parsed.id),
),
)
.limit(1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The ne(pastPaper.id, parsed.id) predicate in the linkedAnswerKey query is never effective. The query already filters on eq(pastPaper.questionPaperId, parsed.id), so the only row whose id could equal parsed.id would be a paper whose questionPaperId equals its own id — a self-reference that is caught earlier in the same transaction. Removing the redundant clause makes the intent clearer.

Suggested change
const [linkedAnswerKey] = await tx
.select({
id: pastPaper.id,
title: pastPaper.title,
})
.from(pastPaper)
.where(
and(
eq(pastPaper.questionPaperId, parsed.id),
ne(pastPaper.id, parsed.id),
),
)
.limit(1);
const [linkedAnswerKey] = await tx
.select({
id: pastPaper.id,
title: pastPaper.title,
})
.from(pastPaper)
.where(
eq(pastPaper.questionPaperId, parsed.id),
)
.limit(1);

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.

2 participants