Architecture

What Archer runs on, and what leaves it

Written for the person who has to approve a vendor before a contractor can put a solicitation into it. Every dependency below is one the code actually calls — this page is generated from the system, not from an intention.

The short version

Archer is a multi-tenant web application. A contractor uploads a solicitation, Archer reads it, prices it against that company’s own model, and produces the deliverables the bid needs. It runs on Vercel, stores everything in Supabase, and sends the solicitation to Anthropic’s API to be read.

The trust boundary is the org. Every piece of bid data belongs to exactly one, and the section on tenancy below says precisely what enforces that — including the part that is application code rather than database policy, because that distinction is the first thing a security review asks about and the answer should not be buried.

External dependencies

Four services, plus two that every page load touches without holding any bid data. Nothing else is called at runtime.

ServiceWhat it doesWhat reaches itRequired
Anthropic (Claude API)Reads the solicitation and extracts sites, areas, square footage, tasks, wage rules and dates.The solicitation itself — the PDF, or its full extracted text. This is the largest movement of customer data in the system.No. Without a key, Archer falls back to a keyword pre-scan and says so on the bid.
Supabase — PostgresEvery bid, requirement version, priced model, scenario, pricing model and company profile.All of it. Bid data does not live anywhere else.Yes, in the hosted product.
Supabase — StorageKeeps the uploaded solicitation so a bid can be re-read later.The original file, in a private bucket. Deleting a bid deletes the file.Yes.
Supabase Auth + GoogleThe only way to sign in. Archer never sees or stores a password.Nothing of yours. Google returns an email, a name and an avatar URL.Yes.
VercelHosting, TLS and the edge network.Requests in transit. No bid data at rest.Yes.
Google Fonts, Google avatar CDNServes the typeface and the profile picture shown in the app bar.The visitor's IP and user agent, on every page load. No bid data.No, but currently unavoidable without a self-hosting change.
Market-data providers (BLS, USAspending) are read-only public sources and receive no customer data.

One bid, end to end

Each step is a separate package, and the boundary between them is deliberate: the pricing engine performs no I/O at all, which is what makes the arithmetic testable in isolation and keeps a network failure from ever producing a wrong number.

  • Upload. The file is stored, and parsed to text — PDF, Word or Excel. Size-capped per document type.
  • Extract. The text or the PDF goes to Claude, constrained to a schema. If that fails for any reason, a keyword pre-scan runs instead and the bid is flagged as a starting point rather than a reading of the document.
  • Review. A person corrects the requirements. Nothing is priced from an extraction nobody has looked at.
  • Price. The engine turns requirements plus that company’s pricing model into hours, cost, and a price. Pure arithmetic, no I/O.
  • Deliver. Excel with live formulas, a PDF summary, a technical proposal, or the customer’s own bid form filled in.

How one company’s pricing is kept from another’s

This is the question that matters most, so here is the unvarnished answer. Archer reaches its own database with a service-role credential, which bypasses Postgres’s row-level security. That means database policies are not the thing separating one company’s bids from another’s. Application code is.

That code is deliberately small and does one thing: every route resolves the caller’s organization from their signed session, and never from anything in the URL or the request body. There is no org identifier a caller can tamper with, because none is ever read from the request. A bid belonging to another organization answers “not found” rather than “forbidden”, so probing cannot confirm that an id exists.

Storage follows the same shape: objects are filed under the organization’s id, the bucket is private, and files are served only through a signed, expiring URL issued after the same check.

The honest trade-off: a service-role credential is used because the application writes across several tables and object storage in one operation. The cost is that a bug in an API route, rather than a misconfigured database policy, is what would breach the boundary. That is why every route handler is audited individually — and why an unguarded delete handler found in exactly that audit was fixed the same day.

Access

Invite-only. Access is granted by email address before a person has ever signed in, and claimed automatically when they first do. Sign-in is Google only. There are no passwords to steal, and no password reset flow to attack.

What Archer does not have

A vendor page that lists only strengths is not useful to anyone doing this job properly. These are true today.

  • No SOC 2 report and no third-party penetration test. Neither has been started.
  • No SSO beyond Google. No SAML, no SCIM, no directory sync.
  • No customer-managed encryption keys. Data is encrypted at rest and in transit by the platform defaults.
  • No Content-Security-Policy yet. Other security headers are set; a meaningful CSP needs the app's inline styles and third-party font loading moved first, and a policy widened until it passes would prove nothing.
  • No formal data-residency guarantee. Infrastructure is US-based, but it is not contractually pinned.
  • Audit logging covers authentication, not per-record reads.

If one of these is a blocker for your review, say so and we will tell you straight whether it is on the roadmap or not.

Reviewing Archer as a vendor?

Ask for anything this page does not cover. A question we cannot answer is one we would rather know about before you sign, not after.