sandbox-post-refresh-automation

Automating the post-sandbox-refresh cleanup via the `SandboxPostCopy` interface — the Apex class that runs ONCE after a sandbox refresh / clone completes, before users can log in. Used to mask emails, deactivate users, scrub integration endpoints, disable scheduled jobs, repopulate sample data, and reapply any per-environment configuration that the metadata copy doesn't carry. Covers the interface contract (`runApexClass` setting, `SandboxContext` parameter, single-execution semantics), the email-masking pattern that prevents production emails firing from sandbox tests, and the runbook checklist of what every refresh should reset. NOT for the sandbox refresh-strategy decision (use devops/sandbox-strategy-designer), NOT for general bulk Apex (use apex/scheduled-apex).

Best use case

sandbox-post-refresh-automation is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Automating the post-sandbox-refresh cleanup via the `SandboxPostCopy` interface — the Apex class that runs ONCE after a sandbox refresh / clone completes, before users can log in. Used to mask emails, deactivate users, scrub integration endpoints, disable scheduled jobs, repopulate sample data, and reapply any per-environment configuration that the metadata copy doesn't carry. Covers the interface contract (`runApexClass` setting, `SandboxContext` parameter, single-execution semantics), the email-masking pattern that prevents production emails firing from sandbox tests, and the runbook checklist of what every refresh should reset. NOT for the sandbox refresh-strategy decision (use devops/sandbox-strategy-designer), NOT for general bulk Apex (use apex/scheduled-apex).

Teams using sandbox-post-refresh-automation 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/sandbox-post-refresh-automation/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/admin/sandbox-post-refresh-automation/SKILL.md"

Manual Installation

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

How sandbox-post-refresh-automation Compares

Feature / Agentsandbox-post-refresh-automationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Automating the post-sandbox-refresh cleanup via the `SandboxPostCopy` interface — the Apex class that runs ONCE after a sandbox refresh / clone completes, before users can log in. Used to mask emails, deactivate users, scrub integration endpoints, disable scheduled jobs, repopulate sample data, and reapply any per-environment configuration that the metadata copy doesn't carry. Covers the interface contract (`runApexClass` setting, `SandboxContext` parameter, single-execution semantics), the email-masking pattern that prevents production emails firing from sandbox tests, and the runbook checklist of what every refresh should reset. NOT for the sandbox refresh-strategy decision (use devops/sandbox-strategy-designer), NOT for general bulk Apex (use apex/scheduled-apex).

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.

SKILL.md Source

# Sandbox Post-Refresh Automation

When a sandbox is refreshed (full, partial, dev, dev-pro), the
metadata + data are copied from the source. Users are then locked
out for a final preparation step before the sandbox becomes
available. The `SandboxPostCopy` interface is Salesforce's hook
into that step: an Apex class you specify in the sandbox refresh
configuration runs ONCE, before users can log in.

It's the right place to:

- **Mask emails** so test sends don't fire to real customers.
- **Deactivate users** who shouldn't have sandbox access.
- **Scrub integration endpoints** that point at production
  systems.
- **Disable scheduled jobs** that would race with prod
  (replicator, escalator, etc.).
- **Repopulate test data** that doesn't survive the copy (or
  shouldn't — auth tokens, caches, etc.).
- **Reapply environment-specific config** (named credentials,
  Custom Setting values keyed to environment, feature flags).

Without it, every refresh is a manual cleanup checklist that
inevitably gets forgotten on one of the steps. The most common
forgotten-step disaster: prod-pointing integration endpoints stay
configured; a developer in the sandbox triggers the integration;
production data changes.

What this skill is NOT. The strategic question of how many
sandboxes / which tier / refresh cadence lives in
`devops/sandbox-strategy-designer`. Generic Apex scheduling is
`apex/scheduled-apex`. This skill is specifically about the
post-refresh hook and what it should do.

---

## Before Starting

