Skip to main content

Local Bypass Mode for Development & Presentations

Document Overview

This document provides the comprehensive technical specification for implementing a secure local bypass mode in the BIO-QMS documentation viewer. The bypass mode enables zero-friction development and offline presentations while maintaining production security through multiple safety mechanisms.

Key Design Principles:

  • Developer Productivity: Eliminate auth friction during local development
  • Offline Presentations: Support demos without network connectivity
  • Production Safety: Multiple layers prevent bypass in production deployments
  • Audit Trail: All bypass activations logged for security monitoring
  • Visual Indicators: Clear "DEV MODE" watermark when bypass active

Table of Contents

  1. Bypass Detection Logic
  2. Implementation Architecture
  3. Safety Mechanisms
  4. Development Mode Features
  5. Presentation Mode Integration
  6. Local Logging
  7. Configuration
  8. Testing with Bypass
  9. Security Audit Trail
  10. Documentation
  11. Implementation Guide
  12. Troubleshooting

1. Bypass Detection Logic

1.1 Detection Modes

The bypass system supports three detection modes, evaluated in order:

PriorityModeActivationUse Case
1Environment VariableVITE_AUTH_MODE=nonePrimary dev mode, CI/CD testing
2URL Parameter?bypass=localQuick testing, presentations
3Build-Time FlagVite dev server detectionAutomatic dev mode

1.2 Environment Variable Detection

Variable: VITE_AUTH_MODE=none

Behavior:

  • Full bypass, no auth checks anywhere in application
  • All auth provider methods return immediately
  • No network requests to auth service
  • All documents visible regardless of NDA status

Implementation:

// src/config/auth.config.ts

export type AuthMode = 'none' | 'gcp';

export interface AuthConfig {
mode: AuthMode;
bypassEnabled: boolean;
bypassSource: 'env' | 'url' | 'build' | null;
}

export function getAuthConfig(): AuthConfig {
// Priority 1: Environment variable
const envMode = import.meta.env.VITE_AUTH_MODE as AuthMode;

if (envMode === 'none') {
return {
mode: 'none',
bypassEnabled: true,
bypassSource: 'env'
};
}

// Priority 2: URL parameter (localhost only)
if (isLocalhostBypass()) {
return {
mode: 'none',
bypassEnabled: true,
bypassSource: 'url'
};
}

// Priority 3: Dev server detection
if (isDevServer()) {
return {
mode: 'none',
bypassEnabled: true,
bypassSource: 'build'
};
}

// Default: GCP auth required
return {
mode: 'gcp',
bypassEnabled: false,
bypassSource: null
};
}

1.3 URL Parameter Detection

Parameter: ?bypass=local

Security Constraints:

  • Only activates on localhost, 127.0.0.1, or [::1]
  • Production domains reject parameter with CSP violation
  • Server-side validation (Cloud Run rejects parameter)

Hostname Verification:

// src/auth/bypass/hostnameValidator.ts

const ALLOWED_HOSTNAMES = [
'localhost',
'127.0.0.1',
'[::1]',
'0.0.0.0'
];

const PROD_DOMAINS = [
'docs.coditect.ai',
'bio-qms.docs.coditect.ai',
'coditect.ai'
];

export function isLocalhostBypass(): boolean {
const params = new URLSearchParams(window.location.search);

if (!params.has('bypass') || params.get('bypass') !== 'local') {
return false;
}

const hostname = window.location.hostname;

// Check if localhost
const isLocalhost = ALLOWED_HOSTNAMES.includes(hostname);

// Check if production domain
const isProd = PROD_DOMAINS.some(domain =>
hostname.includes(domain)
);

if (isProd && isLocalhost === false) {
console.error('SECURITY VIOLATION: Bypass parameter on production domain');

// Send security alert
sendSecurityAlert({
type: 'bypass_attempt_production',
hostname,
url: window.location.href,
timestamp: new Date().toISOString()
});

return false;
}

return isLocalhost;
}

1.4 Build-Time Detection

Method: Vite dev server vs production build detection

Implementation:

// src/auth/bypass/buildDetector.ts

export function isDevServer(): boolean {
// Vite sets this automatically
const isDev = import.meta.env.DEV;
const isProduction = import.meta.env.PROD;

// Check if running on Vite dev server (typically port 5173)
const isDevPort = window.location.port === '5173' || window.location.port === '3000';

// Dev mode if:
// 1. Vite DEV flag is true, OR
// 2. Running on typical dev port AND not production build
return isDev || (isDevPort && !isProduction);
}

export function getBuildInfo(): BuildInfo {
return {
env: import.meta.env.MODE,
isDev: import.meta.env.DEV,
isProd: import.meta.env.PROD,
timestamp: import.meta.env.VITE_BUILD_TIMESTAMP,
commit: import.meta.env.VITE_GIT_COMMIT,
version: import.meta.env.VITE_APP_VERSION || '1.0.0'
};
}

1.5 Detection Flow Diagram

┌─────────────────────┐
│ App Initialization │
└──────────┬──────────┘

┌──────▼──────┐
│ Check ENV │
│ AUTH_MODE? │
└──┬────────┬─┘
│ none │ gcp
│ │
▼ │
┌────┐ │
│Bypass│ │
│ ON │ │
└────┘ │

┌──────▼────────┐
│ Check URL │
│ ?bypass=local?│
└──┬────────┬───┘
│ Yes │ No
│ │
┌────▼────┐ │
│Localhost?│ │
└──┬───┬──┘ │
│Yes│No │
│ │ │
▼ ▼ │
┌────┐┌────┐│
│ON ││OFF ││
└────┘└────┘│

┌──────▼──────┐
│ Check Build │
│ Dev Server? │
└──┬────────┬─┘
│ Yes │ No
│ │
┌──▼──┐ ┌──▼──┐
│ ON │ │ GCP │
│ │ │ AUTH│
└─────┘ └─────┘

2. Implementation Architecture

2.1 Component Overview

┌──────────────────────────────────────────────────────┐
│ BIO-QMS Viewer App │
├──────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ AuthBypassProvider │ │
│ │ (Wraps AuthProvider, short-circuits checks) │ │
│ └────────────┬─────────────────────────────────┬─┘ │
│ │ │ │
│ ┌──────────▼──────────┐ ┌────────────▼───┐│
│ │ NoopTokenValidator │ │ MockUser ││
│ │ (validates all) │ │ Context ││
│ └─────────────────────┘ └────────────────┘│
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ DevModeIndicator │ │
│ │ (Prominent watermark banner) │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ LocalAccessLogger │ │
│ │ (Browser console + localStorage log) │ │
│ └────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────┘

2.2 AuthBypassProvider

Purpose: Wraps the standard AuthProvider and short-circuits all auth checks when bypass is active.

Implementation:

// src/auth/bypass/AuthBypassProvider.tsx

