Skip to content
evernote-prod-checklist logo

Evernote Production Checklist

evernote-prod-checklist

Production readiness checklist for Evernote integrations. Use when preparing to deploy Evernote integration to production, or auditing production readiness. Trigger with phrases like "evernote production", "deploy evernote", "evernote go live", "production checklist evernote".

SKILL.md

Full skill instructions

Evernote Production Checklist

Overview

Comprehensive checklist for deploying Evernote integrations to production, covering API keys, security, performance, monitoring, and compliance.

Prerequisites

  • Completed development and testing
  • Production API key approved
  • Production infrastructure ready

Pre-Production Checklist

1. API Key Configuration

## API Key Requirements

- [ ] Production API key requested and approved
- [ ] Consumer key and secret stored in secret manager
- [ ] Sandbox mode disabled for production
- [ ] API key permissions match application needs
- [ ] Rate limit boost requested (if needed for initial sync)

## Key Management
- [ ] Different keys for dev/​staging/​production
- [ ] Key rotation procedure documented
- [ ] Emergency key revocation process defined

2. Environment Configuration

// config/​production.js
module.exports = {
  evernote: {
    // NEVER use sandbox in production
    sandbox: false,

    // Production endpoints
    serviceHost: 'www.evernote.com',

    // Timeouts
    requestTimeout: 30000, // 30 seconds
    connectionTimeout: 10000, // 10 seconds

    // Rate limiting
    maxRequestsPerMinute: 50,
    retryAttempts: 3,
    retryDelay: 1000
  },

  session: {
    secure: true,
    httpOnly: true,
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  },

  logging: {
    level: 'info',
    redactTokens: true
  }
};

3. Security Checklist

## Authentication & Authorization

- [ ] OAuth 1.0a implemented correctly
- [ ] CSRF protection on OAuth flow
- [ ] OAuth state validation
- [ ] Token expiration handling
- [ ] Token refresh workflow (re-auth before expiry)

## Data Protection

- [ ] Tokens encrypted at rest
- [ ] HTTPS enforced (no HTTP fallback)
- [ ] TLS 1.2+ required
- [ ] Sensitive data redacted from logs
- [ ] PII handling compliant with privacy policy

## Input Validation

- [ ] All user inputs validated
- [ ] ENML content sanitized
- [ ] File upload restrictions enforced
- [ ] SQL injection prevention (if using database)
- [ ] XSS prevention in rendered content

4. Error Handling

// middleware/​error-handler.js
const logger = require('../​utils/​secure-logger');

function productionErrorHandler(err, req, res, next) {
  // Log full error internally
  logger.error('Unhandled error', {
    error: err.message,
    stack: err.stack,
    path: req.path,
    method: req.method,
    userId: req.session?.userId
  });

  // Generic response to user
  const statusCode = err.statusCode || 500;

  // Never expose internal details
  res.status(statusCode).json({
    error: statusCode === 500 ?
      'An unexpected error occurred' :
      err.userMessage || 'Request failed',
    requestId: req.id // For support reference
  });
}

module.exports = productionErrorHandler;

5. Rate Limit Handling

// Production rate limit configuration
const rateLimitConfig = {
  // Conservative defaults
  maxRetries: 3,
  baseDelay: 1000,
  maxDelay: 60000,

  // Batch processing limits
  batchSize: 10,
  batchDelay: 500,

  // Circuit breaker
  failureThreshold: 5,
  recoveryTime: 60000
};

// Circuit breaker implementation
class CircuitBreaker {
  constructor(options) {
    this.failureCount = 0;
    this.failureThreshold = options.failureThreshold || 5;
    this.recoveryTime = options.recoveryTime || 60000;
    this.state = 'CLOSED';
    this.lastFailure = null;
  }

  async execute(operation) {
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailure > this.recoveryTime) {
        this.state = 'HALF_OPEN';
      } else {
        throw new Error('Circuit breaker is OPEN');
      }
    }

    try {
      const result = await operation();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  onSuccess() {
    this.failureCount = 0;
    this.state = 'CLOSED';
  }

  onFailure() {
    this.failureCount++;
    this.lastFailure = Date.now();

    if (this.failureCount >= this.failureThreshold) {
      this.state = 'OPEN';
    }
  }
}

6. Monitoring & Alerting

// monitoring/​metrics.js
const prometheus = require('prom-client');

// API call metrics
const apiCalls = new prometheus.Counter({
  name: 'evernote_api_calls_total',
  help: 'Total Evernote API calls',
  labelNames: ['operation', 'status']
});

const apiLatency = new prometheus.Histogram({
  name: 'evernote_api_latency_seconds',
  help: 'Evernote API call latency',
  labelNames: ['operation'],
  buckets: [0.1, 0.5, 1, 2, 5, 10]
});

const rateLimits = new prometheus.Counter({
  name: 'evernote_rate_limits_total',
  help: 'Total rate limit hits'
});

const authErrors = new prometheus.Counter({
  name: 'evernote_auth_errors_total',
  help: 'Total authentication errors',
  labelNames: ['type']
});