- **Confirm the sandbox tier matters.** All tiers support
  SandboxPostCopy. Some org features (e.g. partial-data sandbox
  data sampling) interact with the post-copy step.
- **Decide which actions are non-negotiable.** Email masking is
  always non-negotiable. Endpoint scrub is non-negotiable for orgs
  with prod-pointing integrations. Scheduled-job disable is
  non-negotiable if any scheduled job mutates external state.
- **Document the runbook explicitly.** The post-copy class IS the
  runbook; it's executable documentation. Future you reads it.
- **Plan idempotency.** The class runs once per refresh; failure
  during the run can leave the sandbox half-prepared. Build the
  class to be safe to re-run if needed.

---

## Core Concepts

### The `SandboxPostCopy` interface

```apex
global class MySandboxPrep implements SandboxPostCopy {
    global void runApexClass(SandboxContext context) {
        // Runs once, after sandbox refresh, before users log in.
        maskEmails();
        deactivateProdOnlyUsers();
        scrubIntegrationEndpoints();
        disableScheduledJobs();
        repopulateSampleData();
        applyEnvironmentConfig();
    }
}
```

Three things to know:

1. **`global` is required.** Internal `public` won't satisfy the
   interface contract.
2. **`SandboxContext` exposes** `sandboxName()`, `sandboxId()`,
   and `organizationId()`. Use these for environment-aware
   logic ("if dev sandbox, do X; if full sandbox, do Y").
3. **Configured at refresh time.** Setup → Sandboxes → click the
   sandbox → Apex Class field. Specify the class name. Saved with
   the sandbox; persists across refreshes.

### What runs vs what doesn't get copied

The metadata + data copy doesn't include:

- **Login Hours / Login IP Ranges** on profiles (security
  intentional).
- **Outbound message workflow targets** (always reset to a "do
  not deliver" placeholder by Salesforce — but verify in your
  org).
- **Scheduled jobs** — they DO copy, which is usually the wrong
  outcome. Sandbox post-copy disables them.
- **Single-sign-on certificates** for some IdP integrations.

What DOES copy and is dangerous in sandbox:

- **Named Credentials** — point at prod by default unless the
  named credential was already environment-aware.
- **Connected App configurations** — OAuth callback URLs are
  prod-shaped.
- **Custom Setting values** — usually carry prod values; rewrite
  in post-copy.
- **Workflow + Apex outbound emails** — if email deliverability
  is "All emails", the sandbox can fire emails to real customers
  unless masked.

### Email masking patterns

**Hardest constraint.** A refreshed sandbox with no email mask +
deliverability = "All emails" + a developer running a test = real
customers receive sandbox-generated emails.

**Mitigation A: Org-wide deliverability "System emails only".**
Setup → Email → Deliverability → Access Level → System emails
only. Done at the org level; survives across refreshes if set on
the sandbox post-copy. Belt-and-suspenders with email masking.

**Mitigation B: Mask user emails.**

```apex
private static void maskEmails() {
    List<User> toUpdate = new List<User>();
    for (User u : [SELECT Id, Email FROM User WHERE Email != NULL AND IsActive = TRUE]) {
        // Replace @ with .invalid + a tag — emails won't deliver, but
        // can be reverse-engineered for debugging.
        u.Email = u.Email.replace('@', '+sandbox@') + '.invalid';
        toUpdate.add(u);
    }
    update toUpdate;
}
```

The `.invalid` TLD is reserved by IETF for non-routable use —
mail servers reject delivery. The `+sandbox@` tag preserves the
original local-part for forensic debugging.

### Disabling scheduled jobs

```apex
private static void disableScheduledJobs() {
    for (CronTrigger ct : [
        SELECT Id FROM CronTrigger
        WHERE State IN ('WAITING', 'ACQUIRED', 'EXECUTING')
    ]) {
        try {
            System.abortJob(ct.Id);
        } catch (Exception ex) {
            // Some jobs can't be aborted (in-flight); log and continue.
        }
    }
}
```

