Chapter 56

Submitting to the Official Marketplace: claude-plugins-official Review Process and Analysis of 101 Official Plugins

Chapter 56: Enterprise Plugin Deployment: Private Registry and Access Control

56.1 The Enterprise Difference

The clawhub.ai public marketplace is an ideal publication platform for individual developers and open-source projects, but enterprise environments have fundamentally different needs:

Data security: Enterprise-internal Plugins may contain proprietary business logic, internal API integrations, and database credentials. None of this should ever be uploaded to a public registry.

Compliance requirements: Finance, healthcare, and government sectors have strict software supply chain security mandates (SBOM, code signing, vulnerability scanning) that public marketplace review processes may not satisfy.

Access control: Enterprises need precise control over which teams and individuals can install which Plugins, with a complete operational audit trail.

Version pinning: Production environments need to lock Plugin versions, preventing unexpected changes from automatic updates.

Air-gapped deployment: Some enterprise environments are fully isolated from the internet and cannot reach clawhub.ai, requiring an on-premises registry service.

A Private Plugin Registry is designed to solve exactly these problems.

56.2 Private Registry Architecture

Enterprise Private Registry Architecture

┌─────────────────────────────────────────────────────┐
│  Corporate Intranet                                  │
│                                                     │
│  ┌─────────────┐   ┌─────────────────────────────┐  │
│  │ Developer   │   │  Private Registry Service   │  │
│  │ Workstation │──▶│                             │  │
│  └─────────────┘   │  ┌─────────────────────┐   │  │
│                    │  │  Package Storage     │   │  │
│  ┌─────────────┐   │  │  (S3/MinIO/NFS)     │   │  │
│  │ Claude Code │──▶│  └─────────────────────┘   │  │
│  │ (end users) │   │                             │  │
│  └─────────────┘   │  ┌─────────────────────┐   │  │
│                    │  │  Registry API Server │   │  │
│  ┌─────────────┐   │  │  (registry.corp.com) │   │  │
│  │ CI/CD       │──▶│  └─────────────────────┘   │  │
│  │ (GitHub/    │   │                             │  │
│  │  Jenkins)   │   │  ┌─────────────────────┐   │  │
│  └─────────────┘   │  │  Auth Service        │   │  │
│                    │  │  (LDAP/OIDC/SAML)   │   │  │
│                    │  └─────────────────────┘   │  │
│                    │                             │  │
│                    │  ┌─────────────────────┐   │  │
│                    │  │  Audit Log Store     │   │  │
│                    │  │  (PostgreSQL)        │   │  │
│                    │  └─────────────────────┘   │  │
│                    └─────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

56.3 Deploying the Private Registry

Docker Deployment

Anthropic provides the open-source claude-registry-server for self-hosting:

docker run -d \
  --name claude-registry \
  -p 3000:3000 \
  -v /data/registry:/data \
  -e DATABASE_URL="postgresql://user:pass@db:5432/registry" \
  -e STORAGE_BACKEND="s3" \
  -e S3_BUCKET="my-claude-plugins" \
  -e AUTH_PROVIDER="oidc" \
  -e OIDC_ISSUER="https://sso.corp.com" \
  -e OIDC_CLIENT_ID="claude-registry" \
  anthropic/claude-registry-server:latest

Full Docker Compose Deployment

# docker-compose.yml
version: "3.9"

services:
  registry:
    image: anthropic/claude-registry-server:latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://registry:${DB_PASSWORD}@postgres:5432/registry
      STORAGE_BACKEND: s3
      S3_ENDPOINT: http://minio:9000
      S3_BUCKET: claude-plugins
      S3_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      S3_SECRET_KEY: ${MINIO_SECRET_KEY}
      AUTH_PROVIDER: oidc
      OIDC_ISSUER: https://sso.corp.com
      OIDC_CLIENT_ID: claude-registry
      OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
      SIGNING_KEY_PATH: /secrets/registry-signing.key
      AUDIT_LOG_ENABLED: "true"
    volumes:
      - ./secrets:/secrets:ro
    depends_on:
      - postgres
      - minio
  
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: registry
      POSTGRES_USER: registry
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
  
  minio:
    image: minio/minio:latest
    command: server /data
    environment:
      MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
      MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
    volumes:
      - minio_data:/data

volumes:
  postgres_data:
  minio_data:

56.4 Access Control Model

Role-Based Access Control (RBAC)

# registry-config.yaml

