gear_ai_v1

Gear AI CoPilot - Security & Compliance

Overview

This document outlines the security architecture, compliance requirements, and best practices for Gear AI CoPilot. Given the sensitive nature of personal vehicle data, financial information, and location tracking, security is a foundational pillar of the platform.

Security Architecture

Defense in Depth Strategy

The application implements multiple layers of security:

┌─────────────────────────────────────────────┐
│  Layer 1: Client-Side Security              │
│  - Input validation                         │
│  - XSS prevention                           │
│  - Secure storage (Keychain/Keystore)       │
└──────────────────┬──────────────────────────┘
                   │
┌──────────────────▼──────────────────────────┐
│  Layer 2: Transport Security                │
│  - TLS 1.3                                  │
│  - Certificate pinning                      │
│  - Encrypted API requests                  │
└──────────────────┬──────────────────────────┘
                   │
┌──────────────────▼──────────────────────────┐
│  Layer 3: Application Security              │
│  - JWT authentication                       │
│  - API rate limiting                        │
│  - Input sanitization                       │
└──────────────────┬──────────────────────────┘
                   │
┌──────────────────▼──────────────────────────┐
│  Layer 4: Database Security                 │
│  - Row Level Security (RLS)                 │
│  - Encrypted columns                        │
│  - Audit logging                            │
└─────────────────────────────────────────────┘

Authentication & Authorization

1. Firebase Authentication

Identity Provider: Firebase Auth serves as the primary identity provider.

Supported Methods:

Implementation:

// services/auth-service.ts
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword } from 'firebase/auth';

export async function signUpUser(email: string, password: string) {
  const auth = getAuth();
  
  // Validate password strength
  if (password.length < 12) {
    throw new Error('Password must be at least 12 characters');
  }
  
  const userCredential = await createUserWithEmailAndPassword(auth, email, password);
  
  // Send verification email
  await sendEmailVerification(userCredential.user);
  
  // Sync to Supabase
  await syncUserToSupabase(userCredential.user);
  
  return userCredential.user;
}

2. Row Level Security (RLS)

All user data in Supabase is protected by RLS policies.

Example Policy:

-- Users can only access their own vehicles
CREATE POLICY "Users can view their own vehicles"
  ON public.vehicles FOR SELECT
  USING (
    auth.uid() = (
      SELECT firebase_uid 
      FROM public.users 
      WHERE user_id = vehicles.user_id
    )
  );

Enforcement:

3. JWT Token Management

Token Lifecycle:

  1. User authenticates via Firebase
  2. Firebase issues JWT token (1 hour expiration)
  3. Token included in Authorization header for API requests
  4. Supabase validates JWT signature and claims
  5. Token auto-refreshes 5 minutes before expiration

Token Structure:

interface JWTClaims {
  sub: string;        // User ID
  email: string;      // User email
  email_verified: boolean;
  firebase: {
    sign_in_provider: string;
  };
  iat: number;        // Issued at
  exp: number;        // Expiration
  aud: string;        // Audience
  iss: string;        // Issuer
}

Data Protection

1. Encryption at Rest

Database Encryption:

Encrypted Columns:

-- Financial account numbers
CREATE TABLE public.financial_accounts (
  account_id UUID PRIMARY KEY,
  -- Encrypted column for account number
  account_number_encrypted BYTEA,
  encryption_key_id VARCHAR(50)
);

-- Encryption function
CREATE OR REPLACE FUNCTION encrypt_account_number(
  account_number VARCHAR,
  key TEXT
) RETURNS BYTEA AS $$
BEGIN
  RETURN pgp_sym_encrypt(account_number, key);
END;
$$ LANGUAGE plpgsql;

-- Decryption function (restricted access)
CREATE OR REPLACE FUNCTION decrypt_account_number(
  encrypted_data BYTEA,
  key TEXT
) RETURNS VARCHAR AS $$
BEGIN
  RETURN pgp_sym_decrypt(encrypted_data, key);
END;
$$ LANGUAGE plpgsql;

File Storage Encryption:

2. Encryption in Transit

TLS Configuration:

Implementation:

// Mobile app certificate pinning
// app.json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSAppTransportSecurity": {
          "NSPinnedDomains": {
            "api.supabase.co": {
              "NSIncludesSubdomains": true,
              "NSPinnedLeafIdentities": [
                {
                  "SPKI-SHA256-PIN": "your-certificate-hash"
                }
              ]
            }
          }
        }
      }
    }
  }
}