import React, { createContext, useContext, useEffect, useState } from 'react';
import { AuthProvider, User } from '../AuthProvider.interface';
import { getAuthConfig } from '../../config/auth.config';
import { MockUserProvider } from './MockUserProvider';
import { NoopTokenValidator } from './NoopTokenValidator';
import { LocalAccessLogger } from './LocalAccessLogger';

interface BypassContextValue {
bypassActive: boolean;
bypassSource: 'env' | 'url' | 'build' | null;
mockUser: User;
}

const BypassContext = createContext<BypassContextValue | undefined>(undefined);

interface AuthBypassProviderProps {
authProvider: AuthProvider;
children: React.ReactNode;
}

export function AuthBypassProvider({ authProvider, children }: AuthBypassProviderProps) {
const config = getAuthConfig();
const [bypassActive] = useState(config.bypassEnabled);
const logger = new LocalAccessLogger();

useEffect(() => {
if (bypassActive) {
console.warn(
'%c⚠️ AUTH BYPASS ACTIVE — DO NOT USE IN PRODUCTION',
'background: #ff0000; color: #ffffff; font-size: 16px; font-weight: bold; padding: 10px;'
);

logger.logBypassActivation({
source: config.bypassSource!,
hostname: window.location.hostname,
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent
});
}
}, [bypassActive, config.bypassSource, logger]);

if (!bypassActive) {
// No bypass, use real auth provider
return <>{children}</>;
}

// Bypass active, wrap with mock provider
const mockUser: User = {
id: 'local-dev-user',
email: 'dev@localhost',
name: 'Local Development User',
orgId: 'local-org',
ndaStatus: 'accepted' // All documents accessible
};

const contextValue: BypassContextValue = {
bypassActive: true,
bypassSource: config.bypassSource!,
mockUser
};

return (
<BypassContext.Provider value={contextValue}>
<MockUserProvider user={mockUser}>
{children}
</MockUserProvider>
</BypassContext.Provider>
);
}

export function useBypass(): BypassContextValue {
const context = useContext(BypassContext);

if (!context) {
// Bypass not active
return {
bypassActive: false,
bypassSource: null,
mockUser: null as any
};
}

return context;
}

2.3 MockUserProvider

Purpose: Provides synthetic user data for components expecting authenticated context.

Implementation:

// src/auth/bypass/MockUserProvider.tsx

import React, { createContext, useContext } from 'react';
import { User } from '../AuthProvider.interface';

const MockUserContext = createContext<User | null>(null);

interface MockUserProviderProps {
user: User;
children: React.ReactNode;
}

export function MockUserProvider({ user, children }: MockUserProviderProps) {
return (
<MockUserContext.Provider value={user}>
{children}
</MockUserContext.Provider>
);
}

export function useMockUser(): User | null {
return useContext(MockUserContext);
}

// Extended mock user for testing different scenarios
export const MockUsers = {
developer: {
id: 'dev-user',
email: 'dev@localhost',
name: 'Local Developer',
orgId: 'local-org',
ndaStatus: 'accepted' as const
},

ndaPending: {
id: 'nda-pending-user',
email: 'pending@localhost',
name: 'NDA Pending User',
orgId: 'local-org',
ndaStatus: 'pending' as const
},

ndaDeclined: {
id: 'nda-declined-user',
email: 'declined@localhost',
name: 'NDA Declined User',
orgId: 'local-org',
ndaStatus: 'declined' as const
},

researcher: {
id: 'researcher-user',
email: 'researcher@localhost',
name: 'Research Scientist',
orgId: 'biotech-labs',
ndaStatus: 'accepted' as const
}
};

2.4 NoopTokenValidator

Purpose: Validates all tokens as true without making API calls.

Implementation:

// src/auth/bypass/NoopTokenValidator.ts

import { TokenValidator } from '../TokenValidator.interface';

export class NoopTokenValidator implements TokenValidator {
async validateToken(token: string): Promise<boolean> {
// Bypass mode: all tokens valid
return true;
}

async validateClaims(claims: Record<string, any>): Promise<boolean> {
// Bypass mode: all claims valid
return true;
}

async verifySignature(token: string): Promise<boolean> {
// Bypass mode: no signature verification
return true;
}

async checkExpiry(token: string): Promise<boolean> {
// Bypass mode: tokens never expire
return true;
}

isExpired(expiryTimestamp: number): boolean {
// Bypass mode: nothing is expired
return false;
}
}

2.5 Feature Flag Integration

Purpose: Enable granular bypass controls for specific features.

Implementation:

// src/config/featureFlags.ts

export interface FeatureFlags {
bypassAuth: boolean;
bypassNdaGating: boolean;
bypassRateLimiting: boolean;
bypassAnalytics: boolean;
showDevIndicators: boolean;
}

export function getFeatureFlags(): FeatureFlags {
const config = getAuthConfig();
const bypassActive = config.bypassEnabled;

return {
// Auth bypass
bypassAuth: bypassActive,

// NDA gating (only bypass if auth bypass active)
bypassNdaGating: bypassActive,

// Rate limiting (always bypass in dev)
bypassRateLimiting: isDevServer() || bypassActive,

// Analytics (bypass in dev only, not in presentations)
bypassAnalytics: isDevServer(),

// Dev indicators (show watermark)
showDevIndicators: bypassActive
};
}

// Hook for components
export function useFeatureFlag(flag: keyof FeatureFlags): boolean {
const flags = getFeatureFlags();
return flags[flag];
}

3. Safety Mechanisms

3.1 Production Bypass Prevention

Strategy: Multiple layers ensure bypass cannot activate in production.

Layer 1: Build-Time Validation

Script: scripts/validate-production-auth.sh

#!/bin/bash
# scripts/validate-production-auth.sh

set -e

ENV_FILE="${1:-.env.production}"

echo "🔒 Validating production auth configuration..."

if [ ! -f "$ENV_FILE" ]; then
echo "❌ Environment file not found: $ENV_FILE"
exit 1
fi

source "$ENV_FILE"

# Check AUTH_MODE
if [ "$VITE_AUTH_MODE" = "none" ]; then
echo "❌ CRITICAL: Production build MUST use AUTH_MODE=gcp, found: none"
exit 1
fi

if [ -z "$VITE_AUTH_MODE" ]; then
echo "❌ CRITICAL: VITE_AUTH_MODE is not set"
exit 1
fi

if [ "$VITE_AUTH_MODE" != "gcp" ]; then
echo "❌ CRITICAL: Invalid AUTH_MODE for production: $VITE_AUTH_MODE"
exit 1
fi

echo "✅ Production auth mode validated: gcp"
echo "✅ Production build is SAFE to deploy"

CI/CD Integration:

# .github/workflows/deploy.yml

jobs:
deploy-production:
runs-on: ubuntu-latest
steps:
- name: Validate Auth Configuration
run: |
./scripts/validate-production-auth.sh .env.production
if [ $? -ne 0 ]; then
echo "::error::Production auth validation failed"
exit 1
fi

- name: Build Production
run: npm run build --mode production

