Claude-code-plugins-plus linear-prod-checklist
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/linear-pack/skills/linear-prod-checklist" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-linear-prod-checklist && rm -rf "$T"
manifest:
plugins/saas-packs/linear-pack/skills/linear-prod-checklist/SKILL.mdsource content
Linear Production Checklist
Overview
Comprehensive checklist and implementation patterns for deploying Linear integrations to production. Covers authentication, error handling, rate limiting, monitoring, data handling, and deployment verification.
Prerequisites
- Working development integration passing all tests
- Production Linear workspace (or production API key)
- Deployment infrastructure (Vercel, Cloud Run, etc.)
- Secret management solution (not
files in production).env
Pre-Production Checklist
1. Authentication & Security
[ ] Production API key generated (separate from dev) [ ] API key stored in secret manager (Vault, AWS SM, GCP SM) [ ] OAuth redirect URIs updated for production domain [ ] Webhook secrets are unique per environment [ ] All dev secrets rotated before launch [ ] HTTPS enforced on all endpoints [ ] Webhook HMAC-SHA256 verification implemented [ ] Webhook timestamp validation (< 60s age) [ ] Token refresh flow implemented (mandatory since Oct 2025)
2. Error Handling & Resilience
[ ] All Linear API calls wrapped in try/catch [ ] Rate limit retry with exponential backoff (max 5 retries) [ ] 30s timeout on all API calls [ ] Graceful degradation when Linear API is down [ ] Error logging includes context (no secrets in logs) [ ] InvalidInputLinearError caught separately from network errors [ ] Alerts configured for auth failures and error rate spikes
3. Performance & Rate Limits
[ ] Pagination with first:50 for all list queries [ ] Caching for static data (teams, states, labels) — 10-30 min TTL [ ] Request batching for bulk operations (20 mutations per batch) [ ] Query complexity stays under 5,000 pts per request [ ] No polling — webhooks for real-time updates [ ] N+1 query patterns eliminated (use rawRequest for joins) [ ] Response times monitored with p95 alerting
4. Monitoring & Observability
[ ] Health check endpoint hitting Linear API [ ] API latency metrics collected per operation [ ] Error rate monitoring with alerting (>1% = alert) [ ] Rate limit remaining tracked (alert if < 100 requests) [ ] Structured JSON logging for API calls and webhooks [ ] Webhook delivery tracking via Linear-Delivery header
5. Data Handling
[ ] No PII logged or stored unnecessarily [ ] Webhook event idempotency (deduplicate by Linear-Delivery) [ ] Data retention policy defined for synced data [ ] Stale data detection with periodic consistency checks
Production Configuration
import { LinearClient } from "@linear/sdk"; interface ProdConfig { linear: { apiKey: string; webhookSecret: string }; rateLimit: { maxRetries: number; baseDelayMs: number; maxDelayMs: number }; cache: { teamsTtl: number; statesTtl: number; labelsTtl: number }; timeouts: { requestMs: number; webhookProcessMs: number }; } const config: ProdConfig = { linear: { apiKey: await getSecret("linear-api-key-prod"), webhookSecret: await getSecret("linear-webhook-secret-prod"), }, rateLimit: { maxRetries: 5, baseDelayMs: 1000, maxDelayMs: 30000 }, cache: { teamsTtl: 600, statesTtl: 1800, labelsTtl: 600 }, timeouts: { requestMs: 30000, webhookProcessMs: 5000 }, }; function createProductionClient(): LinearClient { return new LinearClient({ apiKey: config.linear.apiKey }); }
Health Check Implementation
interface HealthStatus { status: "healthy" | "degraded" | "unhealthy"; latencyMs: number; details: { authentication: boolean; apiReachable: boolean; rateLimitOk: boolean; }; timestamp: string; } async function checkHealth(client: LinearClient): Promise<HealthStatus> { const start = Date.now(); const details = { authentication: false, apiReachable: false, rateLimitOk: true }; try { const viewer = await client.viewer; details.authentication = true; details.apiReachable = true; const latencyMs = Date.now() - start; return { status: latencyMs > 3000 ? "degraded" : "healthy", latencyMs, details, timestamp: new Date().toISOString(), }; } catch (error: any) { details.apiReachable = !error.message?.includes("ENOTFOUND"); return { status: "unhealthy", latencyMs: Date.now() - start, details, timestamp: new Date().toISOString(), }; } } // Express endpoint app.get("/health/linear", async (req, res) => { const health = await checkHealth(client); res.status(health.status === "unhealthy" ? 503 : 200).json(health); });
Deployment Verification Script
// scripts/verify-deployment.ts import { LinearClient } from "@linear/sdk"; async function verify(): Promise<void> { console.log("Verifying Linear integration...\n"); const checks = [ { name: "Environment variables", check: async () => !!(process.env.LINEAR_API_KEY && process.env.LINEAR_WEBHOOK_SECRET), }, { name: "API authentication", check: async () => { await new LinearClient({ apiKey: process.env.LINEAR_API_KEY! }).viewer; return true; }, }, { name: "Team access", check: async () => { const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! }); const teams = await client.teams(); return teams.nodes.length > 0; }, }, { name: "Write capability", check: async () => { const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! }); const teams = await client.teams(); const r = await client.createIssue({ teamId: teams.nodes[0].id, title: "[DEPLOY-CHECK] Safe to delete", }); if (r.success) { const issue = await r.issue; await issue?.delete(); } return r.success; }, }, ]; let passed = 0; let failed = 0; for (const { name, check } of checks) { try { const ok = await check(); console.log(ok ? ` PASS: ${name}` : ` FAIL: ${name}`); ok ? passed++ : failed++; } catch (error: any) { console.log(` FAIL: ${name} — ${error.message}`); failed++; } } console.log(`\nResults: ${passed} passed, ${failed} failed`); if (failed > 0) process.exit(1); } verify();
Post-Deployment Monitoring
// Key metrics to track after deploy const ALERT_THRESHOLDS = { errorRate: 0.01, // Alert if >1% of requests fail p99LatencyMs: 3000, // Alert if p99 > 3 seconds rateLimitRemaining: 100, // Alert if remaining requests < 100 }; // First 30 minutes after deploy: watch for // - Auth failures (key mismatch between environments) // - Rate limit spikes (init burst fetching too much data) // - Webhook signature failures (secret not updated in new env)
Error Handling
| Issue | Cause | Solution |
|---|---|---|
Health check | API key invalid/expired | Regenerate key, update secret manager |
| Webhook sig fails in prod | Secret mismatch | Verify matches Linear webhook config |
| Rate limit burst on deploy | Startup fetches too much | Add request queue, cache static data |
| Deploy verification fails | Missing env vars | Run verification locally first |