Skip to content

fix: unblock camera for proctored skill tests (Permissions-Policy)#395

Open
KRISHNA-RATHI-32 wants to merge 2 commits into
Sachinchaurasiya360:mainfrom
KRISHNA-RATHI-32:fix/camera-permissions-policy
Open

fix: unblock camera for proctored skill tests (Permissions-Policy)#395
KRISHNA-RATHI-32 wants to merge 2 commits into
Sachinchaurasiya360:mainfrom
KRISHNA-RATHI-32:fix/camera-permissions-policy

Conversation

@KRISHNA-RATHI-32
Copy link
Copy Markdown

@KRISHNA-RATHI-32 KRISHNA-RATHI-32 commented May 22, 2026

Problem

Camera access fails on proctored skill tests with:

[Violation] Permissions policy violation: camera is not allowed in this document.

Users see "Camera access denied" but it's not a user permission issue — the browser never even shows a permission prompt.

Root Cause

client/vercel.json line 27 sets:

Permissions-Policy: camera=(), microphone=(), geolocation=(), interest-cohort=()

camera=() blocks camera access at the document level for all origins, including self. This overrides any user permission and causes getUserMedia() to fail immediately.

Changes

File What
client/vercel.json camera=()camera=(self), microphone=()microphone=(self)
client/src/hooks/useFaceDetection.ts Granular error messages (policy block vs user denial vs no device vs in-use)
client/src/module/student/skill-verification/SkillTestPage.tsx Same improved error handling in camera gate UI

Security Note

camera=(self) allows camera only for the site's own origin — third-party embeds still cannot access it. geolocation=() and interest-cohort=() remain fully blocked.

Testing

After deploy, verify:

  1. Open /test/:testId → click "Enable Camera & Continue" → camera prompt should appear
  2. Check response headers: Permissions-Policy: camera=(self), microphone=(self), ...
  3. Block camera in browser settings → should show "Camera permission denied" (not "policy blocked")

Summary by CodeRabbit

  • Bug Fixes

    • Improved camera permission flow with clearer, specific messages for permission denied, site/security policy blocks, no camera found, and camera-in-use situations.
  • Chores

    • Permissions policy updated to explicitly allow camera and microphone.
    • Deployment workflow restricted to run only for the primary repository to avoid unintended builds.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f473bc7-259e-4795-bd98-681a9b71ddaf

📥 Commits

Reviewing files that changed from the base of the PR and between 634b04d and 442fbe4.

📒 Files selected for processing (1)
  • .github/workflows/deploy.yml

📝 Walkthrough

Walkthrough

Refines camera access error messages (distinguishing policy blocks, permission denial, no device, device-in-use), enables camera/microphone via Permissions-Policy, and adds a repository guard to the deploy workflow.

Changes

Camera Access Error Handling

Layer / File(s) Summary
HTTP Permissions-Policy header configuration
client/vercel.json
The Permissions-Policy header now enables camera and microphone for (self) while keeping geolocation and interest-cohort disabled.
Granular camera error messaging
client/src/hooks/useFaceDetection.ts, client/src/module/student/skill-verification/SkillTestPage.tsx
getUserMedia error handling now distinguishes NotAllowedError (checked for permissions/feature policy vs permission denial), NotFoundError (no camera), NotReadableError (camera in use), and a fallback "not available" message.

CI Workflow Guard

Layer / File(s) Summary
Deploy job repository guard
.github/workflows/deploy.yml
Added if: github.repository == 'Sachinchaurasiya360/InternHack' to the build-and-deploy job to restrict when the deploy workflow runs.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

I’m a rabbit by the camera’s light,
I hop to tell what’s wrong or right,
“No device”, “In use”, or “Policy block” —
Clear words so users don’t get stuck,
🐰📸 Cheers to smoother starts tonight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: unblocking camera access for proctored skill tests by fixing the Permissions-Policy header.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
client/src/module/student/skill-verification/SkillTestPage.tsx (1)

496-496: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace arbitrary text sizes with standard scale classes.

The code uses text-[11px] (line 496) and text-[10px] (lines 745, 752, 759, 766), which violates the coding guideline: "Do not use arbitrary bracket sizes like text-[17px], use standard scale classes instead."

Use text-xs (0.75rem / 12px) instead for design system consistency. As per coding guidelines, TailwindCSS v4 canonical classes should be used without arbitrary bracket values.

📏 Proposed fix: use standard text-xs class
- <p className="text-[11px] text-gray-500 dark:text-gray-400">
+ <p className="text-xs text-gray-500 dark:text-gray-400">
    {item.label}
  </p>
- <span className="px-2 py-1 bg-red-50 dark:bg-red-900/30 text-red-600 dark:text-red-400 text-[10px] font-semibold rounded-md flex items-center gap-1">
+ <span className="px-2 py-1 bg-red-50 dark:bg-red-900/30 text-red-600 dark:text-red-400 text-xs font-semibold rounded-md flex items-center gap-1">

Apply the same change to all other text-[10px] occurrences on lines 752, 759, and 766.

Also applies to: 745-745, 752-752, 759-759, 766-766