- name: Deploy to Cloud Run
run: gcloud run deploy bio-qms-viewer --image=$IMAGE

Layer 2: Vite Build Plugin

Purpose: Strip bypass code from production bundles.

// vite-plugins/stripBypassCode.ts

import { Plugin } from 'vite';

export function stripBypassCode(): Plugin {
return {
name: 'strip-bypass-code',

transform(code, id) {
// Only strip in production builds
if (process.env.NODE_ENV !== 'production') {
return null;
}

// Remove bypass detection code
let transformedCode = code;

// Replace bypass check with constant false
transformedCode = transformedCode.replace(
/isLocalhostBypass\(\)/g,
'false'
);

// Replace bypass parameter check
transformedCode = transformedCode.replace(
/params\.get\(['"]bypass['"]\)/g,
'null'
);

// Remove dev server detection
transformedCode = transformedCode.replace(
/isDevServer\(\)/g,
'false'
);

return {
code: transformedCode,
map: null
};
}
};
}

Vite Config:

// vite.config.ts

import { defineConfig } from 'vite';
import { stripBypassCode } from './vite-plugins/stripBypassCode';

export default defineConfig({
plugins: [
react(),
tailwindcss(),

// Strip bypass code in production
process.env.NODE_ENV === 'production' && stripBypassCode()
].filter(Boolean)
});

Layer 3: Server-Side Rejection

Purpose: Cloud Run rejects bypass parameter at edge.

Configuration: app.yaml

# Cloud Run configuration

env_variables:
VITE_AUTH_MODE: gcp

# CSP header rejects bypass parameter
handlers:
- url: /.*
script: auto
secure: always
redirect_http_response_code: 301

# Request filtering
before_request:
- validate_no_bypass_param

Middleware:

// server/middleware/validateBypass.ts

export function validateNoBypassParam(req, res, next) {
const bypassParam = req.query.bypass;

if (bypassParam) {
// Log security violation
console.error('Security violation: bypass parameter detected in production', {
ip: req.ip,
url: req.url,
userAgent: req.headers['user-agent'],
timestamp: new Date().toISOString()
});

// Send alert to monitoring
sendSecurityAlert({
type: 'bypass_attempt',
details: {
ip: req.ip,
url: req.url
}
});

// Reject request
res.status(403).json({
error: 'Forbidden',
message: 'Bypass parameter not allowed in production'
});

return;
}

next();
}

Layer 4: CSP Header

Purpose: Content Security Policy prevents parameter injection.

Content-Security-Policy:
default-src 'self';
script-src 'self';
connect-src 'self' https://auth.coditect.ai;
form-action 'none';

Violation Reporting:

// CSP violation handler

window.addEventListener('securitypolicyviolation', (event) => {
console.error('CSP Violation:', event);

sendSecurityAlert({
type: 'csp_violation',
details: {
violatedDirective: event.violatedDirective,
blockedURI: event.blockedURI,
sourceFile: event.sourceFile,
lineNumber: event.lineNumber
}
});
});

3.2 Hostname Verification

Purpose: Bypass only activates on verified localhost addresses.

Implementation:

// src/auth/bypass/hostnameValidator.ts

export function isValidLocalhost(): boolean {
const hostname = window.location.hostname;

const validHostnames = [
'localhost',
'127.0.0.1',
'[::1]',
'0.0.0.0',
// Vite default dev server
'localhost:5173',
'127.0.0.1:5173'
];

return validHostnames.some(valid =>
hostname === valid || hostname.startsWith(valid)
);
}

export function validateHostnameBeforeBypass(): boolean {
if (!isValidLocalhost()) {
console.error('Bypass rejected: hostname validation failed', {
hostname: window.location.hostname,
href: window.location.href
});

return false;
}

// Additional check: not a production domain
const isProd = isProductionDomain(window.location.hostname);

if (isProd) {
console.error('Bypass rejected: production domain detected', {
hostname: window.location.hostname
});

return false;
}

return true;
}

function isProductionDomain(hostname: string): boolean {
const prodDomains = [
'coditect.ai',
'docs.coditect.ai',
'bio-qms.docs.coditect.ai'
];

return prodDomains.some(domain => hostname.includes(domain));
}

3.3 Visual Indicators

Purpose: Prominent "DEV MODE" banner when bypass active.

Implementation:

// src/components/DevModeIndicator.tsx

import React from 'react';
import { AlertTriangle } from 'lucide-react';
import { useBypass } from '../auth/bypass/AuthBypassProvider';
import { getBuildInfo } from '../auth/bypass/buildDetector';

export function DevModeIndicator() {
const { bypassActive, bypassSource } = useBypass();

if (!bypassActive) {
return null;
}

const buildInfo = getBuildInfo();

return (
<div className="dev-mode-banner">
<div className="dev-mode-banner-content">
<AlertTriangle size={24} className="dev-mode-icon" />

<div className="dev-mode-text">
<strong>DEVELOPMENT MODEUNAUTHENTICATED</strong>
<span className="dev-mode-details">
Bypass: {bypassSource} | Build: {buildInfo.env} |
{buildInfo.commit && ` Commit: ${buildInfo.commit.slice(0, 7)}`}
</span>
</div>

<button
onClick={() => window.location.href = '/?bypass=off'}
className="dev-mode-disable"
>
Disable Bypass
</button>
</div>
</div>
);
}

Styles:

/* styles.css */

.dev-mode-banner {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
background: linear-gradient(135deg, #ff6b6b 0%, #ff0000 100%);
border-bottom: 3px solid #cc0000;
padding: 12px 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.dev-mode-banner-content {
display: flex;
align-items: center;
gap: 16px;
max-width: 1400px;
margin: 0 auto;
color: white;
}

.dev-mode-icon {
animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.1); }
}

.dev-mode-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}

.dev-mode-text strong {
font-size: 16px;
font-weight: 700;
letter-spacing: 0.5px;
}

.dev-mode-details {
font-size: 12px;
opacity: 0.9;
font-family: 'Monaco', 'Courier New', monospace;
}

.dev-mode-disable {
padding: 8px 16px;
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.4);
color: white;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
font-weight: 600;
transition: all 0.2s;
}

.dev-mode-disable:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}

/* Watermark in bottom-right */
.dev-mode-watermark {
position: fixed;
bottom: 20px;
right: 20px;
background: rgba(255, 0, 0, 0.8);
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 11px;
font-weight: 700;
z-index: 9998;
pointer-events: none;
font-family: 'Monaco', 'Courier New', monospace;
}

3.4 Console Warnings

Purpose: Log prominent warnings in browser console.

Implementation:

// src/auth/bypass/consoleWarnings.ts

