Skip to content
OpenSmartRoute
Skillv1.0.0

ideogram-enterprise-rbac

Implement team-based access control and credit management for Ideogram. Use when managing multiple teams with separate budgets, enforcing content policies, or implementing API key isolation for enterp

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (plugins/saas-packs/ideogram-pack/skills/ideogram-enterprise-rbac/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill ideogram-enterprise-rbac. Copyright stays with the author (MIT).

Ideogram Enterprise RBAC

Overview

Implement team-based access control for Ideogram's API. Since Ideogram uses a single API key per account with no built-in roles or scopes, enterprise access control must be implemented at the application layer: separate API keys per team, proxy-based content filtering, per-team budget limits, and usage tracking.

Architecture

┌──────────────────────────────────────────┐
│  Application Proxy Layer                  │
│  ┌──────────┐  ┌──────────┐  ┌────────┐ │
│  │ Marketing│  │ Product  │  │ Social │ │
│  │ API Key  │  │ API Key  │  │API Key │ │
│  └────┬─────┘  └────┬─────┘  └───┬────┘ │
│       └──────────────┼────────────┘      │
│                      ▼                   │
│  ┌────────────────────────────────────┐  │
│  │ Content Filter + Budget Enforcer   │  │
│  └──────────────────┬─────────────────┘  │
└─────────────────────┼────────────────────┘
                      ▼
          Ideogram API (api.ideogram.ai)

Instructions

Step 1: Team Configuration

interface TeamConfig {
  name: string;
  apiKey: string;             // Separate Ideogram API key per team
  dailyBudgetUSD: number;
  allowedStyles: string[];
  allowedModels: string[];
  maxConcurrency: number;
  contentPolicy: "strict" | "moderate" | "permissive";
}

const TEAM_CONFIGS: Record<string, TeamConfig> = {
  marketing: {
    name: "Marketing",
    apiKey: process.env.IDEOGRAM_KEY_MARKETING!,
    dailyBudgetUSD: 20,
    allowedStyles: ["DESIGN", "REALISTIC"],
    allowedModels: ["V_2", "V_2_TURBO"],
    maxConcurrency: 5,
    contentPolicy: "strict",
  },
  product: {
    name: "Product Design",
    apiKey: process.env.IDEOGRAM_KEY_PRODUCT!,
    dailyBudgetUSD: 50,
    allowedStyles: ["DESIGN", "REALISTIC", "RENDER_3D", "GENERAL"],
    allowedModels: ["V_2", "V_2_TURBO"],
    maxConcurrency: 8,
    contentPolicy: "moderate",
  },
  social: {
    name: "Social Media",
    apiKey: process.env.IDEOGRAM_KEY_SOCIAL!,
    dailyBudgetUSD: 10,
    allowedStyles: ["DESIGN", "ANIME", "GENERAL"],
    allowedModels: ["V_2_TURBO"],
    maxConcurrency: 3,
    contentPolicy: "strict",
  },
};

Step 2: Content Policy Enforcement

interface ContentCheck {
  allowed: boolean;
  reason?: string;
}

const BLOCKED_TERMS: Record<string, RegExp[]> = {
  strict: [
    /\b(competitor|trademark|brand)\b/i,
    /\b(violent|weapon|blood|gore)\b/i,
    /\b(nsfw|nude|explicit)\b/i,
  ],
  moderate: [
    /\b(nsfw|nude|explicit)\b/i,
  ],
  permissive: [],
};

function checkContentPolicy(prompt: string, policy: "strict" | "moderate" | "permissive"): ContentCheck {
  const patterns = BLOCKED_TERMS[policy] ?? [];
  for (const pattern of patterns) {
    if (pattern.test(prompt)) {
      return { allowed: false, reason: `Blocked by ${policy} policy: ${pattern.source}` };
    }
  }
  if (prompt.length > 10000) {
    return { allowed: false, reason: "Prompt exceeds 10,000 character limit" };
  }
  return { allowed: true };
}

Step 3: Budget Enforcer

const dailySpend = new Map<string, number>();

function trackSpend(teamId: string, model: string, numImages: number = 1) {
  const costPerImage: Record<string, number> = {
    V_2_TURBO: 0.05, V_2: 0.08, V_2A_TURBO: 0.025, V_2A: 0.04,
  };

  const cost = (costPerImage[model] ?? 0.08) * numImages;
  const current = dailySpend.get(teamId) ?? 0;
  dailySpend.set(teamId, current + cost);

  return current + cost;
}

function checkBudget(teamId: string): { allowed: boolean; remaining: number } {
  const config = TEAM_CONFIGS[teamId];
  if (!config) return { allowed: false, remaining: 0 };

  const spent = dailySpend.get(teamId) ?? 0;
  const remaining = config.dailyBudgetUSD - spent;

  return { allowed: remaining > 0, remaining };
}

// Reset daily at midnight
setInterval(() => {
  dailySpend.clear();
  console.log("Daily budget counters reset");
}, 86400000);

Step 4: Team-Scoped Proxy

async function teamGenerate(
  teamId: string,
  prompt: string,
  options: { style_type?: string; model?: string; aspect_ratio?: string } = {}
) {
  const config = TEAM_CONFIGS[teamId];
  if (!config) throw new Error(`Unknown team: ${teamId}`);

  // Check content policy
  const contentCheck = checkContentPolicy(prompt, config.contentPolicy);
  if (!contentCheck.allowed) {
    throw new Error(`Content blocked: ${contentCheck.reason}`);
  }

  // Check style permission
  const style = options.style_type ?? "AUTO";
  if (style !== "AUTO" && !config.allowedStyles.includes(style)) {
    throw new Error(`Style ${style} not allowed for team ${config.name}`);
  }

  // Check model permission
  const model = options.model ?? config.allowedModels[0];
  if (!config.allowedModels.includes(model)) {
    throw new Error(`Model ${model} not allowed for team ${config.name}`);
  }

  // Check budget
  const budget = checkBudget(teamId);
  if (!budget.allowed) {
    throw new Error(`Daily budget exceeded for team ${config.name}. Remaining: $${budget.remaining.toFixed(2)}`);
  }

  // Generate using team's API key
  const response = await fetch("https://api.ideogram.ai/generate", {
    method: "POST",
    headers: {
      "Api-Key": config.apiKey,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      image_request: {
        prompt,
        model,
        style_type: style,
        aspect_ratio: options.aspect_ratio ?? "ASPECT_1_1",
        magic_prompt_option: "AUTO",
      },
    }),
  });

  if (!response.ok) throw new Error(`Ideogram API error: ${response.status}`);

  // Track spending
  trackSpend(teamId, model);

  return response.json();
}

