hubspot-policy-guardrails

Implement HubSpot lint rules, secret scanning, and CI policy checks. Use when setting up code quality rules for HubSpot integrations, preventing token leaks, or configuring CI guardrails. Trigger with phrases like "hubspot policy", "hubspot lint", "hubspot guardrails", "hubspot security check", "hubspot eslint rules".

1,868 stars

Best use case

hubspot-policy-guardrails is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Implement HubSpot lint rules, secret scanning, and CI policy checks. Use when setting up code quality rules for HubSpot integrations, preventing token leaks, or configuring CI guardrails. Trigger with phrases like "hubspot policy", "hubspot lint", "hubspot guardrails", "hubspot security check", "hubspot eslint rules".

Teams using hubspot-policy-guardrails should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/hubspot-policy-guardrails/SKILL.md --create-dirs "https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/main/plugins/saas-packs/hubspot-pack/skills/hubspot-policy-guardrails/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/hubspot-policy-guardrails/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How hubspot-policy-guardrails Compares

Feature / Agenthubspot-policy-guardrailsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Implement HubSpot lint rules, secret scanning, and CI policy checks. Use when setting up code quality rules for HubSpot integrations, preventing token leaks, or configuring CI guardrails. Trigger with phrases like "hubspot policy", "hubspot lint", "hubspot guardrails", "hubspot security check", "hubspot eslint rules".

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# HubSpot Policy & Guardrails

## Overview

Automated policy enforcement for HubSpot integrations: secret scanning, ESLint rules, CI checks for token leaks, and runtime guardrails.

## Prerequisites

- ESLint configured in project
- CI/CD pipeline (GitHub Actions)
- TypeScript for compile-time enforcement

## Instructions

### Step 1: Secret Scanning (Prevent Token Leaks)

```yaml
# .github/workflows/hubspot-security.yml
name: HubSpot Security Scan
on: [push, pull_request]

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Scan for HubSpot private app tokens
        run: |
          # Pattern: pat-{region}{number}-{uuid}
          if grep -rE "pat-[a-z]{2}[0-9]-[a-f0-9-]{36}" \
            --include="*.ts" --include="*.js" --include="*.json" --include="*.yaml" \
            --exclude-dir=node_modules --exclude-dir=.git .; then
            echo "::error::HubSpot private app token found in source code!"
            echo "Rotate this token immediately in HubSpot Settings > Private Apps"
            exit 1
          fi

      - name: Scan for deprecated API keys
        run: |
          # Pattern: hapikey=uuid
          if grep -rE "hapikey=[a-f0-9-]{36}" \
            --include="*.ts" --include="*.js" --include="*.env.example" \
            --exclude-dir=node_modules .; then
            echo "::error::Deprecated HubSpot API key found! Migrate to private app tokens."
            exit 1
          fi

      - name: Verify .gitignore includes .env files
        run: |
          if ! grep -q "^\.env$" .gitignore; then
            echo "::error::.gitignore missing .env entry"
            exit 1
          fi
```

### Step 2: ESLint Rule -- No Deprecated API Key Auth

```javascript
// eslint-rules/no-hubspot-api-key.js
module.exports = {
  meta: {
    type: 'problem',
    docs: { description: 'Disallow deprecated HubSpot API key authentication' },
    messages: {
      noApiKey: 'HubSpot API keys are deprecated. Use accessToken from a private app instead.',
      useAccessToken: 'Use { accessToken: process.env.HUBSPOT_ACCESS_TOKEN } instead of { apiKey }',
    },
  },
  create(context) {
    return {
      Property(node) {
        if (
          node.key.type === 'Identifier' &&
          node.key.name === 'apiKey' &&
          node.parent?.parent?.callee?.name === 'Client'
        ) {
          context.report({ node, messageId: 'noApiKey' });
        }
      },
      Literal(node) {
        if (typeof node.value === 'string') {
          // Detect hardcoded private app tokens
          if (node.value.match(/^pat-[a-z]{2}\d-[a-f0-9-]{36}$/)) {
            context.report({
              node,
              message: 'Hardcoded HubSpot access token detected. Use environment variable.',
            });
          }
          // Detect deprecated API keys
          if (node.value.match(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/) &&
              node.parent?.key?.name === 'apiKey') {
            context.report({ node, messageId: 'useAccessToken' });
          }
        }
      },
    };
  },
};
```

### Step 3: TypeScript Compile-Time Guardrails