export function displayConsoleWarning() {
const styles = {
error: 'background: #ff0000; color: #ffffff; font-size: 20px; font-weight: bold; padding: 12px 20px; border-radius: 4px;',
warn: 'background: #ff6b00; color: #ffffff; font-size: 14px; padding: 8px 12px;',
info: 'color: #666; font-size: 12px;'
};

console.log(
'%c⚠️ AUTH BYPASS ACTIVE',
styles.error
);

console.log(
'%cDO NOT USE IN PRODUCTION',
styles.warn
);

console.log(
'%cAll authentication checks are disabled. This mode is for local development and presentations only.',
styles.info
);

console.table({
'Bypass Source': getAuthConfig().bypassSource,
'Hostname': window.location.hostname,
'Build Environment': import.meta.env.MODE,
'Timestamp': new Date().toISOString()
});

// Repeat warning every 5 minutes
setInterval(() => {
console.warn('⚠️ AUTH BYPASS STILL ACTIVE');
}, 5 * 60 * 1000);
}

4. Development Mode Features

4.1 Hot Reload Without Re-authentication

Benefit: Vite HMR (Hot Module Replacement) works seamlessly without auth interruptions.

Implementation:

// src/main.tsx

if (import.meta.hot) {
import.meta.hot.accept(() => {
// Hot reload: preserve auth state
console.log('HMR: Module reloaded, auth state preserved');
});
}

4.2 All Documents Visible

Behavior: NDA gating disabled, all documents accessible regardless of audience scope.

Implementation:

// src/components/DocumentFilter.tsx

export function shouldShowDocument(doc: Document, user: User | null): boolean {
const { bypassActive } = useBypass();

// Bypass mode: show all documents
if (bypassActive) {
return true;
}

// Normal mode: check NDA status
if (doc.ndaRequired && user?.ndaStatus !== 'accepted') {
return false;
}

// Check org scope
if (doc.orgScope && doc.orgScope !== user?.orgId) {
return false;
}

return true;
}

4.3 Mock User Switcher

Purpose: Test different user roles/permissions without re-authentication.

Implementation:

// src/components/MockUserSwitcher.tsx

import React, { useState } from 'react';
import { User, ChevronDown } from 'lucide-react';
import { MockUsers } from '../auth/bypass/MockUserProvider';
import { useBypass } from '../auth/bypass/AuthBypassProvider';

export function MockUserSwitcher() {
const { bypassActive } = useBypass();
const [currentUser, setCurrentUser] = useState<string>('developer');
const [isOpen, setIsOpen] = useState(false);

if (!bypassActive) {
return null;
}

const users = Object.entries(MockUsers);
const selectedUser = MockUsers[currentUser as keyof typeof MockUsers];

return (
<div className="mock-user-switcher">
<button
onClick={() => setIsOpen(!isOpen)}
className="mock-user-button"
>
<User size={16} />
<span>{selectedUser.name}</span>
<ChevronDown size={14} />
</button>

{isOpen && (
<div className="mock-user-dropdown">
{users.map(([key, user]) => (
<button
key={key}
onClick={() => {
setCurrentUser(key);
setIsOpen(false);

// Update mock user in context
localStorage.setItem('mock_user_key', key);
window.location.reload();
}}
className={`mock-user-option ${currentUser === key ? 'active' : ''}`}
>
<div className="mock-user-info">
<strong>{user.name}</strong>
<span className="mock-user-email">{user.email}</span>
<span className={`mock-user-nda nda-${user.ndaStatus}`}>
NDA: {user.ndaStatus}
</span>
</div>
</button>
))}
</div>
)}
</div>
);
}

4.4 Network Tab Indicators

Purpose: Show "(bypassed)" indicator for auth requests in DevTools.

Implementation:

// src/auth/bypass/networkIndicator.ts

export function interceptAuthRequests() {
const { bypassActive } = useBypass();

if (!bypassActive) {
return;
}

// Intercept fetch for auth endpoints
const originalFetch = window.fetch;

window.fetch = async (...args) => {
const [url, options] = args;

// Check if auth endpoint
if (typeof url === 'string' && url.includes('auth.coditect.ai')) {
console.log(
'%c[BYPASSED]',
'background: #ff6b00; color: white; padding: 2px 6px; border-radius: 2px;',
url
);

// Return mock response
return Promise.resolve(new Response(
JSON.stringify({ bypassed: true }),
{
status: 200,
headers: { 'Content-Type': 'application/json' }
}
));
}

return originalFetch(...args);
};
}

4.5 Performance Profiling

Benefit: Profile without auth overhead for accurate measurements.

Usage:

// Example: Profile document loading

import { useBypass } from '../auth/bypass/AuthBypassProvider';

export function useDocumentLoad(docId: string) {
const { bypassActive } = useBypass();

useEffect(() => {
const startTime = performance.now();

loadDocument(docId).then(() => {
const loadTime = performance.now() - startTime;

console.log(`Document loaded in ${loadTime.toFixed(2)}ms`, {
bypassed: bypassActive,
authOverhead: bypassActive ? '0ms' : 'included'
});
});
}, [docId, bypassActive]);
}

5. Presentation Mode Integration

5.1 Seamless Integration

Design: Presentation mode (A.3) works seamlessly with bypass.

Implementation:

// src/components/PresentationMode.tsx

export function PresentationMode({ doc }: PresentationModeProps) {
const { bypassActive } = useBypass();
const [isPresentationMode, setIsPresentationMode] = useState(false);

// Presentation mode benefits from bypass:
// - No auth popups during screen sharing
// - Clean URLs without tokens
// - No network latency from auth checks

useEffect(() => {
if (isPresentationMode && bypassActive) {
console.log('Presentation mode + bypass active: optimal for demos');
}
}, [isPresentationMode, bypassActive]);

return (
<div className={isPresentationMode ? 'presentation-mode' : ''}>
{/* Presentation UI */}
</div>
);
}

5.2 No Auth Popups

Behavior: Screen sharing never interrupted by auth prompts.

Rationale:

  • Bypass mode = no auth required
  • No token expiry checks during presentation
  • No network requests to auth service

5.3 Clean URLs

Benefit: URLs don't contain JWT tokens or auth parameters.

Example:

✅ With Bypass:  https://localhost:5173/#/compliance/fda-21-cfr-part-11
❌ With Auth: https://bio-qms.docs.coditect.ai/#/compliance/fda-21-cfr-part-11?token=eyJhbG...

5.4 Audience Scope Override

Purpose: Demo all documents regardless of NDA status.

Implementation:

// src/filters/audienceFilter.ts

export function getVisibleDocuments(
documents: Document[],
user: User | null
): Document[] {
const { bypassActive } = useBypass();

if (bypassActive) {
// Bypass: show all documents
return documents;
}

// Normal: filter by NDA status and org
return documents.filter(doc => {
if (doc.ndaRequired && user?.ndaStatus !== 'accepted') {
return false;
}

if (doc.orgScope && doc.orgScope !== user?.orgId) {
return false;
}

return true;
});
}

6. Local Logging

6.1 Browser Console Logging

Purpose: All access events logged to browser console in dev mode.

Implementation:

// src/logging/devLogger.ts