rbac:
  roles:
    viewer:
      permissions:
        - registry:package:read
        - registry:package:install
    
    developer:
      inherit: viewer
      permissions:
        - registry:package:publish
        - registry:package:deprecate
    
    namespace_admin:
      inherit: developer
      permissions:
        - registry:namespace:manage
        - registry:package:delete
    
    registry_admin:
      inherit: namespace_admin
      permissions:
        - registry:admin:manage_users
        - registry:admin:view_audit_logs
        - registry:admin:manage_policies
  
  namespaces:
    platform:
      admins: ["platform-team"]
      developers: ["platform-team", "senior-engineers"]
      viewers: ["@all"]
    
    data-team:
      admins: ["data-team-leads"]
      developers: ["data-team"]
      viewers: ["data-team", "analytics-team"]
    
    security:
      admins: ["security-team"]
      developers: ["security-team"]
      viewers: ["security-team"]    # restricted: security team only

Policy Engine with OPA

For more expressive access rules, the registry integrates Open Policy Agent:

# policies/install-policy.rego
package registry.install

default allow = false

# Allow install: user has viewer permission AND package is approved
allow {
  has_permission(input.user, "registry:package:install")
  input.package.reviewStatus == "approved"
  not is_blacklisted(input.package)
}

# High-risk packages require explicit approval
allow {
  has_permission(input.user, "registry:package:install")
  input.package.riskLevel == "high"
  has_approval(input.user, input.package.id)
}

is_blacklisted(package) {
  data.blacklist[package.name]
}

56.5 Configuring Claude Code to Use the Private Registry

User-Level Configuration

# Add the private registry
claude config registry add \
  --name corp \
  --url https://registry.corp.com \
  --auth-type oidc \
  --oidc-issuer https://sso.corp.com \
  --priority 1  # higher priority than public marketplace

# Verify connectivity
claude registry ping corp
# ✓ Connected to registry.corp.com
# ✓ Authenticated as: [email protected]
# ✓ Available namespaces: platform, data-team

# Search the private registry
claude plugin search --registry corp "database"

Organization-Level Policy (Enforced)

Enterprise admins can deploy an org policy file via MDM or GPO to enforce registry settings for all employees:

// /etc/claude/org-policy.json
{
  "registries": {
    "required": [
      {
        "name": "corp",
        "url": "https://registry.corp.com",
        "auth": "oidc",
        "priority": 1
      }
    ],
    "allowPublic": false,     // block access to the public marketplace
    "allowUnlisted": false    // block installation of unlisted packages
  },
  "plugins": {
    "allowList": ["corp/security-*", "corp/platform-*"],
    "blockList": ["*:dangerous-*"]
  }
}

56.6 Publishing to the Private Registry

From the CLI

# Login to the private registry
claude-plugin login --registry https://registry.corp.com

# Publish to private registry (instead of public marketplace)
claude-plugin publish \
  --registry https://registry.corp.com \
  --namespace platform \
  weather-plugin-1.0.0.clpkg

CI/CD Pipeline

# .github/workflows/publish-private.yml
name: Publish to Private Registry

on:
  push:
    tags: ['v*.*.*']

jobs:
  publish:
    runs-on: self-hosted  # internal runner
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          
      - name: Build and validate
        run: |
          npm ci
          npm run build
          npm install -g @claude/plugin-cli
          claude-plugin validate --strict
          
      - name: Security scan (SBOM + dependency audit)
        run: |
          npx @cyclonedx/cyclonedx-npm --output-file sbom.json
          npm audit --audit-level=high
          
      - name: Pack
        run: claude-plugin pack
        
      - name: Publish with SBOM
        env:
          REGISTRY_TOKEN: ${{ secrets.INTERNAL_REGISTRY_TOKEN }}
        run: |
          claude-plugin login \
            --registry https://registry.corp.com \
            --token $REGISTRY_TOKEN
          claude-plugin publish \
            --registry https://registry.corp.com \
            --namespace platform \
            --sbom sbom.json \
            *.clpkg

56.7 Version Pinning and Upgrade Strategy

Plugin Lock File

Similar to package-lock.json, a Plugin lock file ensures version consistency across the organization:

// .claude-plugin-lock.json (committed to version control)
{
  "lockVersion": 1,
  "generatedAt": "2026-04-28T10:00:00Z",
  "registry": "https://registry.corp.com",
  "plugins": {
    "corp/database-plugin": {
      "version": "2.1.3",
      "integrity": "sha256-abc123...",
      "resolved": "https://registry.corp.com/corp/database-plugin/-/2.1.3.clpkg"
    },
    "corp/security-plugin": {
      "version": "1.4.0",
      "integrity": "sha256-def456...",
      "resolved": "https://registry.corp.com/corp/security-plugin/-/1.4.0.clpkg"
    }
  }
}
# Install from lock file (no automatic upgrades)
claude plugin install --frozen-lockfile

# Update to latest and refresh lock file
claude plugin update

