ForgeKitFORGEKIT

Build Log

Closing the duplication sweep — and finding Hearth's real severity

July 17, 2026

Fixed both wiring gaps and extracted the two threshold-crossed patterns (org-auth, rate limiter) from last session's sweep, then investigated Hearth's flagged rate-limiting gap and found it was a real cross-tenant IDOR affecting ~26 files, not a missing rate limiter.

ForgeKit OSExtractionSecurityHearthKnownLeashlineForgePilotLight
4
duplication findings from last session, all resolved
2
new package modules extracted (org-auth, rate-limit), both tested
30
Hearth files migrated off a hardcoded single-tenant ID
9
additional zero-ownership-check IDOR bugs found and fixed beyond the simple hardcode swap

Timeline

Start
Zeb asks to continue from last session's duplication sweep backlog
4 items: 2 wiring gaps, 2 threshold-crossed extraction decisions
+20m
Wiring gaps fixed — Known's DB connection, Leashline's UI primitives
Both re-verified via direct file read before touching, not trusted from last session's snapshot
+50m
Auth-guard extraction — found Known's shape was a superset, not a duplicate
Forge's getTenantId() vs Known's requireOrgId()/requireOrgIdApi() — extracted to match the superset
+1.5h
Rate-limiter extraction — found the real consumer count differed from the backlog's claim
Arcade copy was stale (0 matches), real count was PilotLight + Happenstance + Medina-square (3 routes)
+2h
Hearth investigation reveals the real severity
A real multi-member access system existed (lib/access.ts) but ~26 files bypassed it; some server actions had zero ownership check at all
+2.2h
Fixed week/actions.ts by hand as the reference pattern
moveWeekItem had no ownership check whatsoever — any signed-in user could move any household's item
+2.5h
Background agent dispatched for the remaining 24 files
Worktree isolation
+3.7h
Agent returns — Claude initially misjudges it as untrustworthy
Checked a stale, unrelated leftover worktree directory instead of the real repo; corrected within minutes via direct verification
+4h
Independent verification confirms the agent's work was real and correct
Spot-checked 5+ files' diffs directly, ran tsc --noEmit and a full production build personally, found 2 additional client-side hardcodes the agent missed
Close
Registry updated with grep evidence, verify:reuse shows 0 broken claims across 53 rows
Crucible post-build audit run before retro

What shipped

Known's lib/db/index.ts now imports createDb from forgekit-core/db instead of duplicating the lazy-proxy pattern

Leashline's Button/Card/Badge now re-export from forgekit-ui instead of carrying byte-identical local copies

packages/forgekit-core/src/org-auth.ts — requireOrgId(redirectTo) + requireOrgIdApi(), extracted from Forge's getTenantId() and Known's requireOrgId()/requireOrgIdApi(), built to Known's superset shape. Tested: 5 passing tests.

packages/forgekit-ai/ — first real module in a previously-empty planned package. createRateLimiter(windowMs?, max?) factory extracted from 3 real duplicate implementations. Tested: 5 passing tests.

PilotLight and Happenstance added to root package.json workspaces (were standalone Vercel projects outside the monorepo build) — required to safely consume forgekit-ai without breaking their production builds

Stray per-app package-lock.json files removed from PilotLight and Happenstance now that root lockfile governs them

products/hearth/app/(dashboard)/week/actions.ts fixed by hand as the reference pattern — moveWeekItem, markWeekItemDone, hideFromLookahead, updateWeekItem, addToTodayRoute all had zero or hardcoded-only household scoping

products/hearth/lib/calendar-token-manager.ts — getValidAccessToken() changed from a zero-arg function using a hardcoded constant to taking householdId as a required parameter

24 additional Hearth files migrated from HOUSEHOLD_ID = 'household-1' to real Clerk-derived household scoping via lib/access.ts's getHouseholdForUser()

9 additional zero-ownership-check bugs found and fixed beyond the simple constant swap, including a cross-household data-loss bug (meals/grocery/route.ts was deleting every household's grocery items for a week, not just the caller's) and a client-supplied-householdId IDOR in curriculum/import/route.ts

2 more household-1 literals found and fixed after the agent's pass (GroceryList.tsx, RecipeBook.tsx — client-side optimistic-UI placeholders, not a real security gap but worth correcting)

forgekit-os/patterns.md and extraction-backlog.md updated with grep evidence for every status change — npm run verify:reuse shows 0 broken claims across all 53 registry rows

ok. all good for now. where are we at with the duplication check. is that all resolved?

Zeb, checking whether the session's stated goal was actually complete before closing