// Alert thresholds (configure in alerting system)
const alertRules = `
groups:
- name: evernote
  rules:
  - alert: HighRateLimitRate
    expr: rate(evernote_rate_limits_total[5m]) > 0.1
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: High Evernote rate limit rate

  - alert: HighAuthErrorRate
    expr: rate(evernote_auth_errors_total[5m]) > 0.05
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: High Evernote authentication error rate

  - alert: HighAPILatency
    expr: histogram_quantile(0.95, evernote_api_latency_seconds) > 5
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: High Evernote API latency
`;

7. Health Checks

// routes/​health.js
const express = require('express');
const router = express.Router();

router.get('/​health', (req, res) => {
  res.json({ status: 'ok' });
});

router.get('/​health/​detailed', async (req, res) => {
  const checks = {
    timestamp: new Date().toISOString(),
    status: 'ok',
    checks: {}
  };

  // Database check
  try {
    await db.query('SELECT 1');
    checks.checks.database = { status: 'ok' };
  } catch (error) {
    checks.checks.database = { status: 'error', message: 'Connection failed' };
    checks.status = 'degraded';
  }

  // Redis check
  try {
    await redis.ping();
    checks.checks.redis = { status: 'ok' };
  } catch (error) {
    checks.checks.redis = { status: 'error', message: 'Connection failed' };
    checks.status = 'degraded';
  }

  // Evernote API check (use sparingly)
  checks.checks.evernote = {
    status: 'ok',
    note: 'Not actively checked to preserve rate limits'
  };

  const statusCode = checks.status === 'ok' ? 200 : 503;
  res.status(statusCode).json(checks);
});

module.exports = router;

8. Logging Configuration

// logging/​production.js
const winston = require('winston');

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: {
    service: 'evernote-integration',
    environment: process.env.NODE_ENV
  },
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({
      filename: 'logs/​error.log',
      level: 'error',
      maxsize: 10485760, // 10MB
      maxFiles: 5
    }),
    new winston.transports.File({
      filename: 'logs/​combined.log',
      maxsize: 10485760,
      maxFiles: 5
    })
  ]
});

// Never log tokens
logger.add(winston.format((info) => {
  if (info.token) info.token = '[REDACTED]';
  if (info.accessToken) info.accessToken = '[REDACTED]';
  return info;
})());

module.exports = logger;

9. Deployment Verification

// scripts/​verify-deployment.js

async function verifyDeployment() {
  console.log('=== Deployment Verification ===\n');

  const checks = [];

  // 1. Environment check
  checks.push({
    name: 'Environment variables',
    pass: !!(process.env.EVERNOTE_CONSUMER_KEY &&
             process.env.EVERNOTE_CONSUMER_SECRET),
    critical: true
  });

  // 2. Sandbox mode disabled
  checks.push({
    name: 'Sandbox mode disabled',
    pass: process.env.EVERNOTE_SANDBOX !== 'true',
    critical: true
  });

  // 3. HTTPS enabled
  checks.push({
    name: 'HTTPS configured',
    pass: process.env.APP_URL?.startsWith('https://'),
    critical: true
  });

  // 4. Session secret set
  checks.push({
    name: 'Session secret configured',
    pass: !!process.env.SESSION_SECRET &&
          process.env.SESSION_SECRET.length >= 32,
    critical: true
  });

  // 5. Logging configured
  checks.push({
    name: 'Logging configured',
    pass: process.env.LOG_LEVEL !== 'debug',
    critical: false
  });

  // Report
  let allPassed = true;
  for (const check of checks) {
    const status = check.pass ? 'PASS' : 'FAIL';
    const critical = check.critical ? '(CRITICAL)' : '';
    console.log(`[${status}] ${check.name} ${critical}`);

    if (!check.pass && check.critical) {
      allPassed = false;
    }
  }

  console.log('\n' + (allPassed ?
    'Deployment verification PASSED' :
    'Deployment verification FAILED - fix critical issues'));

  process.exit(allPassed ? 0 : 1);
}

verifyDeployment();

Production Readiness Checklist

## Final Checklist Before Go-Live

### API & Authentication
- [ ] Production API key configured
- [ ] Sandbox mode disabled
- [ ] OAuth flow tested end-to-end
- [ ] Token storage encrypted
- [ ] Token expiration handling tested

### Security
- [ ] HTTPS enforced
- [ ] CSRF protection verified
- [ ] Input validation implemented
- [ ] Error messages don't leak sensitive data
- [ ] Security headers configured (HSTS, CSP, etc.)

### Performance
- [ ] Rate limit handling implemented
- [ ] Circuit breaker configured
- [ ] Timeouts set appropriately
- [ ] Connection pooling enabled
- [ ] Caching strategy implemented

### Monitoring
- [ ] Health check endpoints working
- [ ] Metrics collection configured
- [ ] Alerting rules set up
- [ ] Log aggregation configured
- [ ] Error tracking enabled (Sentry, etc.)

### Operations
- [ ] Runbook documented
- [ ] Rollback procedure tested
- [ ] Backup strategy defined
- [ ] On-call rotation established
- [ ] Incident response plan documented

### Compliance
- [ ] Privacy policy updated
- [ ] Terms of service updated
- [ ] Data retention policy defined
- [ ] GDPR compliance verified (if applicable)
- [ ] User consent mechanisms in place

Output

  • Production configuration templates
  • Security verification checklist
  • Monitoring and alerting setup
  • Health check endpoints
  • Deployment verification script

Resources

Next Steps

For version upgrades, see evernote-upgrade-migration.

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View