documenso-multi-env-setup

v2026.09.24

Configure Documenso across multiple environments (dev, staging, production). Use when setting up environment-specific configurations, managing API keys, or implementing environment promotion workflows. Trigger with phrases like "documenso environments", "documenso staging", "documenso dev setup", "multi-environment documenso".

GitHub
安装命令
npx skhub add jeremylongshore/documenso-multi-env-setup
Markdown
SKILL.md

Documenso Multi-Environment Setup

Output

  • Isolated development, staging, and production workspaces with separate scoped identities, templates, signer controls, and audit boundaries.
  • A promotion/rollback receipt based on synthetic validation rather than production document or signer experiments.

Examples

Validate a versioned template and callback in development using synthetic recipients, promote to staging with separate credentials, and record its lifecycle/authorization/alert results. Release production through an approved canary only; if any gate differs, restore the prior configuration and do not copy production keys or signing artifacts into lower environments.

Overview

Configure Documenso across development, staging, and production with environment isolation, secret management, and promotion workflows. Documenso cloud offers a staging environment at stg-app.documenso.com; self-hosted users run separate instances.

Prerequisites

  • Documenso accounts or instances for each environment
  • Secret management solution (Vault, AWS Secrets Manager, or .env files)
  • Completed documenso-install-auth setup

Environment Architecture

┌─────────────────────────────────────────────────────────────┐
│  Development                                                 │
│  API: stg-app.documenso.com (or localhost:3000 self-hosted) │
│  Key: DOCUMENSO_API_KEY=api_dev_xxx                         │
│  Webhooks: ngrok tunnel                                      │
├─────────────────────────────────────────────────────────────┤
│  Staging                                                     │
│  API: stg-app.documenso.com                                 │
│  Key: DOCUMENSO_API_KEY=api_stg_xxx                         │
│  Webhooks: staging.yourapp.com/webhooks/documenso           │
├─────────────────────────────────────────────────────────────┤
│  Production                                                  │
│  API: app.documenso.com (or sign.yourcompany.com)           │
│  Key: DOCUMENSO_API_KEY=api_prod_xxx                        │
│  Webhooks: api.yourapp.com/webhooks/documenso               │
└─────────────────────────────────────────────────────────────┘

Instructions

Step 1: Environment Configuration Files

# .env.development
DOCUMENSO_API_KEY=api_dev_xxxxxxxxxxxx
DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=whsec_dev_xxxxxxxxxxxx
LOG_LEVEL=debug
NODE_ENV=development

# .env.staging
DOCUMENSO_API_KEY=api_stg_xxxxxxxxxxxx
DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=whsec_stg_xxxxxxxxxxxx
LOG_LEVEL=info
NODE_ENV=staging

# .env.production
DOCUMENSO_API_KEY=api_prod_xxxxxxxxxxxx
DOCUMENSO_BASE_URL=https://app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=whsec_prod_xxxxxxxxxxxx
LOG_LEVEL=warn
NODE_ENV=production

Step 2: Environment-Aware Client Factory

// src/documenso/factory.ts
import { Documenso } from "@documenso/sdk-typescript";

interface EnvConfig {
  apiKey: string;
  baseUrl: string;
  webhookSecret: string;
}

function getConfig(): EnvConfig {
  const apiKey = process.env.DOCUMENSO_API_KEY;
  if (!apiKey) throw new Error("DOCUMENSO_API_KEY required");

  return {
    apiKey,
    baseUrl: process.env.DOCUMENSO_BASE_URL ?? "https://app.documenso.com/api/v2",
    webhookSecret: process.env.DOCUMENSO_WEBHOOK_SECRET ?? "",
  };
}

let client: Documenso | null = null;

export function getClient(): Documenso {
  if (!client) {
    const config = getConfig();
    client = new Documenso({
      apiKey: config.apiKey,
      serverURL: config.baseUrl,
    });
  }
  return client;
}

