Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
408 commits
Select commit Hold shift + click to select a range
78afc0b
kitchens: fix auto-share count + add Resync safety valve + fan-out lo…
thebigjoe1 Aug 23, 2026
fa153b1
kitchens: root-cause fix — /sync/push was skipping auto-share fanout
thebigjoe1 Aug 23, 2026
c759142
kitchens: drop Resync button + endpoint — off/on already re-fans-out
thebigjoe1 Aug 23, 2026
0d3b83d
recipes: wide-screen polish (search cap, ultrawide density, more skel…
thebigjoe1 Aug 23, 2026
95d61eb
recipes: link ingredients to steps for Cook Mode (issue #40)
thebigjoe1 Aug 23, 2026
8d230b1
recipes: close always pushes to /recipes (revert smart back-nav)
thebigjoe1 Aug 23, 2026
c9fdc31
recipes: step-photo close + collapsible step-links + cook-mode ingred…
thebigjoe1 Aug 23, 2026
75e9b15
step-photo modal: drop the X, keep just Cancel + Done to match editor…
thebigjoe1 Aug 23, 2026
17f6c8f
step-photo modal: restore header X (matches dominant CT modal pattern)
thebigjoe1 Aug 23, 2026
ef14ed8
recipes: revert ultrawide density + search cap; step-done marks ingre…
thebigjoe1 Aug 23, 2026
6c0e0dc
tandoor: preserve step->ingredient adjacency on import (issue #40 bonus)
thebigjoe1 Aug 23, 2026
ec76c98
auth: claim all single-user data on first account, purge it on accoun…
thebigjoe1 Aug 23, 2026
70e3f4a
auth: honor X-Forwarded-Proto for reset / invite links + test-email o…
clifmo Aug 24, 2026
f50d11d
server: honor HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars via undici…
thebigjoe1 Aug 25, 2026
51c93ca
fix(import): send X-CSRF-Token on raw-fetch import endpoints (#43)
thebigjoe1 Aug 25, 2026
5a7506d
chore(dev): bump to v1.2.0-dev.01
thebigjoe1 Aug 25, 2026
3876ac2
settings: defer rail-pill measurement one frame so admin-block clicks…
thebigjoe1 Aug 25, 2026
0b41063
usda: swap 1292/1268 → 1292/1293 for correct total-monounsaturated + …
thebigjoe1 Aug 25, 2026
84465f6
fix(native): fall back to server for shared recipes on getRecipe loca…
thebigjoe1 Aug 27, 2026
ab442cc
fix(native): normalize img_url → imgUrl on getRecipe server fallback
thebigjoe1 Aug 27, 2026
19bf0fc
server(proxy-agent): friendlier error when HTTP_PROXY / HTTPS_PROXY i…
thebigjoe1 Aug 27, 2026
00d7765
recipe view/editor + cookbook view: widen ultrawide max-width caps
thebigjoe1 Aug 30, 2026
6d07161
cookbook: search + sort for the recipe grid
thebigjoe1 Aug 30, 2026
13532b2
cookbook: real drag-and-drop reorder + settable cover image
thebigjoe1 Aug 30, 2026
2fa1b6f
cookbook: smooth out choppy drag-reorder animation
thebigjoe1 Aug 30, 2026
9e854c6
cookbook: animate the OTHER cards during drag-reorder, not just the d…
thebigjoe1 Aug 30, 2026
b27942b
cookbook: recipe cards carry the same info as the Recipes tab
thebigjoe1 Aug 30, 2026
9e20486
cookbook: drag from anywhere on the card, sliding move/copy toggle
thebigjoe1 Aug 30, 2026
c83c79c
cookbook: match card size to Recipes page, drop the drag-hint icon
thebigjoe1 Aug 30, 2026
24edc09
cookbook: stretch cards to fill their row so they're uniform height
thebigjoe1 Aug 30, 2026
8414c90
chore: cut v1.2.0-dev.03
thebigjoe1 Aug 30, 2026
24192a9
recipe editor: replace native ingredient-name datalist with a keyboar…
thebigjoe1 Sep 2, 2026
798461b
release: v1.2.0 (ingredient-to-step linking + wide-screen desktop pas…
thebigjoe1 Sep 2, 2026
1862b38
Merge main into dev (v1.1.3 catch-up: keep dev's files)
thebigjoe1 Sep 2, 2026
81136bd
Merge main into dev (v1.2.0 catch-up)
thebigjoe1 Sep 2, 2026
21238f1
chore(deps): security bumps caught during v1.2.0 release audit (fast-…
thebigjoe1 Sep 2, 2026
de58103
Merge main into dev (v1.2.0 security-bump catch-up)
thebigjoe1 Sep 2, 2026
1368319
feat(mcp): Model Context Protocol server + personal access tokens
thebigjoe1 Sep 5, 2026
c501668
fix(settings): API Tokens section header showed raw id instead of the…
thebigjoe1 Sep 5, 2026
a0c97e3
federation(push-recipe): Push to NutriTrace flow. RecipeView gets a c…
thebigjoe1 Sep 6, 2026
c44f277
federation(recipes) expose read:recipes API for NT pull
thebigjoe1 Sep 6, 2026
845fc4c
federation(recipes) fix SQLite single-quote for empty-string COALESCE
thebigjoe1 Sep 6, 2026
8abb384
federation(recipes) drop non-existent portion/unit cols from SELECT
thebigjoe1 Sep 6, 2026
e86d24e
federation(recipes) parse qty, skip section headers, absolutize img_url
thebigjoe1 Sep 6, 2026
3352309
fix(pantry): expanded generic card's photo no longer balloons on desktop
thebigjoe1 Sep 9, 2026
fcec504
chore(deps): bump multer (DoS via aborted uploads + 3 more) and nodem…
thebigjoe1 Sep 9, 2026
06bc3da
federation(recipes) fall back to name-match pantry lookup for unlinke…
thebigjoe1 Sep 9, 2026
072d335
federation(recipes) follow generic->variant nutrition inheritance so …
thebigjoe1 Sep 9, 2026
9ac3cc8
federation(recipes) reverse variant->generic walk + temp _debug per i…
thebigjoe1 Sep 10, 2026
edba001
federation(recipes) prefer designated variant over generic's own part…
thebigjoe1 Sep 10, 2026
74b99c3
federation(recipes) derive calories from macros when pantry entry onl…
thebigjoe1 Sep 10, 2026
e9115ca
federation(recipes) strip diagnostic _debug field now that variant + …
thebigjoe1 Sep 10, 2026
40474d8
federation(pantry) add read:pantry scope + GET /api/v1/pantry so NT c…
thebigjoe1 Sep 10, 2026
b4f9fa6
federation(recipes) ship linked pantry row's photo per ingredient so …
thebigjoe1 Sep 10, 2026
ddefb5b
chore(deps): bump root nodemailer (recipient-validation bypass + 3 more)
thebigjoe1 Sep 10, 2026
65db755
federation(pantry) add q/limit/offset to /api/v1/pantry, matching com…
thebigjoe1 Sep 10, 2026
aecd026
settings: fold NutriTrace Federation into Food Sources
thebigjoe1 Sep 10, 2026
8a88f55
pantry: NutriTrace as a fourth search source alongside OFF/USDA
thebigjoe1 Sep 10, 2026
7d5d34c
settings: give NutriTrace its own sub-heading in Food Sources, move a…
thebigjoe1 Sep 10, 2026
0b82fcd
fix(pantry): expiring-soon spotlight mislabels already-expired items
thebigjoe1 Sep 10, 2026
b47b16a
chore(dev): bump to v1.3.0-dev.01
thebigjoe1 Sep 10, 2026
67e40db
fix(recipes): honor kitchen shares on cooks/comments reads, require a…
thebigjoe1 Sep 12, 2026
2eaa8ea
feat(webhooks): outgoing webhooks and general public REST API
thebigjoe1 Sep 12, 2026
9ba4524
fix(security): exclude backup archives from the public uploads directory
thebigjoe1 Sep 13, 2026
bc74c82
Replace issue templates with forms
thebigjoe1 Sep 15, 2026
5054824
Replace issue templates with forms
thebigjoe1 Sep 15, 2026
56b63f4
Uploads: safe extensions and sandboxed serving
thebigjoe1 Sep 15, 2026
3dacd65
Use the smart_toy icon for Trace settings
thebigjoe1 Sep 16, 2026
0f16fe0
Shopping API for sister apps: a shopping token scope to list, add, ch…
thebigjoe1 Sep 17, 2026
37c02b1
Add Claude Fable 5.1 to Trace models
thebigjoe1 Sep 17, 2026
00e9834
fix(shopping): dedupe drag-zone rows by id to stop each_key_duplicate…
thebigjoe1 Sep 17, 2026
72668d2
chore(deps): bump adm-zip 0.6.0 -> 0.6.1 (symlink extraction fix now …
thebigjoe1 Sep 17, 2026
623baf9
fix(combobox): drop same-name suggestions so duplicate pantry names d…
thebigjoe1 Sep 17, 2026
de82d9e
shopping: merge duplicate items in aisle/flat views, offer pantry res…
thebigjoe1 Sep 17, 2026
6c245f6
Trace settings match NutriTrace: env lock banner, save on blur, voice…
thebigjoe1 Sep 17, 2026
db21d2a
Trace settings: show the server's provider and model when AI is env-l…
thebigjoe1 Sep 17, 2026
cd09690
Sync status pill in the sidebar, and one colour rule for sync state
thebigjoe1 Sep 17, 2026
82e5d29
Roadmap: offline PWA editing after the next main release
thebigjoe1 Sep 17, 2026
69474e1
Support: name the iOS fund in the README and in Settings, About
thebigjoe1 Sep 17, 2026
d322b6e
README: the fund covers both developer accounts
thebigjoe1 Sep 17, 2026
4d7d915
README: iOS fund total includes tax and fees
thebigjoe1 Sep 17, 2026
45ccab9
fix(api): pantry writes reach the write router, MCP read tools requir…
thebigjoe1 Sep 17, 2026
0e55e76
fix(webhooks): send CSRF headers from the settings UI, fire meal.cook…
thebigjoe1 Sep 17, 2026
ccbfd27
fix(security): guard a relocated BACKUPS_PATH, check every resolved a…
thebigjoe1 Sep 17, 2026
61677b1
chore(dev): bump to v1.3.0-dev.02
thebigjoe1 Sep 17, 2026
b17acab
README: keep the Apple hardware generic
thebigjoe1 Sep 18, 2026
91f9a48
README: prices live on the Support page, not here
thebigjoe1 Sep 18, 2026
a508763
chore(deps): bump devalue to 5.9.4 (DoS advisory)
thebigjoe1 Sep 19, 2026
a1cbd38
fix(webhooks): fire events for changes that arrive through Android sync
thebigjoe1 Sep 19, 2026
79d85a9
Screenshots from v1.2.0 with demo data
thebigjoe1 Sep 19, 2026
f1a563b
README: same header layout as the other Trace apps, current screensho…
thebigjoe1 Sep 19, 2026
f76653b
shopping: masonry card grid on wide screens so short groups fill the …
thebigjoe1 Sep 19, 2026
229623e
Shopping screenshot with the masonry card grid
thebigjoe1 Sep 19, 2026
859022b
README: badges in two rows, colored like Fathom's, with platform
thebigjoe1 Sep 19, 2026
e80ef11
README: badges in two rows, colored like Fathom's, with platform (#49)
thebigjoe1 Sep 19, 2026
9345987
fix(android) dragging the Trace button or a reorder handle no longer …
thebigjoe1 Sep 19, 2026
8c9584b
fix(android) back button closes an open sheet, dialog or menu before …
thebigjoe1 Sep 19, 2026
7f2ca95
Container listens on 3003, the same as the host port
thebigjoe1 Sep 19, 2026
15fd58c
fix(android) sheets and dialogs stay below the status bar when their …
thebigjoe1 Sep 19, 2026
c7a63de
chore(dev): bump to v1.3.0-dev.03
thebigjoe1 Sep 19, 2026
d074f22
README: the fund line links straight to Ko-fi
thebigjoe1 Sep 20, 2026
d8e6fbc
release: v1.3.0 (MCP, webhooks, public API, NutriTrace federation, sh…
thebigjoe1 Sep 20, 2026
8d30b12
Merge main into dev (v1.3.0 release prep: keep dev's README and shopp…
thebigjoe1 Sep 20, 2026
a8dc195
fonts: serve Inter and the icon font from the instance instead of Google
thebigjoe1 Sep 20, 2026
0ca055e
updates: off until asked, and the server does the checking instead of…
thebigjoe1 Sep 20, 2026
b0cbedd
Roadmap: offline PWA order is NutriTrace, LiftTrace, CookTrace
thebigjoe1 Sep 20, 2026
92f519d
feat(offline) the web app keeps working without a connection
thebigjoe1 Sep 20, 2026
cf13b67
feat(offline) photos taken with no connection travel with the row
thebigjoe1 Sep 20, 2026
6829e7b
fix(offline) diary and pantry photos become files too, not embedded rows
thebigjoe1 Sep 21, 2026
441130d
feat(offline) your profile and its picture work without a connection
thebigjoe1 Sep 21, 2026
9f16c88
chore(release) collect the co-author trailers a release owes its repo…
thebigjoe1 Sep 21, 2026
4ef0d31
fix(offline) remember on disk what a row created offline became
thebigjoe1 Sep 21, 2026
46f3af0
fix(offline) keep the copy this browser holds, and pick up work queue…
thebigjoe1 Sep 21, 2026
ac39d4d
fix(offline) cap the copy this browser keeps, and never let a full da…
thebigjoe1 Sep 21, 2026
b01fe48
fix(offline) an animated picture kept offline keeps every frame
thebigjoe1 Sep 21, 2026
a22dd73
fix(offline) answer a queued write in the shape its route would, so s…
thebigjoe1 Sep 21, 2026
24e370c
fix(offline) bundle the photo helper instead of fetching it when the …
thebigjoe1 Sep 21, 2026
e2ecd01
fix(offline) size a photo kept offline so the server accepts it
thebigjoe1 Sep 21, 2026
40f49a5
fix(offline) never carry a stale copy across a change that already ti…
thebigjoe1 Sep 21, 2026
146af4d
fix(android) keep the Trace button clear of open sheets and dialogs
thebigjoe1 Sep 21, 2026
4475440
Add a Wear OS companion app: the shopping list in an aisle, the cook …
thebigjoe1 Sep 21, 2026
37f6abf
Pair the watch on launch and resume, gate the sync poll, and say why …
thebigjoe1 Sep 21, 2026
e6b0153
Watch: never show the word null, and pick up a cook that was already …
thebigjoe1 Sep 21, 2026
563c623
Watch: log the cook handoff natively, and import the bridge statically
thebigjoe1 Sep 21, 2026
69697de
Watch: the cook above the list, a heading over the steps, and never a…
thebigjoe1 Sep 21, 2026
d27773d
Never let a name that has not caught up stop the cook reaching the watch
thebigjoe1 Sep 21, 2026
5e47e21
One cook at a time, and starting a timer opens it
thebigjoe1 Sep 21, 2026
02686e7
Cook mode follows the recipe on screen, and the page stops leaving li…
thebigjoe1 Sep 21, 2026
725d387
Give the watch the server's recipe id, not this phone's own
thebigjoe1 Sep 21, 2026
26af4a5
Name the crossing serverRecipeId so the wrong id cannot be passed by …
thebigjoe1 Sep 21, 2026
17fa869
Cook more than one thing at once, and see what is on the go from anyw…
thebigjoe1 Sep 21, 2026
2fd6bca
Cook more than one thing at once, and see what is on the go from anyw…
thebigjoe1 Sep 21, 2026
c29c366
Show the cooking strip where it can be seen, and colour the timers as…
thebigjoe1 Sep 21, 2026
236c45f
Restore the plural label the cooking strip needs
thebigjoe1 Sep 21, 2026
6c56579
Make the cooking strip go where it says, and look like the app
thebigjoe1 Sep 21, 2026
ffeb484
One slim cooking bar with a picker, instead of a stack that buries th…
thebigjoe1 Sep 21, 2026
43cf201
Frost the cooking bar so the page reads through it
thebigjoe1 Sep 21, 2026
57298cb
One timer face on the watch, with longer and stop instead of a tap th…
thebigjoe1 Sep 21, 2026
99c1e61
Show the soonest timer on the watch face while it counts
thebigjoe1 Sep 21, 2026
707bd74
kitchens: pick a role when inviting, edit shared cookbooks, hand a ki…
thebigjoe1 Sep 22, 2026
5066133
Wake the watch once for a burst of checks, not once per tap
thebigjoe1 Sep 22, 2026
9c449f1
One arrow on the role picker, and real buttons in the member row
thebigjoe1 Sep 22, 2026
8c61e1d
Share the kitchen clock with the watch, but only during a cook
thebigjoe1 Sep 22, 2026
6365fa6
Say which dish rang, so a buzz is accountable
thebigjoe1 Sep 22, 2026
3c526f2
Make the update banner mean what it says, and Reload work
thebigjoe1 Sep 22, 2026
e972e11
Document the watch apps and today's fixes
thebigjoe1 Sep 22, 2026
a34a7e3
Pick a role the way the app picks anything, and say what each one does
thebigjoe1 Sep 22, 2026
6cf04fd
Say plainly that a Line Cook cannot change anything
thebigjoe1 Sep 22, 2026
00e3768
release: v1.4.0-dev01 (Wear OS, offline mode, kitchen roles), and kee…
thebigjoe1 Sep 22, 2026
7177602
lockfile: version with the app (it was two releases behind)
thebigjoe1 Sep 22, 2026
70f0998
fix(pantry) the stock check can be unticked again, and ticking it set…
herver1971 Sep 23, 2026
9ecbc5c
pantry: restock from the shopping list sets On Hand to 1, like the ca…
thebigjoe1 Sep 23, 2026
2fd792c
Offer the phone's APK, never the watch one beside it
thebigjoe1 Sep 24, 2026
4d09878
server: read PDFs in a child process so the image starts on CPUs the …
thebigjoe1 Sep 25, 2026
d7bf1f9
chore(dev): bump to v1.4.0-dev02
thebigjoe1 Sep 25, 2026
15ac479
Know where a foldable's crease is
thebigjoe1 Sep 25, 2026
0845e51
Dialogs, sheets and Trace keep off the crease
thebigjoe1 Sep 25, 2026
7f24ee8
Menus take the roomier side of a crease, never across it
thebigjoe1 Sep 25, 2026
d9e932c
Settings uses the crease as its divider
thebigjoe1 Sep 25, 2026
46d14f7
A recipe opens like a cookbook when the phone does
thebigjoe1 Sep 25, 2026
344347d
Changelog: foldables use the crease
thebigjoe1 Sep 25, 2026
815802e
Keep the fold helpers identical across the Trace apps
thebigjoe1 Sep 25, 2026
98ac2bd
Settings splits at the crease at any width, and Diagnostics says what…
thebigjoe1 Sep 25, 2026
fae0b02
Recipes are dealt onto the two pages, not across the crease
thebigjoe1 Sep 25, 2026
62693c1
Say which kind of failure the health probe hit, and how long it took
thebigjoe1 Sep 26, 2026
778fcd3
Settings splits on the room it has, not on a desktop-sized viewport
thebigjoe1 Sep 26, 2026
7899ddc
roadmap: recipe revision history and sub-recipes, with the stable-id …
thebigjoe1 Sep 26, 2026
d0febfd
Import onMount in RecipeView, which was crashing every recipe page
thebigjoe1 Sep 26, 2026
83e42ee
A recipe uses the tablet layout on the room it has, not a 960px viewport
thebigjoe1 Sep 26, 2026
e37f8d4
Keep the ingredients column out of the nutrition block when scrolled
thebigjoe1 Sep 26, 2026
171b685
Shopping deals its aisles into columns, and the pantry spotlight show…
thebigjoe1 Sep 26, 2026
389a4e1
A year of cooking fits the width, and a recipe hero fills its column
thebigjoe1 Sep 26, 2026
e370cc7
Size the heatmap in pixels, since fluid tracks collapsed its cells in…
thebigjoe1 Sep 26, 2026
5f3e522
One failed stats call no longer hides the whole cook dashboard
thebigjoe1 Sep 26, 2026
e3bffc0
Manage splits on the room available, rail and grid together
thebigjoe1 Sep 26, 2026
4e8e7fb
The diary toolbar sits under the header instead of cutting into it
thebigjoe1 Sep 26, 2026
b001d1a
Cap the recipe hero and balance the header columns
thebigjoe1 Sep 26, 2026
5401429
Line the recipe columns up with the hinge when the phone is open flat
thebigjoe1 Sep 27, 2026
d1fa6e7
Nutrition and Recompute sit under the ingredients, where the room is
thebigjoe1 Sep 27, 2026
a35509d
Both fold sources return the same shape, pinned by a test
thebigjoe1 Sep 27, 2026
e2f661d
Pantry search folds accents, and All mode looks up your pantry with t…
herver1971 Sep 27, 2026
2c9d8e4
All mode shows a pantry row as yours, and opens it instead of prefill…
thebigjoe1 Sep 27, 2026
8177927
Every search box folds accents, in the app and on the server
thebigjoe1 Sep 27, 2026
b32505d
The search fold is the same file in all four Trace apps
thebigjoe1 Sep 27, 2026
afdd9a7
chore(dev): bump to v1.4.0-dev03
thebigjoe1 Sep 27, 2026
6ecd2d9
test: the accent search test runs on CI's Node, with better-sqlite3
thebigjoe1 Sep 27, 2026
931de6e
Test fold() on the SQLite the server runs, not node:sqlite, which Nod…
thebigjoe1 Sep 27, 2026
091bebf
README: one Wear OS bullet, a foldables line, and NoteTrace in the fa…
thebigjoe1 Sep 27, 2026
8f13b62
The shopping list's Add button fits on a phone
thebigjoe1 Sep 27, 2026
5952a5c
A cookbook cover uploads from Manage, and so does a recipe video (#63)
thebigjoe1 Sep 27, 2026
693218c
Updating a cookbook writes an embedded cover out as a file, as creati…
thebigjoe1 Sep 27, 2026
7c57b0c
chore(l10n): add Spanish translation
weblate Sep 28, 2026
895c997
Updates: reuse an already-downloaded APK instead of fetching it again
thebigjoe1 Sep 29, 2026
dbf0501
Add GitHub Sponsors to FUNDING.yml [skip ci]
thebigjoe1 Sep 29, 2026
c329368
Add GitHub Sponsors to the Support section [skip ci]
thebigjoe1 Sep 29, 2026
e253e29
chore(l10n): update Spanish translation
weblate Sep 29, 2026
10cbaf1
Add a GitHub Sponsors button to Settings > About
thebigjoe1 Sep 29, 2026
86668c7
Add the release notes footer [skip ci]
thebigjoe1 Sep 29, 2026
3a969e2
Name the fund by what it buys: a Mac and an iPhone [skip ci]
thebigjoe1 Sep 29, 2026
a562e33
Settings: a Support page next to About, and the pane lines up with th…
thebigjoe1 Sep 29, 2026
a33ad37
Settings: the section rail keeps its scroll from section to section
thebigjoe1 Sep 29, 2026
af1b442
Security: multer 2.4.0, undici 6.29.0 and 7.30.0, nodemailer 10.0.12
thebigjoe1 Sep 29, 2026
8cecd67
A wrong file type or an oversized upload answers 415 or 413, not 500
thebigjoe1 Sep 29, 2026
4df9efb
Spanish in the language picker
thebigjoe1 Sep 29, 2026
2e390dc
chore(dev): bump to v1.4.0-dev04
thebigjoe1 Sep 29, 2026
6640d21
About links to the TraceApps family instead of listing the apps
thebigjoe1 Sep 29, 2026
49333e2
Issue forms ask you to search open and closed issues first
thebigjoe1 Sep 30, 2026
7336020
chore(l10n): update Spanish translation
weblate Sep 29, 2026
4e94da2
Tag the GitHub Sponsors links with the app and where they sit
thebigjoe1 Oct 1, 2026
3c26fc3
Changelog: 1.4.0
thebigjoe1 Oct 2, 2026
5d2457d
release: v1.4.0 (watch app, offline mode, kitchen roles, Spanish)
thebigjoe1 Oct 2, 2026
aded8ea
Merge main into dev (v1.4.0 release prep: keep dev's files)
thebigjoe1 Oct 2, 2026
024e15b
Security: fast-uri 3.1.8, ip-address 10.7.3, brace-expansion 5.0.12 a…
thebigjoe1 Oct 2, 2026
f95094b
Merge main into dev (v1.4.0 amendment: keep dev's files)
thebigjoe1 Oct 2, 2026
5fdf0da
Docs: image tags are :latest and :dev only
thebigjoe1 Oct 3, 2026
7406c35
OIDC: refuse unverified email matches, read userinfo, callback withou…
thebigjoe1 Oct 3, 2026
90e6a5a
OIDC test: anchors that hold in every Trace app
thebigjoe1 Oct 3, 2026
446d2b1
Share links: real /r/ paths with previews, open without an account, s…
thebigjoe1 Oct 3, 2026
56f6976
Signing in on a plain-HTTP address says what's wrong instead of looping
thebigjoe1 Oct 3, 2026
22ca3e8
Tandoor exports import: unpack the zip inside the zip, pictures stay …
thebigjoe1 Oct 3, 2026
f0726a6
Wait for sign-in state before rendering, env locks after sign-in with…
thebigjoe1 Oct 3, 2026
3997ea5
release: 1.4.1 (Tandoor import, SSO fixes, share links; link previews…
thebigjoe1 Oct 3, 2026
7621ebe
chore(dev): bump to v1.4.1-dev01
thebigjoe1 Oct 3, 2026
d3ea5de
README: federation pulls food data (cook logging isn't wired yet)
thebigjoe1 Oct 4, 2026
a1ee1ec
Imports say what they skipped as duplicates; importing a recipe you a…
thebigjoe1 Oct 4, 2026
e962c30
chore(dev): bump to v1.4.1-dev02
thebigjoe1 Oct 4, 2026
4762c3a
Shared Trace attach menu (Camera or Gallery on phones), subpath fallb…
thebigjoe1 Oct 5, 2026
cef5897
Ask OpenAI-compatible endpoints for one JSON answer (stream: false)
thebigjoe1 Oct 5, 2026
5d3452a
Smart import keeps its AI order; tests for one-JSON-answer requests
thebigjoe1 Oct 5, 2026
3c03e26
Check every address the server fetches for an account: recipe links, …
thebigjoe1 Oct 6, 2026
cbdf72f
Owner means an admin for home-network reach; follow same-host https u…
thebigjoe1 Oct 6, 2026
3190c54
Refuse control characters in fetched addresses; same-server redirects…
thebigjoe1 Oct 6, 2026
3ac5677
security: escape names and links in every email
thebigjoe1 Oct 6, 2026
3c54a22
security: emailed links use PUBLIC_URL or an address an admin uses, n…
thebigjoe1 Oct 6, 2026
555500a
fix: smart cookbooks count and open their recipes, also on Android (#76)
thebigjoe1 Oct 6, 2026
292eed4
security: the recipe share card escapes its content, isn't cached, bl…
thebigjoe1 Oct 6, 2026
cbb6ade
security: the image proxy passes images only, sent so they can't act …
thebigjoe1 Oct 6, 2026
e8db88a
fix: Android sync keeps ids, deletes, offline edits and accounts apart
thebigjoe1 Oct 6, 2026
5826a98
chore(l10n): add French translation
weblate Oct 7, 2026
9918705
chore(l10n): add Italian translation
weblate Oct 7, 2026
3b69a3f
fix: Android sync keeps accounts apart, makes each row once, and the …
thebigjoe1 Oct 8, 2026
1166600
fix: Android app no longer opens blank after setup sign-in, and ingre…
thebigjoe1 Oct 8, 2026
baf80d8
chore(l10n): update Italian translation
weblate Oct 8, 2026
c8c7e19
chore(security): bump @capacitor/android and @capacitor/core to 8.5.3…
thebigjoe1 Oct 8, 2026
492c812
fix: Trace shows the newest chat messages, not the oldest 100
thebigjoe1 Oct 9, 2026
067a46b
fix: sync stores photos embedded in rows as files, and startup turns …
thebigjoe1 Oct 9, 2026
192c9bd
Changelog: fixes and security carried into 1.4.1
thebigjoe1 Oct 9, 2026
b585268
chore(dev): bump to v1.4.1-dev03
thebigjoe1 Oct 9, 2026
8540caf
Merge remote-tracking branch 'origin/main' into rel-141-work
thebigjoe1 Oct 22, 2026
22c4f83
release: v1.4.1
thebigjoe1 Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,17 @@ JWT_SECRET=change-me-to-a-long-random-secret
# default; public-internet-facing installs should leave this off.
# ALLOW_PRIVATE_WEBHOOK_URLS=1

# Importing a recipe from a link, and smart import's AI address when an
# account sets its own, fetch from this server. An admin may reach addresses
# on the server's own network; other accounts may not, so they can't read
# services only the server can see. Set these to let every account (and a
# single-user install, which has no sign-in). Cloud-metadata addresses stay
# blocked.
# ALLOW_PRIVATE_RECIPE_URLS=1
# ALLOW_PRIVATE_AI_URLS=1
# Behind HTTP_PROXY/HTTPS_PROXY these checks still run, but the proxy makes
# the connection, so what it can reach (its own network) is up to the proxy.

# ── Update checks ─────────────────────────────────────────────────────────
# Off until you turn them on: setup asks, and Settings, Updates can change it.
# When on, the server asks github.com for the latest release every few hours
Expand Down
151 changes: 151 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

21 changes: 10 additions & 11 deletions DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,19 @@ is a discoverability mirror. Both are first-class; pick whichever fits.
- **`ghcr.io/traceapps/cooktrace`** (primary)
- **`traceapps/cooktrace`** on [Docker Hub](https://hub.docker.com/r/traceapps/cooktrace) (mirror)

Pin to whatever risk level fits (examples below use GHCR; swap the prefix
for Docker Hub if preferred):
Two tags are published (examples below use GHCR; swap the prefix for
Docker Hub if preferred):

| Tag | Updates when | Use case |
|-----|--------------|----------|
| `ghcr.io/traceapps/cooktrace:1.0.0` | Never (pinned exact) | Reproducible pin to a specific version |
| `ghcr.io/traceapps/cooktrace:1.0` | Any 1.0.x patch release | Auto-receive bug fixes, no new features |
| `ghcr.io/traceapps/cooktrace:1` | Any 1.x.y minor release | Auto-minor within a major, no breaking |
| `ghcr.io/traceapps/cooktrace:latest` | Every stable release | Absolute latest stable |
| `ghcr.io/traceapps/cooktrace:latest` | Every stable release | Running the app |
| `ghcr.io/traceapps/cooktrace:dev` | Every push to `dev` branch | Leading edge, not for production |

Legacy `1.0.0-rc.N` tags from before the semver switch remain published
indefinitely on GHCR; anyone pinned to a specific rc release is unaffected.
Docker Hub mirroring started post-1.0, so it only carries stable-era tags.
There are no version-number tags (`:1`, `:1.4`, `:1.4.0`); the ones published
for the first releases stopped updating and were retired. To hold a server on
one exact build, pin it by digest
(`ghcr.io/traceapps/cooktrace@sha256:...`; `docker inspect --format
'{{index .RepoDigests 0}}' ghcr.io/traceapps/cooktrace:latest` prints the one you run).

## Testing pre-release builds

Expand All @@ -45,9 +44,9 @@ Every dev-worthy build refreshes the [`dev-latest`](https://github.com/traceapps

### Milestone `v<version>-devNN` (occasional, pinnable)

When a specific feature or fix is worth its own tester milestone (a new AI capability, a wearable integration, a big backup change), a numbered pre-release gets cut: `v1.0.4-dev01`, `v1.1.0-dev01`, etc. These get their own permanent GH release, their own tester-facing notes, and their own Docker tag (`ghcr.io/traceapps/cooktrace:1.0.4-dev01`) alongside `:dev`. `dev-latest` is refreshed to point at the same commit.
When a specific feature or fix is worth its own tester milestone (a new AI capability, a wearable integration, a big backup change), a numbered pre-release gets cut: `v1.0.4-dev01`, `v1.1.0-dev01`, etc. These get their own permanent GH release, their own tester-facing notes, but no Docker tag of their own: the server side of a milestone is the `:dev` image. `dev-latest` is refreshed to point at the same commit.

Iteration numbers are zero-padded two digits for 1 through 9 (`dev01`, `dev02`, …, `dev09`) and natural two digits from 10 onward (`dev10`, `dev11`, …). No dot between `dev` and the number. That keeps the identifier inside SemVer 2.0.0 §9 and gives correct lex ordering everywhere (GitHub Tags, `gh release list`, Docker Hub).
Iteration numbers are zero-padded two digits for 1 through 9 (`dev01`, `dev02`, …, `dev09`) and natural two digits from 10 onward (`dev10`, `dev11`, …). No dot between `dev` and the number. That keeps the identifier inside SemVer 2.0.0 §9 and gives correct lex ordering everywhere (GitHub Tags, `gh release list`).

Use numbered dev builds when reporting bugs ("I saw this on `v1.1.0-dev02`") or if you want to install a specific milestone and stay on it. Everyone else, `dev-latest` covers you.

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Third app in the Trace family alongside [NutriTrace](https://github.com/traceapp

### AI + Federation
- **Trace AI.** Reads your recipes, pantry, diary, and cookbooks; can log a cook, plan a meal, add to shopping, or import a recipe from a URL, all conversationally. 19 tools total. Multi-provider (Claude / OpenAI / Gemini / any OpenAI-compatible endpoint). Smart Log voice, image attach, cook-mode voice control. → [full guide](https://traceapps.github.io/docs/cooktrace/trace/)
- **NutriTrace federation.** Pull food data per-user with a Bearer token; log cooks back to the NT diary. → [full guide](https://traceapps.github.io/docs/cooktrace/nt-federation/)
- **NutriTrace federation.** Pull food data from NutriTrace into your pantry, per user, with a Bearer token. → [full guide](https://traceapps.github.io/docs/cooktrace/nt-federation/)
- **Model Context Protocol (MCP).** Expose your recipes, pantry, shopping list, and cook diary to external AI agents (Claude Desktop, Cursor, Codex) via the standard MCP Streamable HTTP transport. Off by default; opt in with `MCP_ENABLED=1`. Read, write, and destructive tool tiers, each independently gated by its own env flag and token scope. → [full guide](https://traceapps.github.io/docs/cooktrace/mcp/)

### Accounts + platforms
Expand Down Expand Up @@ -139,6 +139,7 @@ The most-asked knobs. Full list at [docs/self-hosting/env-vars](https://traceapp
| `UPLOADS_PATH` | `/data/uploads` | Uploaded images and server-side backups. |
| `PORT` | `3003` | Port the server listens on inside the container (3001 before 1.3.0). |
| `BASE_URL` | - | Mount at a subpath, e.g. `/cooktrace`. |
| `PUBLIC_URL` | - | The full address people open the app at, subpath included (e.g. `https://recipes.example.com`). Links in emails (password reset, invites, sharing) use it. Unset, they use an address an admin has opened the app at. |
| `LOG_LEVEL` | `info` | `error` \| `warn` \| `info` \| `debug`. |
| `INSECURE_COOKIES` | unset | Set to `1` on plain-HTTP LAN deployments so the auth cookie isn't dropped. See [LAN-HTTP notes](https://traceapps.github.io/docs/getting-started/lan-http/). |
| `MAX_SESSION_HOURS` | `8760` | Session-length cap in hours. Lower for shared / kiosk machines. |
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ android {
applicationId "com.cooktrace.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 105
versionName "1.4.0"
versionCode 106
versionName "1.4.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
Expand Down
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
android:dataExtractionRules="@xml/data_extraction_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.cooktrace.app;

import android.content.Context;
import android.content.SharedPreferences;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;

/**
* This install's id, kept where backups never go (res/xml/backup_rules.xml
* and data_extraction_rules.xml leave out this one preferences file). The
* app's database is backed up, and comes back on a new phone, or a second
* one, with the install id inside it. The app compares the two
* (src/lib/db-native.js dbInstallId): when they differ, the database came
* from somewhere else and this install takes a new id, so two phones never
* send the server the same key for different rows.
*/
@CapacitorPlugin(name = "InstallMarker")
public class InstallMarkerPlugin extends Plugin {
static final String FILE = "ct_install_marker";
private static final String KEY = "install_id";

private SharedPreferences prefs() {
return getContext().getSharedPreferences(FILE, Context.MODE_PRIVATE);
}

@PluginMethod
public void get(PluginCall call) {
JSObject ret = new JSObject();
ret.put("value", prefs().getString(KEY, null));
call.resolve(ret);
}

@PluginMethod
public void set(PluginCall call) {
String value = call.getString("value");
boolean ok = prefs().edit().putString(KEY, value).commit();
if (ok) call.resolve(); else call.reject("could not keep the install id");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public void onCreate(android.os.Bundle savedInstanceState) {
// bridge picks them up when it builds its plugin handle map.
registerPlugin(WearPairingPlugin.class);
registerPlugin(FoldPlugin.class);
registerPlugin(InstallMarkerPlugin.class);
super.onCreate(savedInstanceState);
}

Expand Down
6 changes: 6 additions & 0 deletions android/app/src/main/res/xml/backup_rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Auto Backup up to Android 11: everything as before, except this install's
id (InstallMarkerPlugin), which must never reach another phone. -->
<full-backup-content>
<exclude domain="sharedpref" path="ct_install_marker.xml" />
</full-backup-content>
12 changes: 12 additions & 0 deletions android/app/src/main/res/xml/data_extraction_rules.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Android 12 and later: cloud backup and moving to a new phone keep
everything as before, except this install's id (InstallMarkerPlugin),
which must never reach another phone. -->
<data-extraction-rules>
<cloud-backup>
<exclude domain="sharedpref" path="ct_install_marker.xml" />
</cloud-backup>
<device-transfer>
<exclude domain="sharedpref" path="ct_install_marker.xml" />
</device-transfer>
</data-extraction-rules>
4 changes: 2 additions & 2 deletions android/wear/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ android {
minSdkVersion 30
targetSdkVersion rootProject.ext.targetSdkVersion
// Its own numbering; the name tracks the phone app it pairs with.
versionCode 2
versionName "1.4.0"
versionCode 3
versionName "1.4.1"
}

buildFeatures {
Expand Down
16 changes: 16 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<!--
Workbox also precaches the build-time index so an installed app can open
offline. That document has no Express-injected config. A controlled page
can recover the same mount path from its active worker's URL before the
app's module graph reads __CT_CONFIG__; a server-injected value remains
authoritative on network responses.
-->
<script data-base-path-fallback>
(function() {
if (window.__CT_CONFIG__ || !navigator.serviceWorker) return;
var controller = navigator.serviceWorker.controller;
if (!controller || !controller.scriptURL) return;
var basePath = new URL('.', controller.scriptURL).pathname.replace(/\/$/, '');
window.__CT_CONFIG__ = { basePath: basePath === '/' ? '' : basePath };
})();
</script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
Expand Down
50 changes: 19 additions & 31 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cooktrace",
"version": "1.4.0",
"version": "1.4.1",
"private": true,
"type": "module",
"scripts": {
Expand Down
Loading
Loading