Skip to content

Add interviewer question templates and answer keys - #16

Open
AndroidDevAccount wants to merge 46 commits into
humancto:masterfrom
AndroidDevAccount:codex/interview-question-templates
Open

Add interviewer question templates and answer keys#16
AndroidDevAccount wants to merge 46 commits into
humancto:masterfrom
AndroidDevAccount:codex/interview-question-templates

Conversation

@AndroidDevAccount

@AndroidDevAccount AndroidDevAccount commented Jul 28, 2026

Copy link
Copy Markdown

Summary

  • adds an interviewer-only question template selector to the collaborative editor
  • includes short C#, REST, ASP.NET MVC, SQL, LINQ, and SOLID exercises
  • switches editor language and loads the selected prompt immediately
  • opens a plain-language answer key and 0-3 rubric automatically in a right-side panel
  • lets interviewers hide and reopen the answer-key panel
  • hides template and answer-key controls from candidate sessions

Validation

  • JavaScript syntax checked with Node.js
  • repository diff checked for whitespace errors
  • browser-tested on a live two-user-capable session: auto-open, editor resize, answer content, hide, and reopen all verified
  • temporary QA session ended after validation
  • contribution branch contains no deployment configuration, credentials, or personal settings

Summary by CodeRabbit

  • New Features
    • Admins can select built-in question sets or import custom sets (questions + answer keys).
    • Added an interviewer-only Answer Key side panel with open/close and notes-panel integration.
    • Admin dashboard now includes Resume Interview and a Manage Admins flow (add/list).
  • Bug Fixes
    • Improved role-based UI controls so non-admins hide admin-only features.
    • More reliable admin session restore/resume and connected-users display.
  • Documentation
    • Updated question-set docs and added a custom question-set example file.
  • Style / UI
    • Refreshed top bar, connected-users control/dropdown, and dashboard overlay layout.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AndroidDevAccount, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 72e4a17e-152e-4f12-9eb6-9f060a98e446

📥 Commits

Reviewing files that changed from the base of the PR and between e4d06a2 and 467ae02.

📒 Files selected for processing (1)
  • api/admins.js
📝 Walkthrough

Walkthrough

Adds authenticated interview question sets, interviewer template and answer-key controls, admin account and session management, dashboard navigation, candidate-session recovery, and draggable activity-indicator positioning.

Changes

Interview workspace and administration