export class DevLogger {
private enabled: boolean;

constructor() {
this.enabled = useBypass().bypassActive;
}

logAccess(doc: Document) {
if (!this.enabled) return;

console.log(
'%c[ACCESS]',
'background: #00aa00; color: white; padding: 2px 6px; border-radius: 2px;',
{
document: doc.title,
path: doc.path,
ndaRequired: doc.ndaRequired,
timestamp: new Date().toISOString()
}
);
}

logBypassActivation(details: BypassActivationDetails) {
console.group('%c⚠️ BYPASS ACTIVATED', 'font-size: 14px; font-weight: bold;');
console.table(details);
console.groupEnd();
}

logSecurityCheck(check: SecurityCheck) {
console.log(
'%c[SECURITY]',
'background: #ff6b00; color: white; padding: 2px 6px;',
check
);
}
}

export const devLogger = new DevLogger();

6.2 localStorage Access Log

Purpose: Persistent access log for debugging across sessions.

Implementation:

// src/logging/localAccessLog.ts

interface AccessLogEntry {
timestamp: string;
document: string;
path: string;
bypassActive: boolean;
userAgent: string;
}

export class LocalAccessLog {
private storageKey = 'bio_qms_access_log';
private maxEntries = 1000;

logAccess(doc: Document) {
const { bypassActive } = useBypass();

const entry: AccessLogEntry = {
timestamp: new Date().toISOString(),
document: doc.title,
path: doc.path,
bypassActive,
userAgent: navigator.userAgent
};

// Append to log
const log = this.getLog();
log.push(entry);

// Trim if too large
if (log.length > this.maxEntries) {
log.shift();
}

// Save
localStorage.setItem(this.storageKey, JSON.stringify(log));
}

getLog(): AccessLogEntry[] {
try {
const stored = localStorage.getItem(this.storageKey);
return stored ? JSON.parse(stored) : [];
} catch {
return [];
}
}

clearLog() {
localStorage.removeItem(this.storageKey);
}

exportLog(): string {
const log = this.getLog();
return JSON.stringify(log, null, 2);
}
}

export const localAccessLog = new LocalAccessLog();

6.3 Export Local Log

Purpose: Export log for testing validation or debugging.

Implementation:

// src/components/AccessLogExporter.tsx

import React from 'react';
import { Download } from 'lucide-react';
import { localAccessLog } from '../logging/localAccessLog';
import { useBypass } from '../auth/bypass/AuthBypassProvider';

export function AccessLogExporter() {
const { bypassActive } = useBypass();

if (!bypassActive) {
return null;
}

const handleExport = () => {
const log = localAccessLog.exportLog();
const blob = new Blob([log], { type: 'application/json' });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = `bio-qms-access-log-${Date.now()}.json`;
a.click();

URL.revokeObjectURL(url);
};

const handleClear = () => {
if (confirm('Clear access log? This cannot be undone.')) {
localAccessLog.clearLog();
alert('Access log cleared');
}
};

const log = localAccessLog.getLog();

return (
<div className="access-log-exporter">
<button onClick={handleExport} className="btn-export">
<Download size={16} />
Export Log ({log.length} entries)
</button>

<button onClick={handleClear} className="btn-clear">
Clear Log
</button>
</div>
);
}

7. Configuration

7.1 .env.development

Purpose: Default local development configuration.

# .env.development

# Auth Mode: No authentication required
VITE_AUTH_MODE=none

# Build Info (for watermark)
VITE_BUILD_ENV=development
VITE_BUILD_TIMESTAMP=2026-02-16T10:00:00Z
VITE_GIT_COMMIT=local-dev

# Dev Server
VITE_DEV_SERVER_PORT=5173
VITE_DEV_SERVER_HOST=localhost

# Feature Flags
VITE_ENABLE_DEV_TOOLS=true
VITE_ENABLE_MOCK_USER_SWITCHER=true
VITE_ENABLE_ACCESS_LOG=true

# Logging
VITE_LOG_LEVEL=debug
VITE_LOG_BYPASS_EVENTS=true

Usage:

npm run dev  # Automatically loads .env.development

7.2 .env.production

Purpose: Production configuration (bypass DISABLED).

# .env.production

# Auth Mode: GCP authentication REQUIRED
VITE_AUTH_MODE=gcp

# GCP Auth Configuration
VITE_AUTH_ISSUER=https://auth.coditect.ai
VITE_AUTH_AUDIENCE=bio-qms.docs.coditect.ai
VITE_AUTH_JWKS_URI=https://auth.coditect.ai/.well-known/jwks.json
VITE_AUTH_LOGIN_URL=https://auth.coditect.ai/login

# Build Info
VITE_BUILD_ENV=production
VITE_BUILD_TIMESTAMP=${BUILD_TIMESTAMP}
VITE_GIT_COMMIT=${GIT_COMMIT}

# Feature Flags (all dev features DISABLED)
VITE_ENABLE_DEV_TOOLS=false
VITE_ENABLE_MOCK_USER_SWITCHER=false
VITE_ENABLE_ACCESS_LOG=false

# Logging
VITE_LOG_LEVEL=error
VITE_LOG_BYPASS_EVENTS=false

Usage:

npm run build --mode production

7.3 .env.staging

Purpose: Staging environment (bypass DISABLED, test auth).

# .env.staging

# Auth Mode: GCP authentication with staging auth service
VITE_AUTH_MODE=gcp

# Staging Auth Configuration
VITE_AUTH_ISSUER=https://auth-staging.coditect.ai
VITE_AUTH_AUDIENCE=bio-qms-staging.docs.coditect.ai
VITE_AUTH_JWKS_URI=https://auth-staging.coditect.ai/.well-known/jwks.json
VITE_AUTH_LOGIN_URL=https://auth-staging.coditect.ai/login

# Build Info
VITE_BUILD_ENV=staging
VITE_BUILD_TIMESTAMP=${BUILD_TIMESTAMP}
VITE_GIT_COMMIT=${GIT_COMMIT}

# Feature Flags (limited dev features)
VITE_ENABLE_DEV_TOOLS=true
VITE_ENABLE_MOCK_USER_SWITCHER=false
VITE_ENABLE_ACCESS_LOG=true

# Logging
VITE_LOG_LEVEL=info
VITE_LOG_BYPASS_EVENTS=true

7.4 Vite Configuration

Purpose: Environment-specific plugin loading.

// vite.config.ts

import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import { stripBypassCode } from './vite-plugins/stripBypassCode';

export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const isProduction = mode === 'production';
const authMode = env.VITE_AUTH_MODE;

// Validate production auth
if (isProduction && authMode !== 'gcp') {
throw new Error(
`CRITICAL: Production build requires AUTH_MODE=gcp, found: ${authMode}`
);
}