Step 5: Usage Dashboard Data

function teamUsageReport() {
  const report = [];
  for (const [teamId, config] of Object.entries(TEAM_CONFIGS)) {
    const spent = dailySpend.get(teamId) ?? 0;
    report.push({
      team: config.name,
      dailyBudget: config.dailyBudgetUSD,
      spent: spent.toFixed(2),
      remaining: (config.dailyBudgetUSD - spent).toFixed(2),
      utilization: `${((spent / config.dailyBudgetUSD) * 100).toFixed(0)}%`,
    });
  }
  console.table(report);
  return report;
}

Step 6: Key Rotation Schedule

Quarterly key rotation process:
1. Create new API key in Ideogram dashboard for each team
2. Update secrets in your secret manager
3. Deploy with new keys to staging, verify
4. Deploy to production
5. Monitor for 48 hours
6. Delete old keys from Ideogram dashboard

Error Handling

Issue Cause Solution
Budget exceeded Daily limit hit Wait for reset or increase limit
Style not allowed Team policy restriction Use an allowed style type
Content blocked Prompt failed policy Rephrase to comply with team policy
Key not set Missing env variable Check team-specific key config

Output

  • Per-team API key isolation
  • Content policy enforcement (strict/moderate/permissive)
  • Daily budget tracking with automatic enforcement
  • Team-scoped generation proxy
  • Usage dashboard data for reporting

Prerequisites

  • Source-of-truth role inventory, named asset owner, authorized/denied synthetic identities, least-privilege admin role, and rollback mapping revision.

Examples

scope=staging-gallery; mapping_rev=42; owner=creative-ops; allow_probe=pass; deny_probe=pass; rights=test-owned; rollback=rev41 proves the boundary without disclosing groups or assets.

Resources

Next Steps

For migration strategies, see ideogram-migration-deep-dive.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-ideogram-ente-42fe31/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-ideogram-ente-42fe31.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-ideogram-ente-42fe31",
  "kind": "skill",
  "name": "ideogram-enterprise-rbac",
  "description": "Implement team-based access control and credit management for Ideogram. Use when managing multiple teams with separate budgets, enforcing content policies, or implementing API key isolation for enterprise Ideogram usage. Trigger with phrases like \"ideogram RBAC\", \"ideogram enterprise\", \"ideogram teams\", \"ideogram permissions\", \"ideogram multi-tenant\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding",
      "finance"
    ],
    "tags": [
      "skill-md",
      "saas",
      "ideogram",
      "rbac",
      "enterprise",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Implement team-based access control and credit management for Ideogram. Use when managing multiple teams with separate budgets, enforcing content policies, or implementing API key isolation for enterprise Ideogram usage. Trigger with phrases like \"ideogram RBAC\", \"ideogram enterprise\", \"ideogram teams\", \"ideogram permissions\", \"ideogram multi-tenant\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "plugins/saas-packs/ideogram-pack/skills/ideogram-enterprise-rbac/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/plugins/saas-packs/ideogram-pack/skills/ideogram-enterprise-rbac/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/plugins/saas-packs/ideogram-pack/skills/ideogram-enterprise-rbac/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit"
    ],
    "license": "MIT"
  },
  "instructions": "# Ideogram Enterprise RBAC\n\n## Overview\n\nImplement team-based access control for Ideogram's API. Since Ideogram uses a single API key per account with no built-in roles or scopes, enterprise access control must be implemented at the application layer: separate API keys per team, proxy-based content filtering, per-team budget limits, and usage tracking.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────┐\n│  Application Proxy Layer                  │\n│  ┌──────────┐  ┌──────────┐  ┌────────┐ │\n│  │ Marketing│  │ Product  │  │ Social │ │\n│  │ API Key  │  │ API Key  │  │API Key │ │\n",
  "cost": {
    "context_tokens": 1933
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-ideogram-ente-42fe31/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.