gamma-data-handling
Handle data privacy, retention, and compliance for Gamma integrations. Use when implementing GDPR compliance, data retention policies, or managing user data within Gamma workflows. Trigger with phrases like "gamma data", "gamma privacy", "gamma GDPR", "gamma data retention", "gamma compliance".
What this skill does
# Gamma Data Handling
## Overview
Data handling, privacy controls, and compliance for Gamma API integrations. Gamma processes user-submitted content through AI to generate presentations -- understand what data flows where and how to handle PII, retention, and GDPR requirements.
## Prerequisites
- Understanding of data privacy regulations (GDPR, CCPA)
- Completed `gamma-install-auth` setup
- Data classification policies defined
## Data Flow Map
```
User Input (content, prompts)
│
▼
┌──────────────┐
│ Your App │ ← PII may be in content (names, company data)
│ (API key) │
└──────┬───────┘
│ POST /v1.0/generations
▼
┌──────────────┐
│ Gamma API │ ← Content processed by AI
│ (gamma.app) │ ← Images generated
└──────┬───────┘
│ gammaUrl + exportUrl
▼
┌──────────────┐
│ Generated │ ← Presentation stored in Gamma workspace
│ Content │ ← Export files (PDF/PPTX/PNG) temporary
└──────────────┘
```
## Data Classification
| Data Type | Classification | Where Stored | Retention |
|-----------|---------------|--------------|-----------|
| API key | Secret | Your env vars | Active use only |
| Content/prompts | May contain PII | Gamma servers (during generation) | Gamma's policy |
| Generated gammas | User data | Gamma workspace | User-controlled |
| Export files (PDF/PPTX) | User data | Temporary URLs | Download promptly, URLs expire |
| User prompts in logs | PII risk | Your infrastructure | Your policy (sanitize!) |
| Credit usage | Billing data | Gamma | Per Gamma ToS |
## Instructions
### Step 1: Sanitize Content Before Sending
```typescript
// src/gamma/sanitize.ts
// Remove PII from content before sending to Gamma if not needed
interface SanitizeOptions {
removeEmails: boolean;
removePhones: boolean;
maskNames: boolean;
}
function sanitizeContent(content: string, opts: SanitizeOptions): string {
let sanitized = content;
if (opts.removeEmails) {
sanitized = sanitized.replace(/[\w.-]+@[\w.-]+\.\w+/g, "[email]");
}
if (opts.removePhones) {
sanitized = sanitized.replace(/\+?[\d\s()-]{10,}/g, "[phone]");
}
if (opts.maskNames) {
// Only mask if you have a list of known names
// Generic regex would be too aggressive
}
return sanitized;
}
// Usage: sanitize before generation
const safeContent = sanitizeContent(userContent, {
removeEmails: true,
removePhones: true,
maskNames: false,
});
await gamma.generate({
content: safeContent,
outputFormat: "presentation",
});
```
### Step 2: Sanitize Logs
```typescript
// src/gamma/logging.ts
// Never log raw content or API keys
function logGeneration(request: any, result: any) {
console.log(JSON.stringify({
event: "gamma_generation",
timestamp: new Date().toISOString(),
generationId: result.generationId,
outputFormat: request.outputFormat,
contentLength: request.content?.length,
// NEVER log: content (may have PII), apiKey
status: result.status,
creditsUsed: result.creditsUsed,
}));
}
```
### Step 3: Export File Handling
```typescript
// src/gamma/exports.ts
// Export URLs are temporary — download and store securely
import { writeFile } from "node:fs/promises";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
async function archiveExport(
exportUrl: string,
metadata: { generationId: string; userId: string }
) {
// Download immediately — URLs expire
const res = await fetch(exportUrl);
if (!res.ok) throw new Error(`Export download failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
// Store with encryption
const s3 = new S3Client({ region: "us-east-1" });
const key = `gamma-exports/${metadata.userId}/${metadata.generationId}.pdf`;
await s3.send(new PutObjectCommand({
Bucket: process.env.EXPORTS_BUCKET!,
Key: key,
Body: buffer,
ContentType: "application/pdf",
ServerSideEncryption: "aws:kms",
Metadata: {
generationId: metadata.generationId,
archivedAt: new Date().toISOString(),
},
}));
console.log(`Archived: s3://${process.env.EXPORTS_BUCKET}/${key}`);
}
```
### Step 4: Data Retention Policy
```typescript
// src/gamma/retention.ts
interface RetentionPolicy {
exportMaxDays: number; // Delete local export copies
logRetentionDays: number; // Anonymize generation logs
promptRetentionDays: number; // Delete stored prompts
}
const POLICY: RetentionPolicy = {
exportMaxDays: 90, // Keep exports 90 days
logRetentionDays: 30, // Anonymize logs after 30 days
promptRetentionDays: 7, // Delete prompts after 7 days
};
async function enforceRetention() {
const cutoff = new Date();
// Delete old exports from S3
cutoff.setDate(cutoff.getDate() - POLICY.exportMaxDays);
await deleteOldExports(cutoff);
// Anonymize old logs
cutoff.setDate(cutoff.getDate() + POLICY.exportMaxDays - POLICY.logRetentionDays);
await anonymizeLogs(cutoff);
// Delete stored prompts
cutoff.setDate(cutoff.getDate() + POLICY.logRetentionDays - POLICY.promptRetentionDays);
await deletePrompts(cutoff);
}
```
### Step 5: GDPR Request Handling
```typescript
// Handle data subject access/erasure requests
async function handleGdprRequest(
type: "access" | "erasure",
userId: string
) {
if (type === "access") {
// Return all data we store about this user
return {
generations: await db.generations.findMany({ where: { userId } }),
exports: await listS3Objects(`gamma-exports/${userId}/`),
// Note: data stored IN Gamma's workspace is Gamma's responsibility
// Direct user to gamma.app to access/delete their workspace data
};
}
if (type === "erasure") {
// Delete from our systems
await db.generations.deleteMany({ where: { userId } });
await deleteS3Prefix(`gamma-exports/${userId}/`);
// Instruct user to delete Gamma workspace data at gamma.app
return { deleted: true, note: "Delete Gamma workspace data at gamma.app" };
}
}
```
## Compliance Checklist
- [ ] Content sanitized before sending to Gamma API (PII removed if not needed)
- [ ] API keys never logged
- [ ] Export URLs downloaded promptly and stored encrypted
- [ ] Retention policies defined and enforced
- [ ] GDPR access/erasure request process documented
- [ ] User consent obtained for AI processing of their content
- [ ] Gamma DPA signed (if required by your jurisdiction)
- [ ] Logs sanitized (no raw content or PII)
## Error Handling
| Error | Cause | Solution |
|-------|-------|----------|
| Export URL expired | Downloaded too late | Download immediately on generation completion |
| PII in logs | Missing sanitization | Add log sanitization middleware |
| Retention job failed | Scheduler stopped | Monitor cron job health |
| GDPR request incomplete | Gamma workspace not addressed | Direct user to gamma.app for workspace data |
## Resources
- [Gamma Privacy Policy](https://gamma.app/privacy)
- [Gamma Terms of Service](https://gamma.app/tos)
- [GDPR Compliance Guide](https://gdpr.eu/)
## Next Steps
Proceed to `gamma-enterprise-rbac` for access control.
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.