3. Personally Identifiable Information (PII)

PII Data Classification:

Data Type Classification Storage Access Control
Email PII Encrypted User only
VIN PII Hashed + Encrypted User + Support
License Plate PII Encrypted User only
Location History Sensitive PII Anonymized after 90 days User only
Financial Data Sensitive PII Encrypted User only
Photos PII Encrypted User only

Data Minimization:

User Data Rights:

Input Validation & Sanitization

1. Client-Side Validation

// utils/validators.ts
export function validateVIN(vin: string): boolean {
  // VIN must be exactly 17 characters
  if (vin.length !== 17) return false;
  
  // VIN cannot contain I, O, or Q
  if (/[IOQ]/.test(vin)) return false;
  
  // Validate check digit (position 9)
  return validateVINCheckDigit(vin);
}

export function validateEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

export function sanitizeInput(input: string): string {
  // Remove HTML tags
  return input.replace(/<[^>]*>/g, '');
}

2. Server-Side Validation

All Edge Functions validate and sanitize inputs:

// supabase/functions/decode-vin/index.ts
import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';

serve(async (req) => {
  const { vin } = await req.json();
  
  // Validate VIN
  if (!vin || typeof vin !== 'string' || vin.length !== 17) {
    return new Response(
      JSON.stringify({ error: 'Invalid VIN' }),
      { status: 400, headers: { 'Content-Type': 'application/json' } }
    );
  }
  
  // Sanitize VIN (uppercase, remove spaces)
  const sanitizedVIN = vin.toUpperCase().replace(/\s/g, '');
  
  // Process VIN...
});

API Security

1. Rate Limiting

Supabase Edge Functions:

// Rate limiting middleware
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';

const rateLimits = {
  free: { requests: 100, window: 3600 },    // 100/hour
  pro: { requests: 1000, window: 3600 },    // 1000/hour
  dealer: { requests: 10000, window: 3600 }, // 10000/hour
};

async function checkRateLimit(userId: string, tier: string) {
  const limit = rateLimits[tier];
  const now = Math.floor(Date.now() / 1000);
  const windowStart = now - limit.window;
  
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_SERVICE_KEY')!
  );
  
  // Count requests in current window
  const { count } = await supabase
    .from('api_requests')
    .select('*', { count: 'exact', head: true })
    .eq('user_id', userId)
    .gte('timestamp', windowStart);
  
  if (count && count >= limit.requests) {
    throw new Error('Rate limit exceeded');
  }
  
  // Log request
  await supabase.from('api_requests').insert({
    user_id: userId,
    timestamp: now,
  });
}

2. CORS Configuration

// Strict CORS policy
const corsHeaders = {
  'Access-Control-Allow-Origin': process.env.NODE_ENV === 'production' 
    ? 'https://gearai.app' 
    : 'http://localhost:8081',
  'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
  'Access-Control-Max-Age': '86400',
};

3. SQL Injection Prevention

Always use parameterized queries:

// ❌ NEVER do this
const { data } = await supabase
  .from('vehicles')
  .select('*')
  .eq('vin', userInput); // Safe with Supabase client

// ✅ For raw SQL, use parameterized queries
const { data } = await supabase.rpc('get_vehicle_by_vin', {
  vin_param: userInput
});

Vulnerability Management

1. Dependency Scanning

Automated Tools:

Process:

  1. Dependabot creates PR for vulnerable packages
  2. Security team reviews impact
  3. Update applied within 48 hours (critical) or 7 days (high)
  4. Regression testing before merge

2. Code Security Scanning

Static Analysis:

Configuration:

// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:security/recommended'
  ],
  plugins: ['security'],
  rules: {
    'security/detect-object-injection': 'error',
    'security/detect-non-literal-regexp': 'warn',
    'security/detect-unsafe-regex': 'error',
  }
};

3. Penetration Testing

Compliance

1. GDPR (General Data Protection Regulation)

Requirements:

Implementation:

