Skip to content

About

Go account service, portals and admin console for Sesame, self-hostable on SQLite or Postgres. It is built so it cannot read vaults, and the only vault data it stores is encrypted Sync snapshots when Sync is on.

Topics

Resources

Security policy

Stars

11 stars

Watchers

0 watching

Forks

Repository files navigation

Sesame Go API

This is a vault-blind account service. It publishes product, release, and support metadata. It also provides website accounts, beta eligibility, download metadata, desktop linking, and support requests. It does not process payments or issue offline licences.

The service never accepts a vault password, TOTP seed, recovery detail, import file, encrypted vault, or encryption key. Website-account passwords are the only exception. They are Argon2id-hashed and are not connected to a vault.

Metadata endpoints are read-only. They reject request bodies without parsing or logging them. Account endpoints use small, route-specific JSON schemas and reject unknown or vault-shaped fields. There is no vault endpoint.

A signed-in account can create a one-time desktop-link code. It expires after ten minutes. The installed Windows app redeems it directly with the API and receives an opaque device token. The token links the account service only. It does not upload, identify, or unlock a vault, and it does not enable Sync.

Self-hosting

To run your own server for pairing desktops, read SELF-HOSTING.md. The steps below set up the hosted service stack for development.

From a fresh clone:

npm ci
npm run setup
npm run compose:up

npm run setup writes local secrets to the gitignored deploy/compose/.env. It also records the repository build context. It keeps existing values on later runs. Rotating the admin encryption key makes existing MFA secrets unreadable.

npm run compose:up starts PostgreSQL, applies migrations, and runs the API, the account portal, the administration portal, and a local mail catcher:

Service Address
Account portal http://localhost:4175
Administration portal http://localhost:4174
API http://localhost:8787
Mail catcher http://localhost:8025

Then create the first administrator, which prints a one-time setup link:

npm run admin:bootstrap -- bootstrap you@example.com

Registration defaults to invite. Deployments with administration use the database registration_mode flag. SESAME_REGISTRATION_MODE applies only without administration. Change the flag or issue invitations in the portal.

The public marketing site is not part of this deployment and is not required by it. If you run one, set SESAME_PUBLIC_SITE_ORIGIN to its origin: it may then read published metadata anonymously, with no credentials and no unsafe method.

Everything above runs over HTTP on loopback. Behind TLS, set SESAME_SESSION_SECURE and SESAME_ADMIN_SESSION_SECURE to true in deploy/compose/.env and give each origin its real HTTPS address there too. When a flag is missing, npm run setup sets it to true for an HTTPS origin already in that file. The API refuses to start when an HTTPS origin has its flag off.

Local configuration

Use the self-hosting flow above for local development too. npm run setup must run before Compose because it creates deployment-specific secrets and the repository build context in deploy/compose/.env. That file is for local development only. The complete API configuration template is .env.example, and the production Compose values are documented in DEPLOYMENT.md.

The default API address is 127.0.0.1:8787. Compose also starts a local Mailpit inbox at http://localhost:8025, so verification and recovery mail can be tested without an external provider. It is a development-only capture service.

SESAME_SMTP_ALLOW_INSECURE_LOCAL=true is accepted only with SESAME_ENV=development and no SMTP credentials. Every other SMTP configuration requires STARTTLS.

SESAME_SUPPORT_NOTIFY_EMAIL optionally names the inbox that receives a short notice for each new support request and signed-in follow-up. The notice carries the reference and category, never the subject or message.

invite mode accepts either a row in sesame_beta_eligibility with status eligible, or a live single-use value in sesame_beta_invites. Invite values are SHA-256 hashed before storage. closed mode rejects registration even if a client posts directly to the endpoint. Do not use public until registration has a real public purpose and abuse controls have been reviewed.

Account-action email is disabled unless SMTP is configured. When configured, outbound messages are written to a durable sesame_email_outbox table and delivered by a background worker with bounded exponential backoff. The SMTP transport requires STARTTLS and never logs action URLs. Registration remains possible for an eligible user when mail is temporarily unavailable, and signed downloads remain unavailable until the email is verified. The registration response does not report whether the address already has an account.

Migrations and deployment

Migrations are applied by a separate deployment job, not by running API replicas. Run the migration command before starting the API:

go run ./cmd/migrate

The API process (cmd/api) opens the database without migrating and will exit if the schema is not current. This prevents multiple replicas from racing to apply the same migrations and keeps deployment rollback simple.

The Compose stack runs the migrate job after PostgreSQL is healthy and before the API starts. Production deployments should run the same cmd/migrate job once per release before starting API replicas.

Health endpoints

  • GET /livez: lightweight liveness probe.
  • GET /readyz: readiness probe that pings the database; returns 503 when the database is unreachable.
  • GET /healthz is a deprecated alias for /readyz.

Retention and backups

Scheduled maintenance (hourly) purges:

  • expired security records (verification, recovery, email-change, and desktop-link tokens),
  • delivered email-outbox rows older than seven days,
  • failed email-outbox rows older than seven days.

Encrypted PostgreSQL backups should be taken at least daily and retained with a 30-day active retention plus an annual archive. The database contains Argon2id password hashes, SHA-256 token hashes, and encrypted admin TOTP secrets; it never contains vault passwords, TOTP seeds, recovery notes, or encrypted vault blobs.

Test

npm ci
npm run ci

This repository owns its Node and Go command wrappers, lockfile, build, vet, race-test, vulnerability scan, generated OpenAPI inventory, and CI workflow. npm run openapi:generate regenerates openapi/openapi.json from the Go mux registrations; npm run openapi:check fails if that checked-in inventory is stale or incomplete. A checkout does not require the desktop, public website, or browser extension. PostgreSQL integration cases run when SESAME_TEST_DATABASE_URL is set and otherwise skip; CI supplies a fictional test database. The Compose flow remains the supported local stack entry point because setup generates local secrets before starting services.

The account, admin, and self-host console apps each run TypeScript 7 from @typescript/native in their check script. Their typescript alias supplies the TypeScript 6 compiler API required by Svelte and ESLint. This follows Microsoft's compatibility setup. Each app directory under web owns its installation, release:check, and test scripts and builds independently. The account and admin builds need VITE_SESAME_API_URL, and the account build also needs VITE_SESAME_SITE_ORIGIN.

Card processing remains deliberately outside Sesame. A regulated provider must handle card data; Sesame records only its internal entitlement and receipt references after a verified provider event.

Account boundary and API

The website account owns authentication, account and session management, beta eligibility, signed-download and licence metadata, desktop linking, notification preferences, and support history. It does not identify, receive, sync, or unlock a local vault.

See openapi/openapi.json for the generated endpoint, method, authentication/CSRF, availability, and handler-ownership inventory. See API.md for the detailed closed request and response schemas, recent-authentication rules, email-token lifetimes, desktop-link states, release metadata, and support intake restrictions. Account password changes and password-recovery completion update the password and revoke/replace browser sessions inside one PostgreSQL transaction. Email verification also replaces the browser session and revokes passkeys, desktop connections, and pending desktop-link codes that were created while the account was unverified.

About

Go account service, portals and admin console for Sesame, self-hostable on SQLite or Postgres. It is built so it cannot read vaults, and the only vault data it stores is encrypted Sync snapshots when Sync is on.

Topics

Resources

Security policy

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages