---
title: "Founding engineer proof of work"
description: "Ayush Rai on founding engineering: taking an ambiguous product problem through architecture, implementation, deployment, and the next iteration, with the unfinished parts named."
canonical: "https://www.ayushrai.site/pow/founding-engineer/"
last-updated: "2026-10-19"
---

# Founding engineer proof of work

Source: https://www.ayushrai.site/pow/founding-engineer/
Markdown: https://www.ayushrai.site/pow/founding-engineer.md

Ayush Rai on founding engineering: taking an ambiguous product problem through architecture, implementation, deployment, and the next iteration, with the unfinished parts named.

I build products from zero to one—and take ownership of what happens after launch.

I work across product thinking, full-stack engineering, AI systems, infrastructure, and iteration to turn ambiguous problems into working software.

BUILDLOG is the name of this on-page demonstration. Nothing else on this site uses that name. Northline is a fictional team. Every weight, user, and result inside the workbench is synthetic.

The interactive workbench runs in the browser on the HTML page. This Markdown twin records the case studies, the decision log, and the limits.

## RevenueRoles

Live site and repository. [revenueroles.in](https://revenueroles.in/) · [Repository](https://github.com/ayushrai-hub/RevenueRoles) · [Product note](/products/revenueroles)

### Problem

Technical revenue roles are posted under inconsistent titles across employer boards. Comparing them means reading each description.

### Constraints

The useful output is a listing that still links to the original application. Deduplication cannot drop that link. There is no published user or revenue figure, and this page does not add one.

### Design decisions

Classify from the work described, not the title. Pull Greenhouse, Lever, Ashby, and RemoteOK into one schema. Run discovery on a schedule instead of inside a page view. Keep Postgres, including pgvector, as the store, with row-level security in the migrations.

### Implementation

The repository is a monorepo: a Next.js web app, a Next.js API with Inngest for scheduled discovery and a resume queue, and a Python FastAPI classification worker. The site is on Vercel. The homepage answers. Commit notes record production deploys of job discovery and the jobs API in July 2026.

### Trade-offs

Description classification costs more per posting than a title match. That cost is the product. Deduplication stays conservative so a merged row keeps a working apply link.

### Failure modes

A connector can return nothing when a board changes. A scheduled run can overlap. The public page can be up while classification or a signed-in screen is not.

### What is verified

The homepage is live. Connectors have recorded fixtures and tests. The Python pipeline has passing local tests, as recorded on the product note. I have not re-run that suite for this page.

### What remains unfinished

Sign-in, Google OAuth, profiles, resume parsing, the dashboard, and the admin console are implemented and not all verified in production. Saved jobs, applications, notifications, and error monitoring are not built. Transactional email through Resend is partly wired.

### What I would do next

Verify the signed-in path in production or mark it off, then watch discovery freshness: when a run last succeeded, and which source returned zero. Salary display stays blocked on a check of units and ranges.

## Revenue Intelligence Engine

Demo on synthetic data. [Dashboard](https://revopy.vercel.app/) · [API host](https://cashmaker-two.vercel.app/) · [Repository](https://github.com/ayushrai-hub/REVENUE-INTELLIGENCE-ENGINE) · [Project note](/projects#revenue-intelligence-engine)

### Problem

The engine is a systems demo of an explainable account workflow: define an ICP, score accounts, research the top ones, and hold export behind a person. It is not a live sales tool.

### Constraints

The bundled universe is 42 fictional companies. Enrichment is a mock. There is no outbound mail and no CRM write. A 200 from the dashboard does not turn those rows into customers.

### Design decisions

The score is a transparent 100-point rubric, never a model. Research is a later step, optional, at temperature 0 when a key exists, with a deterministic fallback when it does not. Approval is a state: pending, approved, or rejected. Re-runs get a new run id and upsert companies.

### Implementation

FastAPI and SQLAlchemy on the API. Next.js for the console. The repository README names two Vercel projects: the API at cashmaker-two.vercel.app and the dashboard at revopy.vercel.app, which calls the API through /backend. An empty database reseeds the synthetic fixture unless DATABASE_URL points at Postgres.

### Trade-offs

A mock enricher lets the pipeline finish and teaches nothing about vendor coverage. Keeping the model off the score makes the rank explainable and leaves messy qualitative judgment to the research paragraph.

### Failure modes

A cold start can look like new data when it is the fixture again. Fallback research can be mistaken for a model result if the fallback flag is ignored. Export without checking approval defeats the gate.

### What is verified

Both hosts responded when this page was written. The README and the project record agree on the synthetic universe, the rubric, the approval gate, and the absence of CRM or outbound. I did not treat the dashboard as evidence of revenue.

### What remains unfinished

No Clay, Apollo, or CRM integration. No real leads. Contacts and signals in the bundle are fictional. The site's project record still points its demo field at the API host. The README is the source for the dashboard URL.

### What I would do next

Make the fallback flag obvious in the UI, and make a cold start say that the rows are the seeded fixture. A real source waits until the approval path is the habit.

## AGENYRA

Public site is the waitlist. [agenyra.space](https://agenyra.space/) · [Repository](https://github.com/ayushrai-hub/AGENYRA_product) · [Product note](/products/agenyra)

### Problem

The product aim is to represent AI products as structured data before distributing them. The public site is the explanation and the waitlist, not an open catalog.

### Constraints

The public repository can prove the website and the waitlist. It does not contain the product graph. I do not infer search, ranking, or distribution from the name.

### Design decisions

Stage labels live in one module: building, experimental, exploring, planned, and research. Waitlist rows go to Supabase with row-level security and no policies for anon or authenticated roles. The service role is the only writer. Secrets are server-only.

### Implementation

Next.js 16 App Router, React 19, Tailwind CSS v4, deployed on Vercel. The form is a server action with validation, a honeypot, a minimum fill time, and rate limits. Duplicate emails get the same confirmation. No email is sent on signup. Without Supabase env vars the form says it is temporarily unavailable.

### Trade-offs

Publishing the stage model early makes the ambition visitable and requires every sentence to say which layer is real. Keeping the graph private means this repository cannot be cited as the search implementation.

### Failure modes

A missing env var looks like a product bug if the copy does not say the form is unavailable. A service-role key in a client bundle would bypass the row-level lock. The export route is token-protected and unlinked. An unset token returns 404.

### What is verified

agenyra.space responded. The repository README matches the product note: marketing site, stage model, waitlist storage, and a private graph that is not in this public tree. Structured search is described as an internal experiment, not a public capability.

### What remains unfinished

Distribution beyond the site, analytics, personalization, public APIs, and contextual intelligence are later stages. Intent matching is explicitly not the public product.

### What I would do next

Keep the public copy tied to the stage module. The next engineering proof belongs in a described, reviewable slice of structured profiles, not in a broader claim.

## SpiderWeb

Local product, not a public deployment. [Repository](https://github.com/ayushrai-hub/SpiderWeb) · [Project note](/projects#spiderweb)

### Problem

A LinkedIn data export is a pile of CSVs. SpiderWeb turns that export into people, companies, roles, and conversations you can search, with a graph of your own network.

### Constraints

It only knows what the export contains. Connections.csv has no location or industry. Emails are mostly absent. This build has no sign-in. The README says not to expose it on a public network as-is.

### Design decisions

Detect files by name, then by column signature. Scope every query by workspace id. Delete raw uploads after parse unless KEEP_RAW_UPLOADS is set. Skip advertising and security files. Relationship signals are rules that state why a person surfaced. Imports run in-process unless you opt into a Redis queue.

### Implementation

A pnpm monorepo: Next.js web app, Fastify API, Postgres, Redis, and an optional ingestion worker. Docker Compose brings up the data stores. The API refuses to start when the database is down or the schema is behind. The README documents a Vercel split and a self-host path. The project record on this site says there is no production deployment. I am treating that as the status.

### Trade-offs

No authentication made the local loop smaller and makes a public deploy unsafe. Inline ingestion is simple and will not drain a queue you forgot to start. A queue is available when you set the mode and run the worker.

### Failure modes

Queue mode with no worker leaves imports queued. A partial archive imports what it can and says which files failed. Job-change signals need two imports. A single export is one snapshot.

### What is verified

The README and the project record. The README cites its own test commands, including a large unit and integration run and a Playwright pass. I have not re-run them for this page, so I am not pasting those counts as a fresh result.

### What remains unfinished

Real authentication. The design docs mention an assistant, enrichment, and vector search that this build does not implement. There is no production deployment to point at.

### What I would do next

Replace the seeded local identity with a real session before any hosted demo, and keep the workspace constraint under test. A public URL without that step would be a data leak.

## The Open Framework

Front-end prototype. [Live prototype](https://the-open-frameworks.vercel.app/) · [Repository](https://github.com/ayushrai-hub/the-open-framework) · [Product note](/products/the-open-framework)

### Problem

Civil-society organizations, donors, talent, and institutions lack a shared, consent-aware way to discover one another and to see which claims have been checked.

### Constraints

The repository is a front end. It does not run verification, consent, or a durable institutional backend. Illustrative figures and partner names on the live copy are prototype text.

### Design decisions

Publish the journeys so the idea is visitable, and keep federated discovery, audit logs, and the institutional backend in the design-goal column until a service exists.

### Implementation

Vite, React, TypeScript, Tailwind, shadcn/ui, React Router, and TanStack Query, deployed on Vercel. Sign-in writes a mock user to localStorage. The product log notes that most early commits are attributed to the Lovable bot. Later commits under ayushrai-hub remove that branding and record the Vercel setup. I am not treating the prototype as a system I founded as national infrastructure.

### Trade-offs

A wide clickable prototype makes unfinished portals look more real than they are. That is the risk of showing the concept before the backend.

### Failure modes

A reader can mistake mock sign-in and illustrative scale for a running registry. The copy has to keep saying prototype.

### What is verified

The public site responded. The repository matches the product note: client routes, role screens, and a mock session.

### What remains unfinished

Verification, consent records, governance, and any backend that could support them.

### What I would do next

Cut the prototype's implied operations language, and specify the thinnest verification step before adding another portal screen.

## MedVoice

Repository, no public demo. [Repository](https://github.com/ayushrai-hub/MedVoiceERP) · [Product note](/products/medvoice)

### Problem

A pharmaceutical wholesaler bills through a handoff from the person picking stock to the person typing the invoice. Look-alike medicines, pack sizes, and tax make that handoff expensive.

### Constraints

There is no public demo URL. The API still defaults to an in-memory demo catalog. Real catalog import, production speech, the Android app, and live ERP sync are not complete.

### Design decisions

Speech proposes a line. Deterministic rules decide identity, GST, and posting. Ambiguous matches stay unconfirmed. Invoice posting is idempotent. An ERP failure is not a successful sale. Money is integer paise.

### Implementation

A NestJS modular monolith, a Next.js admin, and a Kotlin Android scaffold. Postgres is the intended store. Docker Compose prepares Postgres and Redis. Speech sits behind an adapter: mock by default, Deepgram only with a key. ERP adapters that exist are mock and CSV.

### Trade-offs

Refusing a silent match slows the picker on purpose. A wrong strength is more expensive than an extra confirmation. Coexisting with an existing ERP is slower than pretending to replace it.

### Failure modes

Mock speech says nothing about a noisy warehouse. An in-memory catalog disappears on restart. A model that writes tax or identity would be a product bug, not a feature.

### What is verified

The product note, grounded in the repository: matching, order state, confirmation, deterministic GST on the voice-to-invoice path, and in-memory idempotent invoicing. I have not run a warehouse pilot.

### What remains unfinished

Durable database wiring is partial. Multi-tenant roles are started. Marg, Busy, and Tally are specified, not live. Stock reservation, invoice PDF, and a production rollout are planned.

### What I would do next

Replace the in-memory catalog with Postgres for one real export, and keep the confirmation rule. Speech credentials come after the ledger is durable.

## Decision log

### Monolith versus microservices (from the code)

A small number of processes, split where the runtime or the schedule is actually different. The worker exists because classification or ingestion is not the web request.

Revisit when: Independent teams need independent release cadence, or one workload has a scaling shape the others do not.

### Synchronous versus asynchronous processing (from the code)

Wait when the result is small and the user is blocked on it. Move discovery, import, and research off the request when they are slow, retryable, or scheduled.

Revisit when: A 'fast' step starts timing out, or a background step is so reliable and small that the queue is ceremony.

### Relational database versus specialized storage (from the code)

Postgres where the product is records and relationships. pgvector sits beside the rows in RevenueRoles. It is not a second source of truth.

Revisit when: The query shape is mostly unstructured search, or the working set no longer fits one relational model.

### Build versus buy (illustrative)

Build the ranking, classification, or representation that is the product. Buy or defer the commodity, and keep it behind an adapter.

Revisit when: Real records need the vendor's data, and you can name the failure you will accept when the vendor is down.

### Managed service versus self-hosting (from the code)

Managed hosting for public web apps. Local or self-hosted data when the product is a private export, as with SpiderWeb.

Revisit when: Cost, data residency, or a long-running worker no longer fit the managed defaults.

### Real-time updates versus scheduled processing (from the code)

Schedule or import when the source is a batch and the decision is not sub-minute. Live updates need a source that can push and a user who acts on the push.

Revisit when: The user acts inside the same minute the source changes, and you can see the missed updates.

### AI inference versus deterministic logic (from the code)

Rules own the score, the tax, and the identity decision. A model may draft language or transcribe speech, and the product still completes when the model is absent or wrong.

Revisit when: The language task is the product, you can evaluate it, and a wrong answer has a bounded cost.

## Principles

- **Ship the smallest useful system.** A useful system finishes the workflow. A demo that cannot record the decision is smaller and unfinished.
- **Prefer explicit contracts.** Column names, weight sums, and API errors should be visible. Hidden defaults become the next outage.
- **Keep architecture proportional.** Add a process when the runtime, the language, or the schedule is different. Not because a diagram has boxes left.
- **Make failure observable.** A stuck worker, a rejected row, and a missing env var need a signal that is not a user email.
- **Protect data and permissions early.** Row-level scope and secret handling are cheaper on the first table than on the fifth integration.
- **Test the workflow people use.** Pin the rubric and one bad upload. Leave the rest until a failure teaches you.
- **Measure before optimizing.** A timeout you have seen is a queue. A timeout you imagine is a guess.
- **Automate a workflow you understand.** Schedule the job after the manual run is boring and the failure mode is known.
- **Use a model when it beats a rule.** Language in, language out, with a fallback. Scores, tax, and identity stay on rules unless you can evaluate the alternative.
- **Treat deployment as engineering.** Migrations, env vars, smoke checks, and rollback are part of the change, not an ops favor.
- **Make the trade-off explicit.** Write what you deferred and what evidence would bring it back.
- **Say what is unfinished.** A live URL proves the host answered. It does not prove every screen behind it.

## AI placement

A founding engineer decides where a model belongs. On the Revenue Intelligence Engine the score stays a rubric and the model, when a key exists, writes research text with a fallback. On MedVoice, speech is an input and GST, identity, and posting stay on rules. AGENYRA's public site does not call a model. MailU, a local mailbox tool, is the place I have put retrieval and a local model over one person's mail. It is not a multi-tenant product.

Contract evaluation work at FoCDoT and, later, through Outlier is RLHF-shaped review of model output. The engagements limit how much of that I can publish. I am not citing an Adaptive RAG system on this page. This site does not publish one as a shipped implementation of mine.

_Unverified award metrics are omitted. Wording matches the public site._