```typescript
// src/hubspot/strict-types.ts

// Enforce that all HubSpot operations go through the service layer
// (not raw client calls scattered throughout the codebase)

// BAD: Using raw client anywhere
// const client = new hubspot.Client({ accessToken: '...' });
// client.crm.contacts.basicApi.create(...); // unguarded

// GOOD: All operations through typed service
interface IContactService {
  findByEmail(email: string): Promise<Contact | null>;
  create(data: CreateContactInput): Promise<Contact>;
  update(id: string, data: UpdateContactInput): Promise<Contact>;
  archive(id: string): Promise<void>;
}

// Enforce required properties at compile time
interface CreateContactInput {
  email: string;           // required
  firstname?: string;
  lastname?: string;
  lifecyclestage?: 'subscriber' | 'lead' | 'marketingqualifiedlead' |
    'salesqualifiedlead' | 'opportunity' | 'customer' | 'evangelist';
}

// Prevent passing unknown/dangerous properties
type UpdateContactInput = Partial<Omit<CreateContactInput, 'email'>>;

// Compile-time check: lifecycle stage must be valid
const validStage: CreateContactInput = {
  email: 'test@example.com',
  lifecyclestage: 'customer', // TypeScript enforces valid values
};

// This would fail at compile time:
// lifecyclestage: 'invalid_stage' // Type error
```

### Step 4: Runtime Guardrails

```typescript
// Prevent dangerous operations in production
const BLOCKED_IN_PROD: Record<string, string> = {
  'batch/archive': 'Bulk archiving is blocked in production',
  'gdpr-delete': 'GDPR delete requires manual approval in production',
};

function guardOperation(path: string): void {
  if (process.env.NODE_ENV !== 'production') return;

  for (const [pattern, message] of Object.entries(BLOCKED_IN_PROD)) {
    if (path.includes(pattern)) {
      throw new Error(`BLOCKED: ${message}. Environment: production.`);
    }
  }
}

// Rate limit self-protection (don't consume entire portal quota)
class SelfRateLimiter {
  private callsThisSecond = 0;
  private callsToday = 0;
  private lastSecond = Math.floor(Date.now() / 1000);
  private lastDay = new Date().toDateString();

  private maxPerSecond: number;
  private maxPerDay: number;

  constructor(maxPerSecond = 8, maxPerDay = 400000) {
    this.maxPerSecond = maxPerSecond; // leave 2/sec headroom for other apps
    this.maxPerDay = maxPerDay;       // leave 100K/day headroom
  }

  check(): void {
    const now = Math.floor(Date.now() / 1000);
    const today = new Date().toDateString();

    if (now !== this.lastSecond) {
      this.callsThisSecond = 0;
      this.lastSecond = now;
    }
    if (today !== this.lastDay) {
      this.callsToday = 0;
      this.lastDay = today;
    }

    this.callsThisSecond++;
    this.callsToday++;

    if (this.callsThisSecond > this.maxPerSecond) {
      throw new Error(
        `Self rate limit: ${this.callsThisSecond}/${this.maxPerSecond} per second`
      );
    }
    if (this.callsToday > this.maxPerDay) {
      throw new Error(
        `Self rate limit: ${this.callsToday}/${this.maxPerDay} per day`
      );
    }
  }
}
```

### Step 5: Pre-Commit Hook

```bash
#!/bin/bash
# .husky/pre-commit

# Scan for HubSpot tokens in staged files
PATTERN="pat-[a-z]{2}[0-9]-[a-f0-9-]{36}"
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E "\.(ts|js|json|yaml|yml)$")

if [ -n "$STAGED_FILES" ]; then
  if echo "$STAGED_FILES" | xargs grep -lE "$PATTERN" 2>/dev/null; then
    echo "ERROR: HubSpot access token found in staged files!"
    echo "Remove the token and use environment variables instead."
    exit 1
  fi
fi
```

## Output

- CI secret scanning for HubSpot tokens (private app and legacy API keys)
- ESLint rules preventing deprecated auth and hardcoded tokens
- TypeScript types enforcing valid property values at compile time
- Runtime guardrails blocking dangerous production operations
- Self-rate limiting to avoid consuming entire portal quota
- Pre-commit hook catching tokens before they hit git

## Error Handling

| Issue | Cause | Solution |
|-------|-------|----------|
| False positive on UUID | Pattern too broad | Check context (parent node name) |
| Token leaked to git | Pre-commit hook skipped | Enforce in CI as backup |
| Self-limiter too strict | Conservative defaults | Adjust based on portal usage |
| ESLint rule not running | Plugin not registered | Add to `.eslintrc` plugins array |