🤖 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 `@client/src/module/student/skill-verification/SkillTestPage.tsx` at line 496,
Replace the arbitrary Tailwind text size utilities in the SkillTestPage
component with the standard scale: change all occurrences of text-[11px] and
text-[10px] to text-xs to follow the design system; specifically update the
paragraph element using text-[11px] and the other small text spans/paragraphs
(the occurrences noted in the diff) inside SkillTestPage.tsx so they use text-xs
consistently across the component.
🤖 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 `@client/src/module/student/skill-verification/SkillTestPage.tsx`:
- Around line 361-378: Extract the duplicated getUserMedia error-to-message
logic into a shared helper function (e.g., getCameraErrorMessage) and replace
the inline handling in SkillTestPage (where setCameraError is called) and in
useFaceDetection with calls to that helper; specifically, move the err.name
checks for "NotAllowedError", "NotFoundError", and "NotReadableError" plus the
policy keyword inspection into getCameraErrorMessage(err): string, return the
mapped user-facing string, and update the SkillTestPage catch block and the
corresponding catch in useFaceDetection to call
setCameraError(getCameraErrorMessage(err)) (or use the returned string) instead
of duplicating the logic.

---

Outside diff comments:
In `@client/src/module/student/skill-verification/SkillTestPage.tsx`:
- Line 496: Replace the arbitrary Tailwind text size utilities in the
SkillTestPage component with the standard scale: change all occurrences of
text-[11px] and text-[10px] to text-xs to follow the design system; specifically
update the paragraph element using text-[11px] and the other small text
spans/paragraphs (the occurrences noted in the diff) inside SkillTestPage.tsx so
they use text-xs consistently across the component.
🪄 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

Run ID: 23518da7-85d8-4caf-8bfc-9497a79cc1f9

📥 Commits

Reviewing files that changed from the base of the PR and between 8611468 and a2ee04f.

📒 Files selected for processing (3)
  • client/src/hooks/useFaceDetection.ts
  • client/src/module/student/skill-verification/SkillTestPage.tsx
  • client/vercel.json

Comment on lines +361 to 378
} catch (err: any) {
let msg: string;
if (err?.name === "NotAllowedError") {
const isPolicy =
err?.message?.toLowerCase().includes("permissions policy") ||
err?.message?.toLowerCase().includes("feature policy");
msg = isPolicy
? "Camera is blocked by a site security policy. This is a known issue — please contact support."
: "Camera permission denied. Please allow camera access in your browser settings and try again.";
} else if (err?.name === "NotFoundError") {
msg = "No camera detected. Please connect a camera and try again.";
} else if (err?.name === "NotReadableError") {
msg = "Camera is in use by another app. Please close it and try again.";
} else {
msg = "Camera not available. Please check your device and try again.";
}
setCameraError(msg);
}
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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Extract duplicated error handling to a shared utility.

The getUserMedia error handling logic here is nearly identical to the code in useFaceDetection.ts (lines 67-81). Both map err.name to user-facing messages and inspect the error message for policy-related keywords. This duplication creates a maintenance burden—if the error detection logic needs updating, it must be changed in both locations.

As per coding guidelines, apply the DRY principle and extract this to a shared helper.

♻️ Suggested refactor: extract to shared utility

Create a new utility file, e.g., client/src/utils/cameraErrors.ts:

export function getCameraErrorMessage(err: any): string {
  if (err?.name === "NotAllowedError") {
    const isPolicy =
      err?.message?.toLowerCase().includes("permissions policy") ||
      err?.message?.toLowerCase().includes("feature policy");
    return isPolicy
      ? "Camera blocked by site security policy. Please contact support."
      : "Camera permission denied. Please allow camera access in your browser settings and try again.";
  } else if (err?.name === "NotFoundError") {
    return "No camera found. Please connect a camera and try again.";
  } else if (err?.name === "NotReadableError") {
    return "Camera is in use by another application. Please close it and try again.";
  } else {
    return "Camera not available. Please check your device and try again.";
  }
}

Then replace both occurrences with:

  } catch (err: any) {
-   let msg: string;
-   if (err?.name === "NotAllowedError") {
-     const isPolicy =
-       err?.message?.toLowerCase().includes("permissions policy") ||
-       err?.message?.toLowerCase().includes("feature policy");
-     msg = isPolicy
-       ? "Camera blocked by site security policy. Please contact support."
-       : "Camera permission denied. Please allow camera access in your browser settings and try again.";
-   } else if (err?.name === "NotFoundError") {
-     msg = "No camera found. Please connect a camera and try again.";
-   } else if (err?.name === "NotReadableError") {
-     msg = "Camera is in use by another application. Please close it and try again.";
-   } else {
-     msg = "Camera not available. Please check your device and try again.";
-   }
+   const msg = getCameraErrorMessage(err);
    setCameraError(msg);
🤖 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 `@client/src/module/student/skill-verification/SkillTestPage.tsx` around lines
361 - 378, Extract the duplicated getUserMedia error-to-message logic into a
shared helper function (e.g., getCameraErrorMessage) and replace the inline
handling in SkillTestPage (where setCameraError is called) and in
useFaceDetection with calls to that helper; specifically, move the err.name
checks for "NotAllowedError", "NotFoundError", and "NotReadableError" plus the
policy keyword inspection into getCameraErrorMessage(err): string, return the
mapped user-facing string, and update the SkillTestPage catch block and the
corresponding catch in useFaceDetection to call
setCameraError(getCameraErrorMessage(err)) (or use the returned string) instead
of duplicating the logic.

@KRISHNA-RATHI-32 KRISHNA-RATHI-32 force-pushed the fix/camera-permissions-policy branch from 634b04d to 442fbe4 Compare May 22, 2026 10:21
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