Gamma Enterprise RbacCAUTION
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Overview
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
4f83675ca38aOBSERVED · 2026-10-08Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: gamma-enterprise-rbac description: 'Implement enterprise role-based access control for Gamma integrations. Use when configuring team permissions, multi-tenant access, or enterprise authorization patterns. Trigger with phrases like "gamma RBAC", "gamma permissions", "gamma access control", "gamma enterprise", "gamma roles". ' allowed-tools: Read, Write, Edit version: 1.13.0 license: MIT author: Jeremy Longshore <[email protected]> tags: - saas - gamma - authentication - rbac compatibility: Designed for Claude Code --- # Gamma Enterprise RBAC ## Output Maintain an access receipt with role, approved operation class, policy version, review date, approver, and revocation result. Do not include credentials or presentation content. ## Examples Grant a temporary test role view access to a fictional staging deck, attempt an unauthorized publish, confirm denial, then revoke the role and record only the opaque test outcome. ## Overview Implement role-based access control for Gamma API integrations. Gamma's API uses a single API key per workspace -- granular permissions must be implemented in your application layer. The Teams and Business plans support workspace-level collaboration with shared themes and folders. ## Prerequisites - Gamma Teams or Business subscription - Application database for user/role storage - Completed `gamma-install-auth` setup ## Gamma Access Model ``` Gamma Workspace (1 API key) ├── Themes (shared across workspace) ├── Folders (shared across workspace) └── Generations (tied to API key, not individual users) Your Application Layer (you implement this): ├── Organization │ ├── Admin (manage API key, configure themes) │ ├── Editor (generate presentations, use templates) │ ├── Viewer (view generated presentations, download exports) │ └── Guest (no generation access) ``` **Key point:** Gamma's API does not have per-user authentication. All API calls use the workspace API key. You must enforce per-user permissions in your application. ## Instructions ### Step 1: Define Role Hierarchy ```typescript // src/auth/gamma-roles.ts type GammaRole = "guest" | "viewer" | "editor" | "admin"; const PERMISSIONS: Record<GammaRole, string[]> = { guest: [], viewer: ["generation:view", "export:download"], editor: ["generation:view", "generation:create", "export:download", "template:use"], admin: [ "generation:view", "generation:create", "export:download", "template:use", "template:manage", "theme:manage", "settings:manage", "member:manage", ], }; function hasPermission(role: GammaRole, permission: string): boolean { return PERMISSIONS[role]?.includes(permission) ?? false; } ``` ### Step 2: Authorization Middleware ```typescript // src/middleware/gamma-auth.ts import { Request, Response, NextFunction } from "express"; function requireGammaPermission(permission: string) { return (req: Request, res: Response, next: NextFunction) => { const user = req.user; // Set by your auth middleware if (!user) return res.status(401).json({ error: "Unauthorized" }); if (!hasPermission(user.gammaRole, permission)) { return res.status(403).json({ error: "Forbidden", required: permission, userRole: user.gammaRole, }); } next(); }; } // Usage app.post("/api/presentations", requireGammaPermission("generation:create"), async (req, res) => { const gamma = createGammaClient({ apiKey: process.env.GAMMA_API_KEY! }); const { generationId } = await gamma.generate(req.body); // Track ownership in your database await db.generations.create({ data: { generationId, userId: req.user.id, teamId: req.user.teamId }, }); res.json({ generationId }); } ); app.get("/api/presentations/:id", requireGammaPermission("generation:view"), async (req, res) => { // Only return if user owns it or is in the same team const gen = await db.generations.findFirst({ where: { generationId: req.params.id, teamId: req.user.teamId }, }); if (!gen) return res.status(404).json({ error: "Not found" }); res.json(gen); } ); ``` ### Step 3: Multi-Tenant Workspace Isolation ```typescript // src/tenant/gamma-tenant.ts // Each tenant can have their own Gamma workspace (API key) // or share a workspace with resource-level isolation interface Tenant { id: string; name: string; gammaApiKey: string; // Encrypted in database } class TenantGammaService { private clients = new Map<string, ReturnType<typeof createGammaClient>>(); getClient(tenant: Tenant) { if (!this.clients.has(tenant.id)) { this.clients.set( tenant.id, createGammaClient({ apiKey: tenant.gammaApiKey }) ); } return this.clients.get(tenant.id)!; } async generate(tenant: Tenant, userId: string, content: string, options: any = {}) { const gamma = this.getClient(tenant); const { generationId } = await gamma.generate({ content, ...options, }); // Track with tenant isolation await db.generations.create({ data: { generationId, tenantId: tenant.id, userId }, }); return { generationId }; } } ``` ### Step 4: Credit Quota Per User/Team ```typescript // src/quota/gamma-quotas.ts interface Quota { maxGenerationsPerDay: number; maxCreditsPerMonth: number; } const ROLE_QUOTAS: Record<GammaRole, Quota> = { guest: { maxGenerationsPerDay: 0, maxCreditsPerMonth: 0 }, viewer: { maxGenerationsPerDay: 0, maxCreditsPerMonth: 0 }, editor: { maxGenerationsPerDay: 10, maxCreditsPerMonth: 500 }, admin: { maxGenerationsPerDay: 50, maxCreditsPerMonth: 5000 }, }; async function checkQuota(userId: string, role: GammaRole): Promise<boolean> { const quota = ROLE_QUOTAS[role]; if (quota.maxGenerationsPerDay === 0) return false; const todayCount = await db.generations.count({ where: { userId, createdAt: { gte: new Date(new Date().toDateString()) }, }, }); return todayCount < q
Trust audit
CAUTIONgrade B · trust 89/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | FAIL |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (1)
| Cross-tenant access | Wrong API key | Verify tenant isolation in `getClient()` |
Gates applied: no_behavioural_pass.
4f83675ca38afull audit observations/trust-audit/skill/jeremylongshore__gamma-enterprise-rbac.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-08 | 4f83675ca38a | CAUTION | B | 89 | first audit |
Questions
What does the Gamma Enterprise Rbac skill do?
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Is Gamma Enterprise Rbac safe to install?
With care. The audit graded it B (89/100) and found 1 thing worth knowing before you trust this skill, listed below with the exact line each was found on.
What can Gamma Enterprise Rbac access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does Gamma Enterprise Rbac work with?
Its documentation mentions claude-code. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (4f83675ca38a), read on 2026-10-08. The repository is watched, and a new audit runs when it changes — this is the first audit.