npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

proctoring-sdk

v0.2.0

Published

An AI-powered integrity monitoring solution for online assessments. This SDK integrates real-time webcam face-presence detection, screen share verification, browser tab focus tracking, and activity logging directly into your React application.

Readme

Proctoring SDK (proctoring-sdk)

An AI-powered integrity monitoring solution for online assessments. This SDK integrates real-time webcam face-presence detection, screen share verification, browser tab focus tracking, and activity logging directly into your React application.


Features

  • Face Presence Monitoring: Detects face presence, face absence, and multi-face conditions.
  • Screen Share Tracking: Restricts candidates to sharing their entire monitor and detects when sharing is stopped.
  • Tab & Focus Tracking: Logs incidents when the user switches tabs, minimizes the window, or loses focus.
  • Copy/Paste Log: Logs clipboard copy, cut, and paste interactions during active assessment sessions.
  • Host-Owned Error Recovery: Startup permission/network errors pass rich structured diagnostic data and retry closures to the host application for customized presentation.
  • In-Session Overlays & Telemetry: Fullscreen enforcement, screen interruption alerts, multi-monitor warnings, violation toasts, and live face feedback are handled seamlessly inside the SDK.
  • Offline Mode: Automatically queues telemetry events locally when connection is lost, using cryptographic obfuscation, and flushes them when online status is restored.
  • GDPR-Aligned Data Storage: Ensures all telemetry and screenshots are immediately removed from the candidate's browser local storage after they are uploaded.

Getting Started

  1. Sign Up: Create your developer account on the Protector Dashboard.
  2. Get Your API Key: Go to Settings -> API Keys inside your dashboard and copy your secret Host API Key. This key is used on your backend server to create candidate sessions.

Installation

Install the package and its peer dependencies via npm:

npm install proctoring-sdk

Note: Requires React 18 or 19 and react-dom in the host application.


Quick Start Integration

1. Server-Side: Create a Session

To keep your credentials secure, session registration must be done on your backend server. Use createSession with your Host API Key (retrieved from the Developer Dashboard) and return the sessionToken to your browser.

import { createSession } from "proctoring-sdk";
import type { SessionPolicy } from "proctoring-sdk";

export async function startCandidateAttempt(candidateDetails) {
  // Define what proctoring metrics to enforce
  const policy: SessionPolicy = {
    cameraMonitoring: true,     // Enforce face presence
    screenMonitoring: true,     // Enforce screen share
    tabSwitching: true,         // Enforce tab focus
    copyDetection: true,        // Track clipboard copy
    pasteDetection: true,       // Track clipboard paste
    fullscreenRequired: true,   // Enforce fullscreen mode
    captureEvidence: true,      // Capture screenshots on incident trigger
    multipleMonitorDetection: true, // Warn on multi-monitor setups
  };

  const session = await createSession(
    {
      hostApiKey: process.env.PROCTORING_HOST_API_KEY,
    },
    {
      sessionReferenceId: candidateDetails.attemptId,
      expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
      testDurationMinutes: 120,
      candidate: {
        fullName: candidateDetails.fullName,
        email: candidateDetails.email,
        location: candidateDetails.location,
      },
      job: { position: "Software Engineer" },
      policy,
    }
  );

  return {
    sessionToken: session.sessionToken,
    sessionId: session.sessionId,
  };
}

2. Client-Side: Mount the Component & Handle Errors

Import the <ProctoringSession> component in your React application. Wrap your assessment cards inside it, passing the sessionToken retrieved from your backend.

When startup or permission issues occur (e.g. camera denied, screen share canceled), the SDK yields full-screen rendering to your host app and invokes onError with structured diagnostics and a retry closure.

"use client";
import React, { useState } from "react";
import { ProctoringSession } from "proctoring-sdk";
import type { IncidentEvent, ProctoringError, SessionCompleteResult } from "proctoring-sdk";

