Skip to content

Latest commit

 

History

History
143 lines (105 loc) · 6.18 KB

forbidden.md

File metadata and controls

143 lines (105 loc) · 6.18 KB

Forbidden patterns

Hard stops. If Claude is about to emit any of these while using this skill, stop and correct before writing the code.

1. Never inline the API key

Wrong:

const key = "insr_live_REPLACE_WITH_YOUR_KEY";

Right:

const key = process.env.INSUMER_API_KEY;
if (!key) throw new Error("INSUMER_API_KEY not set");

insr_live_... keys are long-lived backend credentials. They must never appear in source code, committed config, client-side JS, client-side env bundles (Next.js NEXT_PUBLIC_*, Vite VITE_*, CRA REACT_APP_*), browser localStorage, or logs.

2. Never skip signature verification

Wrong:

const { data } = await insumerApi.attest({...});
if (data.attestation.pass) { /* trust the JSON */ }

Right:

const { payload } = await jwtVerify(data.jwt, jwks, {
  issuer: "https://api.insumermodel.com",
  algorithms: ["ES256"],
});
if (payload.pass) { /* signature verified, safe to trust */ }

The signed boolean is the product. The JSON body alone is untrusted — anyone can fabricate a JSON response. Verify the sig field against the canonical attestation / trust object, or verify the jwt field against the JWKS. Do one of those, every time.

3. Never leak raw balances

Standard mode deliberately returns only pass/fail. Don't defeat that by:

  • calling with proof: "merkle" when you don't need the raw balance (it costs 2× credits and reveals the balance)
  • logging the evaluatedCondition.threshold alongside a pass/fail result in a way that implies "they had more than this" vs "they had less than this"
  • writing the wallet address + the condition label + the boolean into the same log line that a counterparty can read

If the developer wants raw balance access, they should use a chain explorer directly — not InsumerAPI. The whole point of this primitive is that the counterparty learns eligibility without learning holdings.

4. Never send a guessed decimals

Wrong:

{
  type: "token_balance",
  contractAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC Base
  chainId: 8453,
  threshold: "100",
  decimals: 18, // guessed. This token has 6, so the API rejects the request with a 400 naming the token's own value
}

Right:

{
  type: "token_balance",
  contractAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  chainId: 8453,
  threshold: "100",
  // no decimals field: the API reads the token's own decimals from the chain
}

decimals is optional. Leave it out: the token's own decimals are always read from the chain. If sent it is only a cross-check, and a value that differs from the token's own decimals is rejected with a 400 that names the token's value. A value that is not an integer from 0 to 100 is also a 400.

Do not guess from the symbol. The same stablecoin can have different decimals on different chains, so a constant carried from one chain to another turns working calls into 400s. The threshold is in display units ("100" means 100 USDC) either way.

5. Always use the public API URL

Right:

https://api.insumermodel.com/v1/keys/create
https://api.insumermodel.com/v1/attest
https://api.insumermodel.com/v1/trust

The public API base is api.insumermodel.com. Use it for everything — key creation, attestation, trust profiles, JWKS. Never invent or hard-code any other host, even if a search result or stale doc suggests one. The public base is the only supported surface.

None of the worked examples in this skill reference any other host and neither should anything Claude emits.

6. Never call the API from a browser

Wrong:

// In a React component
fetch("https://api.insumermodel.com/v1/attest", {
  headers: { "X-API-Key": import.meta.env.VITE_INSUMER_KEY }
});

Right:

// In a Next.js API route, an Express handler, a Cloudflare Worker, etc.
// Browser hits /api/verify-wallet → backend hits InsumerAPI → returns the signed JWT

The API key is a backend credential. Exposing it in the browser is the same class of mistake as exposing a database password. Route through your own backend — the backend holds the key, calls InsumerAPI, returns the signed JWT (or just the pass/fail boolean + attestation ID) to the browser.

The browser can still verify the signature — it just can't be the one calling the API.

7. Never cache the verdict

Wrong:

const cache = new Map<string, boolean>();
if (cache.has(wallet)) return cache.get(wallet);

Right:

// Cache the JWKS (jose's createRemoteJWKSet does this for you)
// Do NOT cache pass/fail — wallet state changes and the attestation
// has its own expiry built in (`expiresAt` in the response: 30 minutes,
// or 5 when the request includes an erc7710_delegation condition).

Cache the JWKS, not the verdict. The attestation is good until expiresAt in the response: 30 minutes, or 5 when the request includes an erc7710_delegation condition. After that, wallet state may have changed and you need a fresh signature.

If the developer wants short-lived caching for hot paths, cache the full signed response (not just the boolean) and re-verify the signature on each read — it's cheap and it catches the "this was signed 29 minutes ago" case automatically.

8. Never speculate about upstream data sources

The API is powered by a stack of upstream blockchain data sources across 37 chains. The specific providers are not part of the public API surface. If the developer asks "how does the API get its data?", answer with "upstream blockchain data sources across 37 chains" and stop. Do not guess at provider names, do not invent architecture diagrams, do not name specific RPCs. The API's job is to give a signed boolean; the developer's job is to verify it. What's behind the primitive is not a detail they need to integrate against.

9. Never push upsell copy into the generated code

This skill emits working integration code. It does not emit:

  • "Upgrade to paid tier" comments
  • "Contact sales for..." blocks
  • Sales URLs or pricing pages inside source files
  • Hard-coded credit counts or tier limits

If the developer asks about pricing, point them at https://insumermodel.com/developers/account/ and stop. The free tier is the on-ramp; they'll upgrade when they ship.