From bigid
Generates a BigID-branded NIST Privacy Framework compliance report (PPTX) by pulling live data from BigID — risk cases, privacy risks, controls, and framework status. Use this skill whenever the user asks to refresh, regenerate, update, or create their privacy posture report, NIST-P report, compliance deck, or privacy dashboard. Also trigger for: "update my privacy report", "refresh the posture deck", "how's our NIST-P score", "give me a compliance slide deck", "show me findings per control", or "break down the NIST controls in detail". The skill produces a ~35-slide detailed deck: executive summary, a dark section-header per NIST-P function, one drilldown slide per control listing every open risk case (case ID, data source, risk score, controls count), and a prioritized remediation roadmap — all sourced live from BigID.
How this skill is triggered — by the user, by Claude, or both
Slash command
/bigid:bigid-privacy-postureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generates a 10-slide BigID-branded NIST Privacy Framework posture deck from live BigID data.
Generates a 10-slide BigID-branded NIST Privacy Framework posture deck from live BigID data.
Any time the user wants a fresh view of their privacy compliance posture. Common triggers:
Follow these 4 steps in order.
Make these API calls in parallel. Store all results for use in Step 2.
get_objects("Privacy Risk Cases API", "get_v1_privacy_risk_cases", {"limit": 200})
get_objects("Privacy Risks", "get_v1_privacy_risks", {"limit": 200})
get_objects("Risk Controls", "get_v1_controls", {})
Also call:
get_objects("Regulations", "get_v1_compliance_frameworks", {})
to get current framework enable/disable status (useful for noting newly enabled frameworks in the report).
Parsing notes:
{data: [...]} — access as response.data. Each case has caseId, caseLabel, privacyRisk (object with name, category), controls[], riskLevel, probability, impact, source (object with name).{rules: [...]} — access as response.rules (NOT response.data.rules). Each rule has name, category, probability, impact, mappedControls[] (or controls[]).id, name, category (contains NIST-P function ID like "CT.DP-P1").framework_name, enabled, and a list of controls.bash_tool to parse it with Python.Map the live data to NIST Privacy Framework functions using the scoring logic in references/scoring.md.
The 5 functions and their control mappings:
| Function | Controls |
|---|---|
| IDENTIFY-P (ID) | ID.IM-P1 through ID.IM-P4, ID.RA-P1 through ID.RA-P4 |
| GOVERN-P (GV) | GV.PO-P1 through GV.PO-P4 |
| CONTROL-P (CT) | CT.DP-P1 through CT.DP-P5 |
| COMMUNICATE-P (CM) | CM.CO-P1 through CM.CO-P4 |
| PROTECT-P (PR) | PR.DS-P1 through PR.DS-P5 |
For each control, assign status:
Derive a percentage score per function based on how many controls are In Place / Partial / Gap.
See references/scoring.md for full scoring rubric and control-to-risk-case mapping logic.
Write a Node.js script to /home/claude/privacy_posture_report.js using the data from Step 1 and scores from Step 2. Then run it with bash_tool.
Always use the BigID branding template — see references/pptx-template.md for the full constants block and applyBigIDBranding() function. Copy it verbatim.
Slide structure (~35 slides total):
For each of the 5 NIST-P functions (IDENTIFY, GOVERN, CONTROL, COMMUNICATE, PROTECT):
Final slides:
Status badge colors:
"2E7D32" (green)"F57F17" (amber)"C62828" (red)Risk score badge colors:
"C62828" (red)"F57F17" (amber)"2E7D32" (green)Controls count badge:
"C62828" (red — uncontrolled)0 controls →
"F57F17"(amber)
Output file: /mnt/user-data/outputs/BigID_NIST_Privacy_Posture_Detailed.pptx
PptxGenJS embeds a separate copy of the logo and gradient bar into every slide. With 35 slides this bloats the file to ~1.5 MB, which exceeds the Claude interface's PPTX preview limit. This step collapses all identical images to a single shared copy, shrinking the file to ~150 KB so it renders in the preview panel.
Run this immediately after generating the PPTX, before QA:
import zipfile, shutil, hashlib, os
from pathlib import Path
SRC = DST = "/mnt/user-data/outputs/BigID_NIST_Privacy_Posture_Detailed.pptx"
TMP = "/tmp/pptx_dedupe"
if os.path.exists(TMP): shutil.rmtree(TMP)
os.makedirs(TMP)
with zipfile.ZipFile(SRC, 'r') as z:
z.extractall(TMP)
media_dir = Path(TMP) / "ppt" / "media"
hash_to_canonical, remap = {}, {}
for f in sorted(media_dir.iterdir()):
if not f.is_file(): continue
h = hashlib.md5(f.read_bytes()).hexdigest()
if h not in hash_to_canonical:
hash_to_canonical[h] = f.name
else:
canonical = hash_to_canonical[h]
if f.name != canonical:
remap[f.name] = canonical
f.unlink()
rels_root = Path(TMP) / "ppt" / "slides" / "_rels"
for rels_file in rels_root.glob("*.rels"):
content = rels_file.read_text()
for old, new in remap.items():
content = content.replace(f"../media/{old}", f"../media/{new}")
rels_file.write_text(content)
os.unlink(DST)
with zipfile.ZipFile(DST, 'w', compression=zipfile.ZIP_DEFLATED, compresslevel=9) as z:
for root, dirs, files in os.walk(TMP):
for file in files:
full = os.path.join(root, file)
z.write(full, os.path.relpath(full, TMP))
print(f"Done: {os.path.getsize(DST)/1024:.0f} KB (was ~1500 KB)")
Save this as /home/claude/dedupe_images.py and run with python3 /home/claude/dedupe_images.py. The output should be under 200 KB.
cp /mnt/user-data/outputs/BigID_NIST_Privacy_Posture_Detailed.pptx /home/claude/
python3 /mnt/skills/public/pptx/scripts/office/soffice.py --headless --convert-to pdf /home/claude/BigID_NIST_Privacy_Posture_Detailed.pptx
mv /BigID_NIST_Privacy_Posture_Detailed.pdf /home/claude/ 2>/dev/null || true
pdftoppm -jpeg -r 120 /home/claude/BigID_NIST_Privacy_Posture_Detailed.pdf /home/claude/qa_slide
Check slides 1, 2, one dark section header, and one control drilldown. Confirm logo and gradient bar are visible (dedup preserves both). LibreOffice may wrap bold titles slightly differently than PowerPoint — this is expected.
Then call present_files with the PPTX path and give a brief summary of what changed vs the previous report (if the user mentioned a prior one), or a headline summary of key findings.
After presenting the file, give a 4-line summary:
Overall score: XX% (▲/▼ vs last run if known)
Biggest gap: [function name] at XX% — [one-line reason]
Most urgent risk: [risk name] on [data source] — score XX, X controls
Next action: [single most important P1 item]
bash_tool with Python to parse it (see Step 1 parsing notes).pptxgenjs is not installed, run npm install -g pptxgenjs before proceeding./mnt/skills/user/bigid-pptx/SKILL.md.references/scoring.md — Full NIST-P scoring rubric: how to map risk cases to controls, how to assign In Place / Partial / Gap status, and how to compute function-level percentagesreferences/pptx-template.md — Complete BigID branding constants and applyBigIDBranding() function; copy verbatim into every generator scriptSearches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Implements vector databases with Pinecone, Weaviate, Qdrant, Milvus, pgvector for semantic search, RAG, recommendations, and similarity systems. Optimizes embeddings, indexing, and hybrid search.
npx claudepluginhub bigexchange/bigid-plugin-official --plugin bigid