return {
plugins: [
react(),
tailwindcss(),

// Strip bypass code in production
isProduction && stripBypassCode()
].filter(Boolean),

define: {
// Inject build-time constants
'__BUILD_TIMESTAMP__': JSON.stringify(new Date().toISOString()),
'__GIT_COMMIT__': JSON.stringify(process.env.GIT_COMMIT || 'unknown'),
'__AUTH_MODE__': JSON.stringify(authMode)
},

server: {
port: 5173,
host: 'localhost',
open: true
},

build: {
sourcemap: !isProduction,
minify: isProduction ? 'terser' : false,

terserOptions: {
compress: {
// Remove bypass code
drop_console: isProduction,
drop_debugger: isProduction,

// Remove dead code
dead_code: true,
conditionals: true
}
}
}
};
});

8. Testing with Bypass

8.1 Unit Tests with Bypass Enabled

Strategy: All unit tests run with bypass to avoid auth mocking complexity.

Configuration:

// vitest.config.ts

import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
environment: 'jsdom',
setupFiles: ['./tests/setup.ts'],

env: {
// Force bypass in tests
VITE_AUTH_MODE: 'none',
VITE_BUILD_ENV: 'test'
}
}
});

Setup File:

// tests/setup.ts

import { vi } from 'vitest';

// Mock auth config to return bypass mode
vi.mock('../src/config/auth.config', () => ({
getAuthConfig: () => ({
mode: 'none',
bypassEnabled: true,
bypassSource: 'env'
})
}));

// Mock window.location
Object.defineProperty(window, 'location', {
value: {
hostname: 'localhost',
href: 'http://localhost:5173',
search: ''
},
writable: true
});

8.2 Integration Tests (Auth-Enabled and Bypassed)

Strategy: Separate test suites for both modes.

Bypass Suite:

// tests/integration/bypass.test.ts

import { render, screen } from '@testing-library/react';
import { describe, it, expect, beforeEach } from 'vitest';
import { Viewer } from '../src/Viewer';

describe('Viewer with Bypass', () => {
beforeEach(() => {
// Set bypass mode
process.env.VITE_AUTH_MODE = 'none';
});

it('should show dev mode indicator', () => {
render(<Viewer />);
expect(screen.getByText(/DEVELOPMENT MODE/i)).toBeInTheDocument();
});

it('should show all documents regardless of NDA', () => {
render(<Viewer />);

// Documents requiring NDA should be visible
expect(screen.getByText(/Confidential Document/i)).toBeInTheDocument();
});

it('should use mock user', () => {
render(<Viewer />);
expect(screen.getByText(/dev@localhost/i)).toBeInTheDocument();
});
});

Auth Suite:

// tests/integration/auth.test.ts

import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, beforeEach } from 'vitest';
import { Viewer } from '../src/Viewer';

describe('Viewer with Auth', () => {
beforeEach(() => {
// Set auth mode
process.env.VITE_AUTH_MODE = 'gcp';
});

it('should redirect to login when unauthenticated', async () => {
render(<Viewer />);

await waitFor(() => {
expect(window.location.href).toContain('/login');
});
});

it('should hide NDA documents when user has not accepted', () => {
// Mock user with NDA pending
localStorage.setItem('bio_qms_auth_token', createMockJWT({
nda_status: 'pending'
}));

render(<Viewer />);

expect(screen.queryByText(/Confidential Document/i)).not.toBeInTheDocument();
});
});

8.3 E2E Tests with Playwright

Bypass Tests:

// tests/e2e/bypass.spec.ts

import { test, expect } from '@playwright/test';

test.describe('Bypass Mode', () => {
test('should activate bypass with URL parameter', async ({ page }) => {
await page.goto('http://localhost:5173/?bypass=local');

// Check for dev mode indicator
await expect(page.locator('.dev-mode-banner')).toBeVisible();
await expect(page.locator('.dev-mode-banner')).toContainText('DEVELOPMENT MODE');
});

test('should show all documents in bypass mode', async ({ page }) => {
await page.goto('http://localhost:5173/?bypass=local');

// Wait for documents to load
await page.waitForSelector('.sidebar');

// Count visible documents
const docs = await page.locator('.document-item').count();
expect(docs).toBeGreaterThan(0);

// Check that NDA-required docs are visible
await expect(page.locator('[data-nda-required="true"]')).toBeVisible();
});

test('should allow mock user switching', async ({ page }) => {
await page.goto('http://localhost:5173/?bypass=local');

// Click mock user switcher
await page.click('.mock-user-button');

// Select different user
await page.click('text=NDA Pending User');

// Page should reload
await page.waitForLoadState('domcontentloaded');

// Check new user is active
await expect(page.locator('.mock-user-button')).toContainText('NDA Pending User');
});
});

8.4 Test Utilities

withBypass() Wrapper:

// tests/utils/withBypass.tsx

import React from 'react';
import { AuthBypassProvider } from '../../src/auth/bypass/AuthBypassProvider';
import { NullAuthProvider } from '../../src/auth/NullAuthProvider';

export function withBypass(component: React.ReactNode) {
const provider = new NullAuthProvider();

return (
<AuthBypassProvider authProvider={provider}>
{component}
</AuthBypassProvider>
);
}

// Usage:
render(withBypass(<Viewer />));

mockAuth() Helper:

// tests/utils/mockAuth.ts

export function mockAuth(options: {
mode: 'bypass' | 'auth';
user?: Partial<User>;
}) {
if (options.mode === 'bypass') {
vi.mock('../../src/config/auth.config', () => ({
getAuthConfig: () => ({
mode: 'none',
bypassEnabled: true,
bypassSource: 'env'
})
}));
} else {
vi.mock('../../src/config/auth.config', () => ({
getAuthConfig: () => ({
mode: 'gcp',
bypassEnabled: false,
bypassSource: null
})
}));

// Mock JWT token
if (options.user) {
localStorage.setItem('bio_qms_auth_token', createMockJWT(options.user));
}
}
}

// Usage:
mockAuth({ mode: 'bypass' });

9. Security Audit Trail

9.1 Log Bypass Activations

Purpose: Record all bypass activations for security review.

Implementation:

// src/logging/bypassAuditLog.ts

interface BypassAuditEntry {
timestamp: string;
source: 'env' | 'url' | 'build';
hostname: string;
url: string;
userAgent: string;
referrer: string;
buildInfo: {
env: string;
commit: string;
timestamp: string;
};
}

export class BypassAuditLog {
private storageKey = 'bio_qms_bypass_audit';

logActivation(config: AuthConfig) {
const entry: BypassAuditEntry = {
timestamp: new Date().toISOString(),
source: config.bypassSource!,
hostname: window.location.hostname,
url: window.location.href,
userAgent: navigator.userAgent,
referrer: document.referrer,
buildInfo: getBuildInfo()
};

// Append to log
const log = this.getLog();
log.push(entry);

// Persist
localStorage.setItem(this.storageKey, JSON.stringify(log));

// Also send to server (if available)
this.sendToServer(entry);
}

private async sendToServer(entry: BypassAuditEntry) {
try {
await fetch('/api/audit/bypass', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(entry)
});
} catch (error) {
console.error('Failed to send bypass audit log:', error);
}
}