Aborts every scheduled / queued job. A safer variant only aborts
jobs whose name matches a documented list of "production-only"
jobs; over-aggressive abort can break sandbox tests.

### Scrubbing integration endpoints

Named Credentials, Custom Settings, Custom Metadata Types — all
copy from production with prod values. Post-copy, rewrite to
sandbox / mock endpoints:

```apex
private static void scrubIntegrationEndpoints() {
    // Named Credentials are not directly Apex-mutable for endpoint URL;
    // typically scrubbed via metadata deploy in the sandbox setup script.
    // Custom Setting / Custom Metadata are mutable.
    Integration_Config__c cfg = Integration_Config__c.getOrgDefaults();
    cfg.Endpoint__c = 'https://mock.example-sandbox.com/api';
    cfg.API_Key__c = 'SANDBOX-MOCK-KEY';
    update cfg;
}
```

For Named Credentials, the sandbox-prep team usually pre-deploys
sandbox-pointing Named Credential metadata as part of the
post-copy + a metadata deploy step.

---

## Decision Guidance

| Situation | Approach | Reason |
|---|---|---|
| New sandbox tier added | Implement `SandboxPostCopy` from scratch | Standard pattern |
| Existing sandbox with manual cleanup checklist | Codify the checklist in post-copy | Manual is forgotten one step at a time |
| Multi-environment Custom Setting values | Custom Setting + post-copy assignment | Centralized; deterministic |
| Prod-pointing Named Credentials | Pre-deploy sandbox NC metadata + post-copy callout (or just rely on deploy) | NC URL not Apex-mutable directly |
| Email deliverability concerns | **System emails only** + email masking (both) | Belt-and-suspenders |
| Scheduled jobs that mutate external state | `System.abortJob` in post-copy | Critical safety mechanism |
| Sandbox-specific feature flags | Custom Metadata + post-copy update | Survives across refreshes |
| Different post-copy for dev vs full sandbox | Use `SandboxContext.sandboxName()` to branch | Environment-aware behavior |
| Failed post-copy run mid-execution | Make every step idempotent; document re-run procedure | Failures happen; design for them |

---

## Recommended Workflow

1. **Inventory the manual post-refresh checklist.** Email masking, user deactivation, endpoint scrub, scheduled-job disable, sample data, env config.
2. **Build the `SandboxPostCopy` class** — one private method per checklist item.
3. **Make every method idempotent.** Re-running shouldn't break anything.
4. **Configure on every sandbox.** Setup → Sandboxes → Apex Class field.
5. **Test by refreshing a low-tier sandbox first.** Verify each method ran (audit log, masked emails, disabled jobs).
6. **Document the class in source control.** It's runbook-as-code.
7. **Keep `Sandbox` org-wide deliverability at "System emails only"** as a belt-and-suspenders default.

---

## Review Checklist

- [ ] Class implements `SandboxPostCopy` with `global` access.
- [ ] `runApexClass` covers email masking, user deactivation, endpoint scrub, scheduled-job disable, sample data, env config.
- [ ] Every step is idempotent (safe to re-run).
- [ ] `SandboxContext` is consulted when behavior should differ per environment.
- [ ] Class name is configured in Setup → Sandboxes for every sandbox.
- [ ] Org-wide deliverability is "System emails only" as a default.
- [ ] Failed-run procedure is documented (how to re-run).

---

## Salesforce-Specific Gotchas