export function AssessmentPortal({ sessionToken }: { sessionToken: string }) {
  const [errorState, setErrorState] = useState<ProctoringError | null>(null);

  // Host-owned error UI
  if (errorState) {
    const { diagnosis, retry } = errorState;
    return (
      <div className="error-card">
        <h2>{diagnosis?.title || "Session Setup Issue"}</h2>
        <p>{diagnosis?.cause || errorState.message}</p>
        {diagnosis?.steps && (
          <ol>
            {diagnosis.steps.map((step, i) => (
              <li key={i}>{step}</li>
            ))}
          </ol>
        )}
        {diagnosis?.retryable && (
          <button
            type="button"
            onClick={() => {
              setErrorState(null);
              retry?.();
            }}
          >
            Retry Setup
          </button>
        )}
      </div>
    );
  }

  return (
    <ProctoringSession
      sessionToken={sessionToken}
      options={{ debug: false, fullscreenRequired: true, multipleMonitorCheck: true }}
      onReady={() => {
        setErrorState(null);
        console.log("Proctoring active");
      }}
      onIncident={(incident: IncidentEvent) => {
        if (incident.type === "heartbeat") return;
        console.log(`Infraction recorded: ${incident.type} (Severity: ${incident.severity})`);
      }}
      onComplete={(result: SessionCompleteResult) => {
        window.location.href = result.redirectUrl || "/complete";
      }}
      onError={(error: ProctoringError) => {
        console.error("Proctoring error:", error.code, error.diagnosis);
        setErrorState(error);
      }}
    >
      {/* Mount your actual exam components inside here */}
      <div className="exam-card">
        <h2>Assessment Question 1</h2>
        <p>Answer the following question...</p>
      </div>
    </ProctoringSession>
  );
}

API Reference

<ProctoringSession> Props

| Prop | Type | Required | Description | | :--- | :--- | :--- | :--- | | sessionToken | string | Yes | Short-lived authorization token received from your backend createSession call. | | options | ProctoringSessionOptions | No | Overrides for thresholds, intervals, and debug controls. | | onReady | () => void | No | Callback triggered when camera, screen, and browser listeners have successfully started. | | onIncident | (incident: IncidentEvent) => void | No | Callback triggered whenever a monitoring incident is recorded. | | onComplete | (result: SessionCompleteResult) => void | No | Callback triggered when the session is successfully finalized. | | onError | (error: ProctoringError) => void | No | Callback triggered on startup, permission, or network failure with diagnosis metadata and retry handler. |

ProctoringError & StartupErrorDiagnosis

When onError fires, it receives a ProctoringError instance:

export interface ProctoringError {
  code: string;                      // Machine-readable code (e.g. camera_permission_denied)
  message: string;                   // Human-readable message
  details?: unknown;                 // Underlying exception or event details
  diagnosis?: StartupErrorDiagnosis; // Structured troubleshooting guidance
  retry?: () => void;                // Closure that resets state and re-runs monitoring startup
}

export interface StartupErrorDiagnosis {
  code: string;                      // Standardized error code
  title: string;                     // Suggested UI heading (e.g. "Camera access is blocked")
  cause: string;                     // Plain-language explanation of what went wrong
  steps: string[];                   // Numbered step-by-step remediation steps for the candidate
  retryable: boolean;                // Whether the issue can be resolved with an immediate retry
}

ProctoringSessionOptions Configuration

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | debug | boolean | false | Enables detailed telemetry logs in the browser console. | | detectionIntervalMs | number | 2000 | Frequency in milliseconds at which the AI models run face presence detection. | | heartbeatIntervalMs | number | 30000 | Frequency in milliseconds for sending diagnostic checkups to the server. | | lowEndMode | boolean | Auto-detected | Runs smaller models and throttles intervals on low-resource machines. | | fullscreenRequired | boolean | false | Shows an in-session modal requiring the user to remain in fullscreen mode. | | multipleMonitorCheck| boolean | false | Detects extended multi-monitor displays on Chromium browsers. |


Publishing to NPM (Maintainers)

  1. Build and test the package:

    npm run build
    npm run typecheck
  2. Verify bundle contents:

    npm pack --dry-run
  3. Authenticate & Publish:

    npm login
    npm publish --access public