# Pin to a specific version
claude plugin pin corp/[email protected]

Controlled Upgrade Process

1. Test environment validation
   └── Install new version in isolated test workspace
   └── Run automated test suite

2. Canary rollout
   └── Push to 5% of users
   └── Monitor error rates and performance for 24 hours

3. Progressive rollout
   └── Expand to 50% of users
   └── Monitor for 48 hours

4. Full rollout
   └── Push to all users
   └── Update lock file

5. Rollback readiness
   └── Retain old version for 30 days
   └── Rollback: claude plugin pin corp/[email protected]

56.8 Supply Chain Security

SBOM Integration

Software Bill of Materials (SBOM) is the foundation of zero-trust supply chain security. The private registry requires all uploaded packages to include an SBOM:

# Generate CycloneDX SBOM
npx @cyclonedx/cyclonedx-npm \
  --output-format json \
  --output-file sbom.json \
  --spec-version 1.4

# Publish with SBOM attached
claude-plugin publish \
  --registry https://registry.corp.com \
  --sbom sbom.json \
  *.clpkg

The registry automatically associates the SBOM with the package and proactively notifies package maintainers when vulnerability databases (OSV, NVD) report new CVEs affecting their package's dependencies.

Code Signing Verification

# registry-config.yaml
signing:
  trustedKeys:
    - id: "platform-team-key"
      publicKey: |
        -----BEGIN PUBLIC KEY-----
        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
        -----END PUBLIC KEY-----
      namespaces: ["platform", "security"]
    
    - id: "external-vendor-key"
      publicKey: |
        -----BEGIN PUBLIC KEY-----
        ...
        -----END PUBLIC KEY-----
      namespaces: ["vendors"]
  
  requireSigning: true
  
  # Specific namespaces must be signed by specific keys
  namespaceKeyRequirements:
    security: ["platform-team-key"]
    vendors: ["external-vendor-key"]

56.9 Audit Logging

Enterprise-grade registries record all operations to an immutable audit log:

{
  "eventId": "audit_abc123",
  "timestamp": "2026-04-28T14:23:45.678Z",
  "actor": {
    "userId": "[email protected]",
    "ipAddress": "10.1.2.3",
    "userAgent": "claude-plugin-cli/1.5.0"
  },
  "action": "package.install",
  "resource": {
    "registry": "https://registry.corp.com",
    "namespace": "platform",
    "package": "database-plugin",
    "version": "2.1.3"
  },
  "outcome": "success",
  "workspaceId": "ws_prod_012"
}

Querying Audit Logs

# All installs by a specific user
claude registry audit query \
  --actor [email protected] \
  --action package.install \
  --since 2026-01-01 \
  --format csv > installs.csv

# All installs of a specific package
claude registry audit query \
  --package platform/database-plugin \
  --action package.install

# Failed publish attempts (security investigation)
claude registry audit query \
  --action package.publish \
  --outcome failure \
  --since 2026-04-01

56.10 High Availability and Disaster Recovery

Multi-Region Replication

# docker-compose.ha.yml

services:
  registry-primary:
    image: anthropic/claude-registry-server:latest
    environment:
      REPLICA_ROLE: primary
      REPLICATION_TARGETS: "https://registry-dr.corp.com"
    
  registry-dr:
    image: anthropic/claude-registry-server:latest
    environment:
      REPLICA_ROLE: replica
      REPLICA_SOURCE: "https://registry.corp.com"
      READ_ONLY: "true"    # DR site is read-only until failover

Offline Cache

Claude Code maintains a local cache of installed Plugin packages, enabling continued operation during network outages:

# Pre-warm the cache for critical Plugins (while online)
claude plugin cache pre-warm \
  corp/[email protected] \
  corp/[email protected]

# Check cache status
claude plugin cache list

Summary

Enterprise Plugin deployment is the endpoint of the entire Plugin ecosystem and the foundation of production reliability. A private registry serves enterprise needs through four core capabilities: access control (RBAC + OPA policy engine) ensures "the right people install the right packages"; supply chain security (SBOM + code signing) ensures "installed packages are trusted and safe"; version pinning and controlled upgrades ensure "production environment stability"; and complete audit logging satisfies "compliance and traceability" requirements.

From Chapter 49 through this chapter, we have walked the complete path of Claude Plugin development — from architectural design through production operations. The four-layer model (MCP → Hooks → LSP → Monitor), the Skill file format, the clawhub.ai publication workflow, Theme Plugins, LSP Plugin development, observability instrumentation, and enterprise registry deployment collectively form a comprehensive framework for building and operating Claude Plugins at any organizational scale.

Rate this chapter
4.8  / 5  (3 ratings)

💬 Comments