1. **`SandboxPostCopy` requires `global` access modifier.** `public` doesn't satisfy the interface contract. (See `references/gotchas.md` § 1.)
2. **`runApexClass` runs ONCE per refresh.** Mid-execution failure leaves the sandbox half-prepared; design for re-runnability. (See `references/gotchas.md` § 2.)
3. **Scheduled jobs DO copy** from prod to sandbox; they fire in the sandbox unless explicitly aborted in post-copy. (See `references/gotchas.md` § 3.)
4. **Named Credential URLs are not Apex-mutable.** Pre-deploy sandbox-pointing NC metadata or accept a stale URL. (See `references/gotchas.md` § 4.)
5. **Email deliverability resets to "System emails only"** on Salesforce's side after refresh — but verify; not all orgs / tiers behave identically. (See `references/gotchas.md` § 5.)
6. **`SandboxContext.sandboxName()` is the developer-given name**, not a hash; rely on it cautiously for branching. (See `references/gotchas.md` § 6.)
7. **The post-copy class must be already deployed in production** before refresh; the sandbox copies the class FROM production. (See `references/gotchas.md` § 7.)

---

## Output Artifacts

| Artifact | Description |
|---|---|
| `SandboxPostCopy` Apex class | The post-copy automation, one method per concern |
| Test class | Asserts each method's effects (mask, deactivate, scrub) |
| Sandbox configuration documentation | Which class is configured on which sandbox tier |
| Manual override runbook | How to re-run the class if it fails mid-execution |

---

## Related Skills

- `devops/sandbox-strategy-designer` — strategic decision (how many sandboxes, what tiers, refresh cadence). This skill is the implementation half.
- `apex/scheduled-apex` — generic scheduled / batch Apex; sandbox-post-copy is a specific runtime.
- `admin/email-templates-and-alerts` — email infrastructure; post-copy interacts with deliverability config.
- `apex/apex-mocking-and-stubs` — for the test class that exercises the post-copy methods.

Related Skills

sandbox-data-masking

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring or reviewing Salesforce Data Mask to protect PII/PHI in partial or full copy sandboxes after a refresh. Trigger keywords: data mask, sandbox masking, PII in sandbox, GDPR sandbox, HIPAA non-production, mask contacts, obfuscate fields non-production. NOT for sandbox refresh mechanics (use sandbox-refresh-and-templates), NOT for production data anonymization, NOT for Shield Platform Encryption at rest.

lwc-wire-refresh-patterns

8
from PranavNagrecha/AwesomeSalesforceSkills

refreshApex, getRecordNotifyChange, and RefreshView API for LWC data refresh: when wired data is stale, forcing re-fetch after imperative DML, cross-component refresh, 2024 RefreshView replacement of getRecordNotifyChange. NOT for wire basics (use lwc-wire-service). NOT for Lightning Data Service writes (use lwc-lds-writes).

sandbox-refresh-and-templates

8
from PranavNagrecha/AwesomeSalesforceSkills

Sandbox refresh cycles, sandbox templates, post-refresh automation via the SandboxPostCopy Apex interface, and data handling during refresh. NOT for sandbox type selection (use sandbox-strategy).

sandbox-data-isolation-gotchas

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when a sandbox has reached out to production systems, sent emails to real users, run live scheduled jobs, or leaked sensitive data after a refresh. Triggers: 'sandbox sent email to real customers', 'scheduled job fired against production API', 'integration hit live system from sandbox', 'Contact email not changed to .invalid', 'SandboxPostCopy did not run'. NOT for planning sandbox refresh cycles (use sandbox-refresh-and-templates), NOT for selecting sandbox types or counts (use environment-strategy), and NOT for scrubbing PII after copy (use sandbox-data-masking if that skill exists — otherwise document the masking logic in SandboxPostCopy).

salesforce-cli-automation

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when automating Salesforce work with the unified Salesforce CLI (`sf`, v2): shell scripts, Make/npm tasks, cron jobs, and CI steps that need stable flags, `--json` output, org aliases, bulk/data commands, plugins, and non-interactive auth patterns. Trigger keywords: sf CLI automation, sfdx migration, JSON output CI, sf project deploy script, sf data bulk, CLI plugins, target-org alias, machine-readable CLI. NOT for choosing or wiring a specific CI platform (GitHub Actions, GitLab, Jenkins, Bitbucket, Azure DevOps—use those devops skills), VS Code Salesforce extensions, or Copado/Gearset release management UIs.

release-notes-automation

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when generating customer- or stakeholder-facing release notes from git history, Jira/ADO ticket links, and Salesforce metadata diffs at deploy time. Triggers: 'auto-generate release notes', 'changelog from commits', 'release notes from PR titles', 'what changed in this deployment'. NOT for managed-package version creation, push upgrades, or org assessment.

postman-for-salesforce

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing or auditing **Postman collections** that exercise Salesforce APIs — collection structure, OAuth authentication (Web Server, JWT bearer, Username-Password, Client Credentials), pre-request scripts that refresh access tokens, environment variables for sandbox vs prod, request chaining via collection variables, response visualizers, and the official Salesforce Postman collection from the Developer Hub. Triggers: 'set up postman for salesforce', 'postman oauth pre-request script', 'postman jwt bearer salesforce', 'postman environment variables instance url access token', 'salesforce postman collection import', 'postman chained requests bulk api job', 'postman session id refresh script'. NOT for general OAuth-flow design (use `security/oauth-flow-design`), Apex callouts from inside Salesforce (use `apex/apex-callout-patterns`), API performance load testing (use `devops/performance-testing-salesforce`), or running `sf` CLI commands (use `devops/salesforce-cli-automation`).

post-deployment-validation

8
from PranavNagrecha/AwesomeSalesforceSkills

Verifying Salesforce deployments succeeded end-to-end after metadata lands in the target org. Covers validation deploys (checkOnly), quick deploy from validated IDs, Apex test result interpretation, Deployment Status page drill-down, and rollback strategies. NOT for writing Apex tests (use apex test patterns). NOT for CI/CD pipeline setup (use github-actions-for-salesforce or gitlab-ci-for-salesforce).

metadata-diff-between-sandboxes

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when comparing metadata between two Salesforce orgs (UAT vs Prod, dev sandbox vs full copy, fork sandbox vs source) to surface drift, identify items needing deployment, or build a destructive-changes manifest. Triggers: 'compare two sandboxes', 'org diff tool', 'metadata drift between UAT and prod', 'find missing metadata in target org'. NOT for code-level diffs in version control or for deploying packages.

cumulusci-automation

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring CumulusCI (cci) for Salesforce project automation: authoring cumulusci.yml tasks and flows, customizing or composing standard flows, integrating Robot Framework acceptance tests, and running cci flows in CI pipelines with JWT-based authentication. Covers task class_path/options wiring, flow step ordering, org and source declarations, cross-project reuse via sources, and the standard flow library (dev_org, qa_org, ci_feature, install_beta). NOT for raw SFDX/sf CLI workflows without CumulusCI, scratch org pool management (use scratch-org-pools), unlocked or managed package versioning (use unlocked-package-development or second-generation-managed-packages), or Salesforce-native DevOps Center pipelines (use devops-center-pipeline).

sandbox-refresh-data-strategies

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing data management strategies for sandbox refreshes: deciding which reference data must be re-seeded after every refresh, using Salesforce's native Data Seeding feature, writing SandboxPostCopy implementations that hand off to Queueable jobs for large data loads, and cleaning up stale data between sprints. Trigger keywords: seed data after sandbox refresh, SandboxPostCopy data strategy, native data seeding Salesforce, reference data re-seed after refresh, post-refresh data cleanup. NOT for sandbox administration setup, sandbox type selection (use sandbox-strategy), sandbox refresh mechanics and PII masking (use sandbox-refresh-and-templates), or scratch org data seeding for CI (use data-seeding-for-testing).

deployment-automation-architecture

8
from PranavNagrecha/AwesomeSalesforceSkills

Deployment automation architecture on Salesforce: pipeline orchestration, branch strategy, environment topology, quality gates, release trains. Selecting between Copado, Gearset, Flosum, and native SFDX + GitHub Actions. NOT for cloud-specific deploy mechanics (use cloud-specific-deployment-architecture). NOT for CI/CD tool tutorials.