// services/gdpr-service.ts
export async function exportUserData(userId: string): Promise<object> {
  // Export all user data in JSON format
  const [user, vehicles, maintenance, chat] = await Promise.all([
    supabase.from('users').select('*').eq('user_id', userId).single(),
    supabase.from('vehicles').select('*').eq('user_id', userId),
    supabase.from('maintenance_records').select('*').in('vehicle_id', vehicleIds),
    supabase.from('chat_sessions').select('*, chat_messages(*)').eq('user_id', userId),
  ]);
  
  return {
    user: user.data,
    vehicles: vehicles.data,
    maintenance: maintenance.data,
    chat: chat.data,
    exported_at: new Date().toISOString(),
  };
}

export async function deleteUserData(userId: string): Promise<void> {
  // Cascade delete via foreign keys
  await supabase.from('users').delete().eq('user_id', userId);
  
  // Log deletion for audit
  await supabase.from('audit_log').insert({
    action: 'user_deletion',
    user_id: userId,
    timestamp: new Date().toISOString(),
  });
}

2. CCPA (California Consumer Privacy Act)

Requirements:

Privacy Notice: See /legal/privacy-policy.md

3. PCI DSS (Payment Card Industry Data Security Standard)

Compliance Strategy:

Stripe Integration Security:

// Never log or store card data
export async function createPaymentMethod(
  cardElement: any // Stripe Elements card
): Promise<string> {
  const stripe = await loadStripe(process.env.STRIPE_PUBLISHABLE_KEY!);
  
  const { paymentMethod, error } = await stripe.createPaymentMethod({
    type: 'card',
    card: cardElement,
  });
  
  if (error) {
    throw new Error(error.message);
  }
  
  // Only return payment method ID, not card details
  return paymentMethod.id;
}

4. SOC 2 Type II (Future Goal)

Timeline: Year 2 after launch

Requirements:

Incident Response

1. Security Incident Response Plan

Phases:

  1. Detection: Monitoring alerts trigger investigation
  2. Containment: Isolate affected systems
  3. Eradication: Remove threat and patch vulnerability
  4. Recovery: Restore normal operations
  5. Post-Incident: Document lessons learned

Breach Notification Timeline:

2. Incident Severity Levels

Level Description Response Time Example
P0 (Critical) Data breach, system compromise 15 minutes Database exposed publicly
P1 (High) Vulnerability actively exploited 1 hour XSS attack detected
P2 (Medium) Potential vulnerability discovered 4 hours Outdated dependency with CVE
P3 (Low) Security best practice violation 24 hours Missing security header

3. Communication Plan

Internal:

External:

Security Monitoring

1. Logging & Audit Trail

Logged Events:

Log Retention: 1 year for audit, 7 days for operational logs

Implementation:

-- Audit log table
CREATE TABLE public.audit_log (
  log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID,
  action VARCHAR(100) NOT NULL,
  resource_type VARCHAR(50),
  resource_id UUID,
  ip_address INET,
  user_agent TEXT,
  success BOOLEAN DEFAULT true,
  error_message TEXT,
  timestamp TIMESTAMP DEFAULT NOW(),
  metadata JSONB
);

-- Trigger for sensitive table access
CREATE OR REPLACE FUNCTION log_financial_access()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.audit_log (user_id, action, resource_type, resource_id)
  VALUES (
    (SELECT user_id FROM public.users WHERE firebase_uid = auth.uid()),
    TG_OP,
    'financial_account',
    NEW.account_id
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER audit_financial_access
AFTER SELECT OR UPDATE OR DELETE ON public.financial_accounts
FOR EACH ROW EXECUTE FUNCTION log_financial_access();

2. Anomaly Detection

Monitored Metrics:

Alerting:

Secure Development Lifecycle

1. Code Review Requirements

2. Security Training

3. Secrets Management

Never commit secrets to version control:

# .gitignore
.env
.env.local
.env.*.local
*.pem
*.key
secrets/

Use environment variables:

// ✅ Correct
const apiKey = process.env.OPENAI_API_KEY;

// ❌ Never do this
const apiKey = 'sk-proj-abc123...';

Secret Rotation:

Conclusion

Security is an ongoing process, not a one-time implementation. This security framework provides a strong foundation, but continuous monitoring, testing, and improvement are essential to protect user data and maintain trust in the Gear AI CoPilot platform.

Security Contact: security@gearai.app
Vulnerability Reporting: See SECURITY.md in repository root