Implement Juicebox data privacy and handling. Use when managing personal data, implementing GDPR compliance, or handling sensitive candidate information. Trigger with phrases like "juicebox data privacy", "juicebox GDPR", "juicebox PII handling", "juicebox data compliance".
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
skills listSkill Instructions
name: juicebox-data-handling description: | Implement Juicebox data privacy and handling. Use when managing personal data, implementing GDPR compliance, or handling sensitive candidate information. Trigger with phrases like "juicebox data privacy", "juicebox GDPR", "juicebox PII handling", "juicebox data compliance". allowed-tools: Read, Write, Edit, Bash(kubectl:), Bash(curl:) version: 1.0.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io
Juicebox Data Handling
Overview
Implement compliant data handling practices for personal and candidate data from Juicebox.
Prerequisites
- Understanding of applicable privacy regulations (GDPR, CCPA)
- Data classification framework
- Legal/compliance team sign-off
Data Classification
| Category | Examples | Retention | Access |
|---|---|---|---|
| Public | Name, title, company | 1 year | All users |
| Contact | Email, phone | 90 days | Recruiters only |
| Sensitive | SSN, salary | 30 days | Admins only |
| Derived | Scores, notes | Permanent | Internal only |
Instructions
Step 1: Data Classification System
// lib/data-classifier.ts
export enum DataCategory {
PUBLIC = 'public',
CONTACT = 'contact',
SENSITIVE = 'sensitive',
DERIVED = 'derived'
}
export const fieldClassification: Record<string, DataCategory> = {
// Public data
name: DataCategory.PUBLIC,
title: DataCategory.PUBLIC,
company: DataCategory.PUBLIC,
location: DataCategory.PUBLIC,
linkedin_url: DataCategory.PUBLIC,
// Contact data
email: DataCategory.CONTACT,
phone: DataCategory.CONTACT,
personal_email: DataCategory.CONTACT,
// Sensitive data
salary: DataCategory.SENSITIVE,
compensation: DataCategory.SENSITIVE,
// Derived data
fit_score: DataCategory.DERIVED,
recruiter_notes: DataCategory.DERIVED
};
export function classifyData(data: Record<string, any>): Record<DataCategory, string[]> {
const classified: Record<DataCategory, string[]> = {
[DataCategory.PUBLIC]: [],
[DataCategory.CONTACT]: [],
[DataCategory.SENSITIVE]: [],
[DataCategory.DERIVED]: []
};
for (const field of Object.keys(data)) {
const category = fieldClassification[field] || DataCategory.DERIVED;
classified[category].push(field);
}
return classified;
}
Step 2: PII Handling
// lib/pii-handler.ts
import crypto from 'crypto';
export class PIIHandler {
// Mask sensitive fields for logging
maskForLogging(profile: Profile): Record<string, any> {
return {
...profile,
email: this.maskEmail(profile.email),
phone: this.maskPhone(profile.phone),
personal_email: undefined // Remove entirely
};
}
private maskEmail(email?: string): string | undefined {
if (!email) return undefined;
const [local, domain] = email.split('@');
return `${local[0]}***@${domain}`;
}
private maskPhone(phone?: string): string | undefined {
if (!phone) return undefined;
return `***-***-${phone.slice(-4)}`;
}
// Encrypt sensitive data at rest
encrypt(data: string, key: Buffer): string {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(data, 'utf8', 'base64');
encrypted += cipher.final('base64');
const tag = cipher.getAuthTag();
return `${iv.toString('base64')}:${tag.toString('base64')}:${encrypted}`;
}
// Decrypt sensitive data
decrypt(encrypted: string, key: Buffer): string {
const [ivB64, tagB64, data] = encrypted.split(':');
const iv = Buffer.from(ivB64, 'base64');
const tag = Buffer.from(tagB64, 'base64');
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
let decrypted = decipher.update(data, 'base64', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
Step 3: Retention Policies
// lib/retention-policy.ts
export class RetentionPolicy {
private policies: Record<DataCategory, number> = {
[DataCategory.PUBLIC]: 365, // 1 year
[DataCategory.CONTACT]: 90, // 90 days
[DataCategory.SENSITIVE]: 30, // 30 days
[DataCategory.DERIVED]: -1 // No auto-delete
};
getRetentionDays(category: DataCategory): number {
return this.policies[category];
}
async enforceRetention(): Promise<RetentionReport> {
const report: RetentionReport = {
processed: 0,
deleted: 0,
errors: []
};
for (const [category, days] of Object.entries(this.policies)) {
if (days < 0) continue; // Skip no-delete categories
const cutoff = new Date();
cutoff.setDate(cutoff.getDate() - days);
const result = await this.deleteExpiredData(category as DataCategory, cutoff);
report.processed += result.processed;
report.deleted += result.deleted;
}
return report;
}
private async deleteExpiredData(
category: DataCategory,
cutoff: Date
): Promise<{ processed: number; deleted: number }> {
// Implementation depends on data storage
return db.$transaction(async (tx) => {
const expired = await tx.profileData.findMany({
where: {
category,
createdAt: { lt: cutoff }
}
});
await tx.profileData.deleteMany({
where: {
id: { in: expired.map(e => e.id) }
}
});
return {
processed: expired.length,
deleted: expired.length
};
});
}
}
// Run retention daily
cron.schedule('0 2 * * *', async () => {
const policy = new RetentionPolicy();
const report = await policy.enforceRetention();
logger.info('Retention policy enforced', report);
});
Step 4: Data Subject Rights
// services/data-rights.ts
export class DataRightsService {
// Right to access
async handleAccessRequest(subjectEmail: string): Promise<DataExport> {
// Find all data for subject
const profiles = await db.profiles.findMany({
where: { email: subjectEmail }
});
// Include access logs
const accessLogs = await db.accessLogs.findMany({
where: { profileEmail: subjectEmail }
});
return {
profiles,
accessLogs,
exportedAt: new Date(),
format: 'json'
};
}
// Right to erasure (GDPR Article 17)
async handleDeletionRequest(
subjectEmail: string,
requestId: string
): Promise<DeletionReport> {
const report: DeletionReport = {
requestId,
subjectEmail,
deletedRecords: 0,
status: 'completed',
completedAt: new Date()
};
await db.$transaction(async (tx) => {
// Delete profile data
const deleted = await tx.profiles.deleteMany({
where: { email: subjectEmail }
});
report.deletedRecords += deleted.count;
// Delete from cache
await cache.deleteByPattern(`*${subjectEmail}*`);
// Log deletion for compliance
await tx.deletionLogs.create({
data: {
requestId,
subjectEmail,
deletedCount: report.deletedRecords,
completedAt: new Date()
}
});
});
// Notify downstream systems
await this.notifyDeletion(subjectEmail, requestId);
return report;
}
// Right to rectification
async handleRectificationRequest(
subjectEmail: string,
corrections: Record<string, any>
): Promise<void> {
await db.profiles.updateMany({
where: { email: subjectEmail },
data: corrections
});
// Log for audit
await db.auditLogs.create({
data: {
type: 'rectification',
subjectEmail,
changes: corrections
}
});
}
}
Step 5: Access Logging
// middleware/access-logging.ts
export function logDataAccess(req: Request, res: Response, next: NextFunction) {
const originalJson = res.json.bind(res);
res.json = (data: any) => {
// Log access to profile data
if (data?.profiles || data?.profile) {
const profiles = data.profiles || [data.profile];
const profileIds = profiles.map((p: any) => p.id);
db.accessLogs.create({
data: {
userId: req.user?.id,
profileIds,
operation: req.method,
path: req.path,
timestamp: new Date(),
ip: req.ip,
userAgent: req.get('user-agent')
}
}).catch(console.error);
}
return originalJson(data);
};
next();
}
Compliance Checklist
## Data Handling Compliance
### GDPR Requirements
- [ ] Lawful basis for processing documented
- [ ] Privacy policy updated
- [ ] Data subject rights implemented
- [ ] Data breach notification process
- [ ] DPA with Juicebox executed
### CCPA Requirements
- [ ] "Do Not Sell" option implemented
- [ ] Consumer rights portal
- [ ] Opt-out mechanisms
- [ ] Annual training completed
### Security
- [ ] Encryption at rest
- [ ] Encryption in transit
- [ ] Access logging
- [ ] Regular audits
Output
- Data classification system
- PII handling utilities
- Retention policy enforcement
- Data subject rights handlers
Resources
Next Steps
After data handling, see juicebox-enterprise-rbac for access controls.
More by jeremylongshore
View allRabbitmq Queue Setup - Auto-activating skill for Backend Development. Triggers on: rabbitmq queue setup, rabbitmq queue setup Part of the Backend Development skill category.
evaluating-machine-learning-models: This skill allows Claude to evaluate machine learning models using a comprehensive suite of metrics. It should be used when the user requests model performance analysis, validation, or testing. Claude can use this skill to assess model accuracy, precision, recall, F1-score, and other relevant metrics. Trigger this skill when the user mentions "evaluate model", "model performance", "testing metrics", "validation results", or requests a comprehensive "model evaluation".
building-neural-networks: This skill allows Claude to construct and configure neural network architectures using the neural-network-builder plugin. It should be used when the user requests the creation of a new neural network, modification of an existing one, or assistance with defining the layers, parameters, and training process. The skill is triggered by requests involving terms like "build a neural network," "define network architecture," "configure layers," or specific mentions of neural network types (e.g., "CNN," "RNN," "transformer").
Oauth Callback Handler - Auto-activating skill for API Integration. Triggers on: oauth callback handler, oauth callback handler Part of the API Integration skill category.
