MainSDK
Search⌘K
Docs

Your first check

Read mainsdk check output, fix a finding with a secret reference, record an expiring exception, check prod settings and run the check in CI with SARIF.

Planned for 0.2

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

At the end of the quickstart, mainsdk check passed. This page reads that output, breaks it on purpose so you see a finding, then fixes the finding properly and covers the cases you'll meet next: a gap you can't fix yet, production settings, and CI.

The check runs on your machine, free, with no account. MainSDK is pre-release; the commands here are the planned design and ship from 0.2 (see the quickstart).

Run it on the clean app

text
$ npx mainsdk check
mainsdk check · pinecart · env dev · Main 27
 secrets   config   policy   network   data
all gates passed · exit 0

Every gate that ran has one line, and exit code 0 means a pass. Run it before every pull request.

Break it on purpose

Paste a live-looking key into a helper:

app/lib/pay.ts
export const stripeKey = "sk_live_51H…";
text
$ npx mainsdk check
mainsdk check · pinecart · env dev · Main 27
 secrets    1 finding
  MAIN-SECRET-0002  critical  app/lib/pay.ts:1
  fix: Move the key to secrets and use secret:STRIPE_SECRET_KEY
 config   policy   network   data
1 gate failed · exit 1
PartWhat it tells you
HeaderThe project, the environment it resolved (dev unless you pass --env) and the baseline
Failed gatesListed first. Each finding has a code, a severity, the file and line, and a fix
MAIN-SECRET-0002A stable code. npx mainsdk explain MAIN-SECRET-0002 prints the cause and fix offline; every code is listed in check codes
Passed gatesOne line, so you can see what ran
Exit code0 passed, 1 a gate failed, 2 a usage or configuration error (with a MAIN-CONFIG- code)

check resolves and tests every overlay combination you use, so a problem that exists only in main.in.yaml or main.env.prod.yaml still shows up.

Fix the finding

Pinecart takes payments with Stripe. Put the key behind a secret: reference in main.yaml and let the pay interface use it on the server:

main.yaml
payments: { driver: stripe }
pay:
  stripe: { key: secret:STRIPE_SECRET_KEY, webhook: secret:STRIPE_WEBHOOK_SECRET }
app/lib/pay.ts
import { pay } from "mainsdk";

export function startCheckout(orderId: string, amountInCents: number) {
  return pay.checkout({ order: orderId, amount: amountInCents, currency: "USD",
    successUrl: "/orders/done", cancelUrl: "/cart" });
}

For local runs, the local secrets driver reads values from .mainsdk/secrets.json, which init git-ignored. In production, your secrets driver (Vault, a cloud secret manager, Doppler or Infisical) supplies them. Run npx mainsdk check again; it exits 0, the same as before you broke it.

If the key was ever committed, rotate it with your provider: it is in your git history. See Payments and Secrets.

When you can't fix it yet

Some gaps take time, such as a partner API that still offers only TLS 1.1. Record an exception in main.yaml with the rule, a reason, an owner and an expiry date:

main.yaml
exceptions:
  - rule: MAIN-NET-0004
    reason: Partner gateway upgrade booked for November
    owner: "@pinecart/platform"
    expires: 2026-11-30

While the exception is open, check passes and your mark reads "Main 27 · 1 exception". The day after it expires, check fails again. See Main 27 and the Main mark.

Check the production settings

bash
npx mainsdk check --env prod

This resolves main.env.prod.yaml and fails with MAIN-CHECK-0026 local driver in production: secrets if, say, secrets.driver is still local. Set a real driver for every interface in main.env.prod.yaml, and the same command passes. Run it before you ship and in CI.

Machine-readable output

bash
npx mainsdk check --json --sarif mainsdk.sarif
json
{ "version": 1, "project": "prj_01JC8Q4W7ZK3M5N8P2R6T9V0XY", "env": "dev", "passed": false,
  "gates": [{ "id": "secrets", "passed": false, "findings": [
    { "code": "MAIN-SECRET-0002", "severity": "critical", "file": "app/lib/pay.ts", "line": 1,
      "rule": "secrets.no_literal", "fix": "Move the key to secrets and use secret:STRIPE_SECRET_KEY" } ] }] }

The JSON is versioned and has a published schema. The SARIF file is SARIF 2.1.0, so GitHub code scanning shows each finding inline on the pull request.

Run it in CI

Gates in your own CI are free on every plan. Check the production settings on every pull request:

.github/workflows/mainsdk.yml
name: mainsdk
on: [pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx mainsdk check --env prod --sarif mainsdk.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: mainsdk.sarif }

To fail only on serious findings while you adopt, add --fail-on <severity>, for example --fail-on critical.

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet