exa-policy-guardrails
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExa Policy & Guardrails
Exa 策略与防护机制
Overview
概述
Automated policy enforcement and guardrails for Exa integrations.
为Exa集成提供自动化策略执行与防护机制。
Prerequisites
前置条件
- ESLint configured in project
- Pre-commit hooks infrastructure
- CI/CD pipeline with policy checks
- TypeScript for type enforcement
- 项目中已配置ESLint
- 具备提交前钩子基础设施
- 带有策略检查的CI/CD流水线
- 用于类型校验的TypeScript
ESLint Rules
ESLint规则
Custom Exa Plugin
自定义Exa插件
javascript
// eslint-plugin-exa/rules/no-hardcoded-keys.js
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Disallow hardcoded Exa API keys',
},
fixable: 'code',
},
create(context) {
return {
Literal(node) {
if (typeof node.value === 'string') {
if (node.value.match(/^sk_(live|test)_[a-zA-Z0-9]{24,}/)) {
context.report({
node,
message: 'Hardcoded Exa API key detected',
});
}
}
},
};
},
};javascript
// eslint-plugin-exa/rules/no-hardcoded-keys.js
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Disallow hardcoded Exa API keys',
},
fixable: 'code',
},
create(context) {
return {
Literal(node) {
if (typeof node.value === 'string') {
if (node.value.match(/^sk_(live|test)_[a-zA-Z0-9]{24,}/)) {
context.report({
node,
message: 'Hardcoded Exa API key detected',
});
}
}
},
};
},
};ESLint Configuration
ESLint配置
javascript
// .eslintrc.js
module.exports = {
plugins: ['exa'],
rules: {
'exa/no-hardcoded-keys': 'error',
'exa/require-error-handling': 'warn',
'exa/use-typed-client': 'warn',
},
};javascript
// .eslintrc.js
module.exports = {
plugins: ['exa'],
rules: {
'exa/no-hardcoded-keys': 'error',
'exa/require-error-handling': 'warn',
'exa/use-typed-client': 'warn',
},
};Pre-Commit Hooks
提交前钩子
yaml
undefinedyaml
undefined.pre-commit-config.yaml
.pre-commit-config.yaml
repos:
- repo: local
hooks:
-
id: exa-secrets-check name: Check for Exa secrets entry: bash -c 'git diff --cached --name-only | xargs grep -l "sk_live_" && exit 1 || exit 0' language: system pass_filenames: false
-
id: exa-config-validate name: Validate Exa configuration entry: node scripts/validate-exa-config.js language: node files: '.exa.json$'
-
undefinedrepos:
- repo: local
hooks:
-
id: exa-secrets-check name: Check for Exa secrets entry: bash -c 'git diff --cached --name-only | xargs grep -l "sk_live_" && exit 1 || exit 0' language: system pass_filenames: false
-
id: exa-config-validate name: Validate Exa configuration entry: node scripts/validate-exa-config.js language: node files: '.exa.json$'
-
undefinedTypeScript Strict Patterns
TypeScript严格模式规范
typescript
// Enforce typed configuration
interface ExaStrictConfig {
apiKey: string; // Required
environment: 'development' | 'staging' | 'production'; // Enum
timeout: number; // Required number, not optional
retries: number;
}
// Disallow any in Exa code
// @ts-expect-error - Using any is forbidden
const client = new Client({ apiKey: any });
// Prefer this
const client = new ExaClient(config satisfies ExaStrictConfig);typescript
// Enforce typed configuration
interface ExaStrictConfig {
apiKey: string; // Required
environment: 'development' | 'staging' | 'production'; // Enum
timeout: number; // Required number, not optional
retries: number;
}
// Disallow any in Exa code
// @ts-expect-error - Using any is forbidden
const client = new Client({ apiKey: any });
// Prefer this
const client = new ExaClient(config satisfies ExaStrictConfig);Architecture Decision Records
架构决策记录
ADR Template
ADR模板
markdown
undefinedmarkdown
undefinedADR-001: Exa Client Initialization
ADR-001: Exa Client Initialization
Status
Status
Accepted
Accepted
Context
Context
We need to decide how to initialize the Exa client across our application.
We need to decide how to initialize the Exa client across our application.
Decision
Decision
We will use the singleton pattern with lazy initialization.
We will use the singleton pattern with lazy initialization.
Consequences
Consequences
- Pro: Single client instance, connection reuse
- Pro: Easy to mock in tests
- Con: Global state requires careful lifecycle management
- Pro: Single client instance, connection reuse
- Pro: Easy to mock in tests
- Con: Global state requires careful lifecycle management
Enforcement
Enforcement
- ESLint rule: exa/use-singleton-client
- CI check: grep for "new ExaClient(" outside allowed files
undefined- ESLint rule: exa/use-singleton-client
- CI check: grep for "new ExaClient(" outside allowed files
undefinedPolicy-as-Code (OPA)
即代码策略(OPA)
rego
undefinedrego
undefinedexa-policy.rego
exa-policy.rego
package exa
package exa
Deny production API keys in non-production environments
Deny production API keys in non-production environments
deny[msg] {
input.environment != "production"
startswith(input.apiKey, "sk_live_")
msg := "Production API keys not allowed in non-production environment"
}
deny[msg] {
input.environment != "production"
startswith(input.apiKey, "sk_live_")
msg := "Production API keys not allowed in non-production environment"
}
Require minimum timeout
Require minimum timeout
deny[msg] {
input.timeout < 10000
msg := sprintf("Timeout too low: %d < 10000ms minimum", [input.timeout])
}
deny[msg] {
input.timeout < 10000
msg := sprintf("Timeout too low: %d < 10000ms minimum", [input.timeout])
}
Require retry configuration
Require retry configuration
deny[msg] {
not input.retries
msg := "Retry configuration is required"
}
undefineddeny[msg] {
not input.retries
msg := "Retry configuration is required"
}
undefinedCI Policy Checks
CI策略检查
yaml
undefinedyaml
undefined.github/workflows/exa-policy.yml
.github/workflows/exa-policy.yml
name: Exa Policy Check
on: [push, pull_request]
jobs:
policy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for hardcoded secrets
run: |
if grep -rE "sk_(live|test)_[a-zA-Z0-9]{24,}" --include="*.ts" --include="*.js" .; then
echo "ERROR: Hardcoded Exa keys found"
exit 1
fi
- name: Validate configuration schema
run: |
npx ajv validate -s exa-config.schema.json -d config/exa/*.json
- name: Run ESLint Exa rules
run: npx eslint --plugin exa --rule 'exa/no-hardcoded-keys: error' src/undefinedname: Exa Policy Check
on: [push, pull_request]
jobs:
policy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for hardcoded secrets
run: |
if grep -rE "sk_(live|test)_[a-zA-Z0-9]{24,}" --include="*.ts" --include="*.js" .; then
echo "ERROR: Hardcoded Exa keys found"
exit 1
fi
- name: Validate configuration schema
run: |
npx ajv validate -s exa-config.schema.json -d config/exa/*.json
- name: Run ESLint Exa rules
run: npx eslint --plugin exa --rule 'exa/no-hardcoded-keys: error' src/undefinedRuntime Guardrails
运行时防护机制
typescript
// Prevent dangerous operations in production
const BLOCKED_IN_PROD = ['deleteAll', 'resetData', 'migrateDown'];
function guardExaOperation(operation: string): void {
const isProd = process.env.NODE_ENV === 'production';
if (isProd && BLOCKED_IN_PROD.includes(operation)) {
throw new Error(`Operation '${operation}' blocked in production`);
}
}
// Rate limit protection
function guardRateLimits(requestsInWindow: number): void {
const limit = parseInt(process.env.EXA_RATE_LIMIT || '100');
if (requestsInWindow > limit * 0.9) {
console.warn('Approaching Exa rate limit');
}
if (requestsInWindow >= limit) {
throw new Error('Exa rate limit exceeded - request blocked');
}
}typescript
// Prevent dangerous operations in production
const BLOCKED_IN_PROD = ['deleteAll', 'resetData', 'migrateDown'];
function guardExaOperation(operation: string): void {
const isProd = process.env.NODE_ENV === 'production';
if (isProd && BLOCKED_IN_PROD.includes(operation)) {
throw new Error(`Operation '${operation}' blocked in production`);
}
}
// Rate limit protection
function guardRateLimits(requestsInWindow: number): void {
const limit = parseInt(process.env.EXA_RATE_LIMIT || '100');
if (requestsInWindow > limit * 0.9) {
console.warn('Approaching Exa rate limit');
}
if (requestsInWindow >= limit) {
throw new Error('Exa rate limit exceeded - request blocked');
}
}Instructions
操作步骤
Step 1: Create ESLint Rules
步骤1:创建ESLint规则
Implement custom lint rules for Exa patterns.
实现针对Exa模式的自定义代码检查规则。
Step 2: Configure Pre-Commit Hooks
步骤2:配置提交前钩子
Set up hooks to catch issues before commit.
设置钩子以在提交前捕获问题。
Step 3: Add CI Policy Checks
步骤3:添加CI策略检查
Implement policy-as-code in CI pipeline.
在CI流水线中实现即代码策略。
Step 4: Enable Runtime Guardrails
步骤4:启用运行时防护机制
Add production safeguards for dangerous operations.
为危险操作添加生产环境防护措施。
Output
输出结果
- ESLint plugin with Exa rules
- Pre-commit hooks blocking secrets
- CI policy checks passing
- Runtime guardrails active
- 带有Exa规则的ESLint插件
- 阻止密钥提交的提交前钩子
- 已通过的CI策略检查
- 已激活的运行时防护机制
Error Handling
错误处理
| Issue | Cause | Solution |
|---|---|---|
| ESLint rule not firing | Wrong config | Check plugin registration |
| Pre-commit skipped | --no-verify | Enforce in CI |
| Policy false positive | Regex too broad | Narrow pattern match |
| Guardrail triggered | Actual issue | Fix or whitelist |
| 问题 | 原因 | 解决方案 |
|---|---|---|
| ESLint规则未触发 | 配置错误 | 检查插件注册情况 |
| 提交前钩子被跳过 | 使用了--no-verify参数 | 在CI中强制执行 |
| 策略误报 | 正则表达式范围过宽 | 缩小匹配模式 |
| 防护机制被触发 | 存在实际问题 | 修复或加入白名单 |
Examples
示例
Quick ESLint Check
快速ESLint检查
bash
npx eslint --plugin exa --rule 'exa/no-hardcoded-keys: error' src/bash
npx eslint --plugin exa --rule 'exa/no-hardcoded-keys: error' src/Resources
参考资源
Next Steps
下一步
For architecture blueprints, see .
exa-architecture-variants如需架构蓝图,请查看。
exa-architecture-variants