Layer / File(s) Summary
Admin authentication and management
api/auth/login.js, api/admins.js
Normalizes admin login, supports Firebase-backed admin accounts, and adds authenticated admin listing and creation.
Template catalog and API
api/interview/templates-data.js, api/interview/templates.js, docs/QUESTION_SETS.md, docs/question-set-example.json, README.md
Adds eleven interview templates with answer keys, grouped question sets, protected custom-set storage, validation, retrieval, and usage documentation.
Interviewer workspace controls
app.html, scripts/firepad.js, scripts/interview-notes.js, styles/main.css
Adds interviewer-only question loading, editor synchronization, answer-key display, dashboard controls, connected-user UI, and related styling.
Admin session continuity
scripts/auth-api.js, scripts/app.js, scripts/firepad.js
Restores candidate and recent admin sessions, prevents duplicate initialization, persists session codes, and supports dashboard return navigation.
Activity indicator interaction
scripts/activity-monitor.js
Adds idempotent monitoring initialization, initial interviewer metrics, viewport-constrained dragging, and session-stored indicator positions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin
  participant TemplatesAPI
  participant JWT
  participant Firebase
  participant Firepad
  participant ACE
  participant AnswerKey
  Admin->>TemplatesAPI: request templates with bearer token
  TemplatesAPI->>JWT: verify admin token
  TemplatesAPI->>Firebase: read custom question sets
  TemplatesAPI-->>Firepad: return templates and question sets
  Firepad->>ACE: replace editor content
  Firepad->>AnswerKey: populate and display answer key
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main interviewer template and answer key feature added by the PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app.html`:
- Around line 735-738: Remove the unconditional interview-templates.js loading
from app.html and move InterviewTemplates, including answerKey data and
interviewer-only plans, behind a server-side authenticated endpoint or Firebase
Security Rules based on verified interviewer claims. Update the interviewer
initialization flow to fetch these templates only after server authorization
succeeds, and ensure candidate sessions never receive or expose the protected
data; client-side isAdmin checks must remain UI-only.
- Around line 561-571: Add an inline default-hidden style to the
template-selector select element, matching the existing answer-key-btn guard, so
it remains hidden until setupSettingsSync confirms an admin user. Preserve the
current JavaScript visibility behavior for authorized users.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fe27cc9-1022-4938-9339-e106e25ad26f

📥 Commits

Reviewing files that changed from the base of the PR and between 707ae28 and 9685f40.

📒 Files selected for processing (4)
  • app.html
  • scripts/firepad.js
  • scripts/interview-templates.js
  • styles/main.css

Comment thread app.html Outdated
Comment thread app.html

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
scripts/firepad.js (2)

575-582: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Validate value.id before using it as an identity/key.

id is copied verbatim from the imported file. A non-string (or whitespace) id produces keys like custom:[object Object]:0 and breaks the dedupe filter at Line 675, so re-importing the same file accumulates duplicate sets.

♻️ Proposed normalization
+          const importedId = typeof value.id === 'string' && value.id.trim()
+            ? value.id.trim().slice(0, 80)
+            : `set-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
           return {
-            id: value.id || `set-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
+            id: importedId,
             name: value.name.trim().slice(0, 120),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/firepad.js` around lines 575 - 582, Normalize and validate value.id
before assigning it in the set object: accept only a non-whitespace string, trim
it, and otherwise generate the existing fallback identifier. Ensure the
resulting id is always a stable string so the dedupe logic remains effective
across repeated imports.

720-724: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Toggle reads the inline style rather than the effective visibility.

answerKeyPanel.style.display is '' until openAnswerKeyPanel/closeAnswerKeyPanel writes it, so this comparison depends on the panel having been opened at least once (currently guaranteed only because the button is disabled until a template loads). Any future path that hides the panel via CSS/class instead of an inline style silently inverts the toggle.

♻️ More robust visibility check
-            if (answerKeyPanel.style.display === 'none') {
+            const isHidden = getComputedStyle(answerKeyPanel).display === 'none';
+            if (isHidden) {
               openAnswerKeyPanel(template);
             } else {
               closeAnswerKeyPanel();
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/firepad.js` around lines 720 - 724, Update the toggle logic around
answerKeyPanel to determine visibility from its effective rendered state rather
than answerKeyPanel.style.display, such as via the established DOM visibility
mechanism. Preserve opening when the panel is hidden and closing when it is
visible, including before any inline style has been assigned or when CSS/classes
control visibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/activity-monitor.js`:
- Around line 555-561: Update the saved-position restoration in the activity
indicator initialization to clamp the restored left/top coordinates to the
current viewport after the indicator’s final content has rendered. Add a resize
handler that re-applies the same bounds calculation so the indicator remains
reachable when the viewport changes.

In `@scripts/app.js`:
- Around line 379-384: Update the Auth.logout flow to remove the localStorage
key recent_admin_session when the admin session ends, ensuring no persisted
interview join code remains available to a later user. Keep rememberAdminSession
unchanged and perform the cleanup alongside the existing logout state reset.

In `@scripts/auth-api.js`:
- Around line 45-48: Update the candidate_session restoration logic around
JSON.parse so it ignores all stored role fields and reconstructs a normalized
candidate-only session with isAdmin forced to false before assigning session.
Preserve the existing handling for invalid or missing stored data, and ensure
Auth.isAdmin() cannot return a forged interviewer role.
- Around line 42-52: Update the auth_session restoration flow so it returns only
when the stored admin session is valid and successfully restored; when it is
expired, removed, or otherwise invalid, continue into the candidate_session
lookup instead of returning early. Preserve the existing candidate session
parsing and cleanup behavior.

In `@scripts/firepad.js`:
- Around line 629-659: Extract the template fetch and related initialization
from setupSettingsSync into an async bootstrapTemplates function, and invoke it
without awaiting so sync wiring proceeds immediately. Remove async from
setupSettingsSync, register the theme selector listener and
settingsRef.on('value') subscription synchronously, and move import, answer-key,
and auto-load handlers into bootstrapTemplates().then(...). Ensure template-load
failure only disables template UI and does not return from or prevent settings
synchronization.
- Around line 695-713: Update loadInterviewTemplate to confirm before calling
editor.setValue when the editor contains non-default content, while preserving
the currentSessionIsNew auto-load path without prompting. Pass { skipConfirm:
true } from the auto-load invocation near the existing template-loading call,
and cancel the template load if the user declines.

In `@styles/main.css`:
- Around line 877-915: Update `#firepad-container.with-answer-key` to reserve the
answer key panel’s effective width, including the 420px minimum, instead of
always using 46%. Add a narrow-screen media query that switches both
`#answer-key-panel` and the editor reservation to a compatible full-width or
stacked layout so the panel never overlays editor content.

---

Nitpick comments:
In `@scripts/firepad.js`:
- Around line 575-582: Normalize and validate value.id before assigning it in
the set object: accept only a non-whitespace string, trim it, and otherwise
generate the existing fallback identifier. Ensure the resulting id is always a
stable string so the dedupe logic remains effective across repeated imports.
- Around line 720-724: Update the toggle logic around answerKeyPanel to
determine visibility from its effective rendered state rather than
answerKeyPanel.style.display, such as via the established DOM visibility
mechanism. Preserve opening when the panel is hidden and closing when it is
visible, including before any inline style has been assigned or when CSS/classes
control visibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 83a2b367-10c3-4140-acbb-2486253b7760

📥 Commits

Reviewing files that changed from the base of the PR and between 9685f40 and 5e53e45.

📒 Files selected for processing (12)
  • README.md
  • api/interview/templates-data.js
  • api/interview/templates.js
  • app.html
  • docs/QUESTION_SETS.md
  • docs/question-set-example.json
  • scripts/activity-monitor.js
  • scripts/app.js
  • scripts/auth-api.js
  • scripts/firepad.js
  • scripts/interview-notes.js
  • styles/main.css

Comment thread scripts/activity-monitor.js
Comment thread scripts/app.js
Comment thread scripts/auth-api.js Outdated
Comment thread scripts/auth-api.js Outdated
Comment thread scripts/firepad.js Outdated
Comment thread scripts/firepad.js Outdated
Comment thread styles/main.css
@AndroidDevAccount

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/firepad.js (1)

796-842: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Inconsistent null guards inside the change/click handlers.

answerKeyButton (lines 806, 818), questionSetFileInput (lines 799-800), and answerKeyPanel (line 837) are dereferenced unguarded here, while the surrounding code (lines 733, 770, 832) treats each as optional. If any of those elements is missing the handler throws mid-way, leaving settingsRef partially updated.

🛡️ Proposed guards
         templateSelector.addEventListener('change', function() {
           if (this.value === '__add_custom__') {
             this.value = activeInterviewTemplateKey || '';
-            questionSetFileInput.value = '';
-            questionSetFileInput.click();
+            if (questionSetFileInput) {
+              questionSetFileInput.value = '';
+              questionSetFileInput.click();
+            }
             return;
           }
           if (this.value === '__change_set__') {
             activeQuestionSetKey = null;
             activeInterviewTemplateKey = null;
-            answerKeyButton.disabled = true;
+            if (answerKeyButton) answerKeyButton.disabled = true;

and at line 837:

-            if (getComputedStyle(answerKeyPanel).display === 'none') {
+            if (!answerKeyPanel || getComputedStyle(answerKeyPanel).display === 'none') {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/firepad.js` around lines 796 - 842, Make the templateSelector change
handler safe when optional elements are absent by guarding questionSetFileInput
before clearing or clicking it, and guarding answerKeyButton before assigning
disabled in both change branches. In the answerKeyButton click handler, also
guard answerKeyPanel before calling getComputedStyle or toggling the panel.
Preserve the existing settings updates and selection behavior when these
elements are present.
🧹 Nitpick comments (5)
styles/main.css (1)

2395-2403: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

.dashboard-page relies on JS supplying display: flex.

align-items/justify-content only take effect if the element is a flex container, but the rule sets no display; the markup starts at display: none and scripts/firepad.js (line 944) assigns 'flex'. Any other show path that assigns 'block' loses the centering. Safer to declare the flex behaviour in CSS and toggle a class or display: none only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@styles/main.css` around lines 2395 - 2403, Update the .dashboard-page rule to
declare its intended flex layout in CSS instead of relying on scripts/firepad.js
to assign display:flex. Preserve hidden-state toggling, but ensure every visible
show path retains flex behavior rather than allowing display:block to override
the centering alignment.
scripts/firepad.js (2)

466-481: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document-level click listener is never removed.

It is bound once via dataset.menuBound, but resetCollaborativeSession doesn't clear that flag or detach the listener, so the closure over usersList outlives the session. Harmless today since the node id is stable; worth tidying if session teardown ever re-renders the top bar.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/firepad.js` around lines 466 - 481, Update the collaborative session
teardown, specifically resetCollaborativeSession, to retain the document-level
click handler registered by the user-count menu and remove it during reset. Also
clear userCountButton.dataset.menuBound so a subsequent session can bind the
handler again, while preserving the existing usersList toggle behavior.

705-731: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Bootstrap can pop a confirm() during page load.

When a session has a saved questionSet but no valid activeQuestionTemplate, line 721 auto-loads the first question with skipConfirm: currentSessionIsNew; on an interviewer refresh of an in-progress session that surfaces a blocking "replace the current code for everyone" dialog before the workspace has settled. Consider skipping the auto-load entirely when the editor already holds candidate content and just rendering the picker.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/firepad.js` around lines 705 - 731, Update the initialization flow
around loadInterviewTemplate in the saved-question-set fallback so it does not
auto-load the first question when the editor already contains candidate content.
In that case, skip the confirm-triggering load and render the question-set
picker instead; preserve the existing first-question auto-load for empty editors
and keep normal rendering behavior unchanged.
api/interview/templates.js (1)

74-116: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

No delete/replace path for custom sets.

Each import creates a fresh custom-* id, so re-importing a corrected file leaves the stale set permanently in the dropdown. A DELETE method (or upsert by client-supplied id) would keep the picker usable. Note scripts/firepad.js already computes a stable id for imported sets and sends it, but this handler ignores it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/interview/templates.js` around lines 74 - 116, The POST handler in the
custom question-set flow ignores the stable client-supplied id, causing
corrected imports to create stale duplicate sets. Read and validate the imported
set id from the request body, reuse it when constructing the Firebase path (with
the existing custom-id format/validation), and preserve generated-id behavior
when no valid id is supplied so re-imports upsert the existing set.
api/auth/login.js (1)

10-23: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the Firebase bootstrap + emailKey into a shared module.

The same init block and emailKey implementation now exist verbatim in api/admins.js (lines 7-20) and the init block again in api/interview/templates.js (lines 7-16). A divergence in the key encoding would silently break login for accounts created by api/admins.js.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/auth/login.js` around lines 10 - 23, Extract the Firebase initialization
block and emailKey function from login.js into a shared module, then update
login.js, admins.js, and interview/templates.js to import and reuse those shared
symbols. Remove the duplicated implementations while preserving the existing
environment-based initialization and base64url email-key behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/admins.js`:
- Around line 22-32: Restrict admin-account creation in the POST handler to the
configured owner by requiring the authenticated token’s email to match
process.env.ADMIN_EMAIL, rather than allowing every token accepted by
requireAdmin. Preserve the existing admin authentication and disabled-account
behavior, and ensure unauthorized non-owner admins receive the appropriate
forbidden response.
- Around line 51-63: Update the GET handler’s additionalAdmins projection to
include each account’s disabled status in the returned admin objects, preserving
the existing owner and other account fields so operators can distinguish
disabled accounts.

In `@api/auth/login.js`:
- Around line 75-89: Guard the ownerLogin calculation so it is true only when
ADMIN_EMAIL is configured and the normalized request email matches it; do not
compare against String(undefined). Update the password-selection flow around
ownerLogin while preserving the Firebase account lookup for requests when
ADMIN_EMAIL is unset or does not match.

In `@api/interview/templates.js`:
- Around line 118-140: The GET handler currently loads and inlines every custom
question set and question body into each response. Update the customQuestionSets
retrieval and response construction to return lightweight set metadata by
default, and include question content and answerKey only for the requested setId
when one is provided; preserve the existing templates/questionSets shape for
built-in data and ensure the selected custom set still exposes its question keys
and bodies.

In `@docs/QUESTION_SETS.md`:
- Around line 3-6: Update the documentation describing the Custom Questions
group to label the file-loading option as “Load custom questions from file…” so
it matches the UI rendered by firepad.js. Keep the surrounding grouping and
import behavior description unchanged.

In `@scripts/app.js`:
- Around line 1840-1844: Reset the sessionStarting flag in the
main-container-missing branch before the early return, so subsequent
startSession() calls can run after the error. Update the session-start flow
around the shown console.error, alert, and return without changing the existing
error messaging.
- Around line 1832-1857: In the main-container setup, capture the existing
dataset.sessionCode before assigning the new sessionCode, then use that captured
previous value for the mismatch check. Remove the redundant re-query or ensure
it does not occur after overwriting the dataset, preserving the existing reload
and resetCollaborativeSession behavior when switching sessions.

---

Outside diff comments:
In `@scripts/firepad.js`:
- Around line 796-842: Make the templateSelector change handler safe when
optional elements are absent by guarding questionSetFileInput before clearing or
clicking it, and guarding answerKeyButton before assigning disabled in both
change branches. In the answerKeyButton click handler, also guard answerKeyPanel
before calling getComputedStyle or toggling the panel. Preserve the existing
settings updates and selection behavior when these elements are present.

---

Nitpick comments:
In `@api/auth/login.js`:
- Around line 10-23: Extract the Firebase initialization block and emailKey
function from login.js into a shared module, then update login.js, admins.js,
and interview/templates.js to import and reuse those shared symbols. Remove the
duplicated implementations while preserving the existing environment-based
initialization and base64url email-key behavior.

In `@api/interview/templates.js`:
- Around line 74-116: The POST handler in the custom question-set flow ignores
the stable client-supplied id, causing corrected imports to create stale
duplicate sets. Read and validate the imported set id from the request body,
reuse it when constructing the Firebase path (with the existing custom-id
format/validation), and preserve generated-id behavior when no valid id is
supplied so re-imports upsert the existing set.

In `@scripts/firepad.js`:
- Around line 466-481: Update the collaborative session teardown, specifically
resetCollaborativeSession, to retain the document-level click handler registered
by the user-count menu and remove it during reset. Also clear
userCountButton.dataset.menuBound so a subsequent session can bind the handler
again, while preserving the existing usersList toggle behavior.
- Around line 705-731: Update the initialization flow around
loadInterviewTemplate in the saved-question-set fallback so it does not
auto-load the first question when the editor already contains candidate content.
In that case, skip the confirm-triggering load and render the question-set
picker instead; preserve the existing first-question auto-load for empty editors
and keep normal rendering behavior unchanged.

In `@styles/main.css`:
- Around line 2395-2403: Update the .dashboard-page rule to declare its intended
flex layout in CSS instead of relying on scripts/firepad.js to assign
display:flex. Preserve hidden-state toggling, but ensure every visible show path
retains flex behavior rather than allowing display:block to override the
centering alignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a504216-46bf-40be-b539-a40a26394704

📥 Commits

Reviewing files that changed from the base of the PR and between 5e53e45 and 354e99f.

📒 Files selected for processing (11)
  • api/admins.js
  • api/auth/login.js
  • api/interview/templates-data.js
  • api/interview/templates.js
  • app.html
  • docs/QUESTION_SETS.md
  • scripts/activity-monitor.js
  • scripts/app.js
  • scripts/auth-api.js
  • scripts/firepad.js
  • styles/main.css
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/interview/templates-data.js
  • scripts/activity-monitor.js
  • scripts/auth-api.js

Comment thread api/admins.js
Comment thread api/admins.js
Comment thread api/auth/login.js
Comment thread api/interview/templates.js Outdated
Comment thread docs/QUESTION_SETS.md
Comment thread scripts/app.js
Comment thread scripts/app.js
@AndroidDevAccount

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
api/admins.js (2)

60-62: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reuse one normalized owner email everywhere.

At Lines 66-67 the owner email is trimmed and lowercased, but the GET owner entry and duplicate-owner check use an untrimmed value. If ADMIN_EMAIL contains surrounding whitespace, the API can display a mismatched owner and allow creation for the configured owner address. Compute the normalized value once and reuse it in both branches.

Also applies to: 80-81

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/admins.js` around lines 60 - 62, Normalize process.env.ADMIN_EMAIL once
by trimming and lowercasing it, then reuse that normalized value when
constructing the GET owner entry and performing the duplicate-owner check.
Update the relevant owner handling in the surrounding admin flow, including the
alternate branch at lines 80-81, so display and comparison use the same
normalized email.

84-95: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make admin creation atomic.

The once('value') check and later set() are separate writes, so concurrent owner requests for the same email can both see no account, both return 201, and the last write can overwrite the password hash. Use a transaction/conditional create on adminAccounts/<emailKey> and return 409 when the reservation fails.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/admins.js` around lines 84 - 95, Replace the separate existence check and
set in the admin creation flow with an atomic transaction or conditional create
on accountRef for adminAccounts/<emailKey>. Ensure only one concurrent request
reserves the account, return 409 when the reservation fails, and preserve the
existing account fields and successful creation response.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@api/admins.js`:
- Around line 60-62: Normalize process.env.ADMIN_EMAIL once by trimming and
lowercasing it, then reuse that normalized value when constructing the GET owner
entry and performing the duplicate-owner check. Update the relevant owner
handling in the surrounding admin flow, including the alternate branch at lines
80-81, so display and comparison use the same normalized email.
- Around line 84-95: Replace the separate existence check and set in the admin
creation flow with an atomic transaction or conditional create on accountRef for
adminAccounts/<emailKey>. Ensure only one concurrent request reserves the
account, return 409 when the reservation fails, and preserve the existing
account fields and successful creation response.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c4e523b-ce0c-48bb-a05c-7881ce654aca

📥 Commits

Reviewing files that changed from the base of the PR and between 354e99f and e4d06a2.

📒 Files selected for processing (8)
  • api/admins.js
  • api/auth/login.js
  • api/interview/templates.js
  • app.html
  • docs/QUESTION_SETS.md
  • scripts/app.js
  • scripts/firepad.js
  • styles/main.css
🚧 Files skipped from review as they are similar to previous changes (7)
  • docs/QUESTION_SETS.md
  • styles/main.css
  • api/auth/login.js
  • app.html
  • scripts/firepad.js
  • scripts/app.js
  • api/interview/templates.js

@AndroidDevAccount

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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