getLog(): BypassAuditEntry[] {
try {
const stored = localStorage.getItem(this.storageKey);
return stored ? JSON.parse(stored) : [];
} catch {
return [];
}
}
}

export const bypassAuditLog = new BypassAuditLog();

9.2 Production Monitoring

Strategy: Alert if bypass parameter detected in production URLs.

Implementation:

// Cloud Run monitoring alert

resource.type="cloud_run_revision"
severity="CRITICAL"
textPayload=~"bypass parameter detected"

// Alert policy:
// - Notify security team immediately
// - Trigger incident response
// - Log full request details

9.3 Penetration Test Scenarios

Test Case 1: Bypass Circumvention

// Try to activate bypass on production domain
// Expected: Rejected, security alert sent

test('cannot bypass on production domain', async ({ page }) => {
// Mock production domain
await page.goto('https://bio-qms.docs.coditect.ai/?bypass=local');

// Should NOT show dev mode indicator
await expect(page.locator('.dev-mode-banner')).not.toBeVisible();

// Should redirect to login
await expect(page.url()).toContain('/login');
});

Test Case 2: Parameter Injection

// Try to inject bypass parameter via various methods
// Expected: All rejected

test('cannot inject bypass via XSS', async ({ page }) => {
await page.goto('https://bio-qms.docs.coditect.ai/?bypass=<script>alert(1)</script>');

// Should be sanitized, no bypass
await expect(page.locator('.dev-mode-banner')).not.toBeVisible();
});

Test Case 3: Environment Variable Override

// Try to override AUTH_MODE via developer tools
// Expected: Impossible, set at build time

test('cannot override AUTH_MODE at runtime', async ({ page }) => {
await page.goto('https://bio-qms.docs.coditect.ai/');

// Try to modify import.meta.env (read-only)
await page.evaluate(() => {
try {
(import.meta.env as any).VITE_AUTH_MODE = 'none';
} catch (e) {
// Expected: readonly error
}
});

// Should still require auth
await expect(page.url()).toContain('/login');
});

10. Documentation

10.1 Developer Guide

Purpose: How to use bypass mode for local development.

Content:

# Using Bypass Mode for Local Development

## Quick Start

1. **Automatic bypass (recommended):**
```bash
npm run dev # Bypass automatically enabled
  1. Manual bypass:
    # In .env.development:
    VITE_AUTH_MODE=none

    # Or via URL:
    http://localhost:5173/?bypass=local

What Gets Bypassed

  • ✅ Authentication required
  • ✅ JWT token validation
  • ✅ NDA gating
  • ✅ Organization scope filtering
  • ✅ Rate limiting
  • ✅ Network requests to auth.coditect.ai

Visual Indicators

When bypass is active, you'll see:

  • 🔴 Red banner at top: "DEVELOPMENT MODE — UNAUTHENTICATED"
  • 📋 Console warning every 5 minutes
  • 🏷️ Watermark in bottom-right corner

Mock User Switcher

Test different user scenarios:

  1. Click user dropdown in header
  2. Select mock user:
    • Developer (NDA accepted)
    • NDA Pending User
    • NDA Declined User
    • Research Scientist
  3. Page reloads with new mock user

Disabling Bypass

To test with real auth:

# Update .env.development:
VITE_AUTH_MODE=gcp

# Or use staging env:
npm run build --mode staging
npm run preview

Troubleshooting

Bypass not activating:

  • Check .env.development has VITE_AUTH_MODE=none
  • Verify URL is localhost or 127.0.0.1
  • Clear browser cache and reload

Still seeing login screen:

  • Check for .env.production override
  • Verify no AUTH_MODE=gcp in shell environment

### 10.2 Security Review Documentation

**Purpose:** Explain why bypass is safe in production.

**Content:**

```markdown
# Bypass Mode Security Review

## Safety Guarantees

### 1. Build-Time Validation
- CI/CD pipeline rejects production builds with `AUTH_MODE=none`
- Vite plugin strips bypass code from production bundles
- TypeScript compilation fails if bypass config invalid

### 2. Server-Side Rejection
- Cloud Run middleware rejects `?bypass=` parameter
- CSP header prevents parameter injection
- WAF rules block suspicious bypass attempts

### 3. Hostname Verification
- Bypass only activates on `localhost`, `127.0.0.1`, `[::1]`
- Production domains (`*.coditect.ai`) always rejected
- DNS rebinding attacks prevented via hostname whitelist

### 4. Code Stripping
- `stripBypassCode()` Vite plugin removes bypass functions
- Minification removes dead code branches
- Source maps exclude bypass implementation

## Attack Surface Analysis

| Attack Vector | Mitigation | Residual Risk |
|---------------|------------|---------------|
| Parameter injection | CSP + server-side validation | None |
| Environment override | Build-time constants (readonly) | None |
| DNS rebinding | Hostname whitelist | Low |
| Code inspection | Code stripping + minification | Low |
| XSS token theft | N/A (no tokens in bypass mode) | None |

## Audit Trail

All bypass activations logged:
- Timestamp
- Hostname
- User agent
- Build info (commit, env, timestamp)

Logs retained for 90 days.

## Compliance

- ✅ SOC 2: Bypass disabled in production (verified)
- ✅ HIPAA: Access controls enforced (bypass dev-only)
- ✅ FDA 21 CFR Part 11: Audit trail maintained

10.3 Troubleshooting Guide

Purpose: Common bypass-related issues and solutions.

Content:

# Bypass Mode Troubleshooting

## Issue: Bypass Not Activating

**Symptoms:**
- Dev mode banner not showing
- Still being redirected to login
- URL parameter `?bypass=local` ignored

**Solutions:**

