Changelog
Notable changes shipped to BuildCalc API. Mirrors CHANGELOG.md in the repo.
Format: Keep a Changelog. Versioning: Semantic Versioning.
Unreleased
(no changes yet)
0.4.0 — 2026-05-29
Audit-batch release. Closes audit-2/audit-5/audit-7 P0+P1 across security posture, MCP discoverability, and marketing surface drift. Stripe wired to LIVE-mode prices (chain completion); R2 backup pipeline added.
Highlights
-
Added: Browser-security headers middleware (
app/middleware/security_headers.py) — HSTS (2-year max-age + includeSubDomains + preload), CSP (default-src 'none'; frame-ancestors 'none'), X-Content-Type-Options, X-Frame-Options DENY, Referrer-Policy, and a Permissions-Policy that disables every powerful browser feature. Production was previously emitting zero browser-security headers. -
Added: IP-throttle on
POST /v1/account/setup-intent(cap = 5 requests / 10 min per IP) — anonymous endpoint that creates real Stripe SetupIntents had no rate limit, Turnstile, or auth. -
Added:
data:productstag exposed to MCP (app/mcp/server.py) — 6 product endpoints + 40,700+ certified SKUs across 9 categories are now discoverable to MCP clients. Tool surface grew 97 → ~105. -
Added:
BodySizeLimitMiddleware(app/middleware/body_size_limit.py) — 1 MB default cap on POST/PUT/PATCH body viaContent-Lengthadvisory. Returns 413 with RFC 7807 envelope +Retry-After: 0+X-Body-Limitheaders. -
Added: R2 backup script (
scripts/backup_to_r2.py) — nightly Postgres dump + upload to Cloudflare R2 with 30-day retention. -
Changed: MCP operation_id naming convention — codes vertical renamed to match the
<vertical>_<verb>pattern already used by costs, benchmarks, and products:list_codes→codes_listget_code→codes_getlist_code_sections→codes_list_sectionsget_code_section→codes_get_sectionget_jurisdiction_applicable_codes→codes_jurisdiction_applicable
REST clients are unaffected (paths and methods unchanged). MCP clients re-discover tools via
tools/listeach session. -
Changed: Stripe wired end-to-end on LIVE-mode prices. Customer Portal + metered overage + webhook signature verification all validated on real cards.
-
Fixed:
DetachedInstanceErroronAPIKeyORM access from the usage-metering middleware — caused ~2 observability events/day. Middleware now uses a plain int stamped onrequest.state.api_key_idinstead of the ORM instance. -
Fixed: 3 Render cron services that had no
startCommandand never produced a single job since creation (buildcalc-api-overage-processorhourly,bcapi-etl-bls-qcewquarterly,buildcalc-api-adoption-scraperquarterly). PATCHed via Render API; first-ever overage job ran 2026-05-29 01:58Z. -
Fixed: CI pipeline was 100% red over the past 20 runs — pgpartman Docker image rename + setuptools < 81 pin for semgrep transitive + mypy advisory pass.
-
Fixed: Marketing surface drift sweep — calculator count (79 → 81), MCP tool count (95+ → ~105), Free tier quota (10k → 1k), status link (BetterStack → Instatus), and v0.4.0 propagated to
llms.txt,agents.md,index.html,pricing.html,signup.html,dashboard.html,404.html. Single source of truth: 81 calculators / 16 categories / 937 code sections / ~105 MCP tools / 40,723 SKUs / 1,000 calls/mo free / 9 product categories.
Operational
- Postmortem: auth-wedge incident
(
docs/postmortems/2026-05-29-auth-wedge.md) documents the brief prod outage during the security-headers middleware rollout and the recovery procedure.
0.3.1 — 2026-05-21
Post-v0.3.0 polish + audit follow-up release. 40+ findings closed across 6 audit batches. Critical fix for stuck docs-site deploy (MDX parse error blocked CF Pages since 2026-05-19). Test suite grew from 484 → 552 passing.
Highlights
- Fixed: docs site deploy unblocked —
benchmarks.mdx:18had(<250k)outside backticks; MDX 3.x parsed it as invalid JSX tag. - Added: live HTTP fetchers replace
NotImplementedErrorstubs for Census C30/BCC/BPS + HUD SOC + EIA RECS (with SSRF allowlist + 200 MB fetch cap). - Added: MCP server exposes
data:costs+data:benchmarkstags (~97 tools total across 4 verticals). - Added:
docs/adr/0017-pyjwt-pysec-2025-183-accepted-risk.md+ ADR-0015 stub +.github/CODEOWNERS. - Added: SDK Python
databenchmarks/module + TypeScriptDataBenchmarksService.ts;docs/openapi.jsonsnapshot refreshed (111 paths, 179 schemas). - Changed: CORS narrowed from
*to explicit allowlist (apex + www + docs); SHA-pinnedpeter-evans/create-pull-request. - Changed: Phase 8 cron orchestrator replaced no-op stub with real per-source fetch + retry + idempotent upsert pipeline.
- Changed: docs overview moved costs + benchmarks from "Coming" to "Live today"; products remains coming (gated LLC).
- Changed: MCP tool count propagated "95+" across marketing landing + pricing + quickstart (was "85+").
- Tests: 552 passing / 69 skipped (up from 484); 13 HTTP
integration tests for
/v1/benchmarks/*, 5 SDK round-trip tests, 6 fetcher unit tests. - Documentation: 4 broken GitHub private-repo links fixed
(ADR-0014, topic_tags, CHANGELOG);
cpiuncURL typo →cpi(2 locations); methodology pages expanded.
See repo CHANGELOG.md for full per-batch detail.
0.3.0 — 2026-05-20
Phase 8 benchmarks vertical SHIPPED. All 15 standardized US residential construction project-type benchmark orchestrators wired with 5-geography output (national + msa_large + msa_medium + msa_small + rural) from federal data (Census C30 + BPS + BCC + BLS OEWS + EIA RECS + HUD SOC). 137 unit tests passing.
Auto-generated Python + TypeScript SDKs also live in sdks/ directory
(publishing to PyPI + npm deferred until NF Nation LLC formation).
Phase 7 products vertical paused on LLC formation (USCO DMCA safe-harbor needed for ICC-ES integration).
Added (Phase 8 sub-dels 3 + 4a + 4b + 5)
- All remaining 14 project-type compute orchestrators: kitchen+bath
remodels (4 types), exterior envelope (roof/siding/window/painting),
interior systems (flooring/HVAC via EIA RECS/electrical panel), and
additions (deck/garage/basement). Shared
_compute_remodel_or_replacement()helper applies the standard 5-geography pattern with hand-set labor_pct/materials_pct splits per project type. - 98 parametrized unit tests (7 dimensions × 14 project types).
- Total Phase 8 tests: 137/137 passing.
Added (Phase 8 sub-del 1)
- Benchmarks vertical — infrastructure shipped. All 15 project
types live in
/v1/benchmarks/listwithstatus="coming_soon"until per-project sub-dels populate data. 4 endpoint skeletons, 2-table schema with GIN index on trade_dependencies, 3 seed JSONs (methodology + scope_norms + msa_tiers; first methodology snapshot versioned for audit reproducibility), ETL framework with 3 core functions, ADR-0016 published, methodology page placeholder live. 4-level confidence taxonomy (measured / derived / derived_industry_method / interpolated) matches Phase 6 spirit.
Added
- Auto-generated SDKs — Python (
buildcalcapi) and TypeScript (@buildcalcapi/sdk) clients live undersdks/{python,typescript}/of the repo. Generated from the committeddocs/openapi.jsonsnapshot via openapi-python-client + openapi-typescript-codegen. Cover all 107 endpoints across the live verticals (codes, calculators, costs). - Auto-regen GitHub Action — opens a PR with refreshed SDKs every
time
docs/openapi.jsonchanges on main.
Deferred
- PyPI + npm package publishing — held until NF Nation LLC is formed and owns the packages on the public registries. Until then SDKs install from source.
0.2.0 — 2026-05-19
Phase 6 costs vertical SHIPPED. Full federal-data labor + permits + materials coverage with 4-level confidence taxonomy.
Added
- Costs vertical — county + ZIP labor paths live. Sub-deliverable 4
closes the labor endpoint with two new geographic paths. See
Costs vertical for curl + response examples and
Methodology for the formula + the 7
known limitations.
GET /v1/costs/labor?trade=&county={FIPS}— OEWS x QCEW geographic-scaled hourly wage estimate. Returnsconfidencefrom the 4-level taxonomy plusconfidence_reason+methodology+inputs.*+paired_trades+all_trades_share_ratio+degenerate_msa+systematic_error_pct_range+bid_markup_factor_range+limitations_note+wage_vs_bid_note+sources+see_also. Full fallback chain: 5-digit NAICS county -> state-level -> parent NAICS 238 -> OEWS MSA direct.GET /v1/costs/labor?trade=&zip={ZIP}— ZIP resolves to dominant county via HUDzip_county_crosswalk(maxres_ratio), then treated as the county path. Response surfacesresolved_county_fips+resolved_msa_code.GET /v1/costs/sources/qcew?area=&naics=— raw QCEW escape hatch.
- Costs vertical — permits endpoint live. Census Building Permits
Survey for ~3,100 US counties + ~930 CBSAs:
GET /v1/costs/permits?jurisdiction=US-XX-NNNNNorUS-MSA-NNNNN— 4 structure-type breakouts (1u / 2u / 3-4u / 5+u) for buildings, units, and valuation.GET /v1/costs/sources/permits/{jurisdiction_code}— raw escape hatch.
- Methodology page at /docs/methodology/costs documents the OEWS x QCEW formula, 4-level confidence taxonomy, full fallback chain, and 7 known limitations (occupational composition, NAICS suppression bias, trade-pair coupling, dominant-county degeneracy, wage-vs-bid distinction, time-series misalignment, geographic completeness over precision).
- 2 new Render crons for Phase 6 costs:
bcapi-etl-bls-qcew(quarterly) populatescost_labor_qcew+cost_labor_qcew_coveragefrom the BLS QCEW single-file CSV.bcapi-etl-census-bps(monthly) populatescost_permits_bpsfrom Census BPS county + CBSA monthly files.
- openpyxl 3.1.* runtime dependency — required by the BLS OEWS XLSX parser. Adds ~1MB; no transitive vulnerabilities at pinning.
- Costs vertical — labor endpoint (MSA path) live. BLS OEWS hourly
wages for 11 construction trades across ~390 US MSAs. See the
Costs vertical docs for full curl + response examples.
GET /v1/costs/labor?trade=&msa=— median + p25 + p75 hourly wage plus employment count for one (trade x MSA) cell. Returnsconfidence: "measured"(direct OEWS, no scaling).GET /v1/costs/sources/oews?msa=&soc=— raw escape hatch returning integer-cents wages for one (MSA, SOC) cell.
- Annual Render cron
bcapi-etl-bls-oewsrunsapp/etl/bls_oews.pyon April 3 at 14:00 UTC after BLS's early-April release. Better Stack heartbeat with 7-day grace. Year-fallback triescurrent_year - 1first. - Costs vertical — materials endpoint (PPI for 15 categories) live.
Three new endpoints under
/v1/costs/*. See the Costs vertical docs for full curl + response examples.GET /v1/costs/list— dynamic per-vertical status (live/coming_soon) based on DB presence checks.GET /v1/costs/materials?category=&period=— BLS Producer Price Index value + 12-month history for 15 construction categories. Multi-series categories (flooring / doors-windows / site) get equal-weight averaging.GET /v1/costs/sources/ppi/{series_id}— raw escape hatch (24 trailing months of one BLS series).
- Monthly Render cron
bcapi-etl-bls-ppirunsapp/etl/bls_ppi.pyon day 16 at 14:00 UTC, after BLS's second-Thursday release. Better Stack heartbeat alerts on missed runs. - HUD USPS ZIP-CBSA crosswalk bootstrap (47k rows) prepping for the county / MSA labor and permits endpoints in subsequent sub-deliverables.
- Codes vertical FTS integration tests +
@pytest.mark.integrationmarker for the whole DB-touching subset of the test suite. Defaultpytest tests/is now clean (325 passed / 48 skipped / 0 failed). - RequestIdMiddleware unit tests (6 new tests, 0 DB needed).
- Public status page at buildcalc-api.betteruptime.com — Better Stack Uptime free tier monitors api / docs / landing + a heartbeat for the hourly overage cron.
- Sitemap at
docs.buildcalcapi.dev/sitemap.xml+ crawl-permissiverobots.txt(was stillDisallow: /from staging hardening). - Custom 404 page on the marketing site with dark theme and next-step CTAs. CF Pages now returns HTTP 404 for unknown URLs.
metadataBase+ root title template on the docs site — OG image refs are now absolute, social previews (Twitter / LinkedIn / Discord) no longer break./v1/openapi.jsondocumented in the Quickstart with a note about the auth-gated schema and intentionally-disabled Swagger UI / ReDoc.- Account-management endpoints (
/v1/account/{usage,api-keys}) now have full curl + sample-response docs — see Authentication → Account management. - NEC 2026 dual-edition seed (107 sections) —
calc_links.pymaps the Article 220 → 120 renumber.code_sectionstotal: 937. - IRC stairs calculators (
/v1/calc/stairs/*) accept optionalirc_edition: "2021" | "2024"and return the citation in the requested edition's numbering.
Changed
- ICC adoption scraper failures (URL break or 0 rows from the PDF) are now FATAL — the cron exits non-zero so a silent ICC outage no longer hides behind a green Render run.
0.1.0 — 2026-05-15
Initial production release. Public launch.
Added
- 79 calculators across 16 categories (concrete, lumber, roofing, drywall, paint, flooring, HVAC, insulation, masonry, electrical, plumbing, doors-windows, gutters, stairs, site, misc). Every formula cites a US code section or manufacturer spec sheet.
- Codes vertical — 830 hand-curated sections across IRC 2021/2024, IBC 2024, NEC 2023, IECC 2024, IPC 2024 + per-state adoption matrix for 49 states (codecheck.com NEC/IRC + ICC Master Chart Jan 2024 for IBC/IECC/IPC). See the Codes vertical docs.
- MCP server at
https://api.buildcalcapi.dev/mcpexposing all calculator + codes endpoints as auto-generated MCP tools (Streamable HTTP transport, MCP spec 2025-03-26). See the MCP integration docs. - Stripe metered billing — 4 tiers (Free 1k/mo · Starter $49 25k · Growth $249 250k · Enterprise custom from $1500). Hourly overage processor cron pushes usage records.
- Programmatic signup at
POST /v1/account/signup— supports both human flow (Cloudflare Turnstile + Stripe SetupIntent) and AI-agent flow (Stripe payment method on file, no challenge). See Authentication. - Mini-dashboard at buildcalcapi.dev/dashboard — self-service usage + key management + Stripe portal.
- RFC 7807 problem+json error responses +
Idempotency-Keysupport per IETF draft on mutating endpoints. See Errors. - Legal: Terms of Service (Common Paper CSA v2.1 + custom Cover Page) and Privacy Policy (hand-written, CCPA + multi-state).
- GlitchTip error tracking (Cloud free tier, replaced Sentry 2026-05-31).
Not yet shipped
These verticals were originally scoped for v0.1.0 but are deferred to later milestones:
- Costs vertical — BLS PPI/OEWS + HUD + Census derived indices.
- Products vertical — ~6k SKUs across 10 categories with manufacturer spec attributes.
- Benchmarks vertical — typical timelines + cost ranges across 15 project types.
- Auto-generated SDKs (Python + TypeScript) —
/v1/openapi.jsonis available auth-gated for SDK-generator tooling in the meantime.