## Resources

- [HubSpot Security Best Practices](https://developers.hubspot.com/docs/guides/apps/private-apps/overview)
- [ESLint Custom Rules](https://eslint.org/docs/latest/extend/custom-rules)
- [Husky Pre-commit Hooks](https://typicode.github.io/husky/)

## Next Steps

For architecture blueprints, see `hubspot-architecture-variants`.

Related Skills

windsurf-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement team-wide Windsurf usage policies, code quality gates, and Cascade guardrails. Use when setting up code review policies for AI-generated code, configuring Turbo mode safety controls, or implementing CI gates for Cascade output. Trigger with phrases like "windsurf policy", "windsurf guardrails", "cascade safety rules", "windsurf team rules", "AI code policy".

vercel-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement lint rules, CI policy checks, and automated guardrails for Vercel projects. Use when setting up code quality rules, preventing secret exposure, or enforcing deployment policies for Vercel applications. Trigger with phrases like "vercel policy", "vercel lint", "vercel guardrails", "vercel best practices check", "vercel secret scan".

supabase-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Enforce organizational governance for Supabase projects: shared RLS policy library with reusable templates, table and column naming conventions, migration review process with CI checks, cost alert thresholds, and security audit scripts scanning for common misconfigurations. Use when establishing Supabase standards across teams, creating RLS policy templates, setting up migration review workflows, or auditing existing projects for security and cost issues. Trigger with phrases like "supabase governance", "supabase policy library", "supabase naming convention", "supabase migration review", "supabase cost alert", "supabase security audit", "supabase RLS template".

snowflake-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement Snowflake governance guardrails with network rules, session policies, authentication policies, and automated compliance checks. Use when enforcing security policies, implementing data governance, or configuring automated compliance for Snowflake. Trigger with phrases like "snowflake policy", "snowflake guardrails", "snowflake governance", "snowflake compliance", "snowflake enforce".

shopify-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement Shopify app policy enforcement with ESLint rules for API key detection, query cost budgets, and App Store compliance checks. Trigger with phrases like "shopify policy", "shopify lint", "shopify guardrails", "shopify compliance", "shopify eslint", "shopify app review".

sentry-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Enforce organizational governance and policy guardrails for Sentry usage. Use when standardizing Sentry configuration across services, enforcing PII scrubbing, building shared config packages, or auditing drift. Trigger with phrases like "sentry governance", "sentry policy", "sentry standards", "enforce sentry config", "sentry compliance".

salesforce-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement Salesforce lint rules, SOQL injection prevention, and API usage guardrails. Use when enforcing Salesforce integration code quality, preventing SOQL injection, or configuring CI policy checks for Salesforce best practices. Trigger with phrases like "salesforce policy", "salesforce lint", "salesforce guardrails", "SOQL injection", "salesforce eslint", "salesforce code review".

retellai-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Retell AI policy guardrails — AI voice agent and phone call automation. Use when working with Retell AI for voice agents, phone calls, or telephony. Trigger with phrases like "retell policy guardrails", "retellai-policy-guardrails", "voice agent".

perplexity-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement content moderation, model selection policy, citation quality enforcement, and per-user usage quotas for Perplexity Sonar API. Trigger with phrases like "perplexity policy", "perplexity guardrails", "perplexity content moderation", "perplexity usage limits", "perplexity safety".

notion-policy-guardrails

1868
from jeremylongshore/claude-code-plugins-plus-skills

Governance for Notion integrations: integration naming standards, page sharing policies, property naming conventions, database schema standards, and access audit scripts. Trigger with phrases like "notion governance", "notion policy", "notion naming convention", "notion access audit", "notion schema standard".

klingai-content-policy

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement content policy compliance for Kling AI prompts and outputs. Use when filtering user prompts or handling moderation. Trigger with phrases like 'klingai content policy', 'kling ai moderation', 'safe video generation', 'klingai content filter'.

hubspot-webhooks-events

1868
from jeremylongshore/claude-code-plugins-plus-skills

Implement HubSpot webhook subscriptions and CRM event handling. Use when setting up webhook endpoints for CRM events, implementing signature verification, or handling contact/deal/company change notifications. Trigger with phrases like "hubspot webhook", "hubspot events", "hubspot subscription", "handle hubspot notifications", "hubspot CRM events".