AlfredSign in

Security

You're trusting us with access to your cloud. Here's exactly how we treat it.

Alfred is built for solo builders, so this page skips the compliance theater and shows the actual mechanics: what we ask for, how it's stored, who can see what, and how you take it back.

Read-only, least privilege

On your cloud provider: the narrowest read access that powers your dashboard, never write access — the exact policies are published below. The one data-plane touch, your app's own database, is a separate read-only connection you explicitly provide.

Encrypted per secret, per tenant

Every credential is envelope-encrypted with its own key, wrapped by Google Cloud KMS, and cryptographically bound to your workspace. A database dump alone is useless.

You can see every access

Connecting, disconnecting, and each decryption of a stored credential is written to your workspace's audit log — names only, never values. (Logging is best-effort by design: it never blocks your dashboard.)

Revocable from your side

Everything Alfred can see, you granted in your own console — and you can revoke it there any time, without asking us.

Where your credentials live

Credentials you connect never live in environment variables, code, or logs. Each one is sealed with AES-256-GCM under its own single-use data key, and that key is wrapped by Google Cloud KMS— the wrapping key never leaves Google's key-management service. Stealing our database yields ciphertext that cannot be opened without also compromising the KMS.

Each ciphertext is additionally bound to your workspace, provider, and secret name: a sealed value copied to any other row — even by someone with direct database write access — fails authentication and will not decrypt. In production the app refuses to touch the vault at all if the KMS configuration is missing, rather than falling back to anything weaker.

Decryption happens only inside an authenticated request scoped to your workspace, in memory, and each decryption is written to your audit log by secret name — values are never logged, returned to the browser, or shown to us.

One tenant, one boundary

Your workspace id travels only inside a signed session token — it is never accepted from a URL or form field. Every query that touches your workspace's data runs under PostgreSQL row-level security, on a restricted database role the app verifies at boot cannot bypass it (a separate privileged connection exists only for login bootstrap and billing webhooks — never for tenant reads). The API surface is default-deny: routes are closed unless explicitly made public.

When Alfred reads your app's own database, it connects with the read-only connection string you provide; once connected, all reads run in READ ONLY transactions with statement timeouts as a second belt, and every use validates that the target is a real public host — connection strings and webhook URLs pointing at internal networks are rejected outright.

The exact access Alfred asks for

No mystery scopes. These are the minimal read-only definitions to use when you connect a cloud — copy them as-is. If Alfred ever needs more, this page changes first.

AWS

No access keys — connecting AWS creates a read-only role in YOUR account via a pre-filled CloudFormation stack (one click, or one CLI command). This is the stack's entire policy — functions, databases, registries, costs, budgets; no S3 objects, no logs, no secrets — and it's shown to you on the review screen before you create it. Delete the stack to revoke Alfred instantly.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AlfredReadOnly",
    "Effect": "Allow",
    "Action": [
      "lambda:ListFunctions",
      "rds:DescribeDBInstances",
      "ecr:DescribeRepositories",
      "ce:GetCostAndUsage",
      "ce:GetDimensionValues",
      "budgets:ViewBudget"
    ],
    "Resource": "*"
  }]
}

Google Cloud

No tokens — you grant Alfred's reader identity the built-in Viewer role on your project, and Alfred mints its own short-lived access from that grant. One honest caveat: Viewer is Google's broad read role, and on storage buckets without uniform bucket-level access, project viewers can also read object contents — enable uniform bucket-level access if that matters to you.

# You never mint or paste anything. You grant Alfred's reader
# identity the read-only Viewer role on YOUR project — one
# command, shown pre-filled on the connect page:

gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member="serviceAccount:alfred-reader@alfred-499713.iam.gserviceaccount.com" \
  --role="roles/viewer" --condition=None

# Optional — unlocks budget features:
gcloud billing accounts add-iam-policy-binding YOUR_BILLING_ACCOUNT_ID \
  --member="serviceAccount:alfred-reader@alfred-499713.iam.gserviceaccount.com" \
  --role="roles/billing.viewer"

# Revoke any time, from your side:
gcloud projects remove-iam-policy-binding YOUR_PROJECT_ID \
  --member="serviceAccount:alfred-reader@alfred-499713.iam.gserviceaccount.com" \
  --role="roles/viewer"

Azure

A Reader-only service principal scoped to one subscription — Reader carries no dataActions at all.

# Don't paste a token minted as yourself — it carries YOUR
# permissions. Create a Reader-only service principal and
# mint AS it (tokens expire in ~1 hour either way):

az ad sp create-for-rbac --name alfred-readonly \
  --role "Reader" --scopes "/subscriptions/YOUR_SUBSCRIPTION_ID"

# Use env vars so the secret stays out of your shell history:
az login --service-principal -u "$AZ_APP_ID" \
  -p "$AZ_CLIENT_SECRET" --tenant "$AZ_TENANT_ID"
az account get-access-token --resource https://management.azure.com

# Reader has no dataActions: Alfred can see THAT your
# database exists — never what's inside it.

Sign-in, sessions, the basics

Authentication is delegated to WorkOS — Alfred never stores or sees your password. Sessions are short-lived signed tokens checked on every request, with a per-member version so access ends when membership does. Signing out ends the session globally, not just in your browser.

Alfred runs on Google Cloud (Cloud Run + Cloud SQL) in me-west1 (Tel Aviv, Israel), serves only over HTTPS, and backs up daily. Roles are enforced server-side: viewers cannot mutate anything, and every credential change is admin-gated and audited.

Who runs this: Alfred is built and operated by a solo founder — that's a trade-off you deserve to know about, and it's also why everything above is designed to fail closed rather than lean on a security team. If Alfred is breached in a way that touches your workspace, you hear it from us within 72 hours, with specifics. Good-faith security research on your own workspace is welcome — we won't lawyer up over a responsible report.

No keys at all — live for GCP and AWS

As of 2026-08-24, connecting GCP or AWS stores zero credentials: you approve a read-only grant in your own console (the command and stack above), and Alfred mints short-lived access on demand — nothing long-lived for anyone to steal, and revocation is a button in yourconsole. Azure still uses a short-lived pasted token (~1h) until its grant flow ships. This paragraph said "designed, not shipped" yesterday — updated the day it changed, as promised.