1. **Check environment variable:**
```bash
cat .env.development | grep AUTH_MODE
# Should output: VITE_AUTH_MODE=none
  1. Verify hostname:

    console.log(window.location.hostname);
    // Must be: localhost, 127.0.0.1, or [::1]
  2. Clear cache:

    rm -rf node_modules/.vite
    npm run dev
  3. Check for production override:

    # .env.production should NOT be loaded
    unset VITE_AUTH_MODE
    npm run dev

Issue: Bypass Active in Production

Symptoms:

  • Red dev banner visible on production domain
  • Console warnings in production

CRITICAL: This should never happen. If it does:

  1. Immediate action:

    • Rollback deployment immediately
    • Notify security team
    • Disable production instance
  2. Investigation:

    • Check build logs for AUTH_MODE=none
    • Verify CI/CD validation ran
    • Inspect deployed bundle for bypass code
  3. Prevention:

    • Run ./scripts/validate-production-auth.sh
    • Review .env.production config
    • Update CI/CD pipeline validation

Issue: Mock User Switcher Not Working

Symptoms:

  • Mock user dropdown not appearing
  • Switching users doesn't change behavior

Solutions:

  1. Verify bypass active:

    import { useBypass } from './auth/bypass/AuthBypassProvider';
    const { bypassActive } = useBypass();
    console.log('Bypass active:', bypassActive);
  2. Check localStorage:

    const mockUser = localStorage.getItem('mock_user_key');
    console.log('Current mock user:', mockUser);
  3. Force reload:

    localStorage.setItem('mock_user_key', 'developer');
    window.location.reload();

Issue: Console Warnings Annoying

Symptom:

  • Console warning every 5 minutes is disruptive

Solution:

Warnings are intentional to prevent accidental production deployment.

To reduce frequency:

// src/auth/bypass/consoleWarnings.ts

// Change interval from 5 minutes to 30 minutes
setInterval(() => {
console.warn('⚠️ AUTH BYPASS STILL ACTIVE');
}, 30 * 60 * 1000); // 30 minutes

Or disable entirely (NOT recommended):

// Comment out the interval
// setInterval(() => { ... }, ...);

---

## 11. Implementation Guide

### 11.1 Phase 1: Core Bypass Infrastructure

**Tasks:**

1. Create `src/auth/bypass/` directory
2. Implement `AuthBypassProvider.tsx`
3. Implement `MockUserProvider.tsx`
4. Implement `NoopTokenValidator.ts`
5. Update `src/config/auth.config.ts` with bypass detection
6. Write unit tests for bypass detection logic

**Acceptance Criteria:**

- [ ] `useBypass()` hook returns correct state
- [ ] `getAuthConfig()` detects all three bypass modes
- [ ] `MockUsers` object provides 4+ test users
- [ ] Unit tests pass with 80%+ coverage

### 11.2 Phase 2: Safety Mechanisms

**Tasks:**

1. Implement hostname validation (`hostnameValidator.ts`)
2. Create Vite plugin (`stripBypassCode.ts`)
3. Add build-time validation script (`validate-production-auth.sh`)
4. Create dev mode visual indicators (`DevModeIndicator.tsx`)
5. Add console warnings (`consoleWarnings.ts`)
6. Update CI/CD pipeline with validation step

**Acceptance Criteria:**

- [ ] Bypass rejected on production domains
- [ ] Vite plugin strips bypass code from production bundle
- [ ] CI/CD rejects production builds with `AUTH_MODE=none`
- [ ] Dev mode banner visible when bypass active
- [ ] Console warnings display correctly

### 11.3 Phase 3: Development Features

**Tasks:**

1. Implement mock user switcher (`MockUserSwitcher.tsx`)
2. Add network request interceptor (`networkIndicator.ts`)
3. Create access log exporter (`AccessLogExporter.tsx`)
4. Integrate with presentation mode (A.3)
5. Add feature flag controls (`featureFlags.ts`)

**Acceptance Criteria:**

- [ ] Mock user switcher functional
- [ ] Auth requests show "(bypassed)" in DevTools
- [ ] Access log exports as JSON
- [ ] Presentation mode works with bypass
- [ ] Feature flags toggle correctly

### 11.4 Phase 4: Logging & Audit

**Tasks:**

1. Implement dev logger (`devLogger.ts`)
2. Create local access log (`localAccessLog.ts`)
3. Build bypass audit log (`bypassAuditLog.ts`)
4. Add server-side logging endpoint
5. Configure production monitoring alerts

**Acceptance Criteria:**

- [ ] All access events logged to console
- [ ] Access log persists in localStorage
- [ ] Bypass activations logged with full context
- [ ] Server receives audit logs (if available)
- [ ] Production alerts trigger correctly

### 11.5 Phase 5: Testing & Documentation

**Tasks:**

1. Write unit tests for all bypass components
2. Create integration test suites (bypass + auth)
3. Write E2E tests with Playwright
4. Document developer guide
5. Document security review
6. Create troubleshooting guide

**Acceptance Criteria:**

- [ ] Unit test coverage >80%
- [ ] Integration tests cover both modes
- [ ] E2E tests pass in all scenarios
- [ ] Developer guide complete and accurate
- [ ] Security review approved
- [ ] Troubleshooting guide comprehensive

---

## 12. Troubleshooting

### 12.1 Common Issues

#### Issue: Environment Variable Not Loading

**Cause:** Vite only loads `.env` files matching the current mode.

**Solution:**

```bash
# Check which mode is active
npm run dev # Loads .env.development
npm run build # Loads .env.production

# Force a specific mode
npm run dev --mode staging # Loads .env.staging

Issue: Bypass Parameter Ignored

Cause: Hostname is not recognized as localhost.

Debug:

console.log('Hostname:', window.location.hostname);
console.log('Is localhost?', isValidLocalhost());

Solution:

Add your hostname to ALLOWED_HOSTNAMES in hostnameValidator.ts.

Issue: Vite Plugin Not Stripping Code

Cause: Plugin only runs in production mode.

Verify:

# Build production bundle
npm run build --mode production

# Inspect bundle
cat dist/assets/index-*.js | grep "isLocalhostBypass"
# Should return no results (code stripped)

Issue: CI/CD Validation Failing

Cause: .env.production not found or invalid.

Debug:

# Run validation locally
./scripts/validate-production-auth.sh .env.production

# Check file exists
ls -la .env.production

# Check contents
cat .env.production | grep VITE_AUTH_MODE

12.2 Debug Commands

Check Auth Config:

import { getAuthConfig } from './config/auth.config';

console.table(getAuthConfig());

Check Bypass State:

import { useBypass } from './auth/bypass/AuthBypassProvider';

const { bypassActive, bypassSource, mockUser } = useBypass();
console.log({ bypassActive, bypassSource, mockUser });

Check Feature Flags:

import { getFeatureFlags } from './config/featureFlags';

console.table(getFeatureFlags());

Inspect Access Log:

import { localAccessLog } from './logging/localAccessLog';

console.table(localAccessLog.getLog());

Document Status

Version: 1.0.0 Status: Active Last Updated: 2026-02-16 Next Review: 2026-03-16

Change Log:

DateVersionChangesAuthor
2026-02-161.0.0Initial comprehensive specificationfrontend-react-typescript-expert

Related Documents:

  • auth-mode-switching.md — Environment-based auth mode switching (GCP JWT)
  • TRACK-A-PRESENTATION-PUBLISHING.md — Parent track (A.4.4 requirements)
  • cloud-run-deployment.md — Production deployment configuration

Implementation Files:

FileDescription
src/auth/bypass/AuthBypassProvider.tsxMain bypass provider wrapper
src/auth/bypass/MockUserProvider.tsxMock user context
src/auth/bypass/NoopTokenValidator.tsNo-op token validator
src/auth/bypass/hostnameValidator.tsHostname verification
src/auth/bypass/buildDetector.tsDev server detection
src/components/DevModeIndicator.tsxVisual dev mode banner
src/components/MockUserSwitcher.tsxMock user dropdown
src/logging/devLogger.tsConsole logging
src/logging/localAccessLog.tslocalStorage access log
src/logging/bypassAuditLog.tsBypass audit trail
vite-plugins/stripBypassCode.tsProduction code stripping
scripts/validate-production-auth.shBuild-time validation

End of Document