export function getWebhookSecret(): string {
  return getConfig().webhookSecret;
}

// Reset for testing
export function resetClient(): void {
  client = null;
}

Step 3: Environment Guards

// src/guards.ts
function requireProduction() {
  if (process.env.NODE_ENV !== "production") {
    throw new Error("This operation requires production environment");
  }
}

function blockProduction(operation: string) {
  if (process.env.NODE_ENV === "production") {
    throw new Error(`${operation} is blocked in production`);
  }
}

// Usage
async function deleteAllDrafts(client: Documenso) {
  blockProduction("deleteAllDrafts"); // Safety guard
  // ... only runs in dev/staging
}

async function sendBulkContracts(client: Documenso) {
  requireProduction(); // Only send real contracts in prod
  // ...
}

Step 4: Mock Client for Development

// src/documenso/mock.ts
import { vi } from "vitest";

export function createMockClient() {
  let docCounter = 0;
  return {
    documents: {
      createV0: vi.fn().mockImplementation(async ({ title }) => ({
        documentId: ++docCounter,
        title,
        status: "DRAFT",
      })),
      setFileV0: vi.fn().mockResolvedValue(undefined),
      findV0: vi.fn().mockResolvedValue({ documents: [] }),
      getV0: vi.fn().mockResolvedValue({ status: "DRAFT", recipients: [] }),
      sendV0: vi.fn().mockResolvedValue(undefined),
      deleteV0: vi.fn().mockResolvedValue(undefined),
    },
    documentsRecipients: {
      createV0: vi.fn().mockResolvedValue({ recipientId: 100 }),
    },
    documentsFields: {
      createV0: vi.fn().mockResolvedValue({ fieldId: 200 }),
    },
  };
}

Step 5: Template Promotion Between Environments

// scripts/promote-template.ts
// Templates can't be copied via API — recreate them per environment
// Keep template configuration in code for consistency

interface TemplateConfig {
  title: string;
  recipients: Array<{ role: string; placeholder: string }>;
  fields: Array<{
    recipientIndex: number;
    type: string;
    pageNumber: number;
    pageX: number;
    pageY: number;
    pageWidth: number;
    pageHeight: number;
  }>;
}

// Template definitions versioned in git
const SERVICE_AGREEMENT: TemplateConfig = {
  title: "Service Agreement Template v2",
  recipients: [
    { role: "SIGNER", placeholder: "Client" },
    { role: "APPROVER", placeholder: "Legal" },
  ],
  fields: [
    { recipientIndex: 0, type: "SIGNATURE", pageNumber: 3, pageX: 10, pageY: 80, pageWidth: 30, pageHeight: 5 },
    { recipientIndex: 0, type: "DATE", pageNumber: 3, pageX: 60, pageY: 80, pageWidth: 20, pageHeight: 3 },
    { recipientIndex: 1, type: "SIGNATURE", pageNumber: 3, pageX: 10, pageY: 90, pageWidth: 30, pageHeight: 5 },
  ],
};

// Apply to any environment by running: ENV=staging tsx scripts/promote-template.ts

Environment Checklist

CheckDevStagingProduction
Separate API keyYesYesYes
Debug loggingOnOnOff
Webhook endpointngrokstaging URLproduction URL
Secret manager.env file.env fileVault/AWS SM
Mock mode availableYesNoNo
Cleanup scripts enabledYesYesNo

Error Handling

IssueCauseSolution
Wrong environment dataMissing NODE_ENVSet explicitly in each environment
Key mismatchUsing dev key in prodVerify env var names per environment
Webhook not receivedWrong URL configuredUpdate webhook URL in each Documenso environment
Mock not workingWrong client injectedCheck factory returns mock in test env

Resources

Next Steps

For monitoring setup, see documenso-observability.

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

skills/.curated/documenso-multi-env-setup

默认分支

main

最新提交

e5a6c3b

Tree SHA

c2dc8e8