ESPP Tax U.S. federal characterization for ESPP sales.
v0.2.8

Latest changes

v0.2.8 2026-10-03

  • Add a review agent so catalog facts stay aligned with the hub.

v0.2.7 2026-09-27

  • Render Architecture diagrams as charts instead of Mermaid source.

v0.2.6 2026-09-27

  • Show a restored calculator report on the App tab instead of hiding it.
  • Add an in-browser iOS/Android calculator simulation and remove the project ship-to-main agent.

v0.2.5 2026-09-27

  • Keep calculator drafts across pages and label architecture assets on the arrows.

v0.2.4 2026-09-27

  • Add an Architecture page next to Vision with logical and physical production diagrams.

v0.2.3 2026-09-27

  • Add a header Calculator home link and let users close release notes without leaving the page.

v0.2.2 2026-09-27

  • Add a header Vision page so users can read the product contract without leaving the app.

v0.2.1 2026-09-27

  • Show the shipped release version in the header and bump it automatically on every merge to main.
  • Add a washed office photo behind the calculator and describe the UI in this app’s own tokens only.
  • Give the calculator a custom look and keep living docs current.
  • fix: update TemplateResponse calls for Starlette 1.0+
  • fix: improve Vercel config for logging and build-time import check
  • fix: make espp_tax importable on Vercel serverless
  • ci: add GitHub Actions workflow to run pytest
  • Add script to publish Vercel-ready code to ESPP_TAX_VERCEL repo
  • Add Vercel deployment configuration for FastAPI web UI
  • Add ESPP Tax workspace skills
  • Prevent scroll from changing number inputs and clarify sale price quick-picks.
  • Add FastAPI + Jinja2 + HTMX web UI for ESPP tax calculator.
  • Add real-world tax inputs and dollar estimates for ESPP sales.
  • Initial ESPP_TAX scaffold for ESPP tax calculations.
Educational only · not tax advice

How it is built

Architecture

Two views of the same production system. Logical is responsibility. Physical is where those responsibilities run. A request carries its own inputs and ends with the response — there is no login and no database.

Living design document last updated 2026-09-27.

Read the full document on GitHub

How to read the diagrams

Start on the left and follow the arrows. The person never talks to the tax engine directly in the browser; pages talk to routes, and only the form path asks espp_tax for characterization. Python callers skip the pages and import the engine. Hosting details stay on the physical diagram so the logical one does not name Vercel or GitHub.

  • Logical: what each layer may do. Presentation never decides qualifying versus disqualifying.
  • Physical: one Vercel project plus GitHub for source and deploy. CI is not on the request path.

Logical

The calculator, App, Vision, and Architecture pages share one app shell. Forms sit between HTTP and the domain: they parse what someone typed and ask the library for characterization and a simplified dollar estimate. A Python caller can skip the browser entirely.

  • Pages: Calculator form (sessionStorage draft in the tab), App simulation (iOS/Android chrome around the same form), Vision summary, Architecture diagrams, and the header release chip
  • Application: Route HTTP, parse the form, build the report dict, load living docs and `version.json`
  • Engine: The only place characterization and tax-dollar math may run

Physical

Production is one Vercel project. HTML comes from a Python serverless function (web.app:app). CSS, JS, and images ride the Static CDN. Fonts, HTMX, and Mermaid come from public CDNs. Those names sit on the arrows, the same way HTML does. GitHub Actions tests and tags releases; that pipeline is not on the request path.

  • HTML: FastAPI + Jinja2 on a Vercel Python serverless function (`web.app:app`)
  • Static CDN: CSS, JS, images, and `version.json` from `public/static/`
  • Public CDNs: Google Fonts, HTMX, and Mermaid load in the browser; they are not on the tax path
  • Tax engine: In-process `src/espp_tax` — no separate service
  • Identity / data store: None
  • CI / release: GitHub Actions on `main`; Vercel deploys the resulting commits

What this omits on purpose

There is no user store, no session, and no separate tax microservice. The engine runs in-process with the function that rendered the page. Product intent — who this is for, and what it must not claim — lives on the Vision page, not here.