Built to survive your security review

A tool that changes production has to answer harder questions than one that watches it. This page is the answers — what has to be true before a single byte changes on your site, and what limits the blast radius when something goes wrong anywhere in the chain.

Defense in depth

Three independent verifiers, each checking the signature at the edge

The widget

In your users’ browsers, before a DOM patch touches the page.

The module runtime

Before a replacement module runs, with per-module checksums too.

The server tier

The sidecar you host, or the PHP library and WordPress plugin themselves where a host cannot run one. Each fails closed.

Want the exact scopes we request?

Every OAuth scope, every token we mint, and everything we deliberately never ask for — laid out per integration.

Permissions & data access →

Nothing applies unsigned

Every fix — front-end, server-side, or code — is signed with your workspace's own key. Verification happens where the fix applies, in software you run: the widget in your users' browsers, the module runtime, and the sidecar behind your backend (or, on a host without one, the PHP library or the WordPress plugin inside your app, which also re-checks every fix kept on the site each time it is used) all check the signature against your workspace's public key before applying anything. Every fix also has a hard expiry, after which your original code runs again.

This is the answer to the post-polyfill.io question every reviewer now asks about third-party scripts: a compromise of the delivery channel is not a compromise of your site, because an unsigned or tampered payload simply never applies.

One part of the widget is not ours to sign. The first time someone adds a screenshot to a report, the widget loads the open-source html2canvas library (version 1.4.1, pinned) from unpkg.com to draw it. Fixes never depend on it. If you would rather no third-party script ever loads on your pages, leave unpkg.com out of your Content Security Policy: reports are then sent without a screenshot.

Keys are per-workspace, and rotation is routine

Each workspace mints its own signing keypair, so a leaked key forges patches for one workspace — never the platform. Admins rotate keys on demand; rotation re-signs all live patches in the same request, so nothing breaks and clients pick up the new key on their next fetch. Private keys, like users' TOTP secrets and Git host tokens, are envelope-encrypted at rest (AES-256-GCM, under a master key kept outside the database).

Patches are constrained data, not code

DOM and server patches are drawn from a fixed vocabulary of operations and validated server-side against hard deny-rules — the client is never the enforcement line, and there is no "run this JavaScript" operation to abuse. The AI never grades its own homework: it proposes ops and nothing else, and your reviewer sets the risk level when they approve, because whether a change is routine depends on your product, not on which operation it used. Rating a patch elevated requires a second, different approver before it can go live. Module patches are real code by nature — always signed, always checksummed, and the rating your reviewer gives them is recorded against their name.

Approval is a control, not a formality

  • Preview-before-live — approvers see the exact patch applied in isolation before anyone else does.
  • Two-approver escalation — elevated-risk patches require two distinct approvers. An approver is the signed-in account itself, never a name typed into a form, so one person can't approve twice, and API tokens can't approve at all.
  • RBAC — reviewers approve patches; only admins touch keys, sites, members, integrations, billing, and credentials. Enforcement is server-side.
  • Session lifecycle — sign-out-everywhere revocation, email-change re-verification, password policy with rotation, account lockout, and rate limiting on every open endpoint.

Two-factor authentication for every member

The admin who creates an engineering workspace enrolls TOTP two-factor at sign-up. A WordPress workspace's sign-up skips that step, and every approval made from wp-admin still asks for the member's password or code. Every member can turn it on from Account in the dashboard: scan a QR code, confirm a live code, and save a set of one-time recovery codes that are shown once and stored only as digests. Members without it see a reminder until they enroll, and admins see who has it on the Members page. Any account with 2FA gets the same challenge whether it signs in with a password, Google or GitHub. A lost authenticator is reset by spending a recovery code at sign-in or by an admin — never by the admin's own session on their own account — and new recovery codes need a live authenticator code. Enrollments, resets and regenerated codes all land in the audit trail.

The server tier stays inside your walls

Server patches are enforced by a sidecar you host — a single static binary. It connects outbound only to pull signed patches; nothing connects into your network, and the socket between your app and the sidecar never leaves your host. If the sidecar is unreachable, your app runs its normal code, exactly as if Sarcio weren't installed. The Java library uses no agents or bytecode manipulation; the PHP library is built for FPM's process model.

Your source code stays yours

Repository access uses your workspace's own connection, which only admins manage. On GitHub that is the Sarcio GitHub App, installed on the repositories an owner picks: Sarcio keeps no long-lived token for it and mints a short-lived one when it needs to. Pasted bot tokens are stored envelope-encrypted and never shown again. Either way, access is checked by API preflight before any clone — a repo the connection can't see is refused outright. For stricter postures, opt a site into remote builds: a dispatched module build runs inside your own CI/CD, and only the validated artifact — schema-checked, size-capped, checksum-verified server-side, single-acceptance, and audited — returns to Sarcio. Drafting a module patch from a report on such a site reads the files it needs through your Git host's API and never clones the repository. AI-drafted edits are themselves treated as hostile input, with path traversal and repository escape refused by the build pipeline.

Everything leaves a trail

A per-workspace, append-only audit log records sign-ins and lockouts, patch approvals/rejections/retirements, key rotations, site changes, integration changes (including GitHub App suspensions and token re-checks), linked accounts and every use of an acting link, writing-instruction changes, plan and billing changes, and member administration — each with actor, source IP, and timestamp. It exposes no update or delete, and admins export it as CSV or JSON for evidence requests. With Jira connected, every patch also exists as a ticket in your tracker, giving change management a paper trail in the system it already watches. The two-approver gate plus the audit trail map cleanly onto SOC 2-style change-management expectations — including the emergency-change path, which is exactly what Sarcio governs.

Tenant isolation and machine access

  • Workspace isolation — every read and mutation is scoped to the signed-in workspace; cross-tenant IDs resolve to 404, so identifiers can't be probed across the boundary.
  • Scoped API tokens — machine tokens carry explicit scopes over a default-deny surface: endpoints outside the scope map (user administration, key rotation, token management itself) refuse token auth entirely. Plaintext is shown once; only a digest is stored; revocation is immediate.
  • Separate identities for people and automation — the connection Sarcio works as belongs to the workspace, and only admins manage it. Members link their own Git host or Jira accounts only so fix PRs and tickets can name them; no token is kept. Letting Sarcio act as a member is an admin policy, off by default, and nothing done on a Git host ever counts toward an approval in Sarcio. Compare them.
  • Zero-downtime credential rotation — sidecar keys rotate with a bounded overlap window, and revocation kills access immediately. Admins are emailed before a saved Git host or Jira token expires.
  • Data lifecycle — full workspace data export (secrets withheld) and slug-confirmed workspace deletion. Automatic report retention deletes or scrubs old reports once they pass your plan's window (30, 90 or 365 days). The Privacy Policy covers what we keep and who processes it, and the Terms of Service cover your responsibilities for the patches you approve.
  • What the AI sees — to draft a fix, the report text, the element the reporter picked, recent console and network lines and, for server and module fixes, the relevant source files are sent to the AI model. Screenshots are not. None of the captured context is copied into your Git host or tracker.

What we don't claim

Honesty is part of the security model. Sarcio is a governed emergency path, not a replacement for your SDLC — the permanent fix still goes through your review and your pipeline, and the system is built to push you there: expiry reminders, orphan flagging, and auto-retire on merge exist precisely so the temporary path never becomes the permanent one.

Put it in front of your security team.

The fastest way to evaluate Sarcio is a workspace of your own — every control on this page is inspectable from the dashboard.

Create a workspace