InsightsSecurity

Public intake with create-only keys

A marketing site that files structured inquiries into internal operations without exposing them: a scoped gateway, per-IP rate limits, and a mail fallback that admits it is unconfirmed.

3 min readEcorpin Engineering
Share:

Scope the browser key to one mutation

The public site ships with a key that can create inquiries and nothing else — no listing, no editing, no access to other resources. Roles stay on the server, where they can be enforced rather than hoped for.

The internal key never enters the browser bundle. Two keys, two trust zones, and a gateway that treats the public one as hostile input with a single allowed verb.

Rate-limit the public path, not the internal one

Public-key inquiry creation is throttled per IP while internal SDK traffic keeps its normal limit. Abuse of the form cannot starve the operations the business runs on.

Validation mirrors the split: inline field errors for the visitor, schema validation on every API input server-side. The browser is a convenience, never the enforcer.

scoped-intake-gateway.ts
// Pattern: Browser-visible key scoped to one mutation
interface ScopedIntakeGateway {
  readonly publicKey: 'Creates contact inquiries. Lists nothing, edits nothing.';
  readonly internalKey: 'Full SDK access, server-side only, never bundled';
  readonly publicLimit: '10 requests per minute per IP (public key only)';
  readonly fallback: 'mailto draft shown as unconfirmed until sent';
}

Admit what the fallback cannot confirm

When the gateway is unreachable, the site falls back to opening a mail draft — and says plainly that receipt is unconfirmed until the visitor sends it. A successful submit, by contrast, confirms receipt and explains the three-step follow-up.

That is the FirmOps pattern we run ourselves: the website writes records, not emails, and every fallback is honest about what it guarantees.

Have a similar architectural challenge?

Talk with our engineering team about trade-offs, cutovers, and sizing for your system.