Repository navigation
Bun 1.4.4 for CVE-2026-111497, SECRET_KEY rotation, Dokploy hosting - #21
Merged
Merged
Conversation
An optional select on the workspace form. The answer goes out as heard_from on workspace_created, so signups can be counted per channel once paid ads start. The page only asks when PostHog is configured.
An optional select on the workspace form. The answer goes out as heard_from on workspace_created, so signups can be counted per channel once paid ads start. The page only asks when PostHog is configured.
…ncorporation hints
…140bb Login and onboarding: Google logo, terms line, two hints removed
Revenue vs profit for a SaaS, an open-source TrustMRR alternative with verified profit, AI token cost per user with October 2026 prices, and what Stripe, Polar, Paddle and Lemon Squeezy leave from one sale. Titles follow DataForSEO volumes; competitor and fee facts cite the providers' own pages, checked 2026-10-19.
Headings and sentences no longer open with Wh- words, inanimate subjects and passives name the actor, adverbs and lazy extremes are gone, and the fees post now says Stripe leaves you the most per sale.
The running costs post prices one stack at three sizes with October 2026 plan prices. The alerts post compares hard limits and budget alerts at ten providers from their docs, and says OpenProfit's spike alert reports a day late. Markdown tables now scroll inside their own box, so the wide tables in the alerts and fees posts no longer widen the page on a phone.
The homepage title reads "OpenProfit: Open-source profit tracking for developers", so "profit" stands as its own word again. The footer link to /open says "Profit database" instead of "Open profit", which sent 51 internal links with the brand phrase to the leaderboard. The homepage JSON-LD adds a WebSite node (name OpenProfit, alternate names "Open Profit" and openprofit.dev) and sameAs links to GitHub and npm on the app. /llms.txt lists the docs, integrations, comparisons and blog posts for AI agents.
…ms-full.txt - Integration pages link to the matching blog posts, and the books and public-pages docs link the posts they explain. /open links the TrustMRR comparison. - Nav and footer Docs links go to /docs/connectors instead of the /docs redirect. The footer adds Benchmarks (/data), and its column titles are h2 so pages keep an unbroken heading outline. - Posts use the wordings people search: the Stripe books post names the Stripe Connector by QuickBooks, the tax post names the T2125 and Schedule C, and the token post's price section names Claude and OpenAI API pricing. Post title tags drop the " · OpenProfit" suffix. - Descriptions over 155 characters are trimmed, and the changelog's is longer. Comparison pages show when they were last updated. - JSON-LD: breadcrumbs on docs, integration, comparison and blog pages, FAQPage from an integration page's common questions, TechArticle on docs. - The sitemap gives blog URLs a lastmod. /llms-full.txt joins the markdown of every page /llms.txt lists.
Each page now says which lines OpenProfit reads, how to create the narrowest key, how costs map to products, and what the provider's API leaves out, with common questions and links to the related blog post and docs. Claims come from the connector code and the providers' own docs.
Vercel's FOCUS charges endpoint accepts at most one year per request. The connector asked for the whole 730-day backfill in one call (366 days on the free plan), so first and full syncs could fail. It now requests 365-day chunks and merges the lines. Cloudflare's billable-usage endpoint returns nothing unless the range includes a subscription's billing cycle anchor day. The 3-day reread usually missed it, so regular syncs stored no usage after the first. The connector now reads the anchor from billable-usage/info, starts the request at the last anchor day on or before the range, and drops lines before the range. A 4xx from either call still falls back to billing history.
Vercel's FOCUS charges endpoint accepts at most one year per request. The connector asked for the whole 730-day backfill in one call (366 days on the free plan), so first and full syncs could fail. It now requests 365-day chunks and merges the lines. Cloudflare's billable-usage endpoint returns nothing unless the range includes a subscription's billing cycle anchor day. The 3-day reread usually missed it, so regular syncs stored no usage after the first. The connector now reads the anchor from billable-usage/info, starts the request at the last anchor day on or before the range, and drops lines before the range. A 4xx from either call still falls back to billing history.
- bun.lock replaces pnpm-lock.yaml, migrated with the same versions. Workspaces move to package.json. - Vite runs under `bun --bun`. Scripts run with `bun` instead of tsx. - Nitro builds with the `bun` preset. The Docker image is oven/bun:1.3-alpine and starts `bun .output/server/index.mjs`. - CI installs Bun with oven-sh/setup-bun. The CLI package tests run with `bun test`; the published CLI still targets Node 20. - postinstall relinks node_modules/.bin/intent: @tanstack/devtools-vite ships a stale `intent` bin that Bun links in its place.
- Payment fees are gross minus refunds minus net, so a provider's balance moves by net. Stripe's other charges and lost disputes count as payment fees. - A yearly flat cost's 12 months add up to the yearly amount. - The export summary keeps a group's bank and other entries apart. - The journal export takes POST, since a whole-workspace export closes the month. - With no country set, the tax report is a plain profit and loss, and a USD workspace exports US dates. - Changing the base currency reconverts gross, refunds and payouts, and reopens exported months. - Onboarding asks for the incorporation date. Equipment must be a one-time cost. - The books read each span once. Unquoted Bank of Canada days are held for an hour. - Polar sync drops old-format lines across the whole reread window. - 0012 re-syncs the whole history of Stripe and Paddle connections and of every connection in a CAD workspace. It sets last_synced_at to 1, not null, so the sync skips first-sync sub-unit mapping and analytics.
Conflicts: - CLAUDE.md: main's intro and Books notes, with commands for Bun. - src/routes/index.tsx: main's version, with the WebSite schema. - src/routes/onboarding.tsx: main's trimmed form, plus the books "Incorporated on" date field without a hint. src/lib/app.ts takes main's version: the "heard from" lists landed twice, once from each branch's copy of the same commit. .cta.json names Bun.
The currency section says a reopened month exports in full again, so you delete the earlier import first. The changelog tells self-hosters who override the container command to use bun.
CI runs the checks before publishing the image, then calls the Dokploy deploy webhook. CLIENT_IP_HEADER reads the client's address from a CDN header such as cf-connecting-ip. Docs, privacy and security pages name OVH and Cloudflare in place of Railway.
scripts/rotate-secret-key.ts decrypts connection credentials and the alert channels' Slack and webhook values with OLD_SECRET_KEY and encrypts them with SECRET_KEY, in one transaction. --dry-run rolls back. Values the new key already opens are skipped, so reruns are safe. encrypt and decrypt take an optional key for it.
Bun before 1.4.4 bundles a Brotli decoder with an out-of-bounds write. fetch() decompresses response bodies, and hosted workspaces choose their alert webhook URLs, so a workspace could answer with a crafted body. The image now pins oven/bun:1.4.4-alpine instead of the 1.3 tag, and packageManager pins the same version for CI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Security fixes after Railway's October 21 incident, plus the Books and hosting work that was on this branch.
Security
4b5ef5d). Bun before 1.4.4 bundles a Brotli decoder with an out-of-bounds write (CVE-2026-111497).fetch()decompresses response bodies, and hosted workspaces choose their own alert webhook URLs, so a workspace could answer with a crafted body. The Dockerfile pinsoven/bun:1.4.4-alpineandpackageManagerpinsbun@1.4.4.scripts/rotate-secret-key.ts(3e7b48f). It re-encrypts connection credentials and alert channel secrets fromOLD_SECRET_KEYtoSECRET_KEYin one transaction.--dry-runrolls back, and a rerun skips values already under the new key. Railway held the productionSECRET_KEY, so it needs rotating.Also on this branch
Before merging
github.repository, so it becomesghcr.io/lobbystack/openprofit. Dokploy still pullsghcr.io/morencyr/openprofit:latest.DOKPLOY_DEPLOY_WEBHOOKsecret, so the deploy step fails until someone adds it.morencyr/openprofit.Testing
bun --versionreports 1.4.4, the landing page,/loginand/sitemap.xmlreturn 200, and magic-link sign-in works.