How this is built
Service Almanac is a one-person company. The founder directs, decides, and merges; AI coding agents implement, test, and review. That only works because the pipeline is stricter than most teams' — machines enforce what a second engineer would normally catch.
This page describes the system as it actually runs. Every claim is backed by code in the repository; anything planned but not built is marked Roadmap. If you find daylight between this page and the product, that is a bug — tell us at hello@servicealmanac.com.
Every change takes the same road
There is one path to production, and it is guarded by machines that do not get tired or make exceptions.
Branch, never main
Every change is a pull request from a branch. GitHub branch protection requires two independent CI checks before anything merges — enforced for administrators too, so there is no side door, including for the founder.
Checks, from zero
A fresh PostgreSQL container, every migration applied from an empty database, a schema-drift check, a blocking dependency vulnerability audit, typecheck, lint, the unit suite, and a production build.
End to end, for real
Cross-tenant isolation tests against real Postgres, then a Playwright suite that signs in through the genuine magic-link flow and drives the product — customer, agreement, visit, invoice — on a production build.
Squash on green, deploy on merge
Green pull requests squash-merge; a push to main deploys to production. Docs-only changes take a fast path; superseded CI runs are canceled instead of queued.
Then prove the deploy took
A post-deploy workflow polls the live origin until it reports the new commit, checks the database answers, probes key pages, and re-registers background jobs — because a deploy that "succeeded" is not the same as a deploy that is serving.
A full CI run also fires every night at 00:30 UTC — deliberately inside the window where the UTC calendar day is ahead of every US timezone, a bug class this project met once, wrote a postmortem for, and now checks for on schedule. The repository is private, so the workflows are not publicly linkable; everything above is quoted from them.
Tested like it matters
The suite runs on every pull request, from an empty database, on a production build.
- Over 2,000 unit test cases across the business logic, including tests that enforce conventions — one walks every source file and fails the build on a hard-coded brand color.
- Integration tests on real Postgres — the multi-tenant isolation invariant (one shop can never read another's data) has its own suite that exercises real queries, not mocks.
- End-to-end on the real product — Playwright signs up through the genuine magic-link email flow and runs the core loop a shop lives in: customer, agreement, visit, invoice, payment.
Watching production
Production is checked by things that do not sleep, and the results are public where a public answer makes sense.
A synthetic customer, twice an hour
A scheduled job creates a disposable tenant in production and drives the three flows that matter — signup, booking, and invoice-to-payment — using the same functions real requests use, then cleans up after itself. A stale result counts as a failure, never as an unknown.
A monitor every hour
Probes seven public surfaces and asserts on their content, checks the database, measures deploy drift (main ahead of production past a grace window), and reads the alert feed.
Severity-routed alerts
Every first-party signal is classified SEV1, 2, or 3. A money path alerts on its first error — no volume threshold — and pages on the monitor’s next run. SEV2 batches hourly, SEV3 goes to a daily digest. The read windows tile the cron cadence so nothing falls between runs.
Structured, redacting logs
One JSON object per line, with key-name redaction for secrets and masking for email addresses built into the logger — not left to call-site discipline.
One id from request to log line to Sentry to job
Every request gets a correlation id — honored from the caller’s x-request-id or trace header, or minted. It rides on every log line, is tagged on any Sentry event the request produces, is echoed back on the response, and follows the request into the background jobs it enqueues.
Sensitive actions leave a durable trail
Sign-ins, email changes, billing changes, exports, deletions, and settings saves each write a tenant-scoped audit row — actor, target, request id, IP — with the metadata passed through the same redaction as logs. The actions that matter, not yet every edit; each shop sees its own activity in settings.
Error tracking and metrics
Sentry on client, server, and edge. Every user-facing feature emits first-party usage events; money paths also emit error events. 90-day retention, reviewed on an internal health dashboard.
Three of those signals are live right now: /api/health (the commit production is serving, and a live database check), /api/health/synthetic (the latest verdict per critical flow), and /api/health/alerts (the severity-classified alert feed).
When things break
Some failures fix themselves. The rest page a human. This section is careful about which is which.
Background jobs re-register on every deploy
The job platform does not sync new cron functions on deploy — a lesson learned when one shipped silently unregistered. The deploy pipeline now performs the registration handshake every time.
Hard bounces suppress themselves
A bounced email writes a suppression record at the send choke point; the address is never mailed again unless a human clears it.
Schedules repair themselves
Weekly and nightly sweeps recreate maintenance visits that a failure or a cancellation left missing. In a healthy shop the sweeps create nothing.
Missed runs are absorbed
Hourly jobs compare against local time with catch-up semantics and per-day dedupe keys: a skipped run is picked up the next hour, and nobody is ever notified twice.
The email circuit breaker recovers itself
After repeated vendor failures it opens, waits out a cooldown, sends one trial call, and closes on success. Retried sends reuse one idempotency key, so a retry can never mail a customer twice.
Risky surfaces have kill switches
One reversible, database-backed flip turns one feature off for every shop while core flows keep working — with an environment-variable break-glass above it for the day the database is the problem. A sweep every 15 minutes can auto-kill an AI surface on an error spike; taking a money surface offline stays a human judgment, on purpose.
Detection without remediation is labeled as such: deploy drift, surface probes, backup failures, and dependency vulnerabilities alert a human rather than acting on their own — on purpose, for now.
Automatic rollbackRoadmap
A failed post-deploy check pages immediately; rolling the deploy back is still a human decision. Wiring the same signal to an automatic rollback is planned.
Independent external monitoringRoadmap
Every monitor above runs downstream of the same CI platform. A third-party uptime check that shares no infrastructure with the thing it watches is documented and pending setup.
Backups that prove themselves
An untested backup is a hope, not a plan — so restore verification is built into the pipeline, and the failure cases are rehearsed.
- The backup pipeline dumps, encrypts, checksums — then restores into a throwaway Postgres and verifies row counts against the manifest. A CI self-test exercises it on every change to backup code, including the negative cases: a wrong passphrase must fail, a tampered artifact must fail its checksum, a non-empty restore target must be refused.
- A written restore runbook covers the platform's point-in-time recovery and the encrypted-artifact path, and keeps a drill log — including the drill that got blocked and what it taught.
Nightly production backupsRoadmap
The nightly run of that pipeline is scheduled and fails loudly right now: it waits on credentials only a human can set, and this page will not pretend otherwise. Until they are set, recovery leans on the database platform’s own point-in-time history.
AI in the product
AI does the typing a shop never has time for. It drafts; a person decides. Always.
Message to job
Paste a voicemail transcript, text, or forwarded email; get a drafted job with the customer matched, the address and phone normalized, and anything doubtful flagged as an issue. The office reviews before it is saved.
Description to quote
Describe the work; get a priced draft anchored on the shop’s own past quotes and actual costs — into a form, not into the customer’s inbox.
Spreadsheet to customer book
Paste a messy spreadsheet; get structured customer and agreement rows with per-row issues, confirmed by a person before anything is written.
Renewal and reminder drafts
Renewal outreach drafted from the agreement, visit, and equipment history; overdue-invoice reminders whose tone scales with how overdue the bill is. Drafts only.
The guardrails
Nothing auto-sends
No AI output reaches a customer without a person sending it. A dedicated test asserts the draft flows import no send path and issue no database writes — if a future change adds one, the build fails.
Structured output, validated twice
Every call demands a strict JSON schema from the model, then re-validates the result with a second schema in code. Bad numbers are clamped, not trusted.
A budget that fails closed
Each shop has a monthly budget of AI calls, spent before the model is called. If the limiter itself is unreachable, the call is blocked — an outage never grants free generations.
Failure degrades, never breaks
A model error falls back to a plain template or an honest "draft it by hand" message. The flow the AI was helping with keeps working; 60-second timeout, bounded retries.
The intake feature is eval-gated
Twenty golden scenarios — garbled texts, a Spanish voicemail, spelled-out phone digits — replay deterministically in CI as a merge gate. Each fixture carries a fingerprint of the prompt, output schema, and model id: change any of them without re-recording and CI fails. A nightly run against the live model catches model drift. (The other AI features have unit tests at the parse layer; golden datasets for them are roadmap.)
AI builds the product
The same honesty applies to how the software gets written. One person plus Claude, inside a loop designed so trust is never the control.
Plan against written docs, build in isolation
Each session plans against the product plan and standing design principles, then works in its own git worktree on its own branch. Written hotspot rules keep parallel sessions off each other’s files; the database schema is a serial resource.
Fresh eyes on every diff
A separate test-writer agent writes the tests in a clean context — and is barred from modifying source to make them pass. An adversarial reviewer agent then checks the diff against the repo’s invariants: tenancy, authorization, migration safety, design rules.
A session cannot end red
A stop-hook runs typecheck, lint, and the full unit suite when a session tries to finish, and blocks it until the tree is green.
Invariants live in machines, not memory
Tenant isolation is enforced by lint rules that ban the raw database client outside a short sanctioned list. Migration files cannot be hand-edited. Destructive commands are denied by permission policy.
Everything leaves a paper trail
Every session ends with a dated handoff and decision record — more than sixty so far. Incidents get postmortems that turn into permanent CI checks: the nightly 00:30 UTC run exists because a timezone bug once turned main red.
The point of all of it: AI-written code gets no discount. It merges through the identical protected pipeline as any code, and nothing merges red.
That is the machinery. The product it exists for is simpler:
Start your free trial