ForgeFX Simulations
ForgeBot Skill Salesforce Vitest 2.1.9
Internal Skill Preview

Salesforce Skill Preview

A read-focused preview of the ForgeFX Salesforce CRM skill, its TypeScript helper layer, and the ordered live sanity tests that prove Doppler credentials, SOAP authentication, organization lookup, and newest-record reads are working before agents depend on CRM data.

HarnessVitest
Layouttests/ folder
Suite2 files / 9 tests
ResultPassing via Doppler

Skill Coverage

Read Salesforce CRM Data

Accounts, Opportunities, Contacts, Leads, Organization, custom objects, and schema describes through raw REST calls.

Keep Writes Explicit

Create/update helpers remain dry-run-first and require named user approval plus query-back verification after a write.

Preserve Credential Path

Live tests and scripts use Doppler with the ForgeApps production config. Secret values are never printed or embedded here.

Sanity Check Order

01Credentials

Finds required Salesforce env var names injected by Doppler.

02Authentication

Performs SOAP login and validates instance URL, session, and API version.

03Organization

Reads the org record and asserts the name matches ForgeFX.

04Account

Reads the most recently created Account by CreatedDate.

05Opportunity

Reads the most recently created Opportunity by CreatedDate.

06Contact

Reads the most recently created Contact by CreatedDate.

07Lead

Reads the most recently created Lead by CreatedDate.

TypeScript Helpers

Auth + RESTscripts/salesforce-client.ts

Reusable SOAP login, query, create, read, update, delete, and describe helper layer.

Read-only CLIscripts/salesforce-query.ts

SOQL SELECT runner for quick probes and legacy Python capability replacement.

Schema Probescripts/describe-salesforce-object.ts

Object fields, create/update flags, and parent relationship checks.

Dry-run Writesscripts/create-salesforce-record.ts

Generic create helper that requires explicit confirmation before mutation.

Test Evidence

PASS 2 files / 9 tests

Verified from the repo root on 2026-07-08 HST using the Doppler-backed command below.

doppler run --project forgeapps --config prd -- pnpm exec vitest run .forgebot/skills/salesforce/tests --coverage.enabled=false

Observed live sanity records: Organization ForgeFX Simulations, newest Account Response Group, newest Opportunity WM Heavy Equipment Operator Simulator, newest Contact Luke Hughes, newest Lead Paul Eldridge.

Full live-smoke.test.ts
import { describe, expect, it } from "vitest";
import { login, query, type SalesforceAuth } from "../scripts/salesforce-client.ts";

type NamedSalesforceRecord = {
  Id: string;
  Name: string;
  CreatedDate?: string;
};

const LIVE_TEST_TIMEOUT_MS = 60_000;
const REQUIRED_DOPPLER_SECRETS = [
  "SALESFORCE_USERNAME",
  "SALESFORCE_PASSWORD",
  "SALESFORCE_SECURITY_TOKEN",
] as const;

let auth: SalesforceAuth | undefined;

function missingRequiredSecrets(): string[] {
  return REQUIRED_DOPPLER_SECRETS.filter((name) => !process.env[name]?.trim());
}

function requireAuth(): SalesforceAuth {
  expect(auth, "The Salesforce authentication sanity check must pass before data tests run.").toBeDefined();
  return auth as SalesforceAuth;
}

async function expectMostRecentlyCreatedNamedRecord(objectName: "Account" | "Opportunity" | "Contact" | "Lead"): Promise<void> {
  const result = await query<NamedSalesforceRecord>(
    requireAuth(),
    `SELECT Id, Name, CreatedDate FROM ${objectName} ORDER BY CreatedDate DESC LIMIT 1`,
  );

  expect(result.totalSize, `${objectName} query should return at least one record.`).toBeGreaterThan(0);
  expect(result.records[0]?.Id, `${objectName} Id should be present.`).toMatch(/\S/);
  expect(result.records[0]?.Name, `${objectName} Name should be present.`).toMatch(/\S/);
  expect(result.records[0]?.CreatedDate, `${objectName} CreatedDate should be present.`).toMatch(/\S/);
}

describe("salesforce live sanity checks", () => {
  it("finds required Doppler-provided Salesforce credentials", () => {
    expect(
      missingRequiredSecrets(),
      "Run with: doppler run --project forgeapps --config prd -- pnpm exec vitest run .forgebot/skills/salesforce/tests/live-smoke.test.ts --coverage.enabled=false",
    ).toEqual([]);
  });

  it(
    "authenticates with Salesforce",
    async () => {
      auth = await login();

      expect(auth.instanceUrl).toMatch(/^https:\/\/.+/);
      expect(auth.sessionId).toMatch(/\S/);
      expect(auth.apiVersion).toMatch(/^\d+\.\d+$/);
    },
    LIVE_TEST_TIMEOUT_MS,
  );

  it(
    "reads the ForgeFX organization name",
    async () => {
      const result = await query<NamedSalesforceRecord>(
        requireAuth(),
        "SELECT Id, Name FROM Organization LIMIT 1",
      );

      expect(result.totalSize).toBe(1);
      expect(result.records[0]?.Name).toMatch(/ForgeFX/i);
    },
    LIVE_TEST_TIMEOUT_MS,
  );

  it("reads the most recently created account", async () => {
    await expectMostRecentlyCreatedNamedRecord("Account");
  }, LIVE_TEST_TIMEOUT_MS);

  it("reads the most recently created opportunity", async () => {
    await expectMostRecentlyCreatedNamedRecord("Opportunity");
  }, LIVE_TEST_TIMEOUT_MS);

  it("reads the most recently created contact", async () => {
    await expectMostRecentlyCreatedNamedRecord("Contact");
  }, LIVE_TEST_TIMEOUT_MS);

  it("reads the most recently created lead", async () => {
    await expectMostRecentlyCreatedNamedRecord("Lead");
  }, LIVE_TEST_TIMEOUT_MS);
});
Full check-skill.test.ts
import { describe, expect, it } from "vitest";
import { mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { checkSkill } from "../scripts/check-skill.ts";

describe("skill scaffold check", () => {
  it("salesforce skill scaffold check passes", () => {
    const result = checkSkill();
    expect(result.ok, result.errors.join("\n")).toBe(true);
    expect(result.frontmatter.name).toMatch(/\S/);
    expect(result.frontmatter.description).toMatch(/\S/);
  });

  it("accepts CRLF frontmatter", () => {
    const dir = mkdtempSync(join(tmpdir(), "salesforce-skill-check-"));
    writeFileSync(
      join(dir, "SKILL.md"),
      "---\r\nname: test-skill\r\ndescription: CRLF frontmatter\r\n---\r\n\r\n# Body\r\n",
      "utf8"
    );

    const result = checkSkill(dir);
    expect(result.ok, result.errors.join("\n")).toBe(true);
    expect(result.frontmatter.name).toBe